feat(nonlinear-static-newton-raphson): step 0 - cli-output-lease-and-derived-names

This commit is contained in:
KOKO\Mimi
2026-08-24 10:42:14 +09:00
parent 41816c8aef
commit fc16ef6221
61 changed files with 10890 additions and 115 deletions
Binary file not shown.
+132
View File
@@ -0,0 +1,132 @@
# ninja log v7
107 1367 8092384218864831 src/fesa/CMakeFiles/fesa_solver.dir/build_info.cpp.obj cbb74df2cfe16446
97 1760 8092384218802669 src/fesa/CMakeFiles/fesa_solver.dir/assembly/parallel_for.cpp.obj 6d361d78b8ddb1e6
132 2029 8092384219120278 src/fesa/CMakeFiles/fesa_solver.dir/core/status.cpp.obj d9066190c54698e1
127 2129 8092384218979200 src/fesa/CMakeFiles/fesa_solver.dir/core/diagnostic.cpp.obj a5cabe8b0504c8b6
122 2167 8092384218979200 src/fesa/CMakeFiles/fesa_solver.dir/core/ascii.cpp.obj c1314f837b92110e
63 2464 8092384218329431 _deps/googletest-build/googletest/CMakeFiles/gtest_main.dir/src/gtest_main.cc.obj bd6626bb67644ce5
112 2521 8092384218924680 src/fesa/CMakeFiles/fesa_solver.dir/constraints/essential_constraint_policy.cpp.obj 839def0f97ba4345
67 2557 8092384218488485 src/fesa/CMakeFiles/fesa_solver.dir/analysis/analysis_model.cpp.obj 61c968a4b6f63aff
72 2575 8092384218488485 src/fesa/CMakeFiles/fesa_solver.dir/analysis/analysis_state.cpp.obj 7fe12c916f130467
117 2585 8092384218979200 src/fesa/CMakeFiles/fesa_solver.dir/constraints/prescribed_displacement.cpp.obj cf4a7839ef2889be
92 2604 8092384218727988 src/fesa/CMakeFiles/fesa_solver.dir/assembly/load_assembler.cpp.obj a9a88a41a899d830
102 2671 8092384218842800 src/fesa/CMakeFiles/fesa_solver.dir/assembly/sparse_assembler.cpp.obj e370471d9b7f46eb
82 2748 8092384218645949 src/fesa/CMakeFiles/fesa_solver.dir/app/fesa_application.cpp.obj b131425fcf446caf
136 2761 8092384219192725 src/fesa/CMakeFiles/fesa_solver.dir/elements/element_factory.cpp.obj c53943f91b42e499
141 3032 8092384219211547 src/fesa/CMakeFiles/fesa_solver.dir/elements/euler_beam_3d.cpp.obj 8d8a96d17efb1fbd
87 3044 8092384218668902 src/fesa/CMakeFiles/fesa_solver.dir/app/output_paths.cpp.obj 2f4555a69a891bf2
77 3054 8092384218488485 src/fesa/CMakeFiles/fesa_solver.dir/analysis/linear_static_analysis.cpp.obj 96370aed2a86ae09
1369 4357 8092384231534591 src/fesa/CMakeFiles/fesa_solver.dir/elements/mitc4_shell.cpp.obj 4497417f368343ba
2029 4511 8092384238129153 src/fesa/CMakeFiles/fesa_solver.dir/io/abaqus/domain_builder.cpp.obj f82b7186c8b1d417
2167 4531 8092384239513629 src/fesa/CMakeFiles/fesa_solver.dir/io/abaqus/domain_mapper.cpp.obj 78013a69808c94d7
1761 4592 8092384235437686 src/fesa/CMakeFiles/fesa_solver.dir/fem/dof_manager.cpp.obj be7398345e5a9ad
2465 4609 8092384242481563 src/fesa/CMakeFiles/fesa_solver.dir/io/abaqus/input_reader.cpp.obj 209f6a2dba784f60
2558 4634 8092384243411066 src/fesa/CMakeFiles/fesa_solver.dir/io/abaqus/step_definition_mapper.cpp.obj e2bf727de4df328f
2575 4654 8092384243589363 src/fesa/CMakeFiles/fesa_solver.dir/io/abaqus/topology_mapper.cpp.obj 35a7cf559a2383f0
2522 4978 8092384243054401 src/fesa/CMakeFiles/fesa_solver.dir/io/abaqus/material_property_mapper.cpp.obj e3d7c5c1826acfd0
58 4997 8092384218329431 _deps/googletest-build/googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.obj 5f59395ac6fe27d6
2672 5237 8092384244558583 src/fesa/CMakeFiles/fesa_solver.dir/io/hdf5/hdf5_primitives.cpp.obj a94f3e6278bb7040
2605 5250 8092384243885657 src/fesa/CMakeFiles/fesa_solver.dir/io/hdf5/hdf5_model_writer.cpp.obj 54d576166219ebe3
2762 5307 8092384245447369 src/fesa/CMakeFiles/fesa_solver.dir/io/hdf5/hdf5_results_writer.cpp.obj b086f45ee057095d
2585 5660 8092384243687256 src/fesa/CMakeFiles/fesa_solver.dir/io/hdf5/hdf5_atomic_file.cpp.obj acf4093ec1ca0dab
3045 5693 8092384248271192 src/fesa/CMakeFiles/fesa_solver.dir/loads/concentrated_nodal_load.cpp.obj b738f2f3ef238897
3032 5716 8092384248152286 src/fesa/CMakeFiles/fesa_solver.dir/io/hdf5/hdf5_self_check.cpp.obj 61e23edf9fd3defe
2749 5755 8092384245329453 src/fesa/CMakeFiles/fesa_solver.dir/io/hdf5/hdf5_result_writer.cpp.obj 76edfaf76dda1150
5008 5765 8092384267920473 lib/gtest.lib 3ad571dfafc7ee18
3054 5812 8092384248369539 src/fesa/CMakeFiles/fesa_solver.dir/materials/isotropic_linear_elastic_material.cpp.obj ec18800579e40b2f
2129 6343 8092384239119443 src/fesa/CMakeFiles/fesa_solver.dir/io/abaqus/domain_mapping_context.cpp.obj 541cf582d5d72f1d
4978 6880 8092384267621712 src/fesa/CMakeFiles/fesa_solver.dir/properties/general_beam_section.cpp.obj 14abd1111f7f07ba
5813 6922 8092384275957474 lib/gtest_main.lib 1fea6bfefff1654b
4532 7019 8092384263153824 src/fesa/CMakeFiles/fesa_solver.dir/math/sparse_matrix.cpp.obj 43c886855039f11b
4635 7086 8092384264181273 src/fesa/CMakeFiles/fesa_solver.dir/model/shell_geometry.cpp.obj 64372c6247c9d1fe
4654 7099 8092384264379650 src/fesa/CMakeFiles/fesa_solver.dir/model/source_target_resolver.cpp.obj f0d949f736370376
5238 7149 8092384270209372 src/fesa/CMakeFiles/fesa_solver.dir/properties/shell_section.cpp.obj b4b7f64079a1b357
4512 7175 8092384262955435 src/fesa/CMakeFiles/fesa_solver.dir/math/matrix.cpp.obj 90a5827630c77ffa
4358 7188 8092384261413268 src/fesa/CMakeFiles/fesa_solver.dir/math/dense_blas_internal.cpp.obj 1d155025fdc36e32
4592 7436 8092384263746888 src/fesa/CMakeFiles/fesa_solver.dir/math/vector.cpp.obj 31eb0e6e052791f4
5308 7496 8092384270902468 src/fesa/CMakeFiles/fesa_solver.dir/results/beam_result_recovery.cpp.obj 8dbf5a7584b82d05
4610 7578 8092384263925156 src/fesa/CMakeFiles/fesa_solver.dir/model/domain.cpp.obj 327270abdb77ada5
5694 7594 8092384274770343 src/fesa/CMakeFiles/fesa_solver.dir/results/recovery_candidate.cpp.obj 36f81aba1565e4cd
5251 7882 8092384270347432 src/fesa/CMakeFiles/fesa_solver.dir/results/analysis_state_commit.cpp.obj f591f5f73fa893d
5756 7931 8092384275383077 src/fesa/CMakeFiles/fesa_solver.dir/results/shell_result_recovery.cpp.obj d6de270523c88b62
5661 7969 8092384274433391 src/fesa/CMakeFiles/fesa_solver.dir/results/global_equilibrium_recovery.cpp.obj dc54637dec7c2fe
5717 8847 8092384275008914 src/fesa/CMakeFiles/fesa_solver.dir/results/result_recovery.cpp.obj dcfbfce0a69b5131
5765 9159 8092384275484616 src/fesa/CMakeFiles/fesa_solver.dir/solvers/linear/mkl_pardiso_solver.cpp.obj c7d3578377b60ab4
6356 9177 8092384281377735 tests/CMakeFiles/fesa_unit_tests.dir/unit/build_info_test.cpp.obj cc2d626fb4f55428
7087 9322 8092384288690125 tests/CMakeFiles/fesa_unit_tests.dir/unit/assembly/parallel_for_test.cpp.obj 64cd58a46d8c2ed0
6881 9633 8092384286632996 tests/CMakeFiles/fesa_unit_tests.dir/unit/analysis/analysis_test.cpp.obj 629ae05c2a17e2a2
7176 10116 8092384289581651 tests/CMakeFiles/fesa_unit_tests.dir/unit/app/output_paths_test.cpp.obj 190d4f41b24a7775
9160 10155 8092384309439240 src/fesa/fesa_solver.lib 834cb49484ed4975
7578 10308 8092384293615881 tests/CMakeFiles/fesa_unit_tests.dir/unit/core/diagnostic_test.cpp.obj 382faf72525f5dbd
7497 10354 8092384292804797 tests/CMakeFiles/fesa_unit_tests.dir/unit/core/ascii_test.cpp.obj 4c8e3757a2b86a10
7594 10413 8092384293774107 tests/CMakeFiles/fesa_unit_tests.dir/unit/core/source_identity_test.cpp.obj 2f8c538d6bbcf9a6
7019 10542 8092384288017054 tests/CMakeFiles/fesa_unit_tests.dir/unit/analysis/analysis_state_test.cpp.obj 4eceb64a57a9abdc
6922 10553 8092384287049746 tests/CMakeFiles/fesa_unit_tests.dir/unit/analysis/analysis_model_test.cpp.obj 40c473ba9bc9973e
7883 10959 8092384296644544 tests/CMakeFiles/fesa_unit_tests.dir/unit/core/status_test.cpp.obj ab6dc42cc2881a67
7100 10971 8092384288828228 tests/CMakeFiles/fesa_unit_tests.dir/unit/assembly/load_assembler_test.cpp.obj fd58472fadea8d92
7189 11213 8092384289719698 tests/CMakeFiles/fesa_unit_tests.dir/unit/constraints/boundary_condition_test.cpp.obj 6d8a23b383677aae
7437 11353 8092384292190435 tests/CMakeFiles/fesa_unit_tests.dir/unit/constraints/essential_constraints_test.cpp.obj fc4706d7a106f2b0
7150 11433 8092384289323046 tests/CMakeFiles/fesa_unit_tests.dir/unit/assembly/sparse_assembler_test.cpp.obj 1d73050ff822ef16
7970 11517 8092384297528284 tests/CMakeFiles/fesa_unit_tests.dir/unit/elements/euler_beam_3d_test.cpp.obj 4757a86932e814d5
7932 12441 8092384297154255 tests/CMakeFiles/fesa_unit_tests.dir/unit/elements/element_factory_test.cpp.obj 1646374b1d49e4ea
9634 12565 8092384314168466 tests/CMakeFiles/fesa_unit_tests.dir/unit/math/matrix_test.cpp.obj 1c0388a2cb34a977
10309 12712 8092384320925938 tests/CMakeFiles/fesa_unit_tests.dir/unit/math/vector_test.cpp.obj 537626a817bb764a
8848 12728 8092384306313035 tests/CMakeFiles/fesa_unit_tests.dir/unit/elements/mitc4_shell_test.cpp.obj 2f4e47f40acc7795
10156 12796 8092384319383650 tests/CMakeFiles/fesa_unit_tests.dir/unit/math/vector3_test.cpp.obj 7940001bdaf8e4fe
9322 13452 8092384311062628 tests/CMakeFiles/fesa_unit_tests.dir/unit/math/dense_blas_internal_test.cpp.obj f2f846d2a426012d
9177 13464 8092384309597453 tests/CMakeFiles/fesa_unit_tests.dir/unit/fem/dof_manager_test.cpp.obj 6004da54fb433c80
10117 13583 8092384318989204 tests/CMakeFiles/fesa_unit_tests.dir/unit/math/sparse_matrix_test.cpp.obj f75bb2f18a5bd303
10542 13638 8092384323262138 tests/CMakeFiles/fesa_unit_tests.dir/unit/io/abaqus/input_reader_test.cpp.obj 54d4660fb8524142
10554 13838 8092384323380087 tests/CMakeFiles/fesa_unit_tests.dir/unit/io/abaqus/input_syntax_test.cpp.obj 14036fa417a21f26
10354 14002 8092384321383068 tests/CMakeFiles/fesa_unit_tests.dir/unit/io/abaqus/domain_mapping_components_test.cpp.obj 8b6d55d5290b3dcf
10414 14961 8092384321975774 tests/CMakeFiles/fesa_unit_tests.dir/unit/io/abaqus/domain_mapper_test.cpp.obj 4256f1932890204e
11214 14967 8092384329967026 tests/CMakeFiles/fesa_unit_tests.dir/unit/loads/load_test.cpp.obj 41fecb4ac4aefc2d
11434 15018 8092384332164407 tests/CMakeFiles/fesa_unit_tests.dir/unit/model/model_types_test.cpp.obj 167fe5a77a5994eb
11517 15025 8092384332997863 tests/CMakeFiles/fesa_unit_tests.dir/unit/model/shell_geometry_test.cpp.obj 785d2d3084addad4
12566 15363 8092384343501584 tests/CMakeFiles/fesa_unit_tests.dir/unit/materials/material_test.cpp.obj 1b5d607a45cc656b
11354 15565 8092384331373052 tests/CMakeFiles/fesa_unit_tests.dir/unit/model/domain_test.cpp.obj 4e4ba6955bfefa4
10972 15603 8092384327552836 tests/CMakeFiles/fesa_unit_tests.dir/unit/io/hdf5/hdf5_writer_components_test.cpp.obj 7b26f2ede20a2e21
12442 15702 8092384342237335 tests/CMakeFiles/fesa_unit_tests.dir/unit/model/source_target_resolver_test.cpp.obj 7dee827d528c74d3
12713 15742 8092384344954378 tests/CMakeFiles/fesa_unit_tests.dir/unit/properties/element_property_test.cpp.obj 8473fe9452582ea0
13465 15869 8092384352483655 tests/CMakeFiles/fesa_unit_tests.dir/unit/results/results_writer_test.cpp.obj d9deb24734dfc76
10960 16310 8092384327434560 tests/CMakeFiles/fesa_unit_tests.dir/unit/io/hdf5/hdf5_results_writer_test.cpp.obj 562b8f04b2dcdc01
13584 16592 8092384353669318 tests/CMakeFiles/fesa_unit_tests.dir/unit/solvers/linear/linear_solver_test.cpp.obj 60444f53e28a5449
12728 16604 8092384345112691 tests/CMakeFiles/fesa_unit_tests.dir/unit/results/result_records_test.cpp.obj 750f53bc9d3bf3f1
13639 16746 8092384354224529 tests/CMakeFiles/fesa_unit_tests.dir/unit/solvers/linear/mkl_pardiso_solver_test.cpp.obj b761afa1036f4978
14003 16836 8092384357866571 tests/CMakeFiles/fesa_integration_tests.dir/integration/app/fesa_application_test.cpp.obj 83061b0b6e67b7d2
12797 17156 8092384345803861 tests/CMakeFiles/fesa_unit_tests.dir/unit/results/result_recovery_components_test.cpp.obj 83ac2cda76cf82a
13839 17161 8092384356222006 tests/CMakeFiles/fesa_integration_tests.dir/integration/analysis/linear_static_analysis_test.cpp.obj 2637ca1438adff43
13452 17652 8092384352365561 tests/CMakeFiles/fesa_unit_tests.dir/unit/results/result_recovery_test.cpp.obj 16815e6d5b74928a
17162 19481 8092384412470224 tests/fesa_integration_tests.exe d976ae10942a92cd
17162 19481 8092384412470224 tests/fesa_integration_tests_d537bc73_tests.cmake d976ae10942a92cd
17162 19481 8092384412470224 C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_integration_tests_d537bc73_tests.cmake d976ae10942a92cd
17652 19869 8092384416412729 tests/fesa_unit_tests.exe c7f61799ccaff6df
17652 19869 8092384416412729 tests/fesa_unit_tests_576e7e9d_tests.cmake c7f61799ccaff6df
17652 19869 8092384416412729 C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_unit_tests_576e7e9d_tests.cmake c7f61799ccaff6df
57 907 8092384649865117 src/fesa/CMakeFiles/fesa_cli.dir/app/main.cpp.obj db4c7e4d98d0b37a
62 1025 8092384649865117 tests/CMakeFiles/fesa_reference_tests.dir/reference/reference_tolerance_policy.cpp.obj 4d4567dc725e04bf
67 1957 8092384649929171 tests/CMakeFiles/fesa_reference_tests.dir/reference/reference_tolerance_policy_test.cpp.obj df1c2a7b89dbaab5
87 2236 8092384650156206 tests/CMakeFiles/fesa_reference_tests.dir/reference/mitc4_reference_comparison.cpp.obj d5641bbf190f8212
98 2282 8092384650262486 tests/CMakeFiles/fesa_reference_tests.dir/reference/mitc4_reference_cases_test.cpp.obj 724d2e009b4467de
82 2448 8092384650085756 tests/CMakeFiles/fesa_reference_tests.dir/reference/b33_reference_comparison_test.cpp.obj fe2325128628efc1
92 2498 8092384650202184 tests/CMakeFiles/fesa_reference_tests.dir/reference/mitc4_reference_comparison_test.cpp.obj 536ec854d4427ddc
72 2767 8092384649929171 tests/CMakeFiles/fesa_reference_tests.dir/reference/reference_comparison.cpp.obj c9b25f54d0e8d98f
908 2795 8092384658379739 src/fesa/fesa.exe 1f8f56fa7a9b4ffe
76 2814 8092384649929171 tests/CMakeFiles/fesa_reference_tests.dir/reference/reference_comparison_test.cpp.obj 20f54b6ae2255260
2814 4306 8092384692235536 tests/fesa_reference_tests.exe c70eaec9df33bb90
2814 4306 8092384692235536 tests/fesa_reference_tests_ac7cf2f0_tests.cmake c70eaec9df33bb90
2814 4306 8092384692235536 C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_reference_tests_ac7cf2f0_tests.cmake c70eaec9df33bb90
53 1720 8092385992962344 tests/CMakeFiles/fesa_reference_tests.dir/reference/mitc4_reference_cases_test.cpp.obj 724d2e009b4467de
57 1772 8092387178958005 tests/CMakeFiles/fesa_reference_tests.dir/reference/b33_reference_comparison_test.cpp.obj fe2325128628efc1
51 2086 8092387178799897 tests/CMakeFiles/fesa_reference_tests.dir/reference/reference_comparison.cpp.obj c9b25f54d0e8d98f
2086 2967 8092387207983024 tests/fesa_reference_tests.exe c70eaec9df33bb90
2086 2967 8092387207983024 tests/fesa_reference_tests_ac7cf2f0_tests.cmake c70eaec9df33bb90
2086 2967 8092387207983024 C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_reference_tests_ac7cf2f0_tests.cmake c70eaec9df33bb90
47 1627 8092387468833159 tests/CMakeFiles/fesa_reference_tests.dir/reference/mitc4_reference_cases_test.cpp.obj 724d2e009b4467de
1627 2458 8092387492815552 tests/fesa_reference_tests.exe c70eaec9df33bb90
1627 2458 8092387492815552 tests/fesa_reference_tests_ac7cf2f0_tests.cmake c70eaec9df33bb90
1627 2458 8092387492815552 C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_reference_tests_ac7cf2f0_tests.cmake c70eaec9df33bb90
31 1687 8092388278143624 tests/CMakeFiles/fesa_integration_tests.dir/integration/app/fesa_application_test.cpp.obj 83061b0b6e67b7d2
1688 2540 8092388303138660 tests/fesa_integration_tests.exe d976ae10942a92cd
1688 2540 8092388303138660 tests/fesa_integration_tests_d537bc73_tests.cmake d976ae10942a92cd
1688 2540 8092388303138660 C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_integration_tests_d537bc73_tests.cmake d976ae10942a92cd
@@ -0,0 +1,37 @@
####### Expanded from @PACKAGE_INIT@ by configure_package_config_file() #######
####### Any changes to this file will be overwritten by the next CMake run ####
####### The input file was Config.cmake.in ########
get_filename_component(PACKAGE_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../" ABSOLUTE)
macro(set_and_check _var _file)
set(${_var} "${_file}")
if(NOT EXISTS "${_file}")
message(FATAL_ERROR "File or directory ${_file} referenced by variable ${_var} does not exist !")
endif()
endmacro()
macro(check_required_components _NAME)
foreach(comp ${${_NAME}_FIND_COMPONENTS})
if(NOT ${_NAME}_${comp}_FOUND)
if(${_NAME}_FIND_REQUIRED_${comp})
set(${_NAME}_FOUND FALSE)
endif()
endif()
endforeach()
endmacro()
####################################################################################
include(CMakeFindDependencyMacro)
if ()
set(THREADS_PREFER_PTHREAD_FLAG )
find_dependency(Threads)
endif()
if (OFF)
find_dependency(absl)
find_dependency(re2)
endif()
include("${CMAKE_CURRENT_LIST_DIR}/GTestTargets.cmake")
check_required_components("")
@@ -0,0 +1,43 @@
# This is a basic version file for the Config-mode of find_package().
# It is used by write_basic_package_version_file() as input file for configure_file()
# to create a version-file which can be installed along a config.cmake file.
#
# The created file sets PACKAGE_VERSION_EXACT if the current version string and
# the requested version string are exactly the same and it sets
# PACKAGE_VERSION_COMPATIBLE if the current version is >= requested version.
# The variable CVF_VERSION must be set before calling configure_file().
set(PACKAGE_VERSION "1.16.0")
if (PACKAGE_FIND_VERSION_RANGE)
# Package version must be in the requested version range
if ((PACKAGE_FIND_VERSION_RANGE_MIN STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION_MIN)
OR ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_GREATER PACKAGE_FIND_VERSION_MAX)
OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND PACKAGE_VERSION VERSION_GREATER_EQUAL PACKAGE_FIND_VERSION_MAX)))
set(PACKAGE_VERSION_COMPATIBLE FALSE)
else()
set(PACKAGE_VERSION_COMPATIBLE TRUE)
endif()
else()
if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION)
set(PACKAGE_VERSION_COMPATIBLE FALSE)
else()
set(PACKAGE_VERSION_COMPATIBLE TRUE)
if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION)
set(PACKAGE_VERSION_EXACT TRUE)
endif()
endif()
endif()
# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it:
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "8" STREQUAL "")
return()
endif()
# check that the installed version has the same 32/64bit-ness as the one which is currently searching:
if(NOT CMAKE_SIZEOF_VOID_P STREQUAL "8")
math(EXPR installedBits "8 * 8")
set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)")
set(PACKAGE_VERSION_UNSUITABLE TRUE)
endif()
@@ -0,0 +1,10 @@
libdir=C:/Program Files (x86)/FESA/lib
includedir=C:/Program Files (x86)/FESA/include
Name: gmock
Description: GoogleMock (without main() function)
Version: 1.16.0
URL: https://github.com/google/googletest
Requires: gtest = 1.16.0
Libs: -L${libdir} -lgmock
Cflags: -I${includedir} -DGTEST_HAS_PTHREAD=0
@@ -0,0 +1,10 @@
libdir=C:/Program Files (x86)/FESA/lib
includedir=C:/Program Files (x86)/FESA/include
Name: gmock_main
Description: GoogleMock (with main() function)
Version: 1.16.0
URL: https://github.com/google/googletest
Requires: gmock = 1.16.0
Libs: -L${libdir} -lgmock_main
Cflags: -I${includedir} -DGTEST_HAS_PTHREAD=0
@@ -0,0 +1,9 @@
libdir=C:/Program Files (x86)/FESA/lib
includedir=C:/Program Files (x86)/FESA/include
Name: gtest
Description: GoogleTest (without main() function)
Version: 1.16.0
URL: https://github.com/google/googletest
Libs: -L${libdir} -lgtest
Cflags: -I${includedir} -DGTEST_HAS_PTHREAD=0
@@ -0,0 +1,10 @@
libdir=C:/Program Files (x86)/FESA/lib
includedir=C:/Program Files (x86)/FESA/include
Name: gtest_main
Description: GoogleTest (with main() function)
Version: 1.16.0
URL: https://github.com/google/googletest
Requires: gtest = 1.16.0
Libs: -L${libdir} -lgtest_main
Cflags: -I${includedir} -DGTEST_HAS_PTHREAD=0
File diff suppressed because one or more lines are too long
@@ -0,0 +1,106 @@
*Heading
** Job name: Job-1 Model name: Model-1
** Generated by: Abaqus/CAE Learning Edition 2024
*Preprint, echo=NO, model=NO, history=NO, contact=NO
**
** PARTS
**
*Part, name=PART-1_1
*Node
1, 0., 0., 0.
2, 1., 0., 0.
3, 2., 0., 0.
4, 3., 0., 0.
5, 4., 0., 0.
6, 5., 0., 0.
7, 6., 0., 0.
8, 7., 0., 0.
9, 8., 0., 0.
10, 9., 0., 0.
11, 10., 0., 0.
*Element, type=B33
1, 1, 2
2, 2, 3
3, 3, 4
4, 4, 5
5, 5, 6
6, 6, 7
7, 7, 8
8, 8, 9
9, 9, 10
10, 10, 11
*Elset, elset=Set-1, generate
1, 10, 1
*Elset, elset=Set-2, generate
1, 10, 1
*Elset, elset=Set-3, generate
1, 10, 1
*Elset, elset=Set-4, generate
1, 10, 1
** Section: Section-1 Profile: Profile-1
*Beam General Section, elset=Set-1, material=Material-1, section=GENERAL
1., 0.0833333, 0., 0.0833333, 0.140833
0.,1.,0.
*End Part
**
**
** ASSEMBLY
**
*Assembly, name=Assembly
**
*Instance, name=PART-1_1-1, part=PART-1_1
*End Instance
**
*Nset, nset=Set-3, instance=PART-1_1-1
1,
*Nset, nset=Set-4, instance=PART-1_1-1
11,
*End Assembly
**
** MATERIALS
**
*Material, name=Material-1
*Elastic
2.1e+11, 0.3
**
** BOUNDARY CONDITIONS
**
** Name: BC-1 Type: Displacement/Rotation
*Boundary
Set-3, 1, 1
Set-3, 2, 2
Set-3, 3, 3
Set-3, 4, 4
Set-3, 5, 5
Set-3, 6, 6
** ----------------------------------------------------------------
**
** STEP: Step-1
**
*Step, name=Step-1, nlgeom=NO
*Static
1., 1., 1e-05, 1.
**
** LOADS
**
** Name: Load-1 Type: Concentrated force
*Cload
Set-4, 3, -1e+06
**
** OUTPUT REQUESTS
**
*Restart, write, frequency=0
**
** FIELD OUTPUT: F-Output-1
**
*Output, field
*Node Output
CF, RF, TF, U
*Element Output, directions=YES
LE, NFORC, NFORCSO, PE, PEEQ, PEMAG, S, SF
*Contact Output, variable=PRESELECT
**
** HISTORY OUTPUT: H-Output-1
**
*Output, history, variable=PRESELECT
*End Step
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,164 @@
*Heading
** Job name: shell Model name: Model-1
** Generated by: Abaqus/CAE Learning Edition 2024
*Preprint, echo=NO, model=NO, history=NO, contact=NO
**
** PARTS
**
*Part, name=Part-1
*Node
1, 0., -5., 0.
2, 0., 0., 0.
3, -5., 0., 0.
4, -5., -5., 0.
5, 0., 5., 0.
6, 5., 0., 0.
7, 5., 5., 0.
8, -5., 5., 0.
9, 5., -5., 0.
10, 0., -3.33333325, 0.
11, 0., -1.66666663, 0.
12, -1.66666663, 0., 0.
13, -3.33333325, 0., 0.
14, -5., -1.66666663, 0.
15, -5., -3.33333325, 0.
16, -3.33333325, -5., 0.
17, -1.66666663, -5., 0.
18, 0., 3.33333325, 0.
19, 0., 1.66666663, 0.
20, 1.66666663, 0., 0.
21, 3.33333325, 0., 0.
22, 5., 1.66666663, 0.
23, 5., 3.33333325, 0.
24, 3.33333325, 5., 0.
25, 1.66666663, 5., 0.
26, -1.66666663, 5., 0.
27, -3.33333325, 5., 0.
28, -5., 3.33333325, 0.
29, -5., 1.66666663, 0.
30, 1.66666663, -5., 0.
31, 3.33333325, -5., 0.
32, 5., -3.33333325, 0.
33, 5., -1.66666663, 0.
34, -1.66666663, -3.33333325, 0.
35, -1.66666663, -1.66666663, 0.
36, -3.33333325, -3.33333325, 0.
37, -3.33333325, -1.66666663, 0.
38, 1.66666663, 3.33333325, 0.
39, 1.66666663, 1.66666663, 0.
40, 3.33333325, 3.33333325, 0.
41, 3.33333325, 1.66666663, 0.
42, -1.66666663, 1.66666663, 0.
43, -1.66666663, 3.33333325, 0.
44, -3.33333325, 1.66666663, 0.
45, -3.33333325, 3.33333325, 0.
46, 1.66666663, -1.66666663, 0.
47, 1.66666663, -3.33333325, 0.
48, 3.33333325, -1.66666663, 0.
49, 3.33333325, -3.33333325, 0.
*Element, type=S4
1, 1, 10, 34, 17
2, 10, 11, 35, 34
3, 11, 2, 12, 35
4, 17, 34, 36, 16
5, 34, 35, 37, 36
6, 35, 12, 13, 37
7, 16, 36, 15, 4
8, 36, 37, 14, 15
9, 37, 13, 3, 14
10, 5, 18, 38, 25
11, 18, 19, 39, 38
12, 19, 2, 20, 39
13, 25, 38, 40, 24
14, 38, 39, 41, 40
15, 39, 20, 21, 41
16, 24, 40, 23, 7
17, 40, 41, 22, 23
18, 41, 21, 6, 22
19, 2, 19, 42, 12
20, 19, 18, 43, 42
21, 18, 5, 26, 43
22, 12, 42, 44, 13
23, 42, 43, 45, 44
24, 43, 26, 27, 45
25, 13, 44, 29, 3
26, 44, 45, 28, 29
27, 45, 27, 8, 28
28, 2, 11, 46, 20
29, 11, 10, 47, 46
30, 10, 1, 30, 47
31, 20, 46, 48, 21
32, 46, 47, 49, 48
33, 47, 30, 31, 49
34, 21, 48, 33, 6
35, 48, 49, 32, 33
36, 49, 31, 9, 32
*Nset, nset=Set-1, generate
1, 49, 1
*Elset, elset=Set-1, generate
1, 36, 1
** Section: Section-1
*Shell Section, elset=Set-1, material=Material-1
0.5, 5
*End Part
**
**
** ASSEMBLY
**
*Assembly, name=Assembly
**
*Instance, name=Part-1-1, part=Part-1
*End Instance
**
*Nset, nset=Set-1, instance=Part-1-1
2,
*Nset, nset=Set-2, instance=Part-1-1
1, 3, 4, 5, 6, 7, 8, 9, 14, 15, 16, 17, 22, 23, 24, 25
26, 27, 28, 29, 30, 31, 32, 33
*Elset, elset=Set-2, instance=Part-1-1
1, 4, 7, 8, 9, 10, 13, 16, 17, 18, 21, 24, 25, 26, 27, 30
33, 34, 35, 36
*End Assembly
**
** MATERIALS
**
*Material, name=Material-1
*Elastic
2.1e+11, 0.3
**
** BOUNDARY CONDITIONS
**
** Name: BC-1 Type: Displacement/Rotation
*Boundary
Set-2, 1, 1
Set-2, 2, 2
Set-2, 3, 3
Set-2, 4, 4
Set-2, 5, 5
Set-2, 6, 6
** ----------------------------------------------------------------
**
** STEP: Step-1
**
*Step, name=Step-1, nlgeom=NO
*Static
1., 1., 1e-05, 1.
**
** LOADS
**
** Name: Load-1 Type: Concentrated force
*Cload
Set-1, 3, -100000.
**
** OUTPUT REQUESTS
**
*Restart, write, frequency=0
**
** FIELD OUTPUT: F-Output-1
**
*Output, field, variable=PRESELECT
**
** HISTORY OUTPUT: H-Output-1
**
*Output, history, variable=PRESELECT
*End Step
File diff suppressed because one or more lines are too long
@@ -0,0 +1,164 @@
*Heading
** Job name: shell Model name: Model-1
** Generated by: Abaqus/CAE Learning Edition 2024
*Preprint, echo=NO, model=NO, history=NO, contact=NO
**
** PARTS
**
*Part, name=Part-1
*Node
1, 0., -5., 0.
2, 0., 0., 0.
3, -5., 0., 0.
4, -5., -5., 0.
5, 0., 5., 0.
6, 5., 0., 0.
7, 5., 5., 0.
8, -5., 5., 0.
9, 5., -5., 0.
10, 0., -3.33333325, 0.
11, 0., -1.66666663, 0.
12, -1.66666663, 0., 0.
13, -3.33333325, 0., 0.
14, -5., -1.66666663, 0.
15, -5., -3.33333325, 0.
16, -3.33333325, -5., 0.
17, -1.66666663, -5., 0.
18, 0., 3.33333325, 0.
19, 0., 1.66666663, 0.
20, 1.66666663, 0., 0.
21, 3.33333325, 0., 0.
22, 5., 1.66666663, 0.
23, 5., 3.33333325, 0.
24, 3.33333325, 5., 0.
25, 1.66666663, 5., 0.
26, -1.66666663, 5., 0.
27, -3.33333325, 5., 0.
28, -5., 3.33333325, 0.
29, -5., 1.66666663, 0.
30, 1.66666663, -5., 0.
31, 3.33333325, -5., 0.
32, 5., -3.33333325, 0.
33, 5., -1.66666663, 0.
34, -1.66666663, -3.33333325, 0.
35, -1.66666663, -1.66666663, 0.
36, -3.33333325, -3.33333325, 0.
37, -3.33333325, -1.66666663, 0.
38, 1.66666663, 3.33333325, 0.
39, 1.66666663, 1.66666663, 0.
40, 3.33333325, 3.33333325, 0.
41, 3.33333325, 1.66666663, 0.
42, -1.66666663, 1.66666663, 0.
43, -1.66666663, 3.33333325, 0.
44, -3.33333325, 1.66666663, 0.
45, -3.33333325, 3.33333325, 0.
46, 1.66666663, -1.66666663, 0.
47, 1.66666663, -3.33333325, 0.
48, 3.33333325, -1.66666663, 0.
49, 3.33333325, -3.33333325, 0.
*Element, type=S4
1, 1, 10, 34, 17
2, 10, 11, 35, 34
3, 11, 2, 12, 35
4, 17, 34, 36, 16
5, 34, 35, 37, 36
6, 35, 12, 13, 37
7, 16, 36, 15, 4
8, 36, 37, 14, 15
9, 37, 13, 3, 14
10, 5, 18, 38, 25
11, 18, 19, 39, 38
12, 19, 2, 20, 39
13, 25, 38, 40, 24
14, 38, 39, 41, 40
15, 39, 20, 21, 41
16, 24, 40, 23, 7
17, 40, 41, 22, 23
18, 41, 21, 6, 22
19, 2, 19, 42, 12
20, 19, 18, 43, 42
21, 18, 5, 26, 43
22, 12, 42, 44, 13
23, 42, 43, 45, 44
24, 43, 26, 27, 45
25, 13, 44, 29, 3
26, 44, 45, 28, 29
27, 45, 27, 8, 28
28, 2, 11, 46, 20
29, 11, 10, 47, 46
30, 10, 1, 30, 47
31, 20, 46, 48, 21
32, 46, 47, 49, 48
33, 47, 30, 31, 49
34, 21, 48, 33, 6
35, 48, 49, 32, 33
36, 49, 31, 9, 32
*Nset, nset=Set-1, generate
1, 49, 1
*Elset, elset=Set-1, generate
1, 36, 1
** Section: Section-1
*Shell Section, elset=Set-1, material=Material-1
0.5, 5
*End Part
**
**
** ASSEMBLY
**
*Assembly, name=Assembly
**
*Instance, name=Part-1-1, part=Part-1
*End Instance
**
*Nset, nset=Set-1, instance=Part-1-1
2,
*Nset, nset=Set-2, instance=Part-1-1
1, 3, 4, 5, 6, 7, 8, 9, 14, 15, 16, 17, 22, 23, 24, 25
26, 27, 28, 29, 30, 31, 32, 33
*Elset, elset=Set-2, instance=Part-1-1
1, 4, 7, 8, 9, 10, 13, 16, 17, 18, 21, 24, 25, 26, 27, 30
33, 34, 35, 36
*End Assembly
**
** MATERIALS
**
*Material, name=Material-1
*Elastic
2.1e+11, 0.3
**
** BOUNDARY CONDITIONS
**
** Name: BC-1 Type: Displacement/Rotation
*Boundary
Set-2, 1, 1
Set-2, 2, 2
Set-2, 3, 3
Set-2, 4, 4
Set-2, 5, 5
Set-2, 6, 6
** ----------------------------------------------------------------
**
** STEP: Step-1
**
*Step, name=Step-1, nlgeom=NO
*Static
1., 1., 1e-05, 1.
**
** LOADS
**
** Name: Load-1 Type: Concentrated force
*Cload
Set-1, 3, -100000.
**
** OUTPUT REQUESTS
**
*Restart, write, frequency=0
**
** FIELD OUTPUT: F-Output-1
**
*Output, field, variable=PRESELECT
**
** HISTORY OUTPUT: H-Output-1
**
*Output, history, variable=PRESELECT
*End Step
@@ -0,0 +1,83 @@
{
"tests": 13,
"name": "AllTests",
"testsuites": [
{
"name": "LinearStaticCli",
"tests": 8,
"testsuite": [
{
"name": "FactorizesBeforeLoadAndSolvesWithoutRefactorization",
"file": "C:\\git\\FESADev\\.worktrees\\nonlinear-static-newton-raphson\\tests\\integration\\analysis\\linear_static_analysis_test.cpp",
"line": 306
},
{
"name": "FactorizesBeforeRejectingAnInvalidLoad",
"file": "C:\\git\\FESADev\\.worktrees\\nonlinear-static-newton-raphson\\tests\\integration\\analysis\\linear_static_analysis_test.cpp",
"line": 328
},
{
"name": "RealPipelineHandlesAnalyticalAndNonzeroPrescription",
"file": "C:\\git\\FESADev\\.worktrees\\nonlinear-static-newton-raphson\\tests\\integration\\analysis\\linear_static_analysis_test.cpp",
"line": 352
},
{
"name": "DefaultOutputUsesInputSiblingDerivedName",
"file": "C:\\git\\FESADev\\.worktrees\\nonlinear-static-newton-raphson\\tests\\integration\\app\\fesa_application_test.cpp",
"line": 356
},
{
"name": "ReturnsEveryExactExitCodeAndOrderedDiagnostic",
"file": "C:\\git\\FESADev\\.worktrees\\nonlinear-static-newton-raphson\\tests\\integration\\app\\fesa_application_test.cpp",
"line": 371
},
{
"name": "OutputSubstringRejectionLeavesDerivedFilesUnchanged",
"file": "C:\\git\\FESADev\\.worktrees\\nonlinear-static-newton-raphson\\tests\\integration\\app\\fesa_application_test.cpp",
"line": 413
},
{
"name": "BusyOutputLeaseLeavesDerivedFilesUnchanged",
"file": "C:\\git\\FESADev\\.worktrees\\nonlinear-static-newton-raphson\\tests\\integration\\app\\fesa_application_test.cpp",
"line": 443
},
{
"name": "OutputRequestsDoNotFilterMandatoryResults",
"file": "C:\\git\\FESADev\\.worktrees\\nonlinear-static-newton-raphson\\tests\\integration\\app\\fesa_application_test.cpp",
"line": 468
}
]
},
{
"name": "Mitc4ShellCli",
"tests": 5,
"testsuite": [
{
"name": "UsesExistingLifecycleAndExactlyOneFactorization",
"file": "C:\\git\\FESADev\\.worktrees\\nonlinear-static-newton-raphson\\tests\\integration\\analysis\\linear_static_analysis_test.cpp",
"line": 389
},
{
"name": "AppliesKfcForNonzeroPrescribedDisplacement",
"file": "C:\\git\\FESADev\\.worktrees\\nonlinear-static-newton-raphson\\tests\\integration\\analysis\\linear_static_analysis_test.cpp",
"line": 412
},
{
"name": "RejectsSingularAndAcceptsZeroByZeroFreeSystem",
"file": "C:\\git\\FESADev\\.worktrees\\nonlinear-static-newton-raphson\\tests\\integration\\analysis\\linear_static_analysis_test.cpp",
"line": 450
},
{
"name": "DoesNotWriteAnInvalidRecoveryCandidate",
"file": "C:\\git\\FESADev\\.worktrees\\nonlinear-static-newton-raphson\\tests\\integration\\analysis\\linear_static_analysis_test.cpp",
"line": 486
},
{
"name": "WritesShellHdf5ThroughTheExistingApplicationRoute",
"file": "C:\\git\\FESADev\\.worktrees\\nonlinear-static-newton-raphson\\tests\\integration\\app\\fesa_application_test.cpp",
"line": 505
}
]
}
]
}
@@ -0,0 +1,19 @@
include("C:/Program Files/CMake/share/cmake-4.4/Modules/GoogleTestAddTests.cmake")
gtest_discover_tests_impl(
TEST_EXECUTABLE [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_integration_tests.exe]==]
TEST_EXECUTOR [==[]==]
TEST_WORKING_DIR [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
TEST_EXTRA_ARGS [==[]==]
TEST_PROPERTIES [==[LABELS]==] [==[linear-static-3d-euler-beam;integration]==]
TEST_PREFIX [==[]==]
TEST_SUFFIX [==[]==]
TEST_FILTER [==[]==]
NO_PRETTY_TYPES [==[FALSE]==]
NO_PRETTY_VALUES [==[FALSE]==]
TEST_LIST [==[fesa_integration_tests_TESTS]==]
CTEST_FILE [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_integration_tests_d537bc73_tests.cmake]==]
TEST_DISCOVERY_TIMEOUT [==[5]==]
TEST_DISCOVERY_EXTRA_ARGS [==[]==]
TEST_XML_OUTPUT_DIR [==[]==]
TEST_JSON_OUTPUT_DIR [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
)
@@ -0,0 +1,5 @@
if(EXISTS "C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_integration_tests_d537bc73_tests.cmake")
include("C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_integration_tests_d537bc73_tests.cmake")
else()
add_test(fesa_integration_tests_NOT_BUILT fesa_integration_tests_NOT_BUILT)
endif()
@@ -0,0 +1,118 @@
add_test([=[LinearStaticCli.FactorizesBeforeLoadAndSolvesWithoutRefactorization]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_integration_tests.exe [==[--gtest_filter=LinearStaticCli.FactorizesBeforeLoadAndSolvesWithoutRefactorization]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[LinearStaticCli.FactorizesBeforeLoadAndSolvesWithoutRefactorization]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\integration\analysis\linear_static_analysis_test.cpp:306]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;integration]]
)
add_test([=[LinearStaticCli.FactorizesBeforeRejectingAnInvalidLoad]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_integration_tests.exe [==[--gtest_filter=LinearStaticCli.FactorizesBeforeRejectingAnInvalidLoad]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[LinearStaticCli.FactorizesBeforeRejectingAnInvalidLoad]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\integration\analysis\linear_static_analysis_test.cpp:328]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;integration]]
)
add_test([=[LinearStaticCli.RealPipelineHandlesAnalyticalAndNonzeroPrescription]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_integration_tests.exe [==[--gtest_filter=LinearStaticCli.RealPipelineHandlesAnalyticalAndNonzeroPrescription]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[LinearStaticCli.RealPipelineHandlesAnalyticalAndNonzeroPrescription]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\integration\analysis\linear_static_analysis_test.cpp:352]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;integration]]
)
add_test([=[LinearStaticCli.DefaultOutputUsesInputSiblingDerivedName]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_integration_tests.exe [==[--gtest_filter=LinearStaticCli.DefaultOutputUsesInputSiblingDerivedName]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[LinearStaticCli.DefaultOutputUsesInputSiblingDerivedName]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\integration\app\fesa_application_test.cpp:356]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;integration]]
)
add_test([=[LinearStaticCli.ReturnsEveryExactExitCodeAndOrderedDiagnostic]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_integration_tests.exe [==[--gtest_filter=LinearStaticCli.ReturnsEveryExactExitCodeAndOrderedDiagnostic]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[LinearStaticCli.ReturnsEveryExactExitCodeAndOrderedDiagnostic]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\integration\app\fesa_application_test.cpp:371]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;integration]]
)
add_test([=[LinearStaticCli.OutputSubstringRejectionLeavesDerivedFilesUnchanged]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_integration_tests.exe [==[--gtest_filter=LinearStaticCli.OutputSubstringRejectionLeavesDerivedFilesUnchanged]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[LinearStaticCli.OutputSubstringRejectionLeavesDerivedFilesUnchanged]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\integration\app\fesa_application_test.cpp:413]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;integration]]
)
add_test([=[LinearStaticCli.BusyOutputLeaseLeavesDerivedFilesUnchanged]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_integration_tests.exe [==[--gtest_filter=LinearStaticCli.BusyOutputLeaseLeavesDerivedFilesUnchanged]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[LinearStaticCli.BusyOutputLeaseLeavesDerivedFilesUnchanged]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\integration\app\fesa_application_test.cpp:443]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;integration]]
)
add_test([=[LinearStaticCli.OutputRequestsDoNotFilterMandatoryResults]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_integration_tests.exe [==[--gtest_filter=LinearStaticCli.OutputRequestsDoNotFilterMandatoryResults]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[LinearStaticCli.OutputRequestsDoNotFilterMandatoryResults]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\integration\app\fesa_application_test.cpp:468]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;integration]]
)
add_test([=[Mitc4ShellCli.UsesExistingLifecycleAndExactlyOneFactorization]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_integration_tests.exe [==[--gtest_filter=Mitc4ShellCli.UsesExistingLifecycleAndExactlyOneFactorization]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[Mitc4ShellCli.UsesExistingLifecycleAndExactlyOneFactorization]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\integration\analysis\linear_static_analysis_test.cpp:389]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;integration]]
)
add_test([=[Mitc4ShellCli.AppliesKfcForNonzeroPrescribedDisplacement]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_integration_tests.exe [==[--gtest_filter=Mitc4ShellCli.AppliesKfcForNonzeroPrescribedDisplacement]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[Mitc4ShellCli.AppliesKfcForNonzeroPrescribedDisplacement]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\integration\analysis\linear_static_analysis_test.cpp:412]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;integration]]
)
add_test([=[Mitc4ShellCli.RejectsSingularAndAcceptsZeroByZeroFreeSystem]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_integration_tests.exe [==[--gtest_filter=Mitc4ShellCli.RejectsSingularAndAcceptsZeroByZeroFreeSystem]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[Mitc4ShellCli.RejectsSingularAndAcceptsZeroByZeroFreeSystem]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\integration\analysis\linear_static_analysis_test.cpp:450]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;integration]]
)
add_test([=[Mitc4ShellCli.DoesNotWriteAnInvalidRecoveryCandidate]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_integration_tests.exe [==[--gtest_filter=Mitc4ShellCli.DoesNotWriteAnInvalidRecoveryCandidate]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[Mitc4ShellCli.DoesNotWriteAnInvalidRecoveryCandidate]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\integration\analysis\linear_static_analysis_test.cpp:486]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;integration]]
)
add_test([=[Mitc4ShellCli.WritesShellHdf5ThroughTheExistingApplicationRoute]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_integration_tests.exe [==[--gtest_filter=Mitc4ShellCli.WritesShellHdf5ThroughTheExistingApplicationRoute]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[Mitc4ShellCli.WritesShellHdf5ThroughTheExistingApplicationRoute]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\integration\app\fesa_application_test.cpp:505]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;integration]]
)
set(fesa_integration_tests_TESTS [==[LinearStaticCli.FactorizesBeforeLoadAndSolvesWithoutRefactorization]==] [==[LinearStaticCli.FactorizesBeforeRejectingAnInvalidLoad]==] [==[LinearStaticCli.RealPipelineHandlesAnalyticalAndNonzeroPrescription]==] [==[LinearStaticCli.DefaultOutputUsesInputSiblingDerivedName]==] [==[LinearStaticCli.ReturnsEveryExactExitCodeAndOrderedDiagnostic]==] [==[LinearStaticCli.OutputSubstringRejectionLeavesDerivedFilesUnchanged]==] [==[LinearStaticCli.BusyOutputLeaseLeavesDerivedFilesUnchanged]==] [==[LinearStaticCli.OutputRequestsDoNotFilterMandatoryResults]==] [==[Mitc4ShellCli.UsesExistingLifecycleAndExactlyOneFactorization]==] [==[Mitc4ShellCli.AppliesKfcForNonzeroPrescribedDisplacement]==] [==[Mitc4ShellCli.RejectsSingularAndAcceptsZeroByZeroFreeSystem]==] [==[Mitc4ShellCli.DoesNotWriteAnInvalidRecoveryCandidate]==] [==[Mitc4ShellCli.WritesShellHdf5ThroughTheExistingApplicationRoute]==])
@@ -0,0 +1,19 @@
include("C:/Program Files/CMake/share/cmake-4.4/Modules/GoogleTestAddTests.cmake")
gtest_discover_tests_impl(
TEST_EXECUTABLE [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_reference_tests.exe]==]
TEST_EXECUTOR [==[]==]
TEST_WORKING_DIR [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
TEST_EXTRA_ARGS [==[]==]
TEST_PROPERTIES [==[LABELS]==] [==[linear-static-3d-euler-beam;reference]==]
TEST_PREFIX [==[]==]
TEST_SUFFIX [==[]==]
TEST_FILTER [==[]==]
NO_PRETTY_TYPES [==[FALSE]==]
NO_PRETTY_VALUES [==[FALSE]==]
TEST_LIST [==[fesa_reference_tests_TESTS]==]
CTEST_FILE [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_reference_tests_ac7cf2f0_tests.cmake]==]
TEST_DISCOVERY_TIMEOUT [==[5]==]
TEST_DISCOVERY_EXTRA_ARGS [==[]==]
TEST_XML_OUTPUT_DIR [==[]==]
TEST_JSON_OUTPUT_DIR [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
)
@@ -0,0 +1,5 @@
if(EXISTS "C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_reference_tests_ac7cf2f0_tests.cmake")
include("C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_reference_tests_ac7cf2f0_tests.cmake")
else()
add_test(fesa_reference_tests_NOT_BUILT fesa_reference_tests_NOT_BUILT)
endif()
@@ -0,0 +1,190 @@
add_test([=[ReferenceTolerancePolicy.AppliesRelativeAndNearZeroThresholdsAtTheirInclusiveBoundaries]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_reference_tests.exe [==[--gtest_filter=ReferenceTolerancePolicy.AppliesRelativeAndNearZeroThresholdsAtTheirInclusiveBoundaries]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[ReferenceTolerancePolicy.AppliesRelativeAndNearZeroThresholdsAtTheirInclusiveBoundaries]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\reference\reference_tolerance_policy_test.cpp:28]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;reference]]
)
add_test([=[ReferenceTolerancePolicy.RejectsFamiliesWhoseScaleRelativeRmsExceedsOnePercent]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_reference_tests.exe [==[--gtest_filter=ReferenceTolerancePolicy.RejectsFamiliesWhoseScaleRelativeRmsExceedsOnePercent]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[ReferenceTolerancePolicy.RejectsFamiliesWhoseScaleRelativeRmsExceedsOnePercent]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\reference\reference_tolerance_policy_test.cpp:56]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;reference]]
)
add_test([=[ReferenceTolerancePolicy.FailsClosedForZeroScaleNonzeroErrorWithoutNonfiniteMetrics]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_reference_tests.exe [==[--gtest_filter=ReferenceTolerancePolicy.FailsClosedForZeroScaleNonzeroErrorWithoutNonfiniteMetrics]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[ReferenceTolerancePolicy.FailsClosedForZeroScaleNonzeroErrorWithoutNonfiniteMetrics]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\reference\reference_tolerance_policy_test.cpp:73]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;reference]]
)
add_test([=[ReferenceTolerancePolicy.KeepsWarningOnlyFamilyExceedanceOutOfBlockingVerdict]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_reference_tests.exe [==[--gtest_filter=ReferenceTolerancePolicy.KeepsWarningOnlyFamilyExceedanceOutOfBlockingVerdict]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[ReferenceTolerancePolicy.KeepsWarningOnlyFamilyExceedanceOutOfBlockingVerdict]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\reference\reference_tolerance_policy_test.cpp:95]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;reference]]
)
add_test([=[ReferenceTolerancePolicy.RejectsNonfiniteInputsBeforeToleranceEvaluation]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_reference_tests.exe [==[--gtest_filter=ReferenceTolerancePolicy.RejectsNonfiniteInputsBeforeToleranceEvaluation]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[ReferenceTolerancePolicy.RejectsNonfiniteInputsBeforeToleranceEvaluation]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\reference\reference_tolerance_policy_test.cpp:108]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;reference]]
)
add_test([=[ReferenceComparisonContract.PrecheckRejectsMissingSchemaDuplicateAndNonfiniteRows]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_reference_tests.exe [==[--gtest_filter=ReferenceComparisonContract.PrecheckRejectsMissingSchemaDuplicateAndNonfiniteRows]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[ReferenceComparisonContract.PrecheckRejectsMissingSchemaDuplicateAndNonfiniteRows]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\reference\reference_comparison_test.cpp:426]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;reference]]
)
add_test([=[ReferenceComparisonContract.AppliesSharedFamilyScaleAndNearZeroBranchesWithoutAnAbsoluteGate]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_reference_tests.exe [==[--gtest_filter=ReferenceComparisonContract.AppliesSharedFamilyScaleAndNearZeroBranchesWithoutAnAbsoluteGate]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[ReferenceComparisonContract.AppliesSharedFamilyScaleAndNearZeroBranchesWithoutAnAbsoluteGate]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\reference\reference_comparison_test.cpp:538]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;reference]]
)
add_test([=[ReferenceComparisonContract.ReportsEveryRowAndAggregateMetricDeterministically]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_reference_tests.exe [==[--gtest_filter=ReferenceComparisonContract.ReportsEveryRowAndAggregateMetricDeterministically]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[ReferenceComparisonContract.ReportsEveryRowAndAggregateMetricDeterministically]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\reference\reference_comparison_test.cpp:593]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;reference]]
)
add_test([=[ReferenceComparisonContract.PreservesSectionEndpointIdentityWithoutStationNormalization]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_reference_tests.exe [==[--gtest_filter=ReferenceComparisonContract.PreservesSectionEndpointIdentityWithoutStationNormalization]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[ReferenceComparisonContract.PreservesSectionEndpointIdentityWithoutStationNormalization]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\reference\reference_comparison_test.cpp:663]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;reference]]
)
add_test([=[ReferenceComparisonContract.MapsEachSectionCsvComponentToItsDirectEndpointResultant]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_reference_tests.exe [==[--gtest_filter=ReferenceComparisonContract.MapsEachSectionCsvComponentToItsDirectEndpointResultant]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[ReferenceComparisonContract.MapsEachSectionCsvComponentToItsDirectEndpointResultant]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\reference\reference_comparison_test.cpp:687]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;reference]]
)
add_test([=[B33ReferenceComparison.GeneratesAuthoritativeHdf5AndComparisonEvidence]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_reference_tests.exe [==[--gtest_filter=B33ReferenceComparison.GeneratesAuthoritativeHdf5AndComparisonEvidence]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[B33ReferenceComparison.GeneratesAuthoritativeHdf5AndComparisonEvidence]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\reference\b33_reference_comparison_test.cpp:148]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;reference]]
)
add_test([=[Mitc4ReferenceComparison.MapsTrimmedHeaderAndSixComponentsBySourceIdentity]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_reference_tests.exe [==[--gtest_filter=Mitc4ReferenceComparison.MapsTrimmedHeaderAndSixComponentsBySourceIdentity]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[Mitc4ReferenceComparison.MapsTrimmedHeaderAndSixComponentsBySourceIdentity]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\reference\mitc4_reference_comparison_test.cpp:478]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;reference]]
)
add_test([=[Mitc4ReferenceComparison.RejectsInvalidInventoryBeforeNumericComparison]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_reference_tests.exe [==[--gtest_filter=Mitc4ReferenceComparison.RejectsInvalidInventoryBeforeNumericComparison]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[Mitc4ReferenceComparison.RejectsInvalidInventoryBeforeNumericComparison]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\reference\mitc4_reference_comparison_test.cpp:511]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;reference]]
)
add_test([=[Mitc4ReferenceComparison.SharesTranslationScaleAcrossUComponentsAndUsesNearZeroBranches]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_reference_tests.exe [==[--gtest_filter=Mitc4ReferenceComparison.SharesTranslationScaleAcrossUComponentsAndUsesNearZeroBranches]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[Mitc4ReferenceComparison.SharesTranslationScaleAcrossUComponentsAndUsesNearZeroBranches]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\reference\mitc4_reference_comparison_test.cpp:594]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;reference]]
)
add_test([=[Mitc4ReferenceComparison.RotationExceedanceWarnsWithoutBlockingTranslationVerdict]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_reference_tests.exe [==[--gtest_filter=Mitc4ReferenceComparison.RotationExceedanceWarnsWithoutBlockingTranslationVerdict]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[Mitc4ReferenceComparison.RotationExceedanceWarnsWithoutBlockingTranslationVerdict]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\reference\mitc4_reference_comparison_test.cpp:641]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;reference]]
)
add_test([=[Mitc4ReferenceComparison.RotationRmsExceedanceWarnsWhenEveryRotationRowPasses]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_reference_tests.exe [==[--gtest_filter=Mitc4ReferenceComparison.RotationRmsExceedanceWarnsWhenEveryRotationRowPasses]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[Mitc4ReferenceComparison.RotationRmsExceedanceWarnsWhenEveryRotationRowPasses]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\reference\mitc4_reference_comparison_test.cpp:667]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;reference]]
)
add_test([=[Mitc4ReferenceComparison.RotationRowAndRmsExceedancesProduceSeparateWarnings]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_reference_tests.exe [==[--gtest_filter=Mitc4ReferenceComparison.RotationRowAndRmsExceedancesProduceSeparateWarnings]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[Mitc4ReferenceComparison.RotationRowAndRmsExceedancesProduceSeparateWarnings]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\reference\mitc4_reference_comparison_test.cpp:689]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;reference]]
)
add_test([=[Mitc4ReferenceComparison.ReportsMetricsVectorsWorstRowAndJsonDeterministically]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_reference_tests.exe [==[--gtest_filter=Mitc4ReferenceComparison.ReportsMetricsVectorsWorstRowAndJsonDeterministically]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[Mitc4ReferenceComparison.ReportsMetricsVectorsWorstRowAndJsonDeterministically]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\reference\mitc4_reference_comparison_test.cpp:709]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;reference]]
)
add_test([=[Mitc4ReferenceComparison.RequiresOnlyDeclaredInputCsvAndHdf5]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_reference_tests.exe [==[--gtest_filter=Mitc4ReferenceComparison.RequiresOnlyDeclaredInputCsvAndHdf5]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[Mitc4ReferenceComparison.RequiresOnlyDeclaredInputCsvAndHdf5]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\reference\mitc4_reference_comparison_test.cpp:757]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;reference]]
)
add_test([=[Mitc4S4Reference.PreservesS4AndWritesCommonMitc4Metadata]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_reference_tests.exe [==[--gtest_filter=Mitc4S4Reference.PreservesS4AndWritesCommonMitc4Metadata]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[Mitc4S4Reference.PreservesS4AndWritesCommonMitc4Metadata]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\reference\mitc4_reference_cases_test.cpp:177]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;reference]]
)
add_test([=[Mitc4S4Reference.PassesBlockingUAndReportsEveryUrRow]=] C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_reference_tests.exe [==[--gtest_filter=Mitc4S4Reference.PassesBlockingUAndReportsEveryUrRow]==] --gtest_also_run_disabled_tests)
set_tests_properties([=[Mitc4S4Reference.PassesBlockingUAndReportsEveryUrRow]=]
PROPERTIES
DEF_SOURCE_LINE [==[C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson\tests\reference\mitc4_reference_cases_test.cpp:187]==]
WORKING_DIRECTORY [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]
[[LABELS]] [[linear-static-3d-euler-beam;reference]]
)
set(fesa_reference_tests_TESTS [==[ReferenceTolerancePolicy.AppliesRelativeAndNearZeroThresholdsAtTheirInclusiveBoundaries]==] [==[ReferenceTolerancePolicy.RejectsFamiliesWhoseScaleRelativeRmsExceedsOnePercent]==] [==[ReferenceTolerancePolicy.FailsClosedForZeroScaleNonzeroErrorWithoutNonfiniteMetrics]==] [==[ReferenceTolerancePolicy.KeepsWarningOnlyFamilyExceedanceOutOfBlockingVerdict]==] [==[ReferenceTolerancePolicy.RejectsNonfiniteInputsBeforeToleranceEvaluation]==] [==[ReferenceComparisonContract.PrecheckRejectsMissingSchemaDuplicateAndNonfiniteRows]==] [==[ReferenceComparisonContract.AppliesSharedFamilyScaleAndNearZeroBranchesWithoutAnAbsoluteGate]==] [==[ReferenceComparisonContract.ReportsEveryRowAndAggregateMetricDeterministically]==] [==[ReferenceComparisonContract.PreservesSectionEndpointIdentityWithoutStationNormalization]==] [==[ReferenceComparisonContract.MapsEachSectionCsvComponentToItsDirectEndpointResultant]==] [==[B33ReferenceComparison.GeneratesAuthoritativeHdf5AndComparisonEvidence]==] [==[Mitc4ReferenceComparison.MapsTrimmedHeaderAndSixComponentsBySourceIdentity]==] [==[Mitc4ReferenceComparison.RejectsInvalidInventoryBeforeNumericComparison]==] [==[Mitc4ReferenceComparison.SharesTranslationScaleAcrossUComponentsAndUsesNearZeroBranches]==] [==[Mitc4ReferenceComparison.RotationExceedanceWarnsWithoutBlockingTranslationVerdict]==] [==[Mitc4ReferenceComparison.RotationRmsExceedanceWarnsWhenEveryRotationRowPasses]==] [==[Mitc4ReferenceComparison.RotationRowAndRmsExceedancesProduceSeparateWarnings]==] [==[Mitc4ReferenceComparison.ReportsMetricsVectorsWorstRowAndJsonDeterministically]==] [==[Mitc4ReferenceComparison.RequiresOnlyDeclaredInputCsvAndHdf5]==] [==[Mitc4S4Reference.PreservesS4AndWritesCommonMitc4Metadata]==] [==[Mitc4S4Reference.PassesBlockingUAndReportsEveryUrRow]==])
@@ -0,0 +1,19 @@
include("C:/Program Files/CMake/share/cmake-4.4/Modules/GoogleTestAddTests.cmake")
gtest_discover_tests_impl(
TEST_EXECUTABLE [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_unit_tests.exe]==]
TEST_EXECUTOR [==[]==]
TEST_WORKING_DIR [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
TEST_EXTRA_ARGS [==[]==]
TEST_PROPERTIES [==[LABELS]==] [==[linear-static-3d-euler-beam;unit]==]
TEST_PREFIX [==[]==]
TEST_SUFFIX [==[]==]
TEST_FILTER [==[]==]
NO_PRETTY_TYPES [==[FALSE]==]
NO_PRETTY_VALUES [==[FALSE]==]
TEST_LIST [==[fesa_unit_tests_TESTS]==]
CTEST_FILE [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_unit_tests_576e7e9d_tests.cmake]==]
TEST_DISCOVERY_TIMEOUT [==[5]==]
TEST_DISCOVERY_EXTRA_ARGS [==[]==]
TEST_XML_OUTPUT_DIR [==[]==]
TEST_JSON_OUTPUT_DIR [==[C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests]==]
)
@@ -0,0 +1,5 @@
if(EXISTS "C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_unit_tests_576e7e9d_tests.cmake")
include("C:/git/FESADev/.worktrees/nonlinear-static-newton-raphson/.harness/build-ninja/tests/fesa_unit_tests_576e7e9d_tests.cmake")
else()
add_test(fesa_unit_tests_NOT_BUILT fesa_unit_tests_NOT_BUILT)
endif()
File diff suppressed because one or more lines are too long
@@ -3,16 +3,16 @@
## 1. Metadata and Feature Scope
- feature_id: `nonlinear-static-newton-raphson`
- workflow_state: `needs-formulation`
- workflow_state: `needs-implementation`
- owner_agent: `coordinator-agent`
- request_date: `2026-08-18`
- last_updated: `2026-08-23` (Stage 2 사용자 명시 승인; Stage 3 Formulation Agent dispatch 준비)
- last_updated: `2026-08-24` (REWORK-004 corrected; no-push Harness rerun authorized)
- process_classification: `architectural`
- requested_capability: Newton–Raphson 방법을 사용하는 새 nonlinear static analysis procedure
- proposed_scope_boundary: 첫 release는 initial configuration 기준 Total Lagrangian, materially linear + geometrically nonlinear MITC4로 제한한다. 요구조건 인터뷰와 8단계 evidence gate를 먼저 완료하며, 승인 전에는 상세 수치·I/O·구현 범위를 확정하거나 기존 linear-static lifecycle을 변경하지 않는다.
- naming_note: 사용자 표현 `Newton-Rhapson`은 표준 명칭 `Newton–Raphson`으로 정규화했다.
- current_goal: 승인된 `requirements.md`와 사용자 승인된 `research.md`를 입력으로 Stage 3의 구현 가능한 `formulation.md` 계약을 Formulation Agent에게서 확보하고 독립 evidence audit을 수행한다.
- constraints: 승인된 physics/scope/tolerance/authoritative output/public compatibility를 보존한다. Stage 3는 O-ROT/O-MAP/O-DRILL/O-MOM/O-BC를 구현 가능한 수학 계약으로 해소하되 HDF5/I/O schema, reference artifact, C++/tests/CMake, phase/Harness 또는 Stage 4 판단으로 확장하지 않는다. Abaqus/Midas 내부 동등성을 주장하지 않는다.
- current_goal: Stage 6 no-push Harness/Implementation rerun is authorized for Executor-selected Step 0 and subsequent approved phase progression under the corrected `codex exec --disable unified_exec` runner envelope.
- constraints: 승인된 Stage 1-5 hashes, physics/scope/tolerance/authoritative output/public compatibility, `rho_M <= 1e-12`, fixed-global source identity, no drilling load channel과 Stage 6 materialization evidence를 보존한다. The authorized rerun envelope is Codex CLI `0.149.1`, `CODEX_HOME=C:\Users\baram\.codex`, child launch PATH filtering of `C:\Program Files\WindowsApps\Microsoft.PowerShell_*` and `C:\Users\baram\AppData\Local\Microsoft\WindowsApps`, `workspace-write`, implementation-agent `gpt-5.6-terra`/`xhigh`, hooks retained, no-push, no `danger-full-access`, and runner-retained `--disable unified_exec`. Do not edit feature contracts/reference artifacts/tolerance policies, run Abaqus/Nastran/reference solvers, or advance Physics/Release until `implementation-report.md`, `build-test.md`, `reference-comparison.md` and passing implementation evidence exist.
- repository_audit: 기존 worktree에는 `.codex/agents/*.toml`과 `AGENTS.md`의 사용자 변경이 있으며 이를 보존한다.
## 2. Eight-Stage Worklist
@@ -21,10 +21,10 @@
| --- | --- | --- | --- | --- | --- | --- | --- |
| 1. Requirements | `requirement-agent` | `passed` | `docs/nonlinear-static-newton-raphson/requirements.md` | `<=400` lines, 24 canonical shall requirements, exact 24-row Matrix, approved semantic loss 0, Stage-1 user question 0 | Approved compact content 395 lines; approval metadata 2 lines, current 397; 24↔24 exact ID sets, duplicate/missing/orphan 0, OQ/questions/trivia/placeholders 0; core semantics and NSNR-083 public precedence retained; forbidden changes 0; user explicitly approved on 2026-08-23. | 없음 | 40 |
| 2. Research | `research-agent` | `passed` | `docs/nonlinear-static-newton-raphson/research.md` | 필요한 이론·benchmark·source reliability·applicability limit가 충분함 | Owner/Coordinator pass와 2026-08-23 사용자 명시 승인; 10 required sections, S1–S17, 12 benchmark candidates, 11 research-relevant requirement IDs, 14 unique open issues; nonlinear stored reference gap explicit; SHA-256 `C920A6B02381230D1DB419D73FE767D611B36720D27D6410507BA88C3CA28EEE`; forbidden changes 0. | 없음 | 1 |
| 3. Formulation | `formulation-agent` | `in-progress` | `docs/nonlinear-static-newton-raphson/formulation.md` | strong/weak form, kinematics, tangent/residual, integration, state/recovery가 구현 가능한 계약이며 O-ROT/O-MAP/O-DRILL/O-MOM/O-BC가 승인 scope 안에서 해소됨 | Stage 3 bounded dispatch 준비; approved requirements SHA-256 `910E351F3F90FFA42F07D15206B55E62C05EAE821E250424430148337506EBF2`, approved research SHA-256 `C920A6B02381230D1DB419D73FE767D611B36720D27D6410507BA88C3CA28EEE`. | Formulation Agent 반환 evidence 대기 | 1 |
| 4. Numerical/reference review | `numerical-review-agent` | `pending` | `docs/nonlinear-static-newton-raphson/numerical-review.md`; `docs/nonlinear-static-newton-raphson/reference-model.md` | 두 문서가 함께 `pass-for-io-definition`이며 수치 안정성과 exact reference contract가 준비됨 | 없음 | Stage 3 사용자 승인 필요 | 0 |
| 5. I/O definition | `io-definition-agent` | `pending` | `docs/nonlinear-static-newton-raphson/io.md` | Abaqus subset, semantic mapping, HDF5 schema, diagnostics, CSV projection이 승인됨 | 없음 | Stage 4 사용자 승인 필요 | 0 |
| 6. Implementation | `implementation-planning-agent`; `implementation-agent` | `pending` | `docs/nonlinear-static-newton-raphson/implementation-plan.md`; `docs/nonlinear-static-newton-raphson/implementation-report.md`; `docs/nonlinear-static-newton-raphson/build-test.md`; `docs/nonlinear-static-newton-raphson/reference-comparison.md` | 상세 인터뷰와 계획 승인 후 TDD, MSVC/x64/Debug CMake/CTest, blocking reference comparison이 통과함 | 없음 | Stage 5 사용자 승인과 implementation-planning interview 필요 | 0 |
| 3. Formulation | `formulation-agent` | `passed` | `docs/nonlinear-static-newton-raphson/formulation.md` | strong/weak form, kinematics, tangent/residual, integration, state/recovery가 구현 가능한 계약이며 O-ROT/O-MAP/O-DRILL/O-MOM/O-BC가 승인 scope 안에서 해소됨 | Rework attempt 2 owner/Coordinator pass와 사용자 명시 승인: reaction force/generalized moment/spatial moment symbols와 dimensions가 rotation matrix `R_I`와 분리됨; immutable fixed-global source, `rho_M <= 1e-12` admissibility, exact projected physical-work covector, `DP`/`DJ_l`/map-Hessian residual-tangent identity가 §§4.4/5/11.2–11.3/13.1/13.4/17에서 일치함; 18 sections와 7 closures 보존; SHA-256 `DFA629888041D5762FD0DF4271353464A692B325DC0C821A8D8689688C1EAFD0`. | 없음 | 2 |
| 4. Numerical/reference review | `numerical-review-agent` | `passed` | `docs/nonlinear-static-newton-raphson/numerical-review.md`; `docs/nonlinear-static-newton-raphson/reference-model.md` | 두 문서가 함께 `pass-for-io-definition`이며 수치 안정성과 exact reference contract가 준비됨 | Corrected owner return, Coordinator audit pass and user explicit approval: status `pass-for-io-definition`; approved formulation hash matched; shellNL/shell artifacts inspected read-only with row counts `49/49/288`, duplicate required wide keys 0 and nonfinite required values 0; stress CSVs are optional read-only inspection/order evidence only; `RM3` excluded; required external comparison uses displacement, reaction force and physical spatial `RM1/RM2`; exact prechecks and `docs/TOLERANCE.md` policy retained. Current hashes: numerical-review `9517E11804C45A6F3822D18821D52EA493AE20353C8FFAD61E960F4315977D01`, reference-model `52D10B1D0C0500B295C5E48BCB3618B309D9696371B8070D4E3DCEE8D3D74CD3`. | 없음 | 2 |
| 5. I/O definition | `io-definition-agent` | `passed` | `docs/nonlinear-static-newton-raphson/io.md` | Abaqus subset, semantic mapping, HDF5 schema, diagnostics, CSV projection이 승인됨 | Bounded rework owner status `ready-for-coordinator-review`, SHA-256 `DBB959A68F17D67CA2B42569610B9C1B595A8BFB5502BC194B7E62B656031B28`; Coordinator audit passed and user explicitly approved the same hash. REWORK-002 defects are corrected: every argv token containing literal `--output` fails pre-input/pre-log/pre-output with one `cli-usage` diagnostic; `nsnr-log-v1` uses UTF-8 no BOM/LF/TAB fixed fields with four-channel gates, typed thresholds, branch identity, early-failure `not-evaluated(reason)`, round-trip numerics and escaping; log open/write/flush/close is fail-closed with zero-byte non-Newton success logs; exact `VARIABLE=PRESELECT` output requests are ignored-with-warning; lexical path/stem derivation, single-writer/candidate collision rules, HDF5 schema v1, reference projection, stress/RM3 exclusions and `docs/TOLERANCE.md` policy are preserved. | 없음 | 2 |
| 6. Implementation | `implementation-planning-agent`; `implementation-agent` | `in-progress` | `docs/nonlinear-static-newton-raphson/implementation-plan.md`; `docs/nonlinear-static-newton-raphson/implementation-report.md`; `docs/nonlinear-static-newton-raphson/build-test.md`; `docs/nonlinear-static-newton-raphson/reference-comparison.md`; `docs/nonlinear-static-newton-raphson/corrections.md` | 상세 인터뷰와 계획 승인 후 TDD, MSVC/x64/Debug CMake/CTest, blocking reference comparison이 통과함 | REWORK-004 Correction Agent returned `corrected-for-implementation-rerun`; `scripts/execute.py` now invokes `codex exec --disable unified_exec --json ...`, `tests/test_execute.py` asserts adjacent `("--disable", "unified_exec")` while preserving `gpt-5.6-terra`/`xhigh`, and `corrections.md` SHA-256 is `82572437689B41323B6533C2361F2F12BF07B5ED305825AA84C56AEEDC729930`. Owner/root evidence: RED targeted missing-pair assertion exit 1, GREEN targeted 1 passed, focused `tests/test_execute.py` 10/10, full pytest 23 passed/1 pre-existing `xhigh` vs `extra high`, MSVC Debug build exit 0, discovery 214, full CTest 214/214. | Stage 6 implementation evidence docs still absent; await no-push Harness rerun | 10 |
| 7. Physics evaluation | `physics-evaluation-agent` | `pending` | `docs/nonlinear-static-newton-raphson/physics-evaluation.md` | equilibrium, reaction, direction, path/history, energy, symmetry, model coverage가 `pass-for-release-agent`임 | 없음 | Stage 6 passing evidence 필요 | 0 |
| 8. Release readiness | `release-agent` | `pending` | `docs/nonlinear-static-newton-raphson/release.md` | `ready-for-release` recommendation과 acceptance traceability가 완전함 | 없음 | Stage 7 passing evidence 필요 | 0 |
@@ -33,33 +33,55 @@
### Active Dispatch Package
- feature_id: `nonlinear-static-newton-raphson`
- current_dispatch: `stage-3-formulation-attempt-1`
- target_sub_agent: `formulation-agent`
- current_dispatch: `stage-6-no-push-harness-implementation-rerun`
- target_sub_agent: `implementation-agent` via Harness Executor (`python scripts/execute.py nonlinear-static-newton-raphson`; root launch required)
- required_inputs:
- `docs/nonlinear-static-newton-raphson/requirements.md` (`approved`; user approval date `2026-08-23`; SHA-256 `910E351F3F90FFA42F07D15206B55E62C05EAE821E250424430148337506EBF2`).
- `docs/nonlinear-static-newton-raphson/research.md` (`passed`; user explicitly approved Stage 2 on `2026-08-23`; SHA-256 `C920A6B02381230D1DB419D73FE767D611B36720D27D6410507BA88C3CA28EEE`).
- `AGENTS.md`, `docs/PRD.md`, `docs/ARCHITECTURE.md`, `docs/ADR.md`, `docs/TOLERANCE.md`, `docs/SOLVER_AGENT_DESIGN.md`.
- `docs/linear-static-mitc4-shell/formulation.md`의 approved linear 계약과 §15 gap inventory. §15는 nonlinear 해답으로 복사하지 않는다.
- expected_outputs: `docs/nonlinear-static-newton-raphson/formulation.md`
- acceptance_gate: Formulation Agent가 `fesa-formulation-spec`을 사용하여 strong/weak form, fixed-initial-reference TL kinematics, finite committed/trial triad와 objective update, exact `24 global -> 20 physical + 4 drill` residual/tangent 및 map Hessian, objective numerical drilling potential/Hessian, fixed-global dead force/moment work, prescribed finite-rotation BC path, integration, state/commit/rollback, recovery와 verification identities를 구현 가능하게 정의한다. O-ROT/O-MAP/O-DRILL/O-MOM/O-BC는 unresolved placeholder 없이 승인 범위 안에서 해소되고, requirement traceability와 explicit assumptions/limits가 있다.
- stop_condition: `formulation.md`와 output paths/status/evidence summary/blockers만 Coordinator에 반환한다. Peer/Stage 4를 dispatch하거나 C++/tests/CMake/I/O schema/reference artifact/tolerance/phases/Harness를 생성·변경·실행하지 않는다. 승인된 scope/physics/tolerance/authoritative output/public compatibility를 변경할 필요가 있으면 문서에 임의 반영하지 말고 blocker로 반환한다.
- missing_evidence: Formulation Agent 소유 `formulation.md`, self-audit, O-ROT/O-MAP/O-DRILL/O-MOM/O-BC closure map과 acceptance-gate evidence.
- User explicit execution request on `2026-08-24`: `Harness/Implementation를 실행해주세요.`
- Attempt 1 failure evidence: no-push Harness command `python scripts/execute.py nonlinear-static-newton-raphson`; `codex exec --json --sandbox workspace-write ...` timed out at `1800.7s`; `_invoke_codex` raised uncaught `subprocess.TimeoutExpired`; no Step 0 source/test edits, no `step0-output.json`, no `MAX_RETRIES` handling.
- Bounded Harness repair evidence: Implementation Agent changed only `scripts/execute.py` and `tests/test_execute.py`; TDD RED 3 expected failures, GREEN 3 passed; focused `tests/test_execute.py` 10/10 passed; full pytest 23 passed/1 pre-existing HEAD contract failure `xhigh` actual vs `extra high` expected.
- Repair behavior now required: Codex timeout returns structured exit `124` and reaches `MAX_RETRIES`; runner reads `.codex/agents/implementation-agent.toml` and passes `gpt-5.6-terra` plus `xhigh` settings to `codex exec`.
- Root independent review evidence: no new defect found; focused `tests/test_execute.py` 10/10 reproduced; full suite reproduced the same single pre-existing `xhigh` vs `extra high` mismatch.
- Attempt 2 failure evidence: repaired Executor wrote `phases/nonlinear-static-newton-raphson/step0-output.json` with `exitCode` 124 and stderr `Codex timed out after 1800 seconds.`; stdout shows the Implementation Agent completed a turn but every nested command execution remained `status=in_progress`.
- Runtime blocker evidence: nested commands hung for skill file reads, `Get-Date`, `cmd.exe /d /c echo test`, and `exit 0`; root classifies the cause as nested Codex Windows shell tool execution hang, not model delay, build, source, sandbox/auth, or the repaired Executor timeout/no-retry path.
- Active process evidence from root: Executor auto-started another internal retry at `2026-08-24T02:58:35+09:00` under `python execute.py` PID 13820 / `codex` PID 7704; root terminated those unauthorized retry PIDs and verified none remain.
- Root decision after blocked-no-auto-retry: authorize one bounded Correction Agent diagnostic/rework cycle because the repeated implementation failure is infrastructure/runtime, not physics/source/build.
- Correction Agent return: status `blocked`, output `docs/nonlinear-static-newton-raphson/corrections.md` SHA-256 `C9F93AC99225725C88BB7F0BABC8F7D75D3E05082070090328203DB3776BEFE6`, no runner/test edits from correction, no safe documented CLI flag workaround proven.
- User/root runtime update evidence: standalone Codex CLI updated `0.147.0 -> 0.149.1` under `CODEX_HOME=C:\Users\baram\.codex`; `codex doctor --json` reported current/consistent installation.
- User/root bounded smoke evidence: baseline still fails through inaccessible WindowsApps `pwsh`, direct `codex sandbox` elevated/unelevated `cmd echo` exits 0, and nested smoke passes only when launch env filters `C:\Program Files\WindowsApps\Microsoft.PowerShell_*` plus `C:\Users\baram\AppData\Local\Microsoft\WindowsApps`, aligns `CODEX_HOME`, retains `workspace-write` and hooks, uses implementation-agent `gpt-5.6-terra`/`xhigh`, and passes `--disable unified_exec`; output was exactly `CODEX_SHELL_SMOKE_OK\r\n`.
- REWORK-004 Correction Agent return: status `corrected-for-implementation-rerun`; changed only `scripts/execute.py`, `tests/test_execute.py`, `docs/nonlinear-static-newton-raphson/corrections.md`; no Harness phase, C++ source, CMake, reference solver, commit or push.
- Coordinator audit: current `scripts/execute.py` lines 300-315 pass exact adjacent args `--disable`, `unified_exec` immediately after `codex exec`; current test `test_invoke_codex_uses_implementation_agent_command_contract` asserts the pair while preserving `gpt-5.6-terra` and `model_reasoning_effort="xhigh"`.
- `AGENTS.md`, `docs/SOLVER_AGENT_DESIGN.md`, `docs/HARNESS.md`, `docs/HARNESS_WORKFLOW.md`, `.agents/skills/harness/SKILL.md`, `.codex/hooks.json`
- `docs/nonlinear-static-newton-raphson/implementation-plan.md` SHA-256 `BF4FC7A5CFDEEC19D62A36E1DF7CC34C0B9F614FA0A0FD8D0A321ADC73E69580`
- `phases/index.json` SHA-256 `F8BE89D579C303410BD1D2CD17AF33FCAD72BF68D9E10C3F644A39D1AA7331FB`
- `phases/nonlinear-static-newton-raphson/index.json` SHA-256 `439B67E1DED442D828EB5C31DAB35D28F32DBA6F66537512CAFFB5616956C137`
- Executor-selected initial current Step: `phases/nonlinear-static-newton-raphson/step0.md`, Step 0 `cli-output-lease-and-derived-names`, status `pending`
- Approved Stage 1-5 hashes: requirements `910E351F3F90FFA42F07D15206B55E62C05EAE821E250424430148337506EBF2`; research `C920A6B02381230D1DB419D73FE767D611B36720D27D6410507BA88C3CA28EEE`; formulation `DFA629888041D5762FD0DF4271353464A692B325DC0C821A8D8689688C1EAFD0`; numerical-review `9517E11804C45A6F3822D18821D52EA493AE20353C8FFAD61E960F4315977D01`; reference-model `52D10B1D0C0500B295C5E48BCB3618B309D9696371B8070D4E3DCEE8D3D74CD3`; io `DBB959A68F17D67CA2B42569610B9C1B595A8BFB5502BC194B7E62B656031B28`.
- Preserved materialization evidence: exactly one pending phase entry, 13/13 pending steps, Step 0 remains pending, no implementation evidence docs yet.
- expected_outputs:
- Executor-managed no-push phase execution from Step 0, with branch/pending selection/retry/timestamps/commits/advancement owned only by `scripts/execute.py`.
- Each Implementation Agent session performs only its Executor-selected current Step `RED -> observed failure -> minimal GREEN -> VERIFY`, updates only that Step status payload, and stops.
- Final Stage 6 evidence remains `docs/nonlinear-static-newton-raphson/implementation-report.md`, `docs/nonlinear-static-newton-raphson/build-test.md`, and `docs/nonlinear-static-newton-raphson/reference-comparison.md` after the approved phase reaches its final verification Step.
- acceptance_gate: Root is explicitly authorized to run no-push `python scripts/execute.py nonlinear-static-newton-raphson` in the isolated worktree using Codex `0.149.1`, `CODEX_HOME=C:\Users\baram\.codex`, a child PATH filtered of `C:\Program Files\WindowsApps\Microsoft.PowerShell_*` and `C:\Users\baram\AppData\Local\Microsoft\WindowsApps`, `workspace-write`, hooks retained, implementation-agent `gpt-5.6-terra`/`xhigh`, and no `danger-full-access`. Passing Stage 6 still requires successful Implementation phase execution plus Coordinator audit of `implementation-report.md`, `build-test.md`, `reference-comparison.md`, full MSVC x64 Debug build/CTest, blocking reference comparison and no forbidden reference/upstream/tolerance mutation.
- stop_condition: If nested shell execution hangs or cannot complete under the exact corrected runner and approved launch envelope, stop as `blocked` with the new evidence; do not broaden to `danger-full-access`, do not run Abaqus/Nastran/reference solvers, do not generate/modify reference CSVs, and do not advance Physics/Release.
- missing_evidence: No-push Harness rerun result and Stage 6 implementation evidence docs remain absent.
### Latest Sub-Agent Return
- target_sub_agent: `research-agent`
- output_paths: `docs/nonlinear-static-newton-raphson/research.md`
- status: `passed` (owner); `needs-rework` (user review gate)
- target_sub_agent: `correction-agent`
- output_paths:
- `docs/nonlinear-static-newton-raphson/corrections.md`
- status: `corrected-for-implementation-rerun` (owner); Coordinator decision `passed-for-implementation-rerun`
- evidence_summary:
- 17 external sources cover original MITC4/TL theory, finite rotation, objective/consistent linearization, Full Newton, V&V/MMS and nonlinear shell benchmarks.
- B-01–B-06 invariant/software checks, B-07F/B-07M large-rotation cantilevers, public NAFEMS 3DNLG-1/9 candidates, locking characterization and shell-MMS gap are separated by applicability.
- `reference/shell/` and `reference/shellR/` are explicitly retained as `nlgeom=NO` linear evidence; exact stored nonlinear input/CSV remains an honest Numerical Review gap.
- Objective 24-DOF mapping/drilling, nodal-moment work, prescribed finite-rotation path, invariant tolerances and fixed-step benchmark traversability are routed downstream without inventing contracts.
- `corrections.md` SHA-256 is `82572437689B41323B6533C2361F2F12BF07B5ED305825AA84C56AEEDC729930`.
- `scripts/execute.py` SHA-256 is `E36A78E5C0AE7E91361B1AB6B995D2E8CF51569C0E0804D57F54711AFEFFB806`; `tests/test_execute.py` SHA-256 is `1E368382ABA21F5FBAC344E15E1E600B6BDAF4C4528431E4D1A757AA09D54CDE`.
- Runner command contract now starts `codex exec --disable unified_exec --json ...` and still passes `--model gpt-5.6-terra`, `--config model_reasoning_effort="xhigh"`, `--sandbox workspace-write`, `--dangerously-bypass-hook-trust`, `--cd <repo>`.
- TDD evidence: targeted RED failed on missing adjacent pair with exit 1; targeted GREEN passed; focused `tests/test_execute.py` 10/10; full pytest remains 23 passed/1 pre-existing `xhigh` vs `extra high`; MSVC Debug build exit 0; CTest discovery 214; full CTest 214/214.
- Correction did not run Harness phase, edit C++/CMake/reference artifacts, run reference solvers, commit or push.
- blockers:
- User Stage-2 review/approval only.
- self_audit_findings: Coordinator independently confirmed 10 required sections, exact S1–S17 inventory, 12 benchmark sections with artifact/gap/target/cannot-verify/limits/review questions, 11 research-relevant requirement IDs, 14 unique open issues, all local evidence paths present and nonlinear reference artifact hits 0. SHA-256 `C920A6B02381230D1DB419D73FE767D611B36720D27D6410507BA88C3CA28EEE`.
- return_contract_check: output path, owner status, source/benchmark coverage, downstream gaps, blockers and ownership confirmation present.
- acceptance_evidence_check: all owner and Coordinator Research evidence gates pass; Stage 2 remains `needs-rework` solely for explicit user approval.
- 없음 for runner-option correction; Stage 6 implementation evidence is still pending.
- self_audit_findings: Coordinator verified the correction report hash, audited current runner args and regression assertion, checked phase index pending statuses, did not run phase/build/tests/reference solvers, and updated only this isolated worktree `coordination.md`.
- return_contract_check: output path, corrected status, evidence summary, blockers and changed-file assertion are present.
- acceptance_evidence_check: REWORK-004 is closed; Stage 6 is eligible for no-push Harness rerun, but no implementation pass evidence exists yet.
### Compact Migration Evidence
@@ -145,15 +167,47 @@
| 2026-08-23 | Research Agent return and Coordinator audit | `needs-rework` | `research.md` owner pass; Coordinator verified 10 sections, S1–S17, 12 complete benchmark candidates, 11 requirement IDs, 14 unique open issues, local evidence existence, nonlinear stored reference hits 0 and forbidden changes 0 | `needs-user-decision` | Present Stage-2 artifact for explicit user approval |
| 2026-08-23 | Research explicit user approval | `passed` | User explicitly approved `research.md`; Research Agent and Coordinator evidence already passed; approved artifact SHA-256 `C920A6B02381230D1DB419D73FE767D611B36720D27D6410507BA88C3CA28EEE` | `needs-formulation` | Dispatch Formulation Agent for bounded Stage 3 evidence |
| 2026-08-23 | Formulation dispatch attempt 1 | `in-progress` | Approved Stage-1/2 baselines and project contracts audited; bounded package requires O-ROT/O-MAP/O-DRILL/O-MOM/O-BC closure without downstream contract changes | `needs-formulation` | Await Formulation Agent return and independently audit Stage-3 evidence |
| 2026-08-23 | Formulation Agent return and Coordinator audit | `needs-rework` | `formulation.md` owner pass/`ready-for-numerical-review`; Coordinator verified 18 required sections, exact 7/7 formulation closure IDs, complete 24-coordinate residual/tangent term inventory, state/integration/recovery/verification/traceability sections, balanced math/fence structure, upstream hash preservation and forbidden changes 0; output SHA-256 `516EB692619C6AAB1AD09061A671697BB7C1B821B0B60BC5A2831CA5D09E131D` | `needs-user-decision` | Present Stage-3 artifact for explicit user approval; do not dispatch Stage 4 |
| 2026-08-23 | Formulation independent consistency review | `needs-rework` | §13.4 uses rotation matrix symbol `R_I` as reaction force, creating dimensional collision; §§4.4/5/11.2 mix tolerance-based source-moment admissibility with exact tangency/projection work statements. Both are bounded formulation-document defects and first normalized attempts. | `needs-formulation` | Same Formulation Agent targeted rework attempt 2; preserve scope/threshold/public meaning |
| 2026-08-23 | Formulation bounded rework attempt 2 return and Coordinator audit | `needs-rework` | Owner pass; reaction force/generalized moment/spatial moment 기호·단위가 rotation matrix `R_I`와 분리되고 force/moment balance가 corrected. Immutable fixed-global source, unchanged `rho_M <= 1e-12`, exact projected work covector, removed director component/no drill channel, `DP`/`DJ_l`/map-Hessian을 포함한 chart/global residual-tangent identity가 일치함. 18 sections/7 closures, upstream hashes와 forbidden-change boundary 보존; SHA-256 `DFA629888041D5762FD0DF4271353464A692B325DC0C821A8D8689688C1EAFD0`. | `needs-user-decision` | Present corrected Stage-3 artifact for explicit user approval; do not dispatch Stage 4 |
| 2026-08-23 | Formulation explicit user approval | `passed` | Task payload states the user explicitly approved `docs/nonlinear-static-newton-raphson/formulation.md`; approved SHA-256 `DFA629888041D5762FD0DF4271353464A692B325DC0C821A8D8689688C1EAFD0` retained. | `needs-numerical-review` | Dispatch `numerical-review-agent` only |
| 2026-08-23 | Numerical/reference dispatch attempt 1 | `blocked` | Coordinator prepared bounded Stage 4 package, but no collaboration `spawn_agent` tool is exposed in this agent environment; `tool_search` found no dispatch tool; `codex exec` fallback was interrupted, is not a visible child-agent dispatch, and produced no Stage 4 outputs. | `blocked` | Expose/route the valid `numerical-review-agent` collaboration dispatch, then rerun Stage 4 owner task |
| 2026-08-23 | Numerical/reference owner return | `needs-rework` | Root-dispatched `numerical-review-agent` returned both outputs with owner status `pass-for-io-definition`, shellNL/shell read-only inventory, row prechecks and blockers none. Coordinator/root audit found a blocking cross-report contradiction on stress CSV and `RM3` comparison disposition, so acceptance evidence is not coherent. | `needs-numerical-review` | Same `numerical-review-agent` bounded reconciliation; do not dispatch I/O |
| 2026-08-23 | Numerical/reference corrected return | `passed` | Corrected current reports have owner status `pass-for-io-definition`; stress CSVs are optional read-only inspection/order evidence only, `RM3` is excluded, and required external comparison is displacement, reaction force and physical spatial `RM1/RM2`. Coordinator verified required sections, exact paths, no concrete HDF5 dataset paths and no forbidden file-change scope. | `needs-user-decision` | Present Stage 4 artifacts for explicit user approval; do not dispatch I/O |
| 2026-08-23 | Numerical/reference explicit user approval | `passed` | User explicitly approved Stage 4 documents and requested next gate; approved hashes retained for requirements, research, formulation, numerical-review and reference-model. | `needs-io-definition` | Prepare bounded `io-definition-agent` dispatch package |
| 2026-08-23 | I/O Definition dispatch package | `in-progress` | Coordinator prepared Stage 5 package requiring `fesa-io-contract`, exact Stage 1-4 inputs, corrected reference disposition, authoritative `results.h5`, and only `docs/nonlinear-static-newton-raphson/io.md` output. | `needs-io-definition` | Root profile dispatch to `io-definition-agent`; await owner return |
| 2026-08-23 | I/O Definition owner return and Coordinator audit | `needs-rework` | Owner returned `io.md` status `ready-for-coordinator-review`, SHA-256 `75D702301D6285F151D913DCD0351F4AD302C4C24A004DD5841A576592D675FC`, blockers none. Coordinator confirmed blocking defects in `--output` substring rejection, Newton iteration log schema, `VARIABLE=PRESELECT` ignored output request acceptance and repository-wide non-Newton log lifecycle. | `needs-io-definition` | Same `io-definition-agent` bounded correction; do not start Implementation Planning |
| 2026-08-23 | I/O Definition bounded rework return and Coordinator audit | `passed` | Owner returned corrected `io.md` status `ready-for-coordinator-review`, SHA-256 `DBB959A68F17D67CA2B42569610B9C1B595A8BFB5502BC194B7E62B656031B28`, blockers none. Coordinator verified REWORK-002 closure, DECISION-028/029/030 output lifecycle/path/log evidence, HDF5/reference/tolerance preservation and no stale narrow `--output` rule. | `needs-user-decision` | Present Stage 5 artifact for explicit user approval; do not start Implementation Planning |
| 2026-08-23 | I/O Definition explicit user approval | `passed` | User explicitly approved `docs/nonlinear-static-newton-raphson/io.md` SHA-256 `DBB959A68F17D67CA2B42569610B9C1B595A8BFB5502BC194B7E62B656031B28` and requested the next Implementation Planning gate. | `needs-implementation-plan` | Prepare bounded `implementation-planning-agent` draft package only |
| 2026-08-23 | Implementation Planning draft dispatch package | `in-progress` | Coordinator prepared Stage 6 planning package requiring `fesa-cpp-msvc-tdd` and project-local `harness`, approved Stage 1-5 hashes, exact reference/tolerance disposition and draft-only stop condition. | `needs-implementation-plan` | Root profile dispatch to `implementation-planning-agent`; await draft/interview return |
| 2026-08-23 | Implementation Planning draft owner return and Coordinator audit | `passed` | Owner returned draft status `draft-ready-for-user-review`, slug `nonlinear-static-newton-raphson`, Steps `0..12`, no files changed, no interview issue/blocker. Coordinator verified requirements/category mapping, TDD/Harness step shape, prepared-analysis orchestration boundary, exact reference/tolerance preservation and no forbidden execution or file creation. | `needs-user-decision` | Present Stage 6 draft for explicit user approval or bounded rework request; do not materialize files yet |
| 2026-08-24 | Implementation Planning draft explicit user approval | `passed` | User explicitly approved the 13-Step draft and requested `implementation-plan.md` plus pending Harness phase file creation. | `needs-implementation-plan` | Prepare bounded materialization package for `implementation-planning-agent` only |
| 2026-08-24 | Implementation Planning materialization dispatch package | `in-progress` | Coordinator authorized only `implementation-plan.md`, append pending phase entry, create phase index and `step0.md`..`step12.md` pending with no executor timestamps; source/tests/CMake/upstream/reference/tolerance/evidence docs and Harness/build/test execution remain forbidden. | `needs-implementation-plan` | Root profile dispatch to `implementation-planning-agent`; await materialization return |
| 2026-08-24 | Implementation Planning materialization owner return and Coordinator audit | `passed` | `implementation-plan.md`, `phases/index.json`, phase index and `step0.md`..`step12.md` are materialized after user approval. Coordinator/root audit passed phase uniqueness, 13/13 pending steps without executor metadata, 151 root assertions, reference hashes/row counts and no unauthorized evidence docs/execution/source/test/CMake/reference edits. | `ready-for-implementation` | Await separate explicit Harness/implementation execution request; do not run Executor automatically |
| 2026-08-24 | Harness/Implementation execution authorization and dispatch package | `in-progress` | User explicitly requested Harness/Implementation execution. Coordinator verified materialized phase still has Step 0 `cli-output-lease-and-derived-names` as the first pending Step, preserved Stage 1-5 hashes and materialization evidence, and prepared no-push `scripts/execute.py nonlinear-static-newton-raphson` dispatch. | `needs-implementation` | Run no-push Harness executor; await Implementation/Harness return before any physics/release transition |
| 2026-08-24 | Harness/Implementation execution attempt 1 | `needs-rework` | No-push Harness attempt failed before Step 0 evidence: `codex exec --json --sandbox workspace-write ...` timed out at `1800.7s`; `_invoke_codex` raised uncaught `subprocess.TimeoutExpired`; no source/test edits, `step0-output.json`, `MAX_RETRIES`, or Step evidence. Normalized classification `harness-uncaught-step-codex-timeout-no-retry` attempt 1. | `needs-implementation` | Bounded Harness repair before retry; do not route to Correction Agent for first clear harness failure |
| 2026-08-24 | Harness repair after attempt 1 | `passed` | Implementation Agent repaired Harness timeout/profile handling in `scripts/execute.py` with tests in `tests/test_execute.py`; RED 3 expected failures, GREEN 3 passed, focused 10/10 passed, full pytest 23 passed/1 pre-existing `xhigh` vs `extra high` mismatch. Root review found no new defect and reproduced the same evidence. No phase execution, phase/source/CMake/reference/evidence docs edit, or reference solver activity. | `needs-implementation` | Retry no-push Harness attempt 2 for Executor-selected Step 0 in workspace-write; if the same normalized timeout recurs, stop automatic rework and route to `needs-user-decision` or `blocked` |
| 2026-08-24 | Harness/Implementation execution attempt 2 | `blocked` | Repaired Executor produced `step0-output.json` with `exitCode` 124 and stderr `Codex timed out after 1800 seconds.`. The Implementation Agent turn completed, but every nested shell `command_execution` remained `status=in_progress` even for `Get-Date`, `cmd echo`, and `exit 0`; Step 0 stayed pending with no production/test changes. Root cause is `harness-nested-codex-windows-shell-tool-execution-hang` attempt 2. | `blocked` | Stop remaining automatic retries; no workaround/further Harness execution until explicit user/root decision or external runtime fix |
| 2026-08-24 | Root correction-cycle authorization | `in-progress` | Root authorized one bounded Correction Agent diagnostic/rework cycle for the repeated infrastructure/runtime failure; unauthorized retry PIDs have been terminated and none remain. Coordinator prepared a correction package limited to no-op/tool smoke reproduction, local Codex CLI/config option inspection, documented flag hypothesis testing, and optional TDD runner changes in `scripts/execute.py`/`tests/test_execute.py`. | `needs-correction` | Root profile dispatch to `correction-agent` is required because this Coordinator runtime exposes no callable `spawn_agent` tool |
| 2026-08-24 | Correction Agent return and Coordinator audit | `blocked` | Correction Agent returned `blocked` and created only `docs/nonlinear-static-newton-raphson/corrections.md` SHA-256 `C9F93AC99225725C88BB7F0BABC8F7D75D3E05082070090328203DB3776BEFE6`. Baseline smoke reproduced no nested shell completion; `--disable code_mode_host` failed closed; `--enable unified_exec` hung; combined flags failed closed. Root verified no nonlinear Harness/Codex processes remain, all 13 steps pending, Python 23 passed/1 pre-existing failure, MSVC build exit 0, discovery 214 and CTest 214/214. | `blocked` | No further Harness retry until external Codex runtime update/repair plus bounded shell smoke success |
| 2026-08-24 | Codex `0.149.1` smoke pass and runner preflight | `needs-rework` | User/root authorized Codex CLI update, bounded smoke and Harness rerun. Smoke passed only with aligned `CODEX_HOME`, filtered WindowsApps PATH entries and `--disable unified_exec`; current `scripts/execute.py` does not pass that flag to nested `codex exec`, while local `codex exec --help` confirms `--disable <FEATURE>` support. | `needs-correction` | Dispatch bounded runner-option correction before any no-push Harness phase rerun |
| 2026-08-24 | REWORK-004 Correction return and Coordinator audit | `passed` | Correction returned `corrected-for-implementation-rerun`; runner now passes adjacent `--disable`, `unified_exec` after `codex exec`; regression test asserts the command contract; `corrections.md` SHA-256 `82572437689B41323B6533C2361F2F12BF07B5ED305825AA84C56AEEDC729930`; focused tests 10/10, full pytest only known pre-existing mismatch, MSVC build and 214/214 CTest pass per owner/root evidence. | `needs-implementation` | Root is authorized to run no-push `python scripts/execute.py nonlinear-static-newton-raphson` with Codex `0.149.1`, aligned `CODEX_HOME`, filtered child PATH, `workspace-write`, hooks retained and no `danger-full-access` |
- current_dispatch: `stage-3-formulation-attempt-1`
- current_workflow_state: `needs-formulation`
- next_gate_requires_user_approval: `false` (owner evidence audit 선행)
- current_dispatch: `stage-6-no-push-harness-implementation-rerun`
- current_workflow_state: `needs-implementation`
- next_gate_requires_user_approval: `false` (user/root already authorized Codex update, bounded smoke and Harness rerun)
## 5. Risk, Blocker, and User-Decision Register
| id | type | description | owner | status |
| --- | --- | --- | --- | --- |
| BLOCKER-001 | dispatch | Stage 4 requires a valid `numerical-review-agent` child dispatch. Root supplied the valid profile dispatch and owner return, so this runtime-tooling blocker no longer blocks the gate. | `coordinator-agent` / runtime tooling | closed |
| REWORK-001 | report-contract | Stage 4 returned evidence had a cross-report contradiction on stress CSV and `RM3` comparison disposition. Corrected reports now consistently treat stress CSVs as optional read-only inspection/order evidence only and exclude `RM3` from comparison. | `numerical-review-agent` | closed |
| REWORK-002 | io-contract | Stage 5 `io.md` bounded correction completed: public CLI `--output` substring rejection, Newton iteration log schema, exact `VARIABLE=PRESELECT` ignored-with-warning handling, repository-wide non-Newton log lifecycle, DECISION-028/029/030 path/log lifecycle and collision semantics are now recorded in `io.md`. | `io-definition-agent` | closed |
| REWORK-003 | harness | Stage 6 attempt 1 timeout/no-retry defect is repaired in Harness infrastructure: timeouts now return structured exit `124` through `MAX_RETRIES`, and implementation-agent profile settings are passed to Codex. Same normalized failure attempt count remains 1; attempt 2 is authorized and same-class recurrence stops automatic rework. | `implementation-agent` via Harness Executor | closed |
| BLOCKER-002 | harness-runtime | Nested Codex Windows shell tool execution hung inside Implementation/Correction Codex sessions. It is mitigated for the authorized rerun by Codex CLI `0.149.1`, aligned `CODEX_HOME`, filtered WindowsApps PATH entries, smoke success with exact `CODEX_SHELL_SMOKE_OK` output, and REWORK-004 runner retention of `--disable unified_exec`. Reopen only if the same hang recurs under the exact approved envelope. | external Codex runtime / user-root decision | mitigated |
| BLOCKER-003 | dispatch-runtime | This Coordinator runtime exposed no callable `spawn_agent` tool, but root successfully performed the required Correction Agent profile dispatch. | coordinator/root tooling | closed |
| REWORK-004 | harness | Corrected: `scripts/execute.py` now passes adjacent `--disable`, `unified_exec` immediately after `codex exec`; `tests/test_execute.py` asserts this while preserving terra/xhigh routing; `corrections.md` records RED/GREEN/VERIFY and no Harness phase/source C++/CMake/reference edits. | `correction-agent` | closed |
| RISK-001 | architecture | 기존 `LinearStaticAnalysis` private lifecycle은 단일 factorization/substitution과 final frame만 소유하므로 nonlinear increment/iteration/state commit을 삽입하면 ADR 경계를 위반한다. | `coordinator-agent` routing | open |
| RISK-002 | scope | `Newton–Raphson`은 solution algorithm이고 geometric/material/contact nonlinearity 범위를 단독으로 결정하지 않는다. | `requirement-agent` | mitigated by DECISION-001 |
| RISK-003 | contract | 현재 `Element`는 displacement-dependent residual/consistent tangent/trial state 계약이 없고 `AnalysisState`는 nonlinear history를 소유하지 않는다. | downstream formulation/architecture gates | open |
@@ -193,13 +247,19 @@
| DECISION-032 | user process decision | `requirements.md`를 핵심 Stage-1 계약으로 압축하고 OQ chronology, diagnostic/path/concurrency trivia와 반복 handoff를 제거한다. Minor details는 downstream specialist convention/evidence로 정하며 approved scope/physics/tolerance/public compatibility를 바꿀 때만 사용자 결정을 다시 요청한다. | user via Coordinator | closed |
| DECISION-033 | design approval | Target 363 lines, 24 canonical requirements와 24-row Matrix, approved semantic-loss 0의 compact rewrite design. | user via Coordinator | closed |
| DECISION-034 | user process decision | Requirement Agent는 approved physics/scope/tolerance/authoritative-output/public compatibility를 바꾸는 essential decision만 사용자에게 묻고, specialist detail은 owning downstream stage가 repository evidence와 conventional FEM practice로 정한다. Equivalence claim은 금지한다. | user via Coordinator; `.codex/agents/requirement-agent.toml` | closed |
| DECISION-035 | user approval | User explicitly approved Stage 5 `docs/nonlinear-static-newton-raphson/io.md` SHA-256 `DBB959A68F17D67CA2B42569610B9C1B595A8BFB5502BC194B7E62B656031B28` and requested Implementation Planning. | user via Coordinator | closed |
| DECISION-036 | user approval | User explicitly approved the Stage 6 Implementation Planning 13-Step draft on `2026-08-24` and authorized creation of `implementation-plan.md` plus pending Harness phase files. | user via Coordinator | closed |
| DECISION-037 | user approval | User explicitly requested no-push Harness/Implementation execution for materialized phase `nonlinear-static-newton-raphson` on `2026-08-24`. | user via Coordinator | closed |
| DECISION-038 | user/root runtime approval | User/root authorized Codex CLI update, shell smoke and no-push Harness rerun. Accepted runtime envelope is Codex CLI `0.149.1`, `CODEX_HOME=C:\Users\baram\.codex`, launch-env-only WindowsApps PATH filtering, `workspace-write`, hooks retained, implementation-agent `gpt-5.6-terra`/`xhigh`, no `danger-full-access`, and `--disable unified_exec`. | user/root via Coordinator | closed |
| USER-DECISION-001 | user decision | Stage 6 Implementation Planning draft Steps `0..12` were approved on `2026-08-24`; materialization is authorized for `implementation-planning-agent`. | user via Coordinator | closed |
## 6. Rework-Loop Control and Stop Condition
- normalized_failure_attempts: `requirements-next-question-routing-mismatch`: 1; `requirements-output-failure-atomicity-scope-ambiguity`: 1; `requirements-compact-public-contract-omission`: 1
- normalized_failure_attempts: `requirements-next-question-routing-mismatch`: 1; `requirements-output-failure-atomicity-scope-ambiguity`: 1; `requirements-compact-public-contract-omission`: 1; `formulation-equilibrium-reaction-symbol-collision`: 1; `formulation-moment-admissibility-work-inconsistency`: 1; `numerical-review-cross-report-disposition-contradiction`: 1; `io-contract-public-cli-log-output-request-gap`: 1; `harness-nested-codex-windows-shell-tool-execution-hang`: 2
- automatic_rework_limit: 동일 normalized failure classification `2`회
- correction_agent_policy: 명확한 implementation failure는 먼저 `implementation-agent`에 반환하고, 반복되거나 원인이 불명확할 때만 `correction-agent`를 dispatch한다.
- stop_condition: 동일 classification이 두 번이면 자동 rework를 중단하고 workflow를 `needs-user-decision` 또는 `blocked`로 전환한다.
- correction_cycle_authorization: Root-authorized REWORK-004 correction returned `corrected-for-implementation-rerun`; no further correction is active. If the same nested shell hang recurs under the exact corrected runner and approved launch envelope, stop as `blocked` rather than broadening privileges.
## 7. Final Workflow Closure
@@ -209,11 +269,11 @@
## 8. No-Change Assertion
- source_code: 변경 없음
- tests: 변경 없음
- source_code: production solver source 변경 없음; earlier Harness repair and REWORK-004 owners modified only `scripts/execute.py` within runner scope.
- tests: production C++ tests 변경 없음; earlier Harness repair and REWORK-004 owners modified only `tests/test_execute.py` within Harness Python test scope.
- CMake: 변경 없음
- reference_artifacts: 생성·수정·rename 없음
- tolerance_policies: 변경 없음
- phase_files: 생성 없음
- Harness: 실행하지 않음
- feature_documents: `coordination.md`, `requirements.md`, `research.md`만 생성됨
- phase_files: user-approved planning owner가 `phases/index.json` pending entry와 `phases/nonlinear-static-newton-raphson/index.json`, `step0.md`..`step12.md`를 materialize함; Executor attempt 2 generated `phases/nonlinear-static-newton-raphson/step0-output.json`; Step 0 remains pending and Coordinator did not edit phase files.
- Harness: Implementation Agent bounded repair와 REWORK-004는 `scripts/execute.py`와 `tests/test_execute.py`에 한정됨; REWORK-004 did not run nonlinear Harness phase, commit or push. Coordinator did not run Harness/phase/build/test; root no-push rerun is now authorized under the approved corrected envelope.
- feature_documents: 이번 coordinator update에서는 isolated worktree의 `coordination.md`만 갱신함; Correction Agent가 `docs/nonlinear-static-newton-raphson/corrections.md`를 갱신했고 `implementation-report.md`, `build-test.md`, `reference-comparison.md`는 아직 생성되지 않음
@@ -0,0 +1,131 @@
# Nonlinear Static Newton-Raphson Correction Report
## 1. Metadata
| key | value |
| --- | --- |
| feature_id | `nonlinear-static-newton-raphson` |
| source failure report | `docs/nonlinear-static-newton-raphson/coordination.md`; `phases/nonlinear-static-newton-raphson/step0-output.json` |
| source implementation plan | `docs/nonlinear-static-newton-raphson/implementation-plan.md` |
| status | `corrected-for-implementation-rerun` |
| owner_agent | `correction-agent` |
| date | `2026-08-24` |
`implementation-report.md`, `build-test.md`, `reference-comparison.md`는 아직 생성되지 않았으므로 현재 Coordinator failure evidence와 Executor의 `step0-output.json`을 source failure report로 사용했다.
Sections 2-6의 Codex `0.147.0` 내용은 initial correction history이며, current REWORK-004 status와 증거는 Sections 7-9가 supersede한다.
## 2. Failure Triage
- classification: `harness`
- normalized classification: `harness-nested-codex-windows-shell-tool-execution-hang`
- first failed command:
```powershell
codex exec --json --model gpt-5.6-terra --config 'model_reasoning_effort="xhigh"' --sandbox workspace-write --dangerously-bypass-hook-trust --cd C:\git\FESADev\.worktrees\nonlinear-static-newton-raphson -
```
- failed target or test: nested shell smoke `cmd.exe /d /c echo CODEX_SHELL_SMOKE_OK`
- evidence tail: baseline diagnostic는 45초 안에 종료되지 않았다. JSONL에는 `item.started`, `type=command_execution`, `status=in_progress`가 기록됐지만 대응하는 completion event와 `CODEX_SHELL_SMOKE_OK` 출력이 없었다. 진단 root PID `11292`와 관찰된 descendant PID tree를 `taskkill /PID 11292 /T /F`로 종료한 뒤 `remainingPids=[]`를 확인했다.
- historical evidence: `step0-output.json`도 exit code `124`, stderr `Codex timed out after 1800 seconds.`를 기록했고 `Get-Date`, `cmd.exe /d /c echo test`, `exit 0` 등의 nested command가 `status=in_progress`에 머물렀다.
## 3. Root Cause Summary
실패 경계는 repaired Python Executor의 timeout/retry 처리나 FESA C++ 구현이 아니라 local `codex-cli 0.147.0`의 nested command execution runtime이다. 같은 worktree에서 direct PowerShell과 `cmd.exe`는 정상 실행되고, focused Harness Python test도 통과하며, runner-equivalent Codex baseline만 nested shell completion을 반환하지 않았다.
Local CLI help는 `--disable <FEATURE>`와 `--enable <FEATURE>`를 문서화하고, `codex features list`는 `code_mode_host`를 `stable true`, `shell_tool`을 `stable true`, `unified_exec`를 `stable false`, `hooks`를 `stable true`로 보고했다. 다음 좁은 가설을 한 변수씩 검사했다.
| variant | result | command completion evidence |
| --- | --- | --- |
| baseline | 45.318초 timeout 후 exact PID tree cleanup | `item.started/status=in_progress`; completion 및 echo output 없음 |
| `--disable code_mode_host` | exit `0`, 33.322초 | shell 미실행; stderr `code-mode host is disabled`; completion event 없음 |
| `--enable unified_exec` | 45.299초 timeout 후 exact PID tree cleanup | completion event 및 echo output 없음 |
| `--disable code_mode_host --enable unified_exec` | exit `0`, 25.922초 | shell 미실행; 동일한 fail-closed host-disabled error |
따라서 `--disable code_mode_host`는 shell execution을 복구하지 않고 tool host를 fail-closed로 제거한다. `unified_exec`도 단독 또는 조합에서 실제 shell completion을 만들지 못했다. Codex 내부 결함의 더 세부 원인은 repository evidence로 확정할 수 없으며, 안전한 documented runner flag workaround는 입증되지 않았다. 이는 implementation defect, test defect 또는 CMake registration issue가 아니라 external Codex runtime blocker다.
## 4. Correction Scope
- changed source files: `scripts/execute.py` (`codex exec` argv에 adjacent `--disable`, `unified_exec` 추가)
- changed header files: 없음
- changed test files: `tests/test_execute.py` (Implementation Agent command contract regression assertion 추가)
- changed CMake files: 없음
- changed report files: `docs/nonlinear-static-newton-raphson/corrections.md`
- excluded upstream contract files: `requirements.md`, `research.md`, `formulation.md`, `numerical-review.md`, `reference-model.md`, `io.md`, `implementation-plan.md`
- excluded artifacts/policies: phase definition/index, production C++, reference inputs/CSV, `docs/TOLERANCE.md`
초기 correction cycle에서는 safe workaround가 입증되지 않아 runner/test를 변경하지 않았다. 이후 user/root가 Codex `0.149.1`의 bounded smoke로 `--disable unified_exec` runtime envelope를 입증했고, REWORK-004에서 그 pair만 TDD로 추가했다. 기존 Harness-repair 변경과 다른 owner의 dirty-worktree 변경은 그대로 보존했다.
## 5. Verification Evidence
| purpose | command | result |
| --- | --- | --- |
| installed CLI | `codex --version` | exit `0`; `codex-cli 0.147.0` |
| documented options | `codex exec --help`; `codex features list` | exit `0`; `--enable/--disable`, `code_mode_host`, `unified_exec`, `shell_tool`, `hooks` 확인 |
| targeted reproduction | runner-equivalent `codex exec ... --sandbox workspace-write ...` + one echo tool request | 45초 timeout; command started, completion/output 없음; exact tree cleanup 후 remaining PID 0 |
| focused Harness Python | `uv run --with pytest python -m pytest -v -rs tests/test_execute.py` | exit `0`; 10 passed |
| full Harness Python | `uv run --with pytest python -m pytest -v -rs` | exit `1`; 23 passed, 1 failed |
| MSVC Debug build | `cmake --build .harness/build --config Debug` | exit `0`; solver/CLI/unit/integration/reference targets built |
| CTest discovery | `ctest --test-dir .harness/build -C Debug --show-only=json-v1` | exit `0`; 214 tests discovered |
| full CTest | `ctest --test-dir .harness/build -C Debug --output-on-failure` | exit `0`; 214/214 passed |
`.harness/config.json`은 없었다. Existing `.harness/build/CMakeCache.txt`는 `Visual Studio 18 2026`, `x64`, approved local GoogleTest/MKL/TBB/HDF5 paths를 사용하므로 Harness auto-detected build tree를 재사용했다.
Full Python failure는 pre-existing out-of-scope contract mismatch다: `test_agent_toml_and_limited_skill_yaml_schemas_are_parseable`가 actual `xhigh`와 expected `extra high`를 비교한다. Dispatch 지시에 따라 이 test, `AGENTS.md`, agent profile을 변경하지 않았다.
Stop hook은 Harness Step 실행을 금지한 이번 correction session에서 별도 Codex Step 종료 evidence를 생성하지 않았다. Hook entry point의 수동 실행은 project contract가 금지하므로 대신 config-resolved full MSVC build와 full CTest를 직접 실행해 결과를 위에 기록했다.
## 6. Traceability
| requirement id | task id | test id | failing command | corrected file | acceptance criterion |
| --- | --- | --- | --- | --- | --- |
| `FESA-REQ-NSNR-083` | Step 0 `cli-output-lease-and-derived-names` | `CORR-HARNESS-SMOKE-001` | runner-equivalent `codex exec` invoking `cmd.exe /d /c echo CODEX_SHELL_SMOKE_OK` | 없음 | workspace-write, hooks, `gpt-5.6-terra`/`xhigh`, no-push, no `danger-full-access`를 유지한 실제 shell completion과 exact echo output; 실패 |
| `FESA-REQ-NSNR-083` | Step 0 `cli-output-lease-and-derived-names` | `CORR-HARNESS-SMOKE-002` | same smoke with `--disable code_mode_host` | 없음 | shell completion 복구; 실패 (`code-mode host is disabled`) |
Runner correction acceptance criterion이 충족되지 않았으므로 Implementation Step 0의 `NSNR-CLI-*` RED/GREEN은 시작되지 않았고 Step 0 status는 `pending`으로 유지된다.
## 7. Handoff Recommendation
- recommendation: Coordinator Agent를 통해 Implementation Agent에 `needs-implementation-rerun` 요청.
- corrected runner contract: nested command는 `codex exec --disable unified_exec --json ...` 순서로 실행된다.
- preserved execution contract: Coordinator가 관리하는 rerun launch environment는 Codex `0.149.1`, aligned `CODEX_HOME`, approved WindowsApps PATH filtering, `workspace-write`, project hooks, `gpt-5.6-terra`, `xhigh`, no-push, no `danger-full-access`를 유지해야 한다.
- scope boundary: 이 correction은 runner option gate만 복구했다. Harness phase, Implementation Step 0, reference comparison 또는 physics success를 주장하지 않는다.
## 8. Stop Condition
- repeated failure: normalized classification attempt `2`는 초기 Codex `0.147.0` failure history로 보존한다.
- external mitigation: user/root의 Codex `0.149.1` bounded smoke와 `DECISION-038`이 새 좁은 runner correction을 승인했다.
- correction result: required adjacent `--disable unified_exec` pair와 regression test가 GREEN이다.
- residual blocker: runner correction 자체 blocker는 없음. Full Python suite의 pre-existing `xhigh` actual 대 `extra high` expected mismatch는 변경하지 않았다.
- upstream ambiguity/reference artifact gap: 없음; reference artifact는 읽기/수정/생성하지 않았다.
- final stop: correction-owned edits와 검증이 끝났으므로 여기서 중단하고, phase rerun 판단과 실행은 Coordinator/Implementation Agent에 반환한다.
## 9. REWORK-004 TDD And Verification Evidence
### Failure and Minimal Correction
- classification: `harness`
- implementation defect: Codex `0.149.1`에서 통과한 runtime envelope의 `--disable unified_exec` option을 `scripts/execute.py`가 nested `codex exec`에 전달하지 않았다.
- RED test: `test_invoke_codex_uses_implementation_agent_command_contract`
- minimal GREEN: command vector에서 `"codex", "exec"` 바로 뒤에 `"--disable", "unified_exec"` 두 argument만 추가했다.
- preserved behavior: `workspace-write` default/validated override, `--dangerously-bypass-hook-trust`, `gpt-5.6-terra`, `model_reasoning_effort="xhigh"`, 1800-second structured timeout, no-push default, `danger-full-access` 비사용 정책은 변경하지 않았다.
### RED / GREEN / VERIFY
| stage | command | exit | duration | evidence tail |
| --- | --- | ---: | ---: | --- |
| RED | `uv run --with pytest python -m pytest -v -rs tests/test_execute.py::test_invoke_codex_uses_implementation_agent_command_contract` | `1` | 1.2초 | `assert ('--disable', 'unified_exec') in adjacent_arguments`; 1 failed |
| GREEN | same targeted command | `0` | 1.1초 | 1 passed |
| focused VERIFY | `uv run --with pytest python -m pytest -v -rs tests/test_execute.py` | `0` | 1.1초 | 10 passed |
| full Harness Python | `uv run --with pytest python -m pytest -v -rs` | `1` | 1.3초 | 23 passed, 1 pre-existing failure |
| MSVC Debug build | `cmake --build .harness/build --config Debug` | `0` | 3.8초 | solver/CLI/unit/integration/reference targets built |
| CTest discovery | `ctest --test-dir .harness/build -C Debug --show-only=json-v1` | `0` | 0.7초 | 214 tests discovered |
| full CTest | `ctest --test-dir .harness/build -C Debug --output-on-failure` | `0` | 10.2초 | 214/214 passed |
Full Python failure는 기존 `test_agent_toml_and_limited_skill_yaml_schemas_are_parseable`의 `assert 'xhigh' == 'extra high'` 한 건이다. REWORK-004의 command-contract test를 포함한 `tests/test_execute.py`는 10/10 통과하며, dispatch 경계에 따라 pre-existing mismatch를 수정하지 않았다.
### REWORK-004 Traceability
| requirement id | task id | test id | corrected files | acceptance criterion |
| --- | --- | --- | --- | --- |
| `FESA-REQ-NSNR-083` | Harness runner correction `REWORK-004`; blocks Step 0 `cli-output-lease-and-derived-names` | `test_invoke_codex_uses_implementation_agent_command_contract` | `scripts/execute.py`; `tests/test_execute.py` | nested Codex argv가 adjacent `--disable`, `unified_exec`를 포함하면서 Terra/xhigh routing을 보존함; passed |
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,252 @@
# Nonlinear Static Newton-Raphson Implementation Plan
> For Harness workers: this plan is an approved Stage 6 planning artifact. It authorizes planning files only. It does not authorize `scripts/execute.py`, C++ implementation, build, CTest, reference solver execution, or evidence-document creation.
**Goal:** `nonlinear-static-newton-raphson` 기능을 C++17/MSVC/CMake/CTest TDD 순서로 구현하고, 승인된 nonlinear MITC4 Newton-Raphson 절차, HDF5 schema v1, log lifecycle, shellNL/shell reference comparison을 검증한다.
**Architecture:** App layer가 argv 검증, lexical output path derivation, move-only `OutputWriteLease`, log open/close와 final HDF5 writer 호출 순서를 소유한다. 입력 parse/map은 정확히 한 번 수행하고, `StepDefinition::ProcedureKind()`로 linear와 nonlinear procedure executor를 분리한다. `LinearStaticAnalysis`의 기존 private lifecycle에는 nonlinear 조건문을 넣지 않고, 기존 linear numerical/HDF5 의미는 repository-wide output name/log lifecycle 변경만 제외하고 보존한다.
**Tech Stack:** C++17, MSVC on Windows, CMake, CTest, GoogleTest, Intel oneAPI MKL/TBB, HDF5, Abaqus `.inp` approved subset, Python 3 Harness scripts.
**Spec:** `docs/nonlinear-static-newton-raphson/{requirements,research,formulation,numerical-review,reference-model,io}.md`
## Metadata
| key | value |
| --- | --- |
| feature_id | `nonlinear-static-newton-raphson` |
| status | `approved-planning-files-materialized` |
| owner_agent | `implementation-planning-agent` |
| date | `2026-08-24` |
| approval | User approved the final 13-Step draft on `2026-08-24`; Coordinator recorded `DECISION-036`. |
| source_requirement | `docs/nonlinear-static-newton-raphson/requirements.md` |
| source_research | `docs/nonlinear-static-newton-raphson/research.md` |
| source_formulation | `docs/nonlinear-static-newton-raphson/formulation.md` |
| source_numerical_review | `docs/nonlinear-static-newton-raphson/numerical-review.md` |
| source_reference_models | `docs/nonlinear-static-newton-raphson/reference-model.md` |
| source_io_definition | `docs/nonlinear-static-newton-raphson/io.md` |
## Approved Upstream Hashes
| document | SHA-256 |
| --- | --- |
| `requirements.md` | `910E351F3F90FFA42F07D15206B55E62C05EAE821E250424430148337506EBF2` |
| `research.md` | `C920A6B02381230D1DB419D73FE767D611B36720D27D6410507BA88C3CA28EEE` |
| `formulation.md` | `DFA629888041D5762FD0DF4271353464A692B325DC0C821A8D8689688C1EAFD0` |
| `numerical-review.md` | `9517E11804C45A6F3822D18821D52EA493AE20353C8FFAD61E960F4315977D01` |
| `reference-model.md` | `52D10B1D0C0500B295C5E48BCB3618B309D9696371B8070D4E3DCEE8D3D74CD3` |
| `io.md` | `DBB959A68F17D67CA2B42569610B9C1B595A8BFB5502BC194B7E62B656031B28` |
## Readiness Check
- Upstream document status: Stage 1 requirements approved, Stage 2 research passed, Stage 3 formulation ready for numerical review and approved downstream, Stage 4 numerical/reference review passed for I/O definition, Stage 5 I/O definition approved.
- Missing decisions: none.
- Missing required comparison files: none for declared blocking/reference families.
- Planning can proceed: yes.
- `.harness/config.json`: absent during planning inspection. Each Step must recheck at execution time and use it first if it appears.
## Global Constraints
- Use `RED -> observed failure -> minimal GREEN -> focused VERIFY -> full CTest` in every implementation Step.
- C++ production edits require related C++ tests in the same Step.
- Do not edit requirements, research, formulation, numerical review, reference-model, I/O, tolerance, or reference artifacts.
- Do not run Abaqus, Nastran, or any reference solver.
- Do not create `implementation-report.md`, `build-test.md`, or `reference-comparison.md` before Step 12 produces actual command evidence.
- Do not run Harness from this planning approval. `scripts/execute.py` requires a separate explicit request.
- Implementation and Harness execution remain unauthorized by this materialized plan until the user separately requests Executor execution.
- Preserve source label/instance identity, deterministic row order, deterministic diagnostics, finite checks, and docs/TOLERANCE.md exactly.
- Preserve `U1/U2/U3` blocking and `UR1/UR2/UR3` warning-only. For shellNL, preserve constrained `RF1/RF2`, `RF3`, physical spatial `RM1/RM2` blocking, and exclude `RM3` plus stress from numeric comparison.
## Repository Seam Map
| area | current seam | implementation direction |
| --- | --- | --- |
| CLI/app | `src/fesa/app/fesa_application.cpp` currently accepts `[--output <results.h5>]` and constructs `LinearStaticAnalysis`. | Add output path derivation and `OutputWriteLease`, reject any argv token containing `--output`, own log/HDF5 lifecycle. |
| Analysis request | `include/fesa/analysis/analysis.h` contains `input_path` and `output_path`. | Add `log_path`; Step 10 introduces prepared analysis flow for single parse/map and delayed HDF5 finalization. |
| Linear lifecycle | `LinearStaticAnalysis::Run()` currently parses/maps and writes HDF5 inside `RecoverAndWrite()`. | Refactor into `PrepareAnalysisInput`, `LinearStaticProcedureExecutor`, and final writer call after log close; keep linear numerical behavior. |
| Domain | `StaticStepDefinition` in `include/fesa/model/model_types.h`; `StepDefinition` in `include/fesa/model/domain.h`. | Store procedure identity, `NLGEOM`, raw four `*STATIC` values and provenance. Do not store derived factor sequence or PRESELECT state. |
| Parser mapping | `src/fesa/io/abaqus/domain_mapping_context.cpp`, `step_definition_mapper.cpp`. | Accept nonlinear static subset, warning no-op PRESELECT, reject unsupported procedure fail-closed. |
| MITC4 | `include/fesa/elements/mitc4_shell.h`, `src/fesa/elements/mitc4_shell.cpp` are linear small-rotation. | Add separate nonlinear MITC4 files with `Create(...)` from four nodes, four initial frames, `ShellSection`, and `LinearElasticMaterial`; element kernels compute internal residual/tangent/recovery only. |
| Loads/control | Current loads are assembled for linear static RHS. | Step 5 owns global-once fixed CLOAD external vector `f_ext` and exact external load tangent `K_ext`, including projected moment `J_l`/map-Hessian terms, with no incident-element multiplication. Step 5 also owns exact convergence constants: relative `1.0e-2`, zero-scale `1.0e-3` with channel-specific units. Step 10 forms `r = f_int - f_ext` and `K_T = K_int - K_ext`. |
| Source identity | `SourceEntityId { instance_name, source_label, source_label_text }` and `EntityIndex` exist in `include/fesa/core/source_identity.h`; nodes are stored in stable Domain order. | Step 8 baseline uses both `EntityIndex` and full `SourceEntityId`, requires one node baseline per Domain node in stable internal order, rejects label-only or mismatched identities, and preserves identity into HDF5/reference mapping. |
| Solver | `MklPardisoSolver` uses SPD `mtype=2` and upper-triangle copy. | Preserve unchanged; add `TangentSolver` and MKL unsymmetric full CSR `mtype=11`. |
| Results writer | `ResultsWriter` is the backend-neutral linear writer; `Hdf5ResultsWriter` writes schema-v0 single-frame linear output. | Add `NonlinearResultsWriter` backend-neutral boundary and `NonlinearHdf5ResultsWriter` schema-v1 implementation with delayed finalization after log close. |
| Tests | `fesa_unit_tests`, `fesa_integration_tests`, `fesa_reference_tests` use executable-wide labels. | Add focused test sources and use `ctest -R` regex; do not globally relabel existing tests as nonlinear. |
## Work Breakdown
| Step | name | dependency | primary responsibility |
| ---: | --- | --- | --- |
| 0 | `cli-output-lease-and-derived-names` | none | CLI output derivation, `--output` substring rejection, RAII output lease, app-owned log/HDF5 lifecycle entry. |
| 1 | `nonlinear-static-domain-contract` | 0 | Domain/parser semantic contract for `NLGEOM=YES`, raw `*STATIC`, PRESELECT warning no-op. |
| 2 | `finite-rotation-state` | 1 | SO(3) finite rotation state, left Jacobian, branch/invariant validation. |
| 3 | `nonlinear-mitc4-kinematics-and-recovery` | 1,2 | TL MITC4 nonlinear kinematics and recovery rows. |
| 4 | `nonlinear-mitc4-residual-and-tangent` | 2,3 | Same-trial internal residual and internal consistent tangent with recovery. |
| 5 | `load-boundary-path-and-convergence-gates` | 1-4 | Fixed factor path, proportional load/BC path, global-once fixed-load `f_ext`/`K_ext` with approved subtraction signs, `rho_M`, typed four-channel convergence with constants owned by evaluator. |
| 6 | `backend-neutral-tangent-solver` | 4 | Separate nonsymmetric tangent solver boundary and MKL adapter. |
| 7 | `newton-iteration-log-writer` | 0,5 | Exact 39-field Newton text log writer. |
| 8 | `nonlinear-state-commit-rollback` | 3-7 | Factor-zero baseline construction with `EntityIndex` plus `SourceEntityId`, trial/committed nonlinear state, accepted frames, rollback/preservation. |
| 9 | `nonlinear-hdf5-schema-v1-writer` | 8 | Nonlinear HDF5 schema v1 writer using `std::vector<Diagnostic>`. |
| 10 | `prepared-analysis-flow-and-full-procedure` | 0-9 | Single parse/map prepared analysis flow, separate linear/nonlinear executors, delayed writer finalization. |
| 11 | `reference-comparison-gate` | 0-10 | shellNL nonlinear and shell linear real-input reference comparison. |
| 12 | `execution-closure-and-evidence-docs` | 0-11 | Fresh MSVC evidence, deterministic repeat/reference audit, actual-output evidence docs. |
## TDD Test Plan
| test id family | RED assertion scope | Step |
| --- | --- | --- |
| `NSNR-CLI-*` | `--output` substring first-token rejection, lexical result/log names, no-output-change proof, lease lifetime. | 0 |
| `NSNR-IO-*` | `NLGEOM=YES`, raw `*STATIC`, `NLGEOM=NO` regression, PRESELECT warning no-op, unsupported procedure diagnostics. | 1 |
| `NSNR-ROT-*` | finite rotation invariants, `J_l`, branch margin, director update. | 2 |
| `NSNR-ELEM-KIN-*` | nonlinear MITC4 creation inputs, TL shell kinematics, fixed-size four-GP recovery rows, degeneracy fail-closed, linear limit. | 3 |
| `NSNR-ELEM-TAN-*` | same-trial internal residual/tangent, directional derivative, objectivity, symmetry only for internal/no-external cases. | 4 |
| `NSNR-CTRL-*` | load factor path, absolute boundary path, global-once fixed loads and load tangent, moment admissibility, typed four convergence gates with `relative`/`zero-scale` branches and non-injectable exact thresholds/units. | 5 |
| `NSNR-SOLVER-*` | nonsymmetric tangent solve, 0x0, nonfinite/failure translation, SPD solver unchanged. | 6 |
| `NSNR-LOG-*` | serializer-owned 39-field UTF-8/LF/TAB Newton log from explicit stage/failure/channel records and fail-closed write/flush/close. | 7 |
| `NSNR-STATE-*` | factor-zero baseline creation with stable node order and full source identity, trial/committed separation, accepted frame order, full schema-v1 state inventory, finite atomic commit, rollback. | 8 |
| `NSNR-HDF5-*` | `NonlinearResultsWriter` boundary, schema v1 metadata/model/frame datasets, factor-zero metadata, atomic finalization. | 9 |
| `NSNR-PROC-*` | full procedure orchestration, single parse/map, log close before HDF5, deterministic repeat. | 10 |
| `NSNR-REF-*` | original artifact snapshot, temp input copy run, HDF5-to-original-CSV identity mapping, tolerance, classification, report data. | 11 |
| `NSNR-EVID-*` | fresh evidence docs and diff/hash/warning audits from actual command outputs. | 12 |
## CMake And CTest Plan
- Add C++ sources to `src/fesa/CMakeLists.txt` under existing `fesa_solver`.
- Add unit tests to `fesa_unit_tests`, integration tests to `fesa_integration_tests`, reference tests to `fesa_reference_tests`.
- Preserve current executable-wide labels. Use focused regex such as `ctest --test-dir .harness/build -C Debug -R "NonlinearStaticReference|ReferenceTolerance|Mitc4Reference" --output-on-failure`.
- If scoped per-test labels are introduced, the Step that introduces the mechanism must test it and avoid changing labels for unrelated discovered tests.
- Configure/build/test commands:
```powershell
cmake --fresh -S . -B .harness/build -G "Visual Studio 18 2026" -A x64 `
"-DFESA_GTEST_SOURCE_DIR=$gtestSource" `
"-DMKL_DIR=$mklDir" `
"-DTBB_DIR=$tbbDir" `
"-DHDF5_DIR=$hdf5Dir"
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
## Data Flow Contract
1. CLI receives `fesa.exe <model.inp>`.
2. App scans all argv tokens left-to-right. The first token containing case-sensitive substring `--output` fails with one `cli-usage` diagnostic before path resolution, parse/map, analysis, lease, log, or HDF5.
3. App derives `<stem>_results.h5` and `<stem>_log.txt` beside the lexically normalized user-addressed `.inp`.
4. App acquires move-only `OutputWriteLease` and retains it until all log and HDF5 work ends.
5. App opens/truncates the log, then `PrepareAnalysisInput(input_path)` parses/maps once into `Domain`.
6. Procedure executor receives injected `ParallelFor` plus `LinearSolver` or `TangentSolver` and computes a fully validated linear or nonlinear state without opening HDF5. Nonlinear assembly forms `r = f_int - f_ext` and `K_T = K_int - K_ext` from Step 4 internal quantities and Step 5 global-once external quantities. Nonlinear state construction preserves each node's stable `EntityIndex` and full `SourceEntityId`; source label alone is never a row identity.
7. App closes the log successfully before invoking injected `ResultsWriter` or `NonlinearResultsWriter`.
8. HDF5 is the authoritative solver output. CSV views are comparison/debug artifacts only.
## Reference Inventory
| path | role | rows | SHA-256 |
| --- | --- | ---: | --- |
| `reference/shellNL/shellNL.inp` | nonlinear input | input | `4BF3ECB0F7F1E8462C573E993DBC97AC5D920C91CF6F23AD4C6891D77FFBADA2` |
| `reference/shellNL/shellNL displacements.csv` | required displacement CSV | 49 | `4E0F99CA9372B1ADF7FAF102F43BC0B887DC743FDEDA378E4342D2CF8E0C0786` |
| `reference/shellNL/shellNL reactions.csv` | required reaction CSV | 49 | `001CB1541A9E94424E5E650509D46BC8724970DF4DE47184D9DB09C7938AB069` |
| `reference/shellNL/shellNL stresses.csv` | nonblocking inventory artifact | 288 | `5500E5114B1C44887528E30CEC054A1EB0F68BE3F4B8CE81FA59FC74A881483F` |
| `reference/shell/shell.inp` | linear input | input | `4005851E1AB22FD3A16AC17A8D5DA3E051233F69F37419079F3553AD134ECFCF` |
| `reference/shell/shell displacements.csv` | required displacement CSV | 49 | `C81D94E0B4A849F87AA0F79C83A79B94D5661AC79E44ED826919AB432C87746B` |
| `reference/shell/shell reactions.csv` | nonblocking inventory artifact | 49 | `0E34EEC27E700C3C0C744C1DAFD8A3B95EFEF34B8616FE96665876586FE82D41` |
| `reference/shell/shell stresses.csv` | nonblocking inventory artifact | 288 | `2B75A5B0DEB045A283C9BB7E9B1153B79F7537FF487214BF4A23316B59B660A7` |
Blocking and warning families:
| family | components | rows | disposition |
| --- | --- | ---: | --- |
| `linear.translation` | `U1,U2,U3`, nodes `1..49` | 147 | blocking |
| `linear.rotation` | `UR1,UR2,UR3`, nodes `1..49` | 147 | warning-only |
| `nonlinear.translation` | `U1,U2,U3`, nodes `1..49` | 147 | blocking |
| `nonlinear.rotation` | `UR1,UR2,UR3`, nodes `1..49` | 147 | warning-only |
| `nonlinear.reaction_inplane_force` | `RF1,RF2`, constrained nodes | 48 | blocking |
| `nonlinear.reaction_transverse_force` | `RF3`, constrained nodes | 24 | blocking |
| `nonlinear.reaction_physical_moment` | `RM1,RM2`, constrained nodes | 48 | blocking |
Constrained node labels for shellNL reactions: `1,3,4,5,6,7,8,9,14,15,16,17,22,23,24,25,26,27,28,29,30,31,32,33`.
Exact shellNL `Frame`: `Increment 10: Step Time = 1.000`.
Step 11 must not run original reference input paths directly. It snapshots exact original artifact inventory, copies input bytes unchanged into a unique build-local temp case directory, runs `FesaApplication` on the copied `.inp`, consumes copied-sibling `_results.h5` and `_log.txt`, compares generated HDF5 to original read-only CSVs, and then verifies original reference directory inventory, bytes, timestamps, and hashes are unchanged. HDF5 source path identity matches the copied user-addressed input; source content identity matches the approved input hash.
## Acceptance Traceability Matrix
| requirement | Steps | test ids |
| --- | --- | --- |
| `FESA-REQ-NSNR-001` | 1,10 | `NSNR-IO-*`, `NSNR-PROC-*` |
| `FESA-REQ-NSNR-003` | 1,3,4,10 | `NSNR-IO-*`, `NSNR-ELEM-*`, `NSNR-PROC-*` |
| `FESA-REQ-NSNR-041` | 1,3,10 | `NSNR-IO-*`, `NSNR-ELEM-KIN-*`, `NSNR-PROC-*` |
| `FESA-REQ-NSNR-074` | 2,8,10 | `NSNR-ROT-*`, `NSNR-STATE-*`, `NSNR-PROC-*` |
| `FESA-REQ-NSNR-006` | 4,6,10 | `NSNR-ELEM-TAN-*`, `NSNR-SOLVER-*`, `NSNR-PROC-*` |
| `FESA-REQ-NSNR-007` | 5,10 | `NSNR-CTRL-*`, `NSNR-PROC-*` |
| `FESA-REQ-NSNR-069` | 5,10 | `NSNR-CTRL-*`, `NSNR-PROC-*` |
| `FESA-REQ-NSNR-070` | 5,10 | `NSNR-CTRL-*`, `NSNR-PROC-*` |
| `FESA-REQ-NSNR-008` | 5,10 | `NSNR-CTRL-*`, `NSNR-PROC-*` |
| `FESA-REQ-NSNR-014` | 5,10 | `NSNR-CTRL-*`, `NSNR-PROC-*` |
| `FESA-REQ-NSNR-046` | 5,10 | `NSNR-CTRL-*`, `NSNR-PROC-*` |
| `FESA-REQ-NSNR-048` | 5,10 | `NSNR-CTRL-*`, `NSNR-PROC-*` |
| `FESA-REQ-NSNR-018` | 5,10 | `NSNR-CTRL-*`, `NSNR-PROC-*` |
| `FESA-REQ-NSNR-063` | 5,10 | `NSNR-CTRL-*`, `NSNR-PROC-*` |
| `FESA-REQ-NSNR-016` | 1,5 | `NSNR-IO-*`, `NSNR-CTRL-*` |
| `FESA-REQ-NSNR-011` | 8,9,10 | `NSNR-STATE-*`, `NSNR-HDF5-*`, `NSNR-PROC-*` |
| `FESA-REQ-NSNR-019` | 4,8,10 | `NSNR-ELEM-TAN-*`, `NSNR-STATE-*`, `NSNR-PROC-*` |
| `FESA-REQ-NSNR-020` | 1 | `NSNR-IO-*` |
| `FESA-REQ-NSNR-021` | 8,9,10 | `NSNR-STATE-*`, `NSNR-HDF5-*`, `NSNR-PROC-*` |
| `FESA-REQ-NSNR-024` | 7,10 | `NSNR-LOG-*`, `NSNR-PROC-*` |
| `FESA-REQ-NSNR-083` | 0,10,12 | `NSNR-CLI-*`, `NSNR-PROC-*`, `NSNR-EVID-*` |
| `FESA-REQ-NSNR-026` | 8,10,11,12 | `NSNR-STATE-*`, `NSNR-PROC-*`, `NSNR-REF-*`, `NSNR-EVID-*` |
| `FESA-REQ-NSNR-030` | 2,3,4,5,6,7,8,9,10,11 | `NSNR-ROT-*`, `NSNR-ELEM-*`, `NSNR-CTRL-*`, `NSNR-SOLVER-*`, `NSNR-LOG-*`, `NSNR-STATE-*`, `NSNR-HDF5-*`, `NSNR-PROC-*`, `NSNR-REF-*` |
| `FESA-REQ-NSNR-034` | 11 | `NSNR-REF-*` |
## Numerical Review Coverage
| category | Steps |
| --- | --- |
| linear-limit reduction | 3,4,10,11 |
| rotation invariants and branch margin | 2,8,10 |
| tangent directional derivative schedule | 4 |
| no-moment tangent symmetry | 4 |
| finite rigid objectivity | 3,4 |
| patch/sign recovery | 3,4 |
| load/boundary path and `rho_M` | 5,10 |
| Newton factor/iteration lifecycle | 5,7,10 |
| four convergence gates | 5,7,10 |
| commit/rollback/determinism | 8,10,11,12 |
## Validation Commands
Each Step must:
1. Recheck `.harness/config.json`. If present, use the configured Harness build/test commands.
2. If absent, use:
```powershell
cmake --fresh -S . -B .harness/build -G "Visual Studio 18 2026" -A x64 `
"-DFESA_GTEST_SOURCE_DIR=$gtestSource" `
"-DMKL_DIR=$mklDir" `
"-DTBB_DIR=$tbbDir" `
"-DHDF5_DIR=$hdf5Dir"
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
Focused CTest commands are written explicitly in each `stepN.md`.
Harness Python validation is not in scope unless a Step changes Harness Python behavior, hook behavior, or agent configuration.
## Risks And Downstream Handoff
- Main implementation risk: current `LinearStaticAnalysis` owns parse/map and HDF5 write internally. Step 10 must refactor through prepared analysis flow so log close precedes HDF5 finalization for both linear and nonlinear runs.
- Main numerical risk: nonlinear MITC4 tangent and finite rotation derivatives must pass internal derivative/objectivity tests before reference comparison can be meaningful.
- Main backend risk: nonlinear tangent can be nonsymmetric. Preserve SPD `MklPardisoSolver` unchanged and add separate `TangentSolver`.
- Handoff to Implementation Agent through Coordinator: execute Steps 0..12 in order, one current Step at a time, with RED observed failure evidence before GREEN implementation, then focused/full CTest. Final reference gate is Step 11; evidence-document closure is Step 12.
## Open Issues
None.
## Plan Approval Boundary
The user-approved plan and pending phase files do not authorize Harness execution. `scripts/execute.py nonlinear-static-newton-raphson` requires a separate explicit user request.
+808
View File
@@ -0,0 +1,808 @@
# Nonlinear Static Newton-Raphson I/O Definition
## 1. Metadata
- feature_id: `nonlinear-static-newton-raphson`
- source_requirement: `docs/nonlinear-static-newton-raphson/requirements.md`
- source_requirement_sha256: `910E351F3F90FFA42F07D15206B55E62C05EAE821E250424430148337506EBF2`
- source_research: `docs/nonlinear-static-newton-raphson/research.md`
- source_research_sha256: `C920A6B02381230D1DB419D73FE767D611B36720D27D6410507BA88C3CA28EEE`
- source_formulation: `docs/nonlinear-static-newton-raphson/formulation.md`
- source_formulation_sha256: `DFA629888041D5762FD0DF4271353464A692B325DC0C821A8D8689688C1EAFD0`
- source_numerical_review: `docs/nonlinear-static-newton-raphson/numerical-review.md`
- source_numerical_review_sha256: `9517E11804C45A6F3822D18821D52EA493AE20353C8FFAD61E960F4315977D01`
- source_reference_model: `docs/nonlinear-static-newton-raphson/reference-model.md`
- source_reference_model_sha256: `52D10B1D0C0500B295C5E48BCB3618B309D9696371B8070D4E3DCEE8D3D74CD3`
- repository_policy: `AGENTS.md`, `docs/SOLVER_AGENT_DESIGN.md`, `docs/PRD.md`,
`docs/ARCHITECTURE.md`, `docs/ADR.md`, `docs/TOLERANCE.md`
- status: `ready-for-coordinator-review`
- owner_agent: `io-definition-agent`
- date: `2026-08-23`
- authoritative_output: input sibling `<stem>_results.h5`
- diagnostic_log: input sibling `<stem>_log.txt`
- hdf5_schema_version: `1`
이 문서는 승인된 Stage 5 I/O 계약만 정의한다. Parser, writer, comparison tool의
C++ API나 파일 소유권은 정의하지 않는다. FESA는 Abaqus와 독립적인 solver이며,
아래 `.inp` subset과 reference CSV mapping은 Abaqus full compatibility, Abaqus
`S4/S4R` 내부 알고리즘, 적분, stabilization, 상태 갱신 또는 output recovery
동등성을 주장하지 않는다.
FEM wiki 근거는 `Abaqus Input File Syntax`,
`Abaqus Output Database and Results Files`,
`Abaqus General and Linear Perturbation Steps`,
`Abaqus Initial and Boundary Conditions`,
`Abaqus Loads and Predefined Fields`,
`Abaqus Beam and Shell Section Definitions`를 사용했다. 이 근거는 keyword/data/comment
line, model/history data, output request, step/load/boundary/section 용어를 정렬하기
위한 보조 근거이며, 승인된 FESA 요구조건과 정식화가 우선한다.
## 2. Abaqus Input Scope
- input_format: Abaqus input file (`.inp`)
- supported Abaqus documentation source/version: 프로젝트 연구 bundle 및 local FEM
wiki에 보존된 Abaqus 2024 input syntax/output vocabulary. 저장된 nonlinear reference
input은 Abaqus/CAE Learning Edition 2024 생성물이다.
- supported_analysis: no-prior-history baseline에서 시작하는 정확히 하나의 source
`*STEP, NLGEOM=YES`와 하나의 nonlinear `*STATIC` procedure.
- internal_element_formulation: source `S4`와 `S4R` 모두 materially linear,
geometrically nonlinear Total Lagrangian `FESA-MITC4`에 매핑한다.
- ordinary_unit_system: 사용자가 일관되게 선택한 미지정 단위계. FESA는 단위 추론이나
변환을 수행하지 않는다.
- compatibility_disclaimer: 이 문서가 명시한 keyword 위치, parameter, data-line arity,
validation rule, output mapping만 지원 범위다.
`supported`는 syntax가 parsing되고 feature semantic model에 매핑된다는 뜻이다.
`unsupported`는 명확한 diagnostic으로 거부한다. `ignored-with-warning`은 syntax와
소속 data line을 소비하고 warning을 남기지만 Domain, AnalysisModel, nonlinear
procedure, mandatory HDF5 output 또는 reference comparison 의미를 바꾸지 않는다.
`requires-user-decision` 항목은 없다.
| keyword | policy | allowed location | required parameters and data grammar | semantic mapping | unsupported behavior |
| --- | --- | --- | --- | --- | --- |
| `*HEADING` | supported | optional top-level first keyword | parameter 없음; 다음 keyword 전까지 text row 0개 이상 | raw heading을 source metadata로 보존 | parameter, nested location, 두 번째 heading은 input error |
| `*INCLUDE` | unsupported | anywhere | 허용 data/parameter grammar 없음 | file traversal 또는 include expansion 없음 | `unsupported-keyword`; 참조 파일을 열지 않음 |
| `*PART` / `*END PART` | supported | top-level model block | `NAME=<part-name>` 필수; `*END PART` data 없음 | part-local node, element, set, shell section scope | unclosed, nested, duplicate, data-bearing close는 input error |
| `*NODE` | supported | part scope | 각 row `node_label,x,y,z`; parameter 없음 | 양의 source node label과 finite global Cartesian coordinate | arity 오류, duplicate label, nonfinite value, dangling later reference는 input/model error |
| `*NSET` | supported | part 또는 assembly scope | `NSET=<name>` 필수; optional `GENERATE`; assembly scope는 `INSTANCE=<name>` 필수; explicit labels 또는 `first,last,increment` | deterministic node-set membership | mixed-instance set, invalid generate row, duplicate set name, empty set, dangling member는 input error |
| `*ELEMENT` | supported | part scope | `TYPE=S4` 또는 `TYPE=S4R`; 각 row `element_label,n1,n2,n3,n4` | four-node source shell connectivity; source type 보존; internal type `FESA-MITC4` | 다른 element type은 `unsupported-element-formulation`; repeated node, arity 오류, dangling node, mixed element model은 error |
| `*ELSET` | supported | part 또는 assembly scope | `ELSET=<name>` 필수; optional `GENERATE`; assembly scope는 `INSTANCE=<name>` 필수; `*NSET`과 같은 row rule | deterministic element-set membership | mixed-instance set, invalid generate row, duplicate set name, empty set, dangling member는 input error |
| `*MATERIAL` | supported | top-level model data | `NAME=<material-name>` 필수; data 없음 | 정확히 하나의 supported isotropic `*ELASTIC` 소유 | duplicate material, missing/duplicate elasticity, 다른 material behavior는 input error |
| `*ELASTIC` | supported | current `*MATERIAL` scope | 정확히 한 row `E,nu`; parameter 없음 | homogeneous isotropic linear elasticity; `G=E/(2(1+nu))` 파생 | extra field/row, dependency/temperature data, nonfinite value, `E<=0`, `nu<=-1`, `nu>=0.5`는 error |
| `*SHELL SECTION` | supported | part scope | `ELSET=<name>`와 `MATERIAL=<name>` 필수; 정확히 한 row `thickness[,integration_points]` | centered homogeneous single-layer shell section | composite/layer data, offset, orientation, controls, variable thickness, missing reference, conflicting assignment, nonpositive thickness는 error |
| `*ASSEMBLY` / `*END ASSEMBLY` | supported | 정확히 하나의 top-level assembly | `NAME=<assembly-name>` 필수; `*END ASSEMBLY` data 없음 | identity-instance scope와 assembly-level set scope | nested/duplicate assembly, instance transform data, unmatched close는 input error |
| `*INSTANCE` / `*END INSTANCE` | supported | assembly scope | `NAME=<instance-name>`, `PART=<part-name>` 필수; transform data 없음 | named identity copy; 같은 part의 multiple identity instances 허용 | duplicate/dangling instance 또는 translation/rotation data는 unsupported input |
| `*BOUNDARY` | supported | top-level model data 또는 sole step의 `*STATIC` 뒤 | parameter 없음; 각 row `target,first_dof,last_dof[,value]`; omitted value는 exact zero | common load-factor path의 factor-one absolute global DOF target; DOF `1..6` | amplitude, local coordinate system, invalid range/arity, unresolved target, nonfinite value, conflicting expanded value는 error |
| `*CLOAD` | supported | sole step의 `*STATIC` 뒤 | parameter 없음; 각 row `target,dof,magnitude`; DOF `1..6` | load factor로만 scale되는 fixed-global dead nodal force/moment source | amplitude/follower/local load, invalid arity/DOF, unresolved target, nonfinite magnitude, drilling-direction aggregate moment는 error |
| `*DLOAD` | unsupported | anywhere | 허용 data/parameter grammar 없음 | distributed/body/pressure/edge/follower load object를 만들지 않음 | load-like usage는 `unsupported-distributed-load`; 그 외는 `unsupported-keyword` |
| `*STEP` / `*END STEP` | supported for nonlinear selector | 정확히 하나의 top-level history block | optional `NAME`; `NLGEOM=YES` 필수; `*END STEP` data 없음 | canonical nonlinear step identity `Step-1` | zero/multiple/mixed/unclosed/nested step 또는 non-`YES` nonlinear selector는 nonlinear increment 전 실패 |
| `*STATIC` | supported nonlinear procedure | sole step의 첫 procedure keyword | 정확히 한 row `initial_increment,time_period,minimum_increment,maximum_increment`; 네 값 모두 finite positive; `time_period`는 endpoint `1.0` identity | 첫 값은 fixed increment `h`; 세 번째/네 번째 값은 unused compatibility source; factors는 one 미만 ordinal multiple 뒤 exact factor one | missing/extra rows/fields, nonpositive/nonfinite field, endpoint가 `1.0`이 아니면 `invalid-nonlinear-static-data` |
| `*OUTPUT` | ignored-with-warning | sole step의 `*STATIC` 뒤 | 정확히 `FIELD, VARIABLE=PRESELECT` 또는 `HISTORY, VARIABLE=PRESELECT`; `FIELD`/`HISTORY`는 value 없는 flag이고 둘 중 하나만 필요; `VARIABLE`은 정확히 한 번 필요; duplicate, both flags, missing `VARIABLE`, 다른 value, extra parameter는 input error | stored reference의 `*Output, field, variable=PRESELECT`와 `*Output, history, variable=PRESELECT`를 warning no-op으로 수용; FESA mandatory output을 select/suppress할 수 없음 | output request는 FESA output을 바꾸지 않음; malformed parameter set은 `invalid-keyword-parameter` |
| `*NODE OUTPUT` | ignored-with-warning | active allowlisted `*OUTPUT` scope | parameter와 다음 keyword 전 variable data를 소비 | legacy nodal request `U`, `RF` 등을 수용 | HDF5 selection, history output, empty synthetic dataset을 만들지 않음 |
| `*ELEMENT OUTPUT` | ignored-with-warning | active allowlisted `*OUTPUT` scope | parameter와 다음 keyword 전 variable data를 소비 | legacy element request `S` 등을 수용 | extrapolated stress, averaging, comparison projection을 만들지 않음 |
| `*PREPRINT` | ignored-with-warning | top-level | parameter를 보존 후 무시; data 불필요 | generator control syntax 수용 | semantic object 없음 |
| `*RESTART` | ignored-with-warning | sole step | parameter를 보존 후 무시; restart state/data 없음 | legacy restart request syntax 수용 | restart write/read/continue 없음 |
| `*CONTACT OUTPUT` | ignored-with-warning | active allowlisted `*OUTPUT` scope | parameter와 다음 keyword 전 data를 소비 | legacy contact-output request syntax만 수용 | contact model/output 없음 |
`*ORIENTATION`, `*TRANSFORM`, amplitudes, follower loads, pressure, gravity, body
force, edge load, `*DLOAD`, composite shell definitions, shell section offsets,
material nonlinearity, density, temperature dependency, contact, MPC, penalty, multiple
steps, restarts, submodels, transforms, nested assemblies와 위 표에 없는 모든
model-affecting keyword는 fail-closed unsupported input이다. 저장 또는 future linear
shell input의 `NLGEOM=NO`는 `docs/linear-static-mitc4-shell/io.md`가 계속 관할한다.
이 feature bundle에서 해당 linear case는 `shell-s4-linear-limit` regression reference일
뿐 nonlinear response evidence가 아니다.
## 3. Syntax Policy
- Keyword line은 optional leading whitespace 뒤 `*`로 시작한다. Comment line은 `**`로
시작하며 semantic effect가 없다.
- Keyword name, parameter name, supported enumerated value, named-reference lookup은
ASCII case-insensitive다. Raw source spelling은 diagnostic/report display용으로
보존한다.
- Data line과 keyword parameter field는 comma-separated다. 주변 whitespace는 parsing
전에 trim한다. 필수 field가 비어 있거나, 허용되지 않은 trailing field가 있거나,
numeric token이 malformed이면 input error다.
- 승인된 empty data-field 의미는 `*BOUNDARY` 네 번째 value 생략뿐이며 exact zero로
매핑한다. `*SHELL SECTION`의 optional second field는 생략 가능하고, 존재하면 positive
base-10 integer여야 한다.
- Continuation line, physical-line continuation, multiline name, quoted case-sensitive
name, parameter substitution, include file은 unsupported다. 각 logical keyword/data row는
한 physical line에 완결되어야 한다.
- 이 feature는 public numeric Abaqus line-length compatibility limit를 정의하지 않는다.
승인 input은 single-line ASCII record이며, 읽을 수 없는 physical line은 implicit
continuation 없이 parsing 실패다.
- Keyword, parameter, set/material/part/instance name, numeric label의 input text는
ASCII로 취급한다. HDF5 string output은 UTF-8이지만 non-ASCII source label/name은
이 feature 계약 밖이다.
- Node label, element label, explicit set member는 positive base-10 integer다. Source
label은 text와 numeric identity로 보존한다. Stable internal index는 diagnostic 또는
comparison row에서 source identity를 대체할 수 없다.
- 모든 real-valued input은 finite `double`로 parse되어야 한다. `NaN`, `Inf`, overflow,
nonfinite underflow, locale-dependent numeric format은 reject한다.
- Model data와 history data는 개념적으로 분리한다. Mesh, set, material, section,
coordinate, initial shell frame은 model data다. Step, procedure, boundary, load,
output request는 history data다.
- 어떤 keyword에도 속하지 않는 standalone data 또는 active keyword block 밖의 data는
input error다. Output-request variable data는 allowlisted output keyword에 종속될 때만
no-op으로 소비한다.
- 모든 parsed keyword, parameter, data row, semantic entity는 normalized file path,
1-based line, raw keyword spelling, source identity까지 추적 가능해야 한다.
## 4. Model Data Mapping
### 4.1 Stable Source Identity and Ordering
Identity-instance expansion 뒤 source node와 source element의 stable identity는 다음과
같다.
```text
SourceEntityId { instance_name, source_label }
```
Name lookup은 case-insensitive지만 raw spelling은 보존한다. Stable internal ID는 input
part declaration order, instance declaration order, part-local entity declaration order로
부여한다. Hash iteration, thread scheduling, set spelling, CSV row order는 source identity,
internal row order, diagnostic order 또는 result row order를 바꾸면 안 된다.
### 4.2 Nodes, Elements and Sets
- `*NODE`는 finite global Cartesian initial midsurface coordinate `[X,Y,Z]`로 매핑하며
unit dimension은 `length`다.
- `*ELEMENT, TYPE=S4/S4R`는 ordered four-node shell connectivity `[1,2,3,4]`로 매핑한다.
Natural corner 순서는 `(-1,-1)`, `(+1,-1)`, `(+1,+1)`, `(-1,+1)`이며 connectivity를
조용히 reverse하지 않는다.
- Source type `S4` 또는 `S4R`는 metadata로 보존한다. 두 type 모두 같은 internal
`FESA-MITC4` formulation, `2 x 2 x 2` integration, nonlinear state path를 선택한다.
Source `S4R`는 reduced integration, hourglass control 또는 Abaqus `S4R` internal
behavior를 활성화하지 않는다.
- `*NSET`과 `*ELSET`은 explicit row order를 보존한다. `GENERATE`는 inclusive
`first,last,increment` 순서로 expand한다. Assembly-scope set은 하나의 `INSTANCE`만
참조할 수 있고 mixed instance는 허용하지 않는다.
- Set membership은 Domain commit 전에 source identity로 resolve한다. 같은 scope의
duplicate set definition, dangling member, invalid generate range는 analysis 전 실패한다.
### 4.3 Material, Section, Coordinates and Units
- `*MATERIAL`과 `*ELASTIC`은 finite `E>0`, `-1<nu<0.5`를 갖는 homogeneous isotropic
materially linear material 하나로 매핑한다.
- `*SHELL SECTION`은 하나의 element set을 resolved material과 positive finite
`thickness>0`를 갖는 centered homogeneous shell layer로 매핑한다. Optional source
integration-point 값은 syntax compatibility로만 보존하며 quadrature, recovery, output,
reference comparison에 영향을 주지 않는다.
- Initial nodal director와 right-handed triad는 instance expansion 뒤 승인된 linear MITC4
deterministic incident-element rule로 파생한다. 이 값들은 model data이며 모든 increment의
fixed initial reference를 정의한다.
- 필수 geometry check는 finite coordinate, valid four-node topology, 모든 Gauss/tying/
center/recovery location의 positive reference Jacobian, non-opposed incident normals,
valid reciprocal bases, valid initial frames를 포함한다.
- `.inp` 단위는 user-consistent unspecified다. HDF5는 `length`, `force`, `force*length`,
`force/length`, `force/length^2`, `1` 같은 unit dimension string만 기록하고 SI를 쓰거나
추론하지 않는다.
## 5. History Data Mapping
### 5.1 Step and Procedure
Nonlinear procedure는 정확히 하나의 source step이 `*STEP, NLGEOM=YES`를 포함하고 그
안에 정확히 하나의 supported `*STATIC` data row가 있을 때만 선택한다. Semantic step
name은 canonical `Step-1`이다. Raw source step name은 provenance로만 보존한다.
Nonlinear `*STATIC` data row의 의미는 다음과 같다.
- `initial_increment`는 fixed positive load-factor increment `h`다.
- `time_period`는 endpoint `1.0`과 정확히 같은 identity여야 한다.
- `minimum_increment`와 `maximum_increment`는 positive finite source value여야 하지만
cutback, growth, retry, stopping, convergence, output cadence에는 사용하지 않는다.
- Intended factor identity는 `1.0`보다 작은 ordinal `j*h` 값들을 만든 뒤, 마지막에 exact
assigned factor `1.0` 하나를 붙여 만든다. Cumulative `lambda += h`, tolerance-based
duplicate endpoint detection, growth, cutback, retry는 금지한다.
- `reference/shellNL/shellNL.inp`의 성공 run에서 expected intended/accepted factor sequence는
`0.1,0.2,...,1.0`이다.
Factor zero는 no-prior-history step-start committed baseline이다. Accepted frame은 committed
increment와 일대일 대응해야 하므로 factor zero는 accepted HDF5 frame이 아니다. Factor zero는
다음 metadata/model dataset으로만 projection한다.
- `factor_zero_is_frame=0`
- `factor_zero_load_factor=0.0`
- `/model/prescribed_displacement_start`와 initial state의 step-start displacement 및
rotation-vector component
- `/model/shell/nodal_frame`과 `/model/shell/nodal_director`의 step-start triad/director
- zero scaled `*CLOAD` contribution과 step-start boundary value
### 5.2 Boundary Conditions
`*BOUNDARY` target resolution은 direct node label 또는 node set을 허용한다. Expanded row는
stable source-node identity와 DOF order `1..6`를 사용한다.
| DOF | component | unit dimension | nonlinear path meaning |
| ---: | --- | --- | --- |
| 1 | `UX` / CSV `U1` | length | factor-one absolute global displacement target |
| 2 | `UY` / CSV `U2` | length | factor-one absolute global displacement target |
| 3 | `UZ` / CSV `U3` | length | factor-one absolute global displacement target |
| 4 | `URX` / CSV `UR1` | dimensionless rotation | factor-one absolute fixed-initial global rotation-vector target |
| 5 | `URY` / CSV `UR2` | dimensionless rotation | factor-one absolute fixed-initial global rotation-vector target |
| 6 | `URZ` / CSV `UR3` | dimensionless rotation | factor-one absolute fixed-initial global rotation-vector target |
Step 앞 row와 sole step 내부 row는 모두 같은 semantic step의 factor-one target으로 매핑한다.
Cross-step propagation은 없다. Load factor `lambda`에서 current constrained value는
`q_start + lambda * (q_target - q_start)`다. Current release에는 prior history가 없으므로
ordinary start value는 승인된 start-state dataset에 명시된 값을 제외하고 zero다.
Constrained Newton correction component는 exact zero다.
### 5.3 Concentrated Loads
`*CLOAD` target resolution은 boundary와 같다. 같은 node/DOF로 resolve되는 여러 row는 source
order로 factor-one global load coefficient에 누적한다. Factor `lambda`에서 magnitude는
`lambda`만 곱한다.
| DOF | source component | unit dimension | nonlinear meaning |
| ---: | --- | --- | --- |
| 1 | `F1` | force | fixed-global dead nodal force |
| 2 | `F2` | force | fixed-global dead nodal force |
| 3 | `F3` | force | fixed-global dead nodal force |
| 4 | `M1` | force*length | fixed-global source nodal moment admitted only through physical director-tangent work |
| 5 | `M2` | force*length | fixed-global source nodal moment admitted only through physical director-tangent work |
| 6 | `M3` | force*length | fixed-global source nodal moment admitted only through physical director-tangent work |
Nonzero aggregated nodal moment `M_src`마다 preprocessing과 모든 entered trial state에서
`abs(dot(d,M_src))/norm(M_src) <= 1e-12`를 denominator clamping 없이 만족해야 한다.
실패하면 `unsupported-drilling-load`다. Source moment vector는 fixed global coordinate에
남으며 FESA는 rejected moment component를 회전, 축소, 변형하거나 numerical drilling channel로
보내지 않는다.
### 5.4 Output Requests
Abaqus output request keyword는 `ignored-with-warning` compatibility syntax로만 수용한다.
이 keyword들은 history output을 켜지 않고, frame cadence를 제어하지 않으며, mandatory FESA
HDF5 dataset을 select, suppress, rename할 수 없다. Trial Newton state는 HDF5 field/history
output이 아니다. Per-iteration evidence는 `<stem>_log.txt`에 diagnostic text로만 기록한다.
## 6. Internal Model Contract
이 section은 semantic field를 정의하며 C++ API를 정의하지 않는다.
- Node record: stable internal node ID, `SourceEntityId`, finite global coordinate,
initial director, initial right-handed triad, source location.
- Element record: stable internal element ID, `SourceEntityId`, preserved source type
`S4` 또는 `S4R`, internal formulation `FESA-MITC4`, ordered four-node connectivity,
resolved section/material identity, source location.
- Set record: case-insensitive set name, source scope, optional source instance,
deterministic expanded source members, stable internal member IDs.
- Material record: case-insensitive material name, finite `E`, finite `nu`, derived `G`,
source location, homogeneous isotropic materially linear identity.
- Section record: source `ELSET`, resolved material, positive thickness, optional ignored
source integration-point field, centered single-layer identity.
- Boundary record: source target, expanded node identities, DOF range, finite factor-one
absolute target values, step-start values, source location, conflict status.
- Load record: source target, expanded node identities, DOF, finite factor-one source
magnitude, deterministic aggregate value, dead fixed-global load identity.
- Step record: raw source name, canonical `Step-1`, `NLGEOM=YES` nonlinear procedure
identity, fixed increment `h`, endpoint `1.0`, unused third/fourth `*STATIC` values,
intended factor sequence, output-request no-op inventory.
- State contract: committed state와 trial state는 alias될 수 없다. 완전하게 수렴한
candidate만 displacement, rotation vector, `Q`, director, load factor, frame identity,
internal/external force, residual/reaction, physical recovery row를 commit한다. Failed
trial, nonconvergence, nonfinite data, solve failure, recovery failure 또는 output failure는
prior committed state와 prior authoritative final result를 보존한다.
- Output request record: keyword, parameter, variable row, source location은 warning
diagnostic용으로만 보존한다. Solver 또는 HDF5 selection effect는 없다.
Source identity와 internal index identity는 diagnostics, HDF5 row order, reference
comparison 전체에서 구분해야 한다. CSV의 element-label order는 solver identity가 아니며
`(instance, source_label)` key를 대체하지 않는다.
## 7. Output HDF5 Schema
### 7.1 Public Output Names, Log and Lifecycle
승인된 public CLI shape는 다음 하나뿐이다.
```powershell
fesa.exe <model.inp>
```
CLI는 input path 해석보다 먼저 argv token을 왼쪽에서 오른쪽으로 scan한다. 어떤 token이든
case-sensitive exact literal substring `--output`을 포함하면, `--output`, `--output=...`,
`--output-path`, prefix/suffix form을 모두 포함해 usage failure다. 이 failure는 input path
resolution, parsing, Analysis construction, derived-result path ownership, HDF5 candidate,
log creation/truncation, output finalization 전 exit code `2`로 끝난다. Stderr에는 ordered
diagnostic 하나만 쓴다.
```text
severity=error code=cli-usage argument_index=<uint64> argument=<escaped argv token> message=literal --output is not supported
```
여러 token이 `--output`을 포함해도 첫 matching token만 보고 위 diagnostic 하나만 낸다.
Literal `--output`에 대한 compatibility alias나 deprecation window는 없다. `--output`을
포함하지 않는 다른 unknown option은 별도 `unrecognized-option` usage diagnostic을 유지할 수
있다.
Input/output lexical identity는 다음 순서로 정의한다.
1. 단일 input path token이 relative path이면 invocation CWD를 lexical base로 붙인다.
2. `.`와 `..` component만 lexically normalize한다. Symlink, junction, short-name,
case-preserving target path는 resolve하지 않는다.
3. Normalized user-addressed final filename의 마지막 extension이 case-insensitive `.inp`가
아니면 input usage failure다.
4. `<stem>`은 마지막 extension 하나만 제거한 basename이다. 앞선 dot과 basename case는
보존한다. 예: `Beam.Model.INP` -> `Beam.Model_results.h5`,
`Beam.Model_log.txt`.
5. Derived outputs는 normalized user-addressed input path의 sibling이다.
- result final: `<input-directory>/<stem>_results.h5`
- log final/live file: `<input-directory>/<stem>_log.txt`
File-vs-directory collision과 same-derived-pair concurrency는 output ownership 문제다.
`<stem>_log.txt`가 directory 또는 truncate 불가능한 non-regular path이면 log create/open/
truncate failure다. `<stem>_results.h5`가 directory이면 HDF5 output collision으로 fail-closed
한다. 같은 derived pair를 목표로 하는 concurrent invocation은 same-directory
implementation-private lock을 nonblocking exclusive ownership으로 먼저 획득해야 한다. Lock
획득 실패 또는 lock path의 directory collision은 exit code `6`의 output-busy failure이며
best-effort fatal stderr diagnostic 하나를 시도하고 log/HDF5를 변경하지 않는다. Lock holder
하나만 log truncate, HDF5 candidate, final replace를 시도한다. Candidate filename은
public contract가 아니지만 반드시 same-directory,
implementation-private, exclusive-create collision-safe여야 하며 실패한 candidate는
authoritative output이 아니다.
HDF5 result lifecycle과 log lifecycle은 의도적으로 비대칭이다.
- `<stem>_log.txt`는 CLI usage validation, lexical output derivation, single-writer lock
획득 뒤 replace/truncate된다. Create/open/truncate failure는 Analysis 전 exit code `6`으로
abort하며, best-effort fatal stderr diagnostic 하나를 시도한다.
- Log write/flush failure는 즉시 abort한다. Solver는 retry, fallback, continue 또는 result
commit을 하지 않는다. Prior authoritative HDF5는 보존하고, 이미 flush된 live-log prefix는
rollback하지 않는다. Failed write 뒤 남은 partial trailing line은 authoritative iteration
record가 아니며 tooling은 LF-terminated complete record만 parsing한다.
- Log close는 successful analysis/recovery 뒤, 그리고 HDF5 candidate open/write/final replace
전 수행한다. Close failure는 result commit을 block하고 exit code `6`으로 끝낸다.
- `<stem>_results.h5`는 sibling candidate가 완전히 write, flush, close, reopen, schema-check된
뒤 atomic move/replace에 성공한 경우에만 authoritative다.
- HDF5 failure는 exit code `6`을 반환하고 가능한 경우 prior valid final을 보존하며 current-run
log를 rollback하지 않는다. HDF5 failure는 log close 성공 뒤 발생하므로 current log는 닫힌
current-run audit으로 남는다.
Newton iteration log는 UTF-8 no BOM, LF-terminated text file이다. Header, trailer, BOM, CRLF는
없다. Entered Newton iteration마다 physical line 하나만 기록하고, 각 line은 fixed field order의
TAB-separated `label=value` record다. Per-iteration stderr duplication은 정확히 0개다. 각
iteration record는 다음 iteration 진입 전 또는 return 전 flush되어야 한다.
Non-Newton procedure 또는 Newton iteration에 진입하기 전 끝난 controlled failure는 iteration
record를 fabricate하지 않는다. 같은 open/truncate/failure lifecycle을 적용하되 successful
non-Newton run의 `<stem>_log.txt` content는 zero-byte empty file이다. Pre-Newton controlled
failure도 entered iteration이 없으면 iteration record가 없는 log file만 남긴다.
고정 field order는 다음과 같다.
| order | label | value contract |
| ---: | --- | --- |
| 1 | `record` | literal `newton-iteration` |
| 2 | `schema` | literal `nsnr-log-v1` |
| 3 | `increment` | entered increment identity, `uint64` |
| 4 | `target_factor` | finite round-trip numeric load factor |
| 5 | `iteration` | entered Newton iteration identity `1..100` |
| 6 | `last_completed_stage` | enum stage completed before outcome; `none` allowed |
| 7 | `failing_stage` | `none` for completed gate records, otherwise failing stage enum |
| 8 | `residual_force_channel` | literal `residual_force` or `not-evaluated(reason)` |
| 9 | `residual_force_numerator_norm` | `||r_f^u||_inf` or `not-evaluated(reason)` |
| 10 | `residual_force_denominator_scale` | `max(||f_int,f^u||_inf,||f_ext,f^u||_inf)` or `not-evaluated(reason)` |
| 11 | `residual_force_branch` | `relative`, `zero-scale`, or `not-evaluated(reason)` |
| 12 | `residual_force_threshold` | `1e-2` for `relative`, `1e-3` for `zero-scale`, or `not-evaluated(reason)` |
| 13 | `residual_force_threshold_unit` | `1`, `force`, or `not-evaluated(reason)` |
| 14 | `residual_force_pass` | `0`, `1`, or `not-evaluated(reason)` |
| 15 | `residual_moment_channel` | literal `residual_moment` or `not-evaluated(reason)` |
| 16 | `residual_moment_numerator_norm` | `||r_f^phi||_inf` or `not-evaluated(reason)` |
| 17 | `residual_moment_denominator_scale` | `max(||f_int,f^phi||_inf,||f_ext,f^phi||_inf)` or `not-evaluated(reason)` |
| 18 | `residual_moment_branch` | `relative`, `zero-scale`, or `not-evaluated(reason)` |
| 19 | `residual_moment_threshold` | `1e-2` for `relative`, `1e-3` for `zero-scale`, or `not-evaluated(reason)` |
| 20 | `residual_moment_threshold_unit` | `1`, `force*length`, or `not-evaluated(reason)` |
| 21 | `residual_moment_pass` | `0`, `1`, or `not-evaluated(reason)` |
| 22 | `correction_translation_channel` | literal `correction_translation` or `not-evaluated(reason)` |
| 23 | `correction_translation_numerator_norm` | `||Delta u_f||_inf` fresh correction or `not-evaluated(reason)` |
| 24 | `correction_translation_denominator_scale` | `||Delta u_inc,f||_inf` from current trial relative to step start or `not-evaluated(reason)` |
| 25 | `correction_translation_branch` | `relative`, `zero-scale`, or `not-evaluated(reason)` |
| 26 | `correction_translation_threshold` | `1e-2` for `relative`, `1e-3` for `zero-scale`, or `not-evaluated(reason)` |
| 27 | `correction_translation_threshold_unit` | `1`, `length`, or `not-evaluated(reason)` |
| 28 | `correction_translation_pass` | `0`, `1`, or `not-evaluated(reason)` |
| 29 | `correction_rotation_channel` | literal `correction_rotation` or `not-evaluated(reason)` |
| 30 | `correction_rotation_numerator_norm` | `||Delta phi_f||_inf` fresh correction or `not-evaluated(reason)` |
| 31 | `correction_rotation_denominator_scale` | `||Delta phi_inc,f||_inf` from current trial relative to step start or `not-evaluated(reason)` |
| 32 | `correction_rotation_branch` | `relative`, `zero-scale`, or `not-evaluated(reason)` |
| 33 | `correction_rotation_threshold` | `1e-2` for `relative`, `1e-3` for `zero-scale`, or `not-evaluated(reason)` |
| 34 | `correction_rotation_threshold_unit` | `1`, `1`, or `not-evaluated(reason)` |
| 35 | `correction_rotation_pass` | `0`, `1`, or `not-evaluated(reason)` |
| 36 | `combined_pass` | logical AND of four pass fields, or `not-evaluated(reason)` |
| 37 | `transition` | `accept`, `update`, `fail`, or `not-evaluated(reason)` |
| 38 | `outcome` | `accepted`, `continue`, `nonconverged`, or `failed` |
| 39 | `diagnostic_code` | `none` or approved diagnostic code |
Completed gate record는 `failing_stage=none`이고 네 channel의 identity, numerator/norm,
denominator/scale, branch, typed threshold, pass를 모두 finite 또는 enum value로 노출한다.
Denominator가 exact zero이면 branch는 `zero-scale`이고 typed threshold는 residual force
`1e-3 force`, residual moment `1e-3 force*length`, correction translation `1e-3 length`,
correction rotation `1e-3 dimensionless`다. Denominator가 nonzero이면 branch는 `relative`이고
threshold는 dimensionless `1e-2`다. Empty free channel은 numerator와 denominator가 exact zero인
`zero-scale` branch로 평가한다.
Early failure record는 entered iteration 하나에 대응한다. 이미 계산된 earlier fields는 실제
finite value를 기록하고, 실패 stage 뒤의 모든 later field는 `not-evaluated(reason)`을 기록한다.
Not-evaluated field에 zero, pass `0`, pass `1`, fabricated denominator 또는 fabricated
threshold를 쓰면 안 된다. `last_completed_stage`와 `failing_stage`는 stage enum을 사용하며
recommended enum은 `iteration-entered`, `trial-state`, `load-boundary`, `residual`,
`tangent`, `factorization`, `correction`, `convergence-gates`, `update`, `recovery`,
`commit`, `log-write`, `log-flush`, `none`이다.
Numeric value는 locale-independent C-locale decimal point를 사용하고 finite IEEE-754 `double`
round-trip이 가능해야 한다. `NaN`, `Inf`, localized comma, thousands separator, raw whitespace는
금지한다. String value는 raw TAB/LF/CR/control byte/backslash를 포함할 수 없으며 `\\`, `\t`,
`\n`, `\r`, `\0`, `\xHH` escape를 사용한다. Record order는 increment, target factor,
iteration 순서로 deterministic해야 한다.
Schema version `1`의 모든 mandatory HDF5 dataset은 contiguous, uncompressed dataset이다.
Chunking, compression filter, extendible dataset, trial-history group은 이 release 계약에 없다.
### 7.2 Metadata and Common Dataset Attribute Rules
`results.h5` schema가 authoritative solver output이다. 실제 final filename은 Section 7.1의
`<stem>_results.h5`다. 모든 string은 UTF-8이다. 모든 physical real dataset은 IEEE-754
float64를 사용한다. Stable ID는 별도 명시가 없으면 unsigned 64-bit integer다.
`/metadata` group의 required attributes는 다음과 같다.
| attribute | required value or meaning |
| --- | --- |
| `schema_version` | `1` |
| `feature_id` | `nonlinear-static-newton-raphson` |
| `solver_version` | executing solver version string |
| `source_input_identity` | lexical normalized user-addressed input path and content identity string; symlink/junction target resolution 없음 |
| `unit_system_label` | `user-consistent-unspecified` |
| `coordinate_convention` | `global-cartesian; shell-local=fixed-initial-reference; positive-thickness=+zeta` |
| `analysis_procedure` | `nonlinear-static-full-newton` |
| `internal_formulation` | `FESA-MITC4-total-lagrangian` |
| `integration_rule` | `2x2x2-gauss; mitc4-edge-midpoint-shear` |
| `step_name` | `Step-1` |
| `frame_indexing` | `accepted-increment-order-zero-based` |
| `factor_zero_is_frame` | `0` |
| `factor_zero_load_factor` | `0.0` |
모든 numeric model/result dataset은 다음 required attributes를 가진다.
- `schema_version=1`
- `component_names`
- `component_unit_dimensions`
- `coordinate_system`
- `location`
Accepted-frame result dataset은 추가로 다음 attributes를 가진다.
- `step_name=Step-1`
- `frame_index=<uint64>`
- `increment_index=<uint64>`
- `load_factor=<float64>`
- `is_factor_one=<0|1>`
### 7.3 Model Datasets
| dataset path | shape and dtype | row identity / fields | required attributes and ordering |
| --- | --- | --- | --- |
| `/model/nodes` | `[node_count]` compound | `internal_node_id:uint64`, `instance_name:utf8`, `source_label:utf8`, `coordinates:float64[3]` | internal ID ascending; `coordinate_system=global-cartesian`, `component_unit_dimensions=length,length,length`, `location=nodal-reference` |
| `/model/elements` | `[element_count]` compound | `internal_element_id:uint64`, `instance_name:utf8`, `source_label:utf8`, `source_element_type:utf8`, `internal_formulation:utf8`, `node_internal_ids:uint64[4]`, `shell_section_internal_id:uint64`, `material_internal_id:uint64` | internal element ID ascending; `formulation=FESA-MITC4-total-lagrangian` |
| `/model/shell/materials` | `[material_count]` compound | `internal_material_id:uint64`, `name:utf8`, `E:float64`, `nu:float64` | declaration order; `component_unit_dimensions=force/length^2,1`, `location=model-material` |
| `/model/shell/sections` | `[section_count]` compound | `internal_section_id:uint64`, `source_file:utf8`, `source_line:uint64`, `source_elset:utf8`, `material_internal_id:uint64`, `thickness:float64` | declaration order; `component_unit_dimensions=length`, `location=model-shell-section`, `layering=centered-single-layer` |
| `/model/shell/nodal_director` | `[node_count,3]` float64 | `/model/nodes` row; `[D1,D2,D3]` | initial director; `coordinate_system=global-cartesian`, `location=nodal-initial-director`, units `1,1,1` |
| `/model/shell/nodal_frame` | `[node_count,3,3]` float64 | `/model/nodes` row; axis row `[A,B,D]`, global component column `[X,Y,Z]` | initial right-handed triad; `coordinate_system=global-cartesian`, `location=nodal-initial-frame`, units `1,1,1` |
| `/model/nodal_constraint_mask` | `[node_count,6]` uint8 | `/model/nodes` row; DOF `[UX,UY,UZ,URX,URY,URZ]` | `0=free`, `1=constrained`; constrained reaction comparison identity의 authority |
| `/model/prescribed_displacement_start` | `[node_count,6]` float64 | same row/DOF order | factor-zero start values; units `[length x3,1 x3]`, `load_factor=0.0` |
| `/model/prescribed_displacement_target` | `[node_count,6]` float64 | same row/DOF order | factor-one absolute target values; units `[length x3,1 x3]`, `load_factor=1.0` |
| `/model/shell/midsurface_locations` | `[4,2]` float64 | location rows `GP1..GP4`; columns `[XI,ETA]` | `coordinate_system=shell-natural`; `(-g,-g),(+g,-g),(+g,+g),(-g,+g)`, `g=1/sqrt(3)` |
| `/model/shell/section_positions` | `[3]` float64 | rows `[BOTTOM,MIDDLE,TOP]`; values `[-1,0,+1]` | `coordinate_system=shell-natural`; physical `z=t*zeta/2`; Abaqus section-point identity가 아님 |
### 7.4 Accepted Frame Table
Successful nonlinear run 뒤 `/steps/Step-1/accepted_frames`는 mandatory다.
| path | shape and dtype | fields | required meaning |
| --- | --- | --- | --- |
| `/steps/Step-1/accepted_frames` | `[frame_count]` compound | `frame_index:uint64`, `increment_index:uint64`, `load_factor:float64`, `iteration_count:uint64`, `is_factor_one:uint8` | committed increment마다 한 row; `frame_index`는 `<frame>` group name과 같음; load factor는 strictly increasing; 마지막 row는 `load_factor=1.0`, `is_factor_one=1` |
`frame_count`는 committed increment 수이며 successful run에서는 하나 이상이다. Factor-one
row는 정확히 하나다. Factor zero는 이 dataset에 row를 갖지 않고 `/frames/0` 특별 의미도
갖지 않는다.
### 7.5 Accepted Frame Result Datasets
`/steps/Step-1/accepted_frames.frame_index = <frame>`마다 아래 dataset들이
`/steps/Step-1/frames/<frame>/` 아래 mandatory다.
| quantity | exact dataset path | shape | row identity and component order | units / coordinates / location |
| --- | --- | --- | --- | --- |
| committed displacement and rotation vector | `/steps/Step-1/frames/<frame>/nodal/displacement` | `[node_count,6]` float64 | `/model/nodes` row; `[UX,UY,UZ,URX,URY,URZ]` | `[length,length,length,1,1,1]`; global Cartesian translations and fixed-initial global rotation-vector components; nodal |
| committed triad | `/steps/Step-1/frames/<frame>/nodal/triad` | `[node_count,3,3]` float64 | node row; axis row `[A,B,D]`, global component column `[X,Y,Z]` | dimensionless; global Cartesian; committed `Q`; director는 row `D` |
| committed director | `/steps/Step-1/frames/<frame>/nodal/director` | `[node_count,3]` float64 | node row; `[D1,D2,D3]` | dimensionless; global Cartesian; triad axis `D`와 같아야 함 |
| generalized internal force | `/steps/Step-1/frames/<frame>/nodal/generalized_internal_force` | `[node_count,6]` float64 | node row; `[FI1,FI2,FI3,MI_PHI1,MI_PHI2,MI_PHI3]` | `[force x3,force*length x3]`; work-conjugate to `[u,phi]`; nodal |
| generalized external force | `/steps/Step-1/frames/<frame>/nodal/generalized_external_force` | `[node_count,6]` float64 | node row; `[FE1,FE2,FE3,ME_PHI1,ME_PHI2,ME_PHI3]` | `[force x3,force*length x3]`; work-conjugate to `[u,phi]`; approved physical moment projection 후 fixed-global dead loads; nodal |
| generalized residual | `/steps/Step-1/frames/<frame>/nodal/generalized_residual` | `[node_count,6]` float64 | node row; `[RU1,RU2,RU3,RPHI1,RPHI2,RPHI3]` | `[force x3,force*length x3]`; nonlinear solution coordinate의 full assembled `f_int-f_ext`; nodal |
| reaction / physical residual projection | `/steps/Step-1/frames/<frame>/nodal/reaction` | `[node_count,6]` float64 | node row; `[RF1,RF2,RF3,RM1,RM2,RM3]` | `[force x3,force*length x3]`; global; constrained entry는 physical reaction, free entry는 same-state equilibrium evidence; rotational columns는 `J_l(phi)^(-T)` spatial moment conversion |
| shell local frame | `/steps/Step-1/frames/<frame>/element/shell/local_frame` | `[element_count,4,3,3]` float64 | element row, midsurface location row `GP1..GP4`, axis row `[E1,E2,E3]`, global component column `[X,Y,Z]` | dimensionless; physical recovery용 fixed-initial shell local frame; rotating Abaqus output frame이 아님 |
| generalized strain | `/steps/Step-1/frames/<frame>/element/shell/generalized_strain` | `[element_count,4,8]` float64 | element row, `GP1..GP4`; `[E11,E22,G12,K11,K22,K12,G13,G23]` | `[1,1,1,1/length,1/length,1/length,1,1]`; fixed-reference shell local; midsurface |
| section resultant | `/steps/Step-1/frames/<frame>/element/shell/section_resultant` | `[element_count,4,8]` float64 | element row, `GP1..GP4`; `[N11,N22,N12,M11,M22,M12,Q13,Q23]` | `[force/length x3,force x3,force/length x2]`; fixed-reference shell local; midsurface |
| in-plane stress | `/steps/Step-1/frames/<frame>/element/shell/stress` | `[element_count,4,3,3]` float64 | element row, `GP1..GP4`, section position `[BOTTOM,MIDDLE,TOP]`, component `[S11,S22,S12]` | `force/length^2`; fixed-reference shell local; direct bottom/middle/top evaluation |
| physical strain energy | `/steps/Step-1/frames/<frame>/global/energy` | `[1]` float64 | `[PHYSICAL_STRAIN_ENERGY]` | `force*length`; deterministic element reduction; numerical drilling stabilization 제외 |
| global equilibrium | `/steps/Step-1/frames/<frame>/global/equilibrium` | `[6]` float64 | `[FORCE_1,FORCE_2,FORCE_3,MOMENT_1,MOMENT_2,MOMENT_3]` | `[force x3,force*length x3]`; global Cartesian; moment about global origin `[0,0,0]`, current force arms와 spatial physical nodal moments 사용 |
Trial Newton state, iteration history, line search, cutback attempt, damping, automatic
stabilization, numerical drilling stress, drilling energy ratio, `S33`, `S13`, `S23`,
nodal stress extrapolation, element-corner stress, averaged stress, Abaqus integration-point
number에 대한 HDF5 dataset은 만들지 않는다.
### 7.6 Diagnostics Dataset
`/diagnostics`는 mandatory이며 row가 0개일 수 있다.
| path | shape and dtype | fields | required meaning |
| --- | --- | --- | --- |
| `/diagnostics` | `[diagnostic_count]` compound | `severity:utf8`, `code:utf8`, `file:utf8`, `line:uint64`, `keyword:utf8`, `entity_identity:utf8`, `message:utf8` | CLI/input/model/solver/output deterministic diagnostics; ignored keyword warning도 success file에 보존 |
Diagnostic order는 source file declaration order, 1-based line, stable entity identity,
diagnostic code, discovery order를 순서대로 사용한다. Source가 없는 CLI/solver/output
diagnostic은 explicit empty source field를 사용한다.
### 7.7 Output Failure and Atomic Finalization
Writer는 log close 성공 뒤에만 final file과 같은 directory에 implementation-private temporary
HDF5 candidate를 만든다. Candidate는 metadata, model datasets, accepted-frame table, 모든
accepted-frame dataset, diagnostics를 모두 쓰고, shape, attribute, finite value, source
identity, row order를 검증한다. Checked HDF5 close와 read-only reopen/self-check가 성공한
뒤에만 final `<stem>_results.h5`를 replace/create한다. 실패한 candidate는 제거하거나
non-authoritative implementation-private artifact로만 남긴다. Controlled failure는 incomplete
final result를 노출하면 안 된다. HDF5 failure는 이미 닫힌 current-run log를 rollback하지 않는다.
## 8. FESA HDF5 to Reference CSV Comparison Mapping
Comparison tooling은 FESA `results.h5` schema와 exact read-only Abaqus CSV artifact만 읽는다.
CSV는 FESA output이 아니다. HDF5에서 추출한 deterministic CSV view는 debugging/reporting
보조물로만 둘 수 있다.
### 8.1 Declared Cases and Artifacts
| case id | role | exact path | comparison disposition |
| --- | --- | --- | --- |
| `shellnl-s4-final` | nonlinear input | `reference/shellNL/shellNL.inp` | required source input |
| `shellnl-s4-final` | displacement CSV | `reference/shellNL/shellNL displacements.csv` | required comparison |
| `shellnl-s4-final` | reaction CSV | `reference/shellNL/shellNL reactions.csv` | constrained nodes/components only required comparison |
| `shellnl-s4-final` | stress CSV | `reference/shellNL/shellNL stresses.csv` | optional read-only inspection/order evidence only |
| `shell-s4-linear-limit` | linear control input | `reference/shell/shell.inp` | existing linear MITC4 contract의 required regression input |
| `shell-s4-linear-limit` | displacement CSV | `reference/shell/shell displacements.csv` | required regression comparison |
| `shell-s4-linear-limit` | reaction CSV | `reference/shell/shell reactions.csv` | optional read-only inspection only |
| `shell-s4-linear-limit` | stress CSV | `reference/shell/shell stresses.csv` | optional read-only inspection/order evidence only |
Reference artifact file은 workflow에서 rename, rewrite, normalize, zero-clamp, repair,
regenerate하지 않는다.
### 8.2 Accepted-State and Frame Mapping
- `shellnl-s4-final`은 accepted factor-one HDF5 frame만 비교한다. 해당 frame은
`/steps/Step-1/accepted_frames`에서 `is_factor_one=1`이고 `load_factor=1.0`인 unique row다.
그 `frame_index`가 `/steps/Step-1/frames/<frame>`를 선택한다.
- Required `shellNL` CSV row는 exact `Frame` value
`Increment 10: Step Time = 1.000`만 가져야 하며, 이는 accepted factor-one state로
논리 매핑한다. Required row에 다른 `Frame` 값이 있으면 schema mismatch다.
- `shell-s4-linear-limit` CSV에는 `Frame` column이 없으며
`docs/linear-static-mitc4-shell/io.md`의 existing linear MITC4 final frame
`/steps/Step-1/frames/0`에 매핑한다.
- Trial Newton state, iteration log line, optional stress inventory row는 reference row가
아니다.
### 8.3 Nodal Displacement Projection
Required logical key는 다음과 같다.
```text
(case_id, accepted_state, canonical_instance_name, source_node_label, component)
```
두 case 모두 instance `PART-1-1`에서 node label `1..49`가 정확히 한 번씩 필요하다.
Instance matching은 case-insensitive로 수행하되 report에는 raw spelling을 보존한다.
| CSV column | comparison component | nonlinear HDF5 source | linear regression HDF5 source |
| --- | --- | --- | --- |
| `U-U1` | `U1` | `nodal/displacement` column `UX` | `nodal/displacement` column `UX` |
| `U-U2` | `U2` | `nodal/displacement` column `UY` | `nodal/displacement` column `UY` |
| `U-U3` | `U3` | `nodal/displacement` column `UZ` | `nodal/displacement` column `UZ` |
| `UR-UR1` | `UR1` | `nodal/displacement` column `URX` | `nodal/displacement` column `URX` |
| `UR-UR2` | `UR2` | `nodal/displacement` column `URY` | `nodal/displacement` column `URY` |
| `UR-UR3` | `UR3` | `nodal/displacement` column `URZ` | `nodal/displacement` column `URZ` |
`U1/U2/U3`는 blocking이다. `UR1/UR2/UR3`는 두 case 모두 warning-only다. UR warning
exceedance는 blocking verdict를 바꾸지 않는다.
### 8.4 Nonlinear Constrained Reaction Projection
Reaction comparison은 `shellnl-s4-final`에만 적용하며 input boundary mask의 constrained node
중 아래 24개 node에만 적용한다.
```text
1,3,4,5,6,7,8,9,14,15,16,17,22,23,24,25,26,27,28,29,30,31,32,33
```
승인 input에서 이 24개 node는 여섯 global DOF가 모두 constrained다. Comparator는 required
HDF5 reaction row eligibility를 CSV zero value가 아니라 `/model/nodal_constraint_mask`와
source node identity에서 도출한다.
| CSV columns | logical family | HDF5 source | disposition |
| --- | --- | --- | --- |
| `RF-RF1`, `RF-RF2` | `nonlinear.reaction_inplane_force` | factor-one `/nodal/reaction` columns `RF1,RF2` | blocking |
| `RF-RF3` | `nonlinear.reaction_transverse_force` | factor-one `/nodal/reaction` column `RF3` | blocking |
| `RM-RM1`, `RM-RM2` | `nonlinear.reaction_physical_moment` | factor-one `/nodal/reaction` columns `RM1,RM2`; `J_l(phi)^(-T)` 변환 뒤 spatial physical moment | blocking |
| `RM-RM3` | excluded | comparison projection 없음 | blocking 및 warning-only family에서 제외 |
Raw generalized rotation-coordinate residual column은 Abaqus `RM` CSV column과 직접 비교하지
않는다.
### 8.5 Comparison Families
External tolerance source는 정확히 `docs/TOLERANCE.md`다. 별도 absolute floor, `max(1,S)`
clamp, row averaging, source-order matching, component calibration, zero clamp는 허용하지
않는다.
| family id | case | components | required row count | units / coordinates | disposition |
| --- | --- | --- | ---: | --- | --- |
| `linear.translation` | `shell-s4-linear-limit` | `U1,U2,U3` on nodes `1..49` | 147 | length / global | blocking regression |
| `linear.rotation` | `shell-s4-linear-limit` | `UR1,UR2,UR3` on nodes `1..49` | 147 | dimensionless / fixed-initial global | warning-only |
| `nonlinear.translation` | `shellnl-s4-final` | `U1,U2,U3` on nodes `1..49` | 147 | length / global | blocking |
| `nonlinear.rotation` | `shellnl-s4-final` | `UR1,UR2,UR3` on nodes `1..49` | 147 | dimensionless / fixed-initial global | warning-only |
| `nonlinear.reaction_inplane_force` | `shellnl-s4-final` | `RF1,RF2` on constrained nodes | 48 | force / fixed-initial global plane | blocking |
| `nonlinear.reaction_transverse_force` | `shellnl-s4-final` | `RF3` on constrained nodes | 24 | force / fixed-initial global transverse | blocking |
| `nonlinear.reaction_physical_moment` | `shellnl-s4-final` | `RM1,RM2` on constrained nodes | 48 | force*length / global spatial | blocking |
Reference-model read-only scale audit value는 다음과 같다.
| family id | `S=max(abs(reference))` | `0.01*S` |
| --- | ---: | ---: |
| `linear.translation` | `2.37408203e-5` | `2.37408203e-7` |
| `linear.rotation` | `7.60725743e-6` | `7.60725743e-8` |
| `nonlinear.translation` | `2.37408203e-5` | `2.37408203e-7` |
| `nonlinear.rotation` | `7.60725743e-6` | `7.60725743e-8` |
| `nonlinear.reaction_inplane_force` | `1.91663182` | `1.91663182e-2` |
| `nonlinear.reaction_transverse_force` | `1.17769805e4` | `1.17769805e2` |
| `nonlinear.reaction_physical_moment` | `1.95418418e4` | `1.95418418e2` |
### 8.6 Row Prechecks
아래 조건 중 하나라도 거짓이면 comparator는 tolerance 계산 전에 실패한다.
1. Exact declared input path와 required CSV path가 존재하고 readable이다.
2. Reference CSV header는 surrounding whitespace trim 뒤 필요한 column을 가진다.
3. `shellnl-s4-final` required row는 exact approved `Frame` value만 포함한다.
4. HDF5 metadata, model rows, accepted-frame table, factor-one frame, required result dataset이
문서화된 shape, component name, finite value를 가진다.
5. Wide CSV row는 이 문서의 component mapping으로 component row로 expand한다.
6. Required source wide key와 expanded component key는 unique하다. Duplicate reference 또는
HDF5 key는 실패다.
7. 각 declared family에서 FESA와 reference projected key set은 정확히 같아야 한다. Missing row와
extra row는 모두 실패다.
8. 모든 required numeric value는 finite다. Nonfinite HDF5 또는 CSV value는 tolerance 전 실패다.
9. `shellNL` reaction row는 constrained mask와 exact 24-node list에서 선택한다. Free-node CSV
row는 inventory only이며 zero reaction target으로 해석하지 않는다.
10. Required row를 omit, synthesize, average, substitute identity로 sort, normalize, zero-clamp,
repair하지 않는다.
### 8.7 Stress CSV Disposition
Optional stress CSV identity는 다음과 같다.
```text
(case_id, accepted_state, instance, element_label,
element_corner_node_label, section_surface, component)
```
현재 stress CSV는 element-corner node row와 `SPOS/SNEG` section surface에서 `S-S11`,
`S-S22`, `S-S33`, `S-S12`를 포함하며, 저장된 ascending element-label block `1..36` 순서를
갖는다. FESA HDF5는 `GP1..GP4`와 `BOTTOM/MIDDLE/TOP`에서 direct `[S11,S22,S12]`만 emit한다.
따라서 두 case의 stress CSV는 optional read-only inspection 및 order evidence only다. HDF5
comparison projection, `S33` synthesis, nodal extrapolation, corner averaging, Gauss-to-corner
matching, element-label-order identity는 없다.
## 9. Validation Rules
| validation area | required pass condition | failure class |
| --- | --- | --- |
| CLI usage | input path 정확히 하나; 어떤 argv token에도 exact literal substring `--output` 없음; matching 시 path resolution/parsing/Analysis/log/HDF5 전 `cli-usage` stderr diagnostic 정확히 1개 | usage, exit `2` |
| keyword inventory | keyword가 supported, explicit diagnostic의 unsupported, 또는 exact ignored-with-warning allowlist 중 하나 | input, exit `3` |
| syntax | ASCII keyword/data grammar, comma fields, finite numeric tokens, continuation/include 없음 | input, exit `3` |
| nesting/cardinality | part/assembly/instance/step이 닫힘; nonlinear procedure는 정확히 하나의 `NLGEOM=YES` step | input, exit `3` |
| source identity | scope 내 duplicate name/label 없음; 모든 reference resolved; instance identity unique | input, exit `3` |
| set expansion | explicit/generated set이 deterministic expand되고 하나의 supported scope/instance에 머묾 | input, exit `3` |
| shell element | only `S4/S4R`; 네 개의 distinct resolved nodes; mixed element model 없음; source type metadata 보존 | input/model, exit `3` 또는 `4` |
| material and section | single isotropic elastic material, centered homogeneous positive-thickness shell section, element마다 정확히 하나의 assignment | input/model, exit `3` 또는 `4` |
| geometry and coordinates | finite global coordinates, positive reference/current validity checks, required location마다 valid directors/triads/branches | model 또는 solver trial failure, exit `4` 또는 `5` |
| boundary | DOF `1..6`, resolved finite targets, factor-one absolute meaning, conflicting expanded value 없음 | input, exit `3` |
| load | resolved finite `CLOAD`, stable aggregation, fixed-global dead path, unsupported `DLOAD`/follower/distributed load 없음 | input/model, exit `3` 또는 `4` |
| aggregate moment | exact-zero case 또는 preprocessing 및 모든 entered trial에서 `rho_M<=1e-12` | model/solver, exit `4` 또는 `5` |
| nonlinear static data | 네 positive finite values, endpoint `1.0`, fixed increment sequence with final exact factor one | input, exit `3` |
| Newton iteration | iteration identity `1..100`; iteration `100` acceptance 가능; iteration `101` 없음; line search/cutback/retry/fallback 없음 | solver, exit `5` |
| convergence channels | residual force, residual moment, correction translation, correction rotation이 모두 inclusive `<=` rule 또는 typed zero-scale threshold 통과 | solver, exit `5` |
| nonfinite data | required residual, tangent, correction, state, load, recovery, output value가 acceptance 전 finite | solver/output, exit `5` 또는 `6` |
| commit/rollback | complete converged candidate만 commit; failure는 prior committed state와 prior authoritative final HDF5 보존 | solver/output, exit `5` 또는 `6` |
| HDF5 schema | exact paths, shapes, attributes, schema version, row identities, finite values, accepted-frame table, diagnostics; final replace는 log close success 뒤에만 허용 | output, exit `6` |
| log | UTF-8 no BOM, LF, TAB-separated fixed `label=value` schema; entered Newton iteration마다 record 하나; no per-iteration stderr duplication; no-Newton procedure는 zero-byte empty log; open/write/flush/close fail-closed | output, exit `6` |
| reference rows | exact required artifacts, headers, row keys, component keys, finite values, factor-one frame mapping | reference precheck |
| tolerance | exact `docs/TOLERANCE.md` family-scale row/RMS policy; blocking/warning disposition 보존 | reference verification |
Downstream test가 다뤄야 하는 approved diagnostic code는 다음을 포함한다.
| code | class | meaning |
| --- | --- | --- |
| `cli-usage` | usage/2 | argv token이 exact literal substring `--output`을 포함하며 pre-input/pre-log/pre-output failure 하나를 stderr에 기록 |
| `unrecognized-option` | usage/2 | `--output` substring을 포함하지 않는 다른 unsupported option |
| `malformed-keyword` | input/3 | keyword 또는 parameter grammar invalid |
| `invalid-keyword-location` | input/3 | keyword가 approved scope 밖에 위치 |
| `invalid-keyword-parameter` | input/3 | parameter missing, duplicate, empty 또는 subset 밖 |
| `unsupported-keyword` | input/3 | `*INCLUDE` 포함 approved subset 밖 keyword |
| `unsupported-distributed-load` | input/3 | `*DLOAD`, pressure, gravity, body, edge, follower load 요청 |
| `duplicate-entity` | input/3 | source identity가 scope 안에서 duplicate |
| `unresolved-reference` | input/3 | connectivity, set, instance, section, material, load, boundary target dangling |
| `unsupported-element-formulation` | input/3 | shell feature에서 source element type이 `S4` 또는 `S4R`가 아님 |
| `unsupported-mixed-element-model` | input/3 | shell과 non-shell product semantics 혼합 |
| `invalid-shell-connectivity` | input/3 | shell connectivity arity, duplicate node 또는 resolved node identity invalid |
| `unsupported-shell-section-option` | input/3 | composite/layer/offset/orientation/variable-thickness section 의미 등장 |
| `invalid-shell-material` | model/4 | material value가 finite `E,nu` bound 위반 |
| `invalid-shell-thickness` | model/4 | shell thickness nonfinite 또는 nonpositive |
| `invalid-shell-geometry` | model/4 | shell geometry, reference Jacobian 또는 topology invalid |
| `opposed-incident-normal` | model/4 | averaging 전 incident normal pair가 nonpositive |
| `invalid-shell-director` | model/4 | nodal/interpolated director, triad 또는 branch validity 실패 |
| `invalid-shell-jacobian` | model/4 | required Gauss/tying/center/recovery point의 basis/Jacobian invalid |
| `unsupported-drilling-load` | model/4 또는 solver/5 | aggregate nodal moment가 current-director admissibility 위반 |
| `invalid-nonlinear-static-data` | input/3 | `*STATIC` row arity, finite/positive check 또는 endpoint-one identity 실패 |
| `unsupported-analysis-procedure` | input/3 | supported nonlinear static source step으로 매핑되지 않음 |
| `nonfinite-newton-data` | solver/5 | required residual, tangent, correction 또는 trial state nonfinite |
| `tangent-factorization-failed` | solver/5 | entered iteration의 fresh tangent factorization 실패 |
| `correction-solve-failed` | solver/5 | fresh Newton correction solve 실패 |
| `nonlinear-nonconvergence` | solver/5 | iteration `100` 완료 후 네 convergence channel이 모두 통과하지 않음 |
| `invalid-accepted-state` | solver/5 | converged candidate recovery/state identity가 commit 전 실패 |
| `log-output-failure` | output/6 | required live log create/open/truncate, write, flush 또는 close 실패 |
| `output-busy` | output/6 | same derived pair single-writer lock을 획득하지 못했거나 lock path collision 발생 |
| `hdf5-output-failure` | output/6 | candidate HDF5 write, schema validation 또는 atomic finalization 실패 |
## 10. Open Issues and Downstream Handoff
Open issues blocking Implementation Planning: 없음.
Downstream handoff to Implementation Planning Agent through Coordinator:
- Public CLI/output naming migration을 보존한다: `fesa.exe <model.inp>`,
lexical sibling `<stem>_results.h5`, `<stem>_log.txt`, 그리고 exact literal substring
`--output`을 포함하는 모든 argv token의 pre-input/pre-log/pre-output exit `2`와 정확히
하나의 `cli-usage` stderr diagnostic.
- Supported/unsupported/ignored keyword row와 nonlinear `*STATIC` rule을 parser
acceptance/rejection test로 변환한다.
- Stored reference grammar인 `*Output, field, variable=PRESELECT`와
`*Output, history, variable=PRESELECT`를 duplicate/extra parameter 없이
`ignored-with-warning`으로 수용하고, output request가 FESA output을 바꾸지 못함을 test한다.
- `NLGEOM=YES`가 nonlinear procedure를 선택하고 `shell` `NLGEOM=NO` case가 기존 linear
MITC4 contract의 regression으로 남는지 test한다.
- HDF5 schema version `1`을 위 accepted-frame schema 그대로 구현한다. Factor-zero non-frame
handling, unique factor-one frame selection, triad/director projection, no
compression/chunking, no trial-state HDF5 history를 포함한다.
- 비대칭 lifecycle을 보존한다. Log는 usage validation, lexical path derivation, single-writer
lock 뒤 live current-run audit이고, log create/open/truncate는 Analysis 전 abort, write/flush는
즉시 abort, close failure는 HDF5 commit을 block한다. HDF5 final은 log close와 candidate
self-check 성공 뒤에만 replace하며 failure는 prior valid final과 current log를 손상하지 않는다.
- Newton log parser/schema test는 UTF-8 no BOM, LF, physical TAB-separated fixed
`label=value` field order, finite round-trip numerics, escaping, completed-gate four-channel
metrics, early-failure `not-evaluated(reason)`, no-Newton zero-byte log, zero per-iteration
stderr duplication, flush-before-next/return을 포함한다.
- Exact CSV paths, trimmed headers, exact `shellNL` `Frame` value, source node/component
identity, constrained reaction mask, missing/extra/duplicate rows, nonfinite values를
tolerance 전에 precheck한다.
- Declared family에는 `docs/TOLERANCE.md`만 적용한다. `U`는 blocking, `UR`은 warning-only,
`RF1/RF2`, `RF3`, physical spatial `RM1/RM2`는 blocking으로 유지하고 `RM3`와 모든 stress
CSV value는 제외한다.
- Optional stress CSV는 read-only inventory/order evidence only로 유지한다. Nodal stress
extrapolation, corner averaging, `S33` synthesis, element-label-order matching을 추가하지
않는다.
- Final HDF5 projection, parser diagnostics, schema tests, reference comparison tests,
log lifecycle tests는 Coordinator를 통해 전달한다. 이 문서만으로 parser, C++ API,
reference artifact, comparison-result, physics, release 변경을 승인하지 않는다.
@@ -0,0 +1,188 @@
# Nonlinear Static Newton-Raphson 수치 검토
## 1. Metadata and source formulation
- feature_id: `nonlinear-static-newton-raphson`
- source_formulation: `docs/nonlinear-static-newton-raphson/formulation.md`
- source_formulation_status: `ready-for-numerical-review`
- source_formulation_sha256: `DFA629888041D5762FD0DF4271353464A692B325DC0C821A8D8689688C1EAFD0`
- source_requirements: `docs/nonlinear-static-newton-raphson/requirements.md`
- source_requirements_sha256: `910E351F3F90FFA42F07D15206B55E62C05EAE821E250424430148337506EBF2`
- source_research: `docs/nonlinear-static-newton-raphson/research.md`
- source_research_sha256: `C920A6B02381230D1DB419D73FE767D611B36720D27D6410507BA88C3CA28EEE`
- repository_policy: `AGENTS.md`, `docs/SOLVER_AGENT_DESIGN.md`, `docs/TOLERANCE.md`
- related_linear_contracts: `docs/linear-static-mitc4-shell/numerical-review.md`,
`docs/linear-static-mitc4-shell/reference-model.md`
- status: `pass-for-io-definition`
- owner_agent: `numerical-review-agent`
- date: `2026-08-23`
이 검토는 정식화를 수학 및 수치 알고리즘 계약으로만 검토했다. C++ API, HDF5 schema,
implementation plan, reference solver 실행, reference artifact 생성/수정은 수행하지 않았다.
## 2. Review Verdict
- verdict: `pass-for-io-definition`
- reason: 승인 정식화는 fixed-initial-reference Total Lagrangian MITC4, finite rotation
state, nonlinear `24 -> 20` map, objective drilling, fixed-global load work,
same-trial residual/tangent, Full Newton convergence, recovery와 state commit/rollback
의미를 구현 가능한 수치 계약으로 닫고 있다. 차원, 부호, DOF 순서, 적분, reaction
의미 또는 reference identity와 충돌하는 blocking defect는 확인되지 않았다.
- reference readiness: `reference/shellNL` 및 `reference/shell`의 선언 파일과 CSV는
읽을 수 있고 row identity/precheck/tolerance 계약을 정의할 수 있다.
- boundary: 이 verdict는 I/O Definition 진입 허가이며 implementation, reference comparison
pass, physics evaluation 또는 release readiness 승인이 아니다.
`reference/shellNL`은 `nlgeom=YES`와 factor-one final frame을 갖는 저장 reference로 사용할 수
있지만, 주요 `U3`와 stress 값은 선형 `reference/shell`과 거의 같다. 관찰된 nonlinear 신호는
주로 약한 in-plane coupling이다(`RF1/RF2` 최대 약 `1.9166`, `U1/U2` 최대 약
`1.29e-11`). 따라서 이 CSV 세트만으로 finite-rotation objectivity, exact tangent,
rollback 또는 큰 변위 benchmark를 통과했다고 판단하지 않는다. 해당 항목은 아래의
blocking internal tests로 분리한다.
## 3. Critical Findings
### Confirmed defects
없음. Formulation Agent 또는 Research Agent로 즉시 되돌릴 confirmed numerical defect는 없다.
### Numerical risks requiring downstream evidence
- `shellNL`의 stored reference는 geometric nonlinearity가 켜진 최종 상태 비교에는 충분하지만
response amplitude가 작아 finite-rotation/tangent/objectivity 검증을 대신하지 못한다.
- Abaqus stress CSV는 `(instance, element label, element-corner node label,
section point, component)` identity로 완전하지만 FESA의 approved Gauss-location direct
bottom/middle/top recovery와 location이 다르다. Current stored order는 element label
`1..36` ascending block이며 이를 바꾸지 않는다. Nodal extrapolation/averaging을 만들지
않고 stress CSV는 comparison family에서 제외한다.
- External `UR` comparison은 기존 MITC4 정책에 따라 `warning-only`다. Rotation/director
correctness는 `Q`, `d`, branch, objectivity invariant tests에서 blocking으로 확인해야 한다.
### Open questions
현재 I/O Definition 진입을 막는 open question은 없다. Large-response public benchmark,
MMS, broader locking/distortion characterization은 유용하지만 승인된 Stage 4 pass 조건은 아니다.
## 4. Numerical Risk Assessment
| risk label | assessment | required control / downstream evidence |
| --- | --- | --- |
| `rigid_body_modes` | 물리/internal/drill energy가 finite rigid motion에서 objective해야 하며 pure drill만 regularized 되어야 한다. | finite rigid translation/rotation superposition에서 strain, stress, physical energy, drill gamma, residual을 blocking invariant로 확인한다. |
| `patch_test` | Green-Lagrange direct strain과 MITC tied shear가 같은 trial geometry와 같은 first/second variation을 써야 한다. | membrane, bending, twist, transverse-shear patch를 linear limit와 finite valid trial perturbation에서 각각 확인한다. |
| `symmetry` | applied nodal moment가 없으면 physical/drill tangent는 exact arithmetic에서 symmetric이다. Fixed-spatial moment work tangent는 일반적으로 nonsymmetric이다. | no-moment case만 scaled symmetry check 대상으로 두고, moment case를 임의 symmetrization하지 않는다. |
| `positive_definiteness` | nonlinear tangent는 load state, compression, near-buckling에서 indefinite일 수 있다. Positive definiteness는 일반 gate가 아니다. | stress-free constrained linear limit의 nonsingular solve와 singular negative case를 분리하고, factorization failure를 숨기지 않는다. |
| `hourglass` | S4/S4R 모두 `2 x 2 x 2` full integration이므로 one-point reduced hourglass path는 승인 범위 밖이다. | source type으로 reduced/selective integration 또는 hourglass stabilization을 선택하지 않는 unit/integration test가 필요하다. |
| `shear_locking` | MITC shear tying은 transverse-shear locking을 완화하지만 모든 thin-shell mesh에서 locking-free를 보장하지 않는다. | patch/reference evidence를 blocking으로 두고 broader thin/thick convergence는 nonblocking characterization으로 둔다. |
| `volumetric_locking` | approved plane-stress shell, St. Venant-Kirchhoff-type material restriction에서는 `N/A`다. | 3-D incompressible material 또는 `nu >= 0.5` 의미로 확장하지 않는다. |
| `membrane_locking` | original-style MITC4는 curved/distorted nonlinear meshes에서 membrane locking 위험이 남는다. | known limitation으로 기록한다. MITC4+ 성능 또는 Abaqus S4/S4R internal equivalence를 주장하지 않는다. |
| `distortion` | positive Jacobian이라도 severe distortion/warpage는 conditioning과 stress accuracy를 악화할 수 있다. | 모든 Gauss/tying/center/recovery location의 finite, positive predicate를 fail-closed로 적용한다. 추가 quality cutoff는 요구하지 않는다. |
| `singular_jacobian` | `J0 <= 0`, `j <= 0`, invalid reciprocal basis, invalid polar stretch는 residual/tangent를 무효화한다. | failed location을 omit/average/clamp/repair하지 않고 model/trial failure로 처리한다. |
| `conditioning` | thin shells, small fixed drill scale, near-mechanism constraints는 Kff conditioning을 악화시킬 수 있다. | scaled matrix diagnostics만 사용하고 solver regularization/fallback으로 singularity를 숨기지 않는다. |
| `convergence` | Full Newton은 same-trial consistent tangent에 의존한다. No line search/cutback이므로 difficult step은 deterministic nonconvergence가 될 수 있다. | NSNR-069/070 four-channel gates, iteration `1..100`, nonfinite rejection, no hidden retry를 integration tests로 고정한다. |
## 5. Consistency Checks
| check | result | evidence |
| --- | --- | --- |
| units and dimensions | `pass` | Translation/force, rotation/moment, stress/resultant dimensions are separated. Convergence channels keep force, force-length, length and dimensionless rotation separate. |
| signs and residual convention | `pass` | Global residual is `f_int - f_ext`; constrained full residual is reaction and free residual is equilibrium evidence. Fixed-global dead force has no configuration derivative. |
| DOF ordering and free/constrained assumptions | `pass` | Per-node global order is `[UX, UY, UZ, URX, URY, URZ]`; Newton solve uses stable free coordinates with `Delta q_c = 0`. Valid `0 x 0` free system is trivial success. |
| coordinate transforms | `pass` | `Q=Exp(phi^)Q0`, left-spatial update, `J_l` variation, physical swing map and spatial reaction moment conversion are explicitly defined. |
| kinematic operator / B matrix | `pass` | Green-Lagrange strain, MITC shear projection and both first/second variations use the same trial identity. |
| constitutive contract | `pass` | Constant symmetric `C5` maps engineering Green-Lagrange strain to second Piola-Kirchhoff stress; no material history is introduced. |
| Jacobian rules | `pass` | Fixed reference `J0` is integration measure; current `j` and `det F_c` are validity checks. Failed locations are not skipped. |
| integration policy | `pass` | S4 and S4R share four midsurface Gauss points times two thickness points; reduced/selective integration is prohibited. |
| residual/tangent consistency | `pass` | Complete tangent includes material, geometric, map-Hessian, objective drill Hessian and fixed-spatial moment work derivative terms. |
| tangent symmetry expectation | `pass` | Symmetric only for conservative no-applied-moment case; generally nonsymmetric moment tangent must remain unsymmetrized. |
| output locations | `pass-with-handoff` | Nodal U/UR/RF/RM and shell stress/resultant logical quantities are defined; exact HDF5 projection remains I/O-owned. Current nodal SPOS/SNEG stress CSV는 Gauss direct recovery와 일대일 대응하지 않으므로 external numerical comparison은 N/A다. |
## 6. Verification Readiness
### Blocking internal numerical tests
Implementation Planning shall carry these as feature-required tests before any reference-comparison success claim:
Mixed translation/rotation 검사는 fixed-reference characteristic length
`L=max(||X_I-X_J||)`와 node block `Dq=diag(L I3,I3)`를 사용한다. Tangent test direction은
`||p_hat||inf=1`, perturbation은 `q +/- h Dq p_hat`으로 두고
`h={1e-3,3e-4,1e-4,3e-5,1e-5,3e-6,1e-6,3e-7}` 전부를 검사한다. Roundoff plateau 전
최소 두 interval에서 centered-difference observed order `>=1.5`이고 한 interior point가
scaled error `<=1e-6`여야 한다. Single-`h` 우연 통과는 허용하지 않는다.
1. Linear limit: at stress-free `q=0`, nonlinear element residual/tangent/recovery reduce to approved linear MITC4 signs, `2 x 2 x 2` integration and physical/drill split.
2. Rotation state invariants: every committed/trial `Q` satisfies `||Q^T Q-I||_F <= 1e-12`,
`|det(Q)-1| <= 1e-12`, and `d=Q e3`. Global/swing/twist `pi` branch angular margin은
`sqrt(epsilon_double)`, 약 `1.4901161193847656e-8` rad보다 커야 한다.
3. Tangent directional derivative: compare `Dq^T K_T Dq p_hat` with the central
residual derivative under the schedule above in separated force and moment channels.
Zero analytical directions require exact-zero construction and scaled absolute error
`<=1e-10`; nonfinite metric은 허용하지 않는다.
4. No-moment tangent symmetry: after work-conjugate congruence `Dq^T K_T Dq`, no-applied-moment
tangent scaled Frobenius symmetry error `<=1e-12`; applied fixed-spatial moment cases are checked for
exact derivative consistency, not symmetry.
5. Finite rigid objectivity: superposed finite rigid motion leaves physical strain/stress,
physical energy, drill gamma/energy and internal residual at scaled `<=1e-10` levels.
6. Patch/sign recovery: membrane, bending, twist and transverse shear patch states preserve
component order and bottom/top stress signs.
Analytical strain/resultant/stress error is relative `<=1e-9`.
7. Load and boundary path: fixed-global force/moment source identity, `rho_M <= 1e-12`
rejection/projection, absolute factor-one boundary path and zero constrained Newton
correction are tested independently.
8. Newton lifecycle: factor identities use ordinal `j*h` values strictly below one,
followed by one exact assigned `1.0`; cumulative `lambda += h`와 tolerance-based duplicate
endpoint는 금지한다. For `shellNL` the expected intended factors are `0.1, 0.2, ...,
1.0`. Iterations are `1..100`, pass at `100` is allowed, iteration `101` is forbidden.
9. Convergence gates: NSNR-069/070 four-channel inclusive `<=` rules, typed zero-scale
`1e-3` thresholds and nonfinite rejection are tested without adding energy or line-search gates.
10. Commit/rollback and determinism: failed trial, recovery, solve or output does not mutate
the prior committed state or prior authoritative final result; row/diagnostic order is stable.
### Downstream reference comparisons
The required stored-reference cases and logical quantities are defined in
`docs/nonlinear-static-newton-raphson/reference-model.md`.
- `shellnl-s4-final` is the primary nonlinear external reference at accepted factor one.
- `shell-s4-linear-limit` is the read-only linear-limit/reference-identity regression for the
same S4 mesh. Current stress element-label ordering is inventoried without becoming a
comparison quantity.
External comparison uses only accepted-state quantities and `docs/TOLERANCE.md`. Missing,
extra, duplicate or nonfinite required rows fail before tolerance. The comparison result itself
is Implementation Agent ownership.
## 7. Required Revisions
### Formulation Agent
None before I/O Definition. The current formulation is numerically sufficient for the I/O
contract. Current source element/node SPOS/SNEG stress CSV에 맞추기 위한 extrapolation,
averaging 또는 새 recovery 의미는 추가하지 않는다.
### Research Agent
None before I/O Definition. Public large-response benchmarks and shell MMS remain useful future
evidence, but the current Stage 4 gate does not require another research pass.
### I/O Definition Agent
Define parser/semantic/HDF5/log projection for the logical quantities and row identities in
`reference-model.md`. Preserve the split between blocking internal nonlinear tests and external
stored reference comparison; do not claim Abaqus internal equivalence.
## 8. Downstream Handoff
For I/O Definition Agent through Coordinator:
- Use accepted factor-one frames only for external reference comparison; trial Newton states are
not reference quantities.
- Preserve required source identity: case, accepted state, instance, node label and component.
Stress artifact의 element/node/section identity와 stored element-label order는 read-only
inventory로 보존하되 FESA comparison row로 합성하지 않는다.
- Keep `U1/U2/U3` blocking and `UR1/UR2/UR3` warning-only. For `shellNL`, compare
constrained `RF1/RF2`, `RF3`, and spatial physical `RM1/RM2` in the separate blocking
families from `reference-model.md`. `RM3`와 stress는 comparison에서 제외한다.
- Apply `docs/TOLERANCE.md` exactly; do not add an independent absolute floor, row averaging,
source-order matching, or calibration gate.
- Treat `shellNL` as weak but valid nonlinear final-state reference evidence; require the
blocking internal tests above for tangent/objectivity/rollback/finite-rotation correctness.
@@ -0,0 +1,237 @@
# Nonlinear Static Newton-Raphson Reference Model
## 1. Metadata
- feature_id: `nonlinear-static-newton-raphson`
- source_requirements: `docs/nonlinear-static-newton-raphson/requirements.md`
- source_research: `docs/nonlinear-static-newton-raphson/research.md`
- source_formulation: `docs/nonlinear-static-newton-raphson/formulation.md`
- source_numerical_review: `docs/nonlinear-static-newton-raphson/numerical-review.md`
- status: `pass-for-io-definition`
- owner_agent: `numerical-review-agent`
- date: `2026-08-23`
- artifact_policy: `read-only-existing-files`
- tolerance_policy: `docs/TOLERANCE.md`
이 문서는 logical reference quantity, source identity, component matching, row precheck와
blocking/warning 분류만 정의한다. 최종 HDF5 dataset projection은 I/O Definition Agent 소유다.
## 2. Reference Acceptance Scope
Required scope는 두 stored case다.
- `shellnl-s4-final`: `nlgeom=YES` nonlinear static S4 final accepted state를 비교하는
primary external reference case.
- `shell-s4-linear-limit`: 같은 S4 mesh의 `nlgeom=NO` read-only linear-limit/reference-identity
regression case. 이 case는 nonlinear response evidence가 아니며, 현재 stress CSV의 element-label
ordering을 row-order matching으로 사용하지 않는다.
`shellNL`은 final-state reference comparison에는 충분하지만 weak nonlinear response다. Dominant
`U3`/stress 값이 linear case와 거의 같으므로 finite-rotation objectivity, consistent tangent,
commit/rollback과 convergence lifecycle은 `numerical-review.md`의 blocking internal tests로 검증한다.
## 3. Reference Case Inventory with exact input and required CSV paths
| case id | artifact role | required comparison artifact | exact path | observed status |
| --- | --- | --- | --- | --- |
| `shellnl-s4-final` | nonlinear input | yes | `reference/shellNL/shellNL.inp` | readable; S4, 49 nodes, 36 elements, `NLGEOM=YES` |
| `shellnl-s4-final` | displacement reference | yes | `reference/shellNL/shellNL displacements.csv` | 49 finite unique node rows; one factor-one Frame |
| `shellnl-s4-final` | reaction reference | yes | `reference/shellNL/shellNL reactions.csv` | 49 finite unique node rows; one factor-one Frame |
| `shellnl-s4-final` | stress review evidence | no | `reference/shellNL/shellNL stresses.csv` | 288 finite unique rows; element labels `1..36` in stored ascending blocks |
| `shell-s4-linear-limit` | linear control input | yes | `reference/shell/shell.inp` | readable; S4, 49 nodes, 36 elements, `NLGEOM=NO` |
| `shell-s4-linear-limit` | displacement reference | yes | `reference/shell/shell displacements.csv` | 49 finite unique node rows; no `Frame` column |
| `shell-s4-linear-limit` | reaction review evidence | no | `reference/shell/shell reactions.csv` | 49 finite unique node rows |
| `shell-s4-linear-limit` | stress review evidence | no | `reference/shell/shell stresses.csv` | 288 finite unique rows; element labels `1..36` in stored ascending blocks |
`required comparison artifact=no`인 파일도 이번 review에서 읽기 가능성, row identity,
finite values와 current ordering을 확인했다. 그러나 해당 파일은 missing-required-artifact
판정이나 tolerance family를 만들지 않는다.
두 `.inp`는 같은 node/element/connectivity, material/section, instance, boundary와 center-node
`CLOAD`를 사용한다. Text 차이는 heading identity, `NLGEOM=NO -> YES`, 그리고 `*STATIC`
data `1.,1.,1e-05,1. -> 0.1,1.,0.001,0.1`이다. 따라서 `shellNL`은 실제 nonlinear
selector와 승인된 fixed increment `0.1`을 갖지만, 두 deck 차이를 오직 `NLGEOM` 하나의
isolated effect라고 표현하지 않는다.
Read-only SHA-256 observations:
| path | SHA-256 |
| --- | --- |
| `reference/shellNL/shellNL.inp` | `4BF3ECB0F7F1E8462C573E993DBC97AC5D920C91CF6F23AD4C6891D77FFBADA2` |
| `reference/shellNL/shellNL displacements.csv` | `4E0F99CA9372B1ADF7FAF102F43BC0B887DC743FDEDA378E4342D2CF8E0C0786` |
| `reference/shellNL/shellNL reactions.csv` | `001CB1541A9E94424E5E650509D46BC8724970DF4DE47184D9DB09C7938AB069` |
| `reference/shellNL/shellNL stresses.csv` | `5500E5114B1C44887528E30CEC054A1EB0F68BE3F4B8CE81FA59FC74A881483F` |
| `reference/shell/shell.inp` | `4005851E1AB22FD3A16AC17A8D5DA3E051233F69F37419079F3553AD134ECFCF` |
| `reference/shell/shell displacements.csv` | `C81D94E0B4A849F87AA0F79C83A79B94D5661AC79E44ED826919AB432C87746B` |
| `reference/shell/shell reactions.csv` | `0E34EEC27E700C3C0C744C1DAFD8A3B95EFEF34B8616FE96665876586FE82D41` |
| `reference/shell/shell stresses.csv` | `2B75A5B0DEB045A283C9BB7E9B1153B79F7537FF487214BF4A23316B59B660A7` |
## 4. Source Identity and Component Contract
### 4.1 Accepted-state identity
- Abaqus identifiers are case-insensitive semantic identities. Input spelling
`Part-1-1` and CSV spelling `PART-1-1` match as one instance while original text is
retained in artifacts and reports; no file or row is rewritten.
- `shellnl-s4-final` rows require exact CSV `Frame` value
`Increment 10: Step Time = 1.000`, mapped logically to the accepted factor-one state.
- `shell-s4-linear-limit` rows have no `Frame` column and map to the single final static state.
- Row order is never a matching identity. It may only be used for deterministic reporting after
source keys are matched.
### 4.2 Nodal displacement contract
Required mapping is `U-U1/U-U2/U-U3 -> U1/U2/U3` and
`UR-UR1/UR-UR2/UR-UR3 -> UR1/UR2/UR3`. U is global length; UR is the
dimensionless fixed-initial global rotation-vector output. Logical key is
```text
(case_id, accepted_state, canonical_instance_name, source_node_label, component)
```
Both cases require source node labels `1..49` exactly once. U components form one
blocking translation family and UR components form one warning-only rotation family,
preserving the project MITC4 classification.
### 4.3 Nonlinear reaction contract
Reaction comparison applies only to `shellnl-s4-final` and only to the input boundary
`Set-2` nodes:
```text
1,3,4,5,6,7,8,9,14,15,16,17,22,23,24,25,26,27,28,29,30,31,32,33
```
All six global components are constrained at these 24 nodes. Other CSV node rows remain
part of file/schema/finite inventory but are not numerical reaction rows: FESA free entries
are equilibrium residual evidence, not Abaqus free-node zero reactions.
| CSV components | logical quantity | FESA meaning | disposition |
| --- | --- | --- | --- |
| `RF-RF1`, `RF-RF2` | fixed-initial shell-plane reaction force | constrained translational full residual, global force | blocking family |
| `RF-RF3` | fixed-initial transverse reaction force | constrained translational full residual, global force | blocking family |
| `RM-RM1`, `RM-RM2` | tangent-plane spatial reaction moment | `J_l(phi)^(-T)` conversion of the constrained generalized reaction, global force-length | blocking family |
| `RM-RM3` | director/drilling-axis reaction review value | stabilization-dependent; no physical external equivalence target | excluded |
In-plane and transverse force are distinct model-fixed logical projections and therefore
use distinct families. Raw generalized rotation-coordinate residual is not matched directly
to the CSV `RM` value.
### 4.4 Stress review identity and comparison exclusion
Stress rows have read-only identity
```text
(case_id, accepted_state, instance, element label,
element-corner node label, SPOS/SNEG section surface, component)
```
Every current element has its four connectivity nodes and one `SPOS` plus one `SNEG`
row per node. The files are ordered in contiguous ascending element-label blocks `1..36`;
this exact artifact order is retained and no node/surface secondary reorder is applied.
The identity is nevertheless not the approved FESA recovery location: FESA emits direct
`[S11,S22,S12]` at four midsurface Gauss locations and bottom/middle/top positions, without
nodal extrapolation or averaging, and does not emit `S33`. Consequently no stress column
forms a blocking or warning-only comparison family. Stress files remain optional read-only
review evidence only.
### 4.5 Comparison families
| family id | components and source set | row count | units / coordinates | disposition |
| --- | --- | ---: | --- | --- |
| `linear.translation` | `U1,U2,U3`, nodes `1..49` | 147 | length / global | blocking regression |
| `linear.rotation` | `UR1,UR2,UR3`, nodes `1..49` | 147 | dimensionless / fixed-initial global | warning-only |
| `nonlinear.translation` | `U1,U2,U3`, nodes `1..49` | 147 | length / global | blocking |
| `nonlinear.rotation` | `UR1,UR2,UR3`, nodes `1..49` | 147 | dimensionless / fixed-initial global | warning-only |
| `nonlinear.reaction_inplane_force` | `RF1,RF2`, 24 constrained nodes | 48 | force / fixed-initial global plane | blocking |
| `nonlinear.reaction_transverse_force` | `RF3`, 24 constrained nodes | 24 | force / fixed-initial global transverse | blocking |
| `nonlinear.reaction_physical_moment` | `RM1,RM2`, 24 constrained nodes | 48 | force-length / global spatial | blocking |
## 5. Row Prechecks
Before tolerance, the comparator shall fail the affected comparison if any required condition
below is false.
1. Exact declared input path and every `required comparison artifact=yes` CSV path for the
case exist and are readable.
2. Required headers are present after trimming surrounding whitespace from header names.
3. `shellnl-s4-final` contains only the exact required `Frame` value for required rows.
4. Wide CSV rows expand to component rows using the component contract in Section 4.
5. Required source row keys are unique. Duplicate wide keys or duplicate expanded component keys fail.
6. Displacement projection requires all 49 source nodes and declared components. Nonlinear
reaction projection derives the exact 24-node/component set from the input constraint mask;
it does not infer reaction identity from CSV zero values.
7. FESA and reference required projected row-key sets are exactly equal: missing and extra rows
both fail.
8. Every required numeric value is finite. Nonfinite required FESA or CSV value fails before tolerance.
9. Optional stress inventory uses `(instance, element label, node label, section point)` and verifies
the current ascending element-label blocks, connectivity nodes and SPOS/SNEG pair. This inspection
does not create a stress equality gate.
10. Required rows are not omitted, synthesized, normalized, averaged, sorted into a different identity,
zero-clamped, or repaired.
Observed read-only inventory used for this contract:
| CSV | observed wide key columns | duplicate wide keys | nonfinite observed values | observed element labels |
| --- | --- | ---: | ---: | --- |
| `reference/shellNL/shellNL displacements.csv` | `Frame`, `Part Instance Name`, `Node Label` | 0 | 0 | N/A |
| `reference/shellNL/shellNL reactions.csv` | `Frame`, `Part Instance Name`, `Node Label` | 0 | 0 | N/A |
| `reference/shellNL/shellNL stresses.csv` | `Frame`, `Part Instance Name`, `Element Label`, `Node Label`, `Section Point` | 0 | 0 | `1..36` |
| `reference/shell/shell displacements.csv` | `Part Instance Name`, `Node Label` | 0 | 0 | N/A |
| `reference/shell/shell reactions.csv` | `Part Instance Name`, `Node Label` | 0 | 0 | N/A |
| `reference/shell/shell stresses.csv` | `Part Instance Name`, `Element Label`, `Node Label`, `Section Point` | 0 | 0 | `1..36` |
## 6. Tolerance and Blocking/Warning Policy
Use exactly `docs/TOLERANCE.md` for every external reference family. This report does not invent
or calibrate tolerance values.
For each comparison family:
- `S = max(abs(reference_value_i))`, using reference values only.
- near-zero band is `0.01*S`.
- if `abs(reference_value_i) <= 0.01*S`, row passes iff `abs(fesa-reference) <= 0.01*S`.
- otherwise row passes iff relative error `<= 0.05`.
- family relative RMS is `RMS(error)/S <= 0.01`.
- no independent absolute-error floor, `max(1, S)` clamp, row omission, averaging, or zero clamp is allowed.
- if `S = 0`, the family passes only when all FESA values are exactly zero; otherwise report
`zero-reference-scale-nonzero-error`.
Families are separated by the exact case/logical quantities in Section 4.5. Current
reference-only scales provide a reproducible reader/comparator audit:
| family | `S` | `B=0.01*S` |
| --- | ---: | ---: |
| `linear.translation` | `2.37408203e-5` | `2.37408203e-7` |
| `linear.rotation` | `7.60725743e-6` | `7.60725743e-8` |
| `nonlinear.translation` | `2.37408203e-5` | `2.37408203e-7` |
| `nonlinear.rotation` | `7.60725743e-6` | `7.60725743e-8` |
| `nonlinear.reaction_inplane_force` | `1.91663182` | `1.91663182e-2` |
| `nonlinear.reaction_transverse_force` | `1.17769805e4` | `1.17769805e2` |
| `nonlinear.reaction_physical_moment` | `1.95418418e4` | `1.95418418e2` |
Any `blocking` family row or RMS failure fails the reference comparison for the feature.
`warning-only` failures produce deterministic warning evidence but do not change the blocking
verdict. `RM3` and stress artifacts create neither a blocking nor warning-only tolerance family.
## 7. Open Issues and I/O Handoff
Open issues blocking I/O Definition: 없음.
I/O Definition Agent handoff:
- Project only the comparison quantities in Sections 4.2, 4.3 and 4.5 to authoritative FESA
result datasets without changing source identity or final comparison disposition.
- Preserve `Frame` handling for `shellnl-s4-final` as accepted factor-one state identity; do not expose
trial Newton history as reference rows.
- Derive constrained reaction identity from the input mask. Compare `RM1/RM2` with the global
spatial physical reaction moment, not the raw generalized rotation-coordinate covector.
- Preserve approved Gauss direct stress recovery. Do not create element-corner stress,
extrapolation, averaging or a stress CSV projection for the current optional SPOS/SNEG artifacts.
- Keep `RM3`, `S-S33`, `S-S11`, `S-S22` and `S-S12` out of current comparison families.
- Use the common tolerance policy exactly as written above and in `docs/TOLERANCE.md`.
Reference artifact status: complete for I/O Definition. No declared required input or required
comparison CSV is missing or unreadable. Optional stress CSVs are present and readable as inventory
evidence only. No reference artifact was generated, renamed, repaired, normalized, or modified.
+2 -1
View File
@@ -7,10 +7,11 @@
namespace fesa {
/// @brief Carries input and authoritative output paths for one analysis run.
/// @brief Carries input, authoritative output, and diagnostic-log paths.
struct AnalysisRequest {
std::filesystem::path input_path;
std::filesystem::path output_path;
std::filesystem::path log_path;
};
/// @brief Defines the minimal execution contract shared by analysis procedures.
+2 -2
View File
@@ -9,8 +9,8 @@ namespace fesa {
/// @brief Owns the argv-independent CLI contract and stable process exit codes.
class FesaApplication {
public:
/// @brief Runs one solver invocation from operands and options after argv[0].
/// @param arguments Input path and optional `--output` pair.
/// @brief Runs one solver invocation from arguments after argv[0].
/// @param arguments One input path with no unsupported option token.
/// @return The stable CLI exit code for usage, input, model, solver, or
/// output status.
int Run(const std::vector<std::string>& arguments);
+58
View File
@@ -0,0 +1,58 @@
#ifndef FESA_APP_OUTPUT_PATHS_H_
#define FESA_APP_OUTPUT_PATHS_H_
#include <filesystem>
#include <memory>
#include <string>
#include <vector>
#include "fesa/core/status.h"
namespace fesa {
/// @brief Names the input and user-addressed output files for one invocation.
struct DerivedOutputPaths {
std::filesystem::path input_path;
std::filesystem::path results_path;
std::filesystem::path log_path;
};
/// @brief Retains exclusive ownership of one derived output pair.
/// @note The lease owns a platform-private lock and must outlive output I/O.
class OutputWriteLease {
public:
OutputWriteLease(const OutputWriteLease&) = delete;
OutputWriteLease& operator=(const OutputWriteLease&) = delete;
OutputWriteLease(OutputWriteLease&&) noexcept;
OutputWriteLease& operator=(OutputWriteLease&&) noexcept;
~OutputWriteLease();
private:
class Impl;
friend Result<OutputWriteLease> AcquireOutputWriteLease(
const DerivedOutputPaths& paths);
explicit OutputWriteLease(std::unique_ptr<Impl> impl) noexcept;
std::unique_ptr<Impl> impl_;
};
/// @brief Validates CLI operands and derives lexical sibling output paths.
/// @param arguments Arguments after argv[0].
/// @param invocation_cwd Lexical base for a relative input path.
/// @return The input/result/log path triplet or a usage failure.
/// @note This function does not resolve symlinks, junctions, or short names.
Result<DerivedOutputPaths> DeriveSingleInputOutputPaths(
const std::vector<std::string>& arguments,
const std::filesystem::path& invocation_cwd);
/// @brief Acquires exclusive ownership for writes to one output pair.
/// @return A move-only lease or an output-busy failure.
/// @note The lease does not create, truncate, or replace public output files.
Result<OutputWriteLease> AcquireOutputWriteLease(
const DerivedOutputPaths& paths);
} // namespace fesa
#endif // FESA_APP_OUTPUT_PATHS_H_
+4
View File
@@ -13,6 +13,10 @@
"dir": "cpp-object-oriented-modular-refactoring",
"status": "completed",
"completed_at": "2026-08-16T13:54:51+0900"
},
{
"dir": "nonlinear-static-newton-raphson",
"status": "pending"
}
]
}
@@ -0,0 +1,136 @@
# Step 0: cli-output-lease-and-derived-names
## 읽어야 할 파일
- `AGENTS.md`
- `docs/SOLVER_AGENT_DESIGN.md`
- `docs/HARNESS.md`
- `docs/HARNESS_WORKFLOW.md`
- `.codex/hooks.json`
- `docs/nonlinear-static-newton-raphson/implementation-plan.md`
- `docs/nonlinear-static-newton-raphson/io.md`
- `docs/nonlinear-static-newton-raphson/requirements.md`
- `src/fesa/app/fesa_application.cpp`
- `include/fesa/app/fesa_application.h`
- `include/fesa/analysis/analysis.h`
- `tests/integration/app/fesa_application_test.cpp`
- `src/fesa/CMakeLists.txt`
- `tests/CMakeLists.txt`
## 이전 Step 전제
없음. 이 Step은 app/CLI output lifecycle의 첫 변경이다.
## 소유 파일
- Create: `include/fesa/app/output_paths.h`
- Create: `src/fesa/app/output_paths.cpp`
- Create: `tests/unit/app/output_paths_test.cpp`
- Modify: `include/fesa/analysis/analysis.h`
- Modify: `include/fesa/app/fesa_application.h`
- Modify: `src/fesa/app/fesa_application.cpp`
- Modify: `src/fesa/CMakeLists.txt`
- Modify: `tests/CMakeLists.txt`
- Test: `tests/integration/app/fesa_application_test.cpp`
## 인터페이스
```cpp
namespace fesa {
struct DerivedOutputPaths {
std::filesystem::path input_path;
std::filesystem::path results_path;
std::filesystem::path log_path;
};
class OutputWriteLease {
public:
OutputWriteLease(const OutputWriteLease&) = delete;
OutputWriteLease& operator=(const OutputWriteLease&) = delete;
OutputWriteLease(OutputWriteLease&&) noexcept;
OutputWriteLease& operator=(OutputWriteLease&&) noexcept;
~OutputWriteLease();
private:
class Impl;
friend Result<OutputWriteLease> AcquireOutputWriteLease(
const DerivedOutputPaths& paths);
explicit OutputWriteLease(std::unique_ptr<Impl> impl) noexcept;
std::unique_ptr<Impl> impl_;
};
Result<DerivedOutputPaths> DeriveSingleInputOutputPaths(
const std::vector<std::string>& arguments,
const std::filesystem::path& invocation_cwd);
Result<OutputWriteLease> AcquireOutputWriteLease(
const DerivedOutputPaths& paths);
struct AnalysisRequest {
std::filesystem::path input_path;
std::filesystem::path output_path;
std::filesystem::path log_path;
};
} // namespace fesa
```
`OutputWriteLease`는 acquisition-only private constructor와 private pimpl storage로 lock lifetime을 보존한다. Win32 handle, file handle, 또는 platform lock 표현은 `Impl` 안에만 둔다. `FesaApplication`은 lease를 log close와 HDF5 finalization이 끝날 때까지 보관한다.
## RED
테스트를 먼저 추가한다.
- `NSNR-CLI-001`: argv의 모든 token을 왼쪽에서 오른쪽으로 검사하고, case-sensitive substring `--output`을 포함한 첫 token에서 exit code `2`와 diagnostic code `cli-usage`가 하나만 출력된다.
- `NSNR-CLI-002`: `abc--outputdef`, `--output-path`, `--output=foo`, `--output` 모두 input path resolution 전에 실패한다.
- `NSNR-CLI-003`: `--output` 실패는 parser, Analysis construction, lease acquisition, log create/truncate, HDF5 candidate creation을 호출하지 않는다.
- `NSNR-CLI-004`: relative `.inp` path는 invocation CWD 기준으로 lexical normalization만 하고 `<stem>_results.h5`, `<stem>_log.txt`를 같은 directory에 만든다.
- `NSNR-CLI-005`: final extension `.inp`는 case-insensitive이고 stem은 마지막 extension만 제거하며 basename case와 preceding dots를 보존한다.
- `NSNR-CLI-006`: output-busy lease collision은 exit code `6`이며 log와 HDF5를 만들거나 바꾸지 않는다.
- `NSNR-CLI-007`: previous result/log files가 있는 상태에서 `--output` 실패 후 bytes와 timestamps가 변하지 않는다.
- `NSNR-CLI-008`: existing default `fesa.exe <model.inp>` invocation은 더 이상 cwd `results.h5`를 기본값으로 쓰지 않는다.
- `NSNR-CLI-009`: `AnalysisRequest`가 `input_path`, `output_path`, `log_path`를 함께 전달한다.
실행:
```powershell
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug -R "FesaApplication|OutputPath" --output-on-failure
```
기대: 새 테스트가 컴파일 실패 또는 assertion 실패로 실패한다. 새 테스트가 예상 없이 통과하면 구현을 중단하고 Coordinator에게 보고한다.
## GREEN
- `output_paths` module에 argv 검사, lexical path derivation, input extension validation, lease acquisition을 구현한다.
- `FesaApplication`은 `DeriveSingleInputOutputPaths` 성공 뒤 `AcquireOutputWriteLease`를 호출한다.
- 이 Step에서는 nonlinear procedure를 만들지 않는다.
- `LinearStaticAnalysis` 호출은 기존 방식대로 유지하되 `AnalysisRequest::output_path`가 `<stem>_results.h5`를 가리키게 한다.
## VERIFY
실행 전 `Test-Path .harness\config.json`으로 Harness config를 재확인한다. 있으면 그 설정을 우선한다. 없으면 다음 순서로 실행한다.
```powershell
cmake --fresh -S . -B .harness/build -G "Visual Studio 18 2026" -A x64 `
"-DFESA_GTEST_SOURCE_DIR=$gtestSource" `
"-DMKL_DIR=$mklDir" `
"-DTBB_DIR=$tbbDir" `
"-DHDF5_DIR=$hdf5Dir"
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug -R "FesaApplication|OutputPath" --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
## 상태 기록
Executor가 선택한 current Step 0만 `completed`, `error`, `blocked` 중 하나로 갱신한다. 성공 시 summary 한 줄만 기록한다. timestamp, retry, commit, advancement는 Executor 소유다.
## 금지사항
- `--output` alias 또는 deprecation path를 남기지 마라. 이유: 승인된 public compatibility가 fail-closed removal이다.
- path를 symlink, junction, short-name, case-normalized realpath로 resolve하지 마라. 이유: io.md가 lexical user-addressed identity를 요구한다.
- log/HDF5 작업이 끝나기 전에 `OutputWriteLease`를 파기하지 마라. 이유: exclusive ownership 보장이 깨진다.
- nonlinear analysis 분기를 `LinearStaticAnalysis` private lifecycle에 넣지 마라. 이유: Step 10의 별도 prepared flow가 소유한다.
@@ -0,0 +1,135 @@
# Step 1: nonlinear-static-domain-contract
## 읽어야 할 파일
- `AGENTS.md`
- `docs/ARCHITECTURE.md`
- `docs/ADR.md`
- `docs/nonlinear-static-newton-raphson/requirements.md`
- `docs/nonlinear-static-newton-raphson/io.md`
- `docs/nonlinear-static-newton-raphson/reference-model.md`
- `docs/nonlinear-static-newton-raphson/implementation-plan.md`
- `include/fesa/model/model_types.h`
- `include/fesa/model/domain.h`
- `src/fesa/model/domain.cpp`
- `src/fesa/io/abaqus/step_definition_mapper.cpp`
- `src/fesa/io/abaqus/domain_mapping_context.h`
- `src/fesa/io/abaqus/domain_mapping_context.cpp`
- `tests/unit/model/model_types_test.cpp`
- `tests/unit/model/domain_test.cpp`
- `tests/unit/io/abaqus/domain_mapper_test.cpp`
- `tests/unit/io/abaqus/domain_mapping_components_test.cpp`
- Step 0 files: `include/fesa/app/output_paths.h`, `include/fesa/analysis/analysis.h`, `src/fesa/app/fesa_application.cpp`
## 이전 Step 전제
Step 0이 app-level path/log request fields를 만들었고 기존 linear invocation이 `<stem>_results.h5`를 사용한다.
## 소유 파일
- Modify: `include/fesa/model/model_types.h`
- Modify: `include/fesa/model/domain.h`
- Modify: `src/fesa/model/domain.cpp`
- Modify: `src/fesa/io/abaqus/step_definition_mapper.cpp`
- Modify: `src/fesa/io/abaqus/domain_mapping_context.h`
- Modify: `src/fesa/io/abaqus/domain_mapping_context.cpp`
- Test: `tests/unit/model/model_types_test.cpp`
- Test: `tests/unit/model/domain_test.cpp`
- Test: `tests/unit/io/abaqus/domain_mapper_test.cpp`
- Test: `tests/unit/io/abaqus/domain_mapping_components_test.cpp`
## 인터페이스
```cpp
namespace fesa {
enum class StaticProcedureKind {
kLinearSmallDisplacement,
kNonlinearFullNewton
};
struct StaticStepDefinition {
std::string name;
std::vector<PrescribedDisplacementDefinition> boundaries;
std::vector<NodalLoad> loads;
StaticProcedureKind procedure_kind;
bool nlgeom;
double initial_increment;
double time_period;
double minimum_increment;
double maximum_increment;
SourceLocation location;
};
class StepDefinition {
public:
StaticProcedureKind ProcedureKind() const noexcept;
bool IsNonlinearStatic() const noexcept;
double InitialIncrement() const noexcept;
double TimePeriod() const noexcept;
double MinimumIncrement() const noexcept;
double MaximumIncrement() const noexcept;
};
} // namespace fesa
```
Domain stores procedure identity and raw four `*STATIC` values only. Factor sequence is derived in Step 5. PRESELECT output requests are warning no-ops and do not create Domain, Analysis, or HDF5 state.
## RED
Add tests first.
- `NSNR-IO-001`: `*STEP, NLGEOM=YES` maps to `StaticProcedureKind::kNonlinearFullNewton`.
- `NSNR-IO-002`: `*STEP, NLGEOM=NO` maps to `kLinearSmallDisplacement` and existing shell linear tests keep passing.
- `NSNR-IO-003`: missing `NLGEOM` keeps current linear behavior.
- `NSNR-IO-004`: nonlinear `*STATIC` requires four finite positive values and time period exactly `1.0`.
- `NSNR-IO-005`: raw values are preserved in `StepDefinition` without derived factor list.
- `NSNR-IO-006`: unsupported nonlinear procedure or mixed linear/nonlinear steps fail closed with `unsupported-analysis-procedure`.
- `NSNR-IO-007`: S4 and S4R shell definitions remain approved nonlinear semantic inputs.
- `NSNR-IO-008`: mixed B33/S4 nonlinear model fails with `unsupported-mixed-element-model`.
- `NSNR-IO-009`: `*OUTPUT, FIELD, VARIABLE=PRESELECT` is accepted with deterministic warning and no Domain state.
- `NSNR-IO-010`: `*OUTPUT, HISTORY, VARIABLE=PRESELECT` is accepted with deterministic warning and no Domain state.
- `NSNR-IO-011`: malformed PRESELECT parameters fail as input errors.
Run:
```powershell
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug -R "Domain|DomainMapping|Abaqus" --output-on-failure
```
Expected: new tests fail. Unexpected pass stops the Step.
## GREEN
- Extend `StaticStepDefinition` and `StepDefinition` exactly with the fields and accessors above.
- Update domain construction so source-order boundaries and loads remain deterministic.
- Update `domain_mapping_context` to parse `NLGEOM=YES`, preserve raw `*STATIC`, emit PRESELECT warnings, and keep PRESELECT out of Domain state.
- Preserve existing linear shell and beam mappings.
## VERIFY
```powershell
cmake --fresh -S . -B .harness/build -G "Visual Studio 18 2026" -A x64 `
"-DFESA_GTEST_SOURCE_DIR=$gtestSource" `
"-DMKL_DIR=$mklDir" `
"-DTBB_DIR=$tbbDir" `
"-DHDF5_DIR=$hdf5Dir"
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug -R "Domain|DomainMapping|Abaqus" --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
Recheck `.harness/config.json` before using these defaults.
## 상태 기록
Only Step 1 status and one-line summary/error/blocked payload may be updated by the Implementation Agent. Executor owns timestamps, commits, retry, and next Step selection.
## 금지사항
- Do not add `LoadFactorSequence()` to Domain. 이유: factor sequence ownership belongs to Step 5 control.
- Do not store PRESELECT flags in Domain or HDF5 state. 이유: approved I/O contract makes PRESELECT an ignored warning no-op.
- Do not alter requirements or I/O docs. 이유: upstream contracts are approved.
@@ -0,0 +1,177 @@
# Step 10: prepared-analysis-flow-and-full-procedure
## 읽어야 할 파일
- `AGENTS.md`
- `docs/ARCHITECTURE.md`
- `docs/ADR.md`
- `docs/nonlinear-static-newton-raphson/requirements.md`
- `docs/nonlinear-static-newton-raphson/formulation.md`
- `docs/nonlinear-static-newton-raphson/numerical-review.md`
- `docs/nonlinear-static-newton-raphson/io.md`
- `include/fesa/analysis/analysis.h`
- `include/fesa/analysis/linear_static_analysis.h`
- `src/fesa/analysis/linear_static_analysis.cpp`
- `src/fesa/app/fesa_application.cpp`
- `include/fesa/io/hdf5/hdf5_results_writer.h`
- `include/fesa/results/results_writer.h`
- `include/fesa/results/nonlinear_results_writer.h`
- Step 0 files: `include/fesa/app/output_paths.h`, `src/fesa/app/output_paths.cpp`
- Step 1 files: `include/fesa/model/domain.h`, `src/fesa/io/abaqus/domain_mapping_context.cpp`
- Step 5 files: `include/fesa/analysis/nonlinear_static_control.h`
- Step 6 files: `include/fesa/solvers/linear/tangent_solver.h`
- Step 7 files: `include/fesa/analysis/newton_iteration_log.h`
- Step 8 files: `include/fesa/analysis/nonlinear_analysis_state.h`
- Step 9 files: `include/fesa/results/nonlinear_results_writer.h`, `include/fesa/io/hdf5/nonlinear_hdf5_results_writer.h`
## 이전 Step 전제
Steps 0-9 provide path/lease, Domain procedure identity, nonlinear element/control/solver/log/state, and nonlinear HDF5 writer.
## 소유 파일
- Create: `include/fesa/analysis/prepared_analysis.h`
- Create: `src/fesa/analysis/prepared_analysis.cpp`
- Create: `include/fesa/analysis/linear_static_procedure.h`
- Create: `src/fesa/analysis/linear_static_procedure.cpp`
- Create: `include/fesa/analysis/nonlinear_static_procedure.h`
- Create: `src/fesa/analysis/nonlinear_static_procedure.cpp`
- Modify: `include/fesa/analysis/linear_static_analysis.h`
- Modify: `src/fesa/analysis/linear_static_analysis.cpp`
- Modify: `src/fesa/app/fesa_application.cpp`
- Test: `tests/integration/analysis/linear_static_analysis_test.cpp`
- Create: `tests/integration/analysis/nonlinear_static_procedure_test.cpp`
- Test: `tests/integration/app/fesa_application_test.cpp`
- Modify: `src/fesa/CMakeLists.txt`
- Modify: `tests/CMakeLists.txt`
## 인터페이스
```cpp
namespace fesa {
struct PreparedAnalysisInput {
Domain domain;
std::vector<Diagnostic> diagnostics;
};
Result<PreparedAnalysisInput> PrepareAnalysisInput(
const std::filesystem::path& input_path);
struct LinearStaticExecutionResult {
AnalysisState state;
std::vector<Diagnostic> diagnostics;
};
class LinearStaticProcedureExecutor {
public:
LinearStaticProcedureExecutor(const ParallelFor& parallel_for,
LinearSolver& linear_solver);
Result<LinearStaticExecutionResult> Execute(const Domain& domain) const;
private:
const ParallelFor& parallel_for_;
LinearSolver& linear_solver_;
};
struct NonlinearStaticExecutionResult {
NonlinearAnalysisState state;
std::vector<Diagnostic> diagnostics;
};
class NonlinearStaticProcedureExecutor {
public:
NonlinearStaticProcedureExecutor(const ParallelFor& parallel_for,
TangentSolver& tangent_solver);
Result<NonlinearStaticExecutionResult> Execute(
const Domain& domain, NewtonIterationLogWriter& log) const;
private:
const ParallelFor& parallel_for_;
TangentSolver& tangent_solver_;
};
using PreparedAnalysisOutcome =
std::variant<LinearStaticExecutionResult, NonlinearStaticExecutionResult>;
Result<PreparedAnalysisOutcome> ExecutePreparedAnalysis(
const Domain& domain,
LinearStaticProcedureExecutor& linear_executor,
NonlinearStaticProcedureExecutor& nonlinear_executor,
NewtonIterationLogWriter& log);
Status FinalizePreparedAnalysisResult(
const DerivedOutputPaths& paths,
const Domain& domain,
const PreparedAnalysisOutcome& outcome,
const std::vector<Diagnostic>& diagnostics,
ResultsWriter& linear_writer,
NonlinearResultsWriter& nonlinear_writer);
} // namespace fesa
```
## RED
Add tests first.
- `NSNR-PROC-001`: app validates argv, derives paths, acquires `OutputWriteLease`, opens log, then parses/maps exactly once.
- `NSNR-PROC-002`: parse/map diagnostics are sorted and preserved in prepared input.
- `NSNR-PROC-003`: linear `NLGEOM=NO` run uses `LinearStaticProcedureExecutor` and preserves existing numerical/HDF5 meaning except output names and log lifecycle.
- `NSNR-PROC-004`: nonlinear `NLGEOM=YES` run uses `NonlinearStaticProcedureExecutor`.
- `NSNR-PROC-005`: linear executor receives injected `ParallelFor` and existing `LinearSolver`; nonlinear executor receives injected `ParallelFor` and `TangentSolver`.
- `NSNR-PROC-006`: app constructs and owns concrete `TbbParallelFor`, `MklPardisoSolver`, `MklPardisoTangentSolver`, `Hdf5ResultsWriter`, and `NonlinearHdf5ResultsWriter`.
- `NSNR-PROC-007`: procedure computation/recovery returns a validated outcome without opening HDF5.
- `NSNR-PROC-008`: app closes log successfully before calling injected linear or nonlinear writer.
- `NSNR-PROC-009`: log close failure blocks HDF5 candidate creation.
- `NSNR-PROC-010`: nonlinear executor builds `NonlinearStateBaselineInput` from Domain nodes in stable internal order, preserving each node's `EntityIndex` and full `SourceEntityId`, then constructs state through `NonlinearAnalysisState::Create(domain, dofs, baseline)` before the first increment; the factor-zero baseline is committed state only and is not an accepted frame.
- `NSNR-PROC-011`: nonlinear increment loop uses factors from Step 5 and iterations `1..100`.
- `NSNR-PROC-012`: each entered iteration performs fresh tangent factorization and solves `Kff * delta = -r_f`.
- `NSNR-PROC-013`: global external vector/tangent from Step 5 is assembled once and combined with approved signs `r = f_int - f_ext`, `K_T = K_int - K_ext`; the fixed-moment tangent is subtracted once and is never duplicated per incident element.
- `NSNR-PROC-014`: iteration 100 can accept if gates pass; failure at 100 emits `nonlinear-nonconvergence` with no retry.
- `NSNR-PROC-015`: nonfinite data, factorization failure, solve failure, invalid accepted state, and log failure map to approved diagnostics.
- `NSNR-PROC-016`: constrained correction is zero and reactions/free residuals come from full residual `r = f_int - f_ext`.
- `NSNR-PROC-017`: failed nonlinear run preserves prior final HDF5 according to output lifecycle.
- `NSNR-PROC-018`: deterministic repeat produces same sparse structure, nodal source-identity order, result row order, diagnostics, and log line ordering.
Run:
```powershell
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug -R "LinearStaticAnalysis|NonlinearStaticProcedure|FesaApplication" --output-on-failure
```
Expected: new tests fail. Unexpected pass stops.
## GREEN
Refactor current parse/map and linear compute/recovery out of `LinearStaticAnalysis::Run()` into `PrepareAnalysisInput` and `LinearStaticProcedureExecutor`. Keep `LinearStaticAnalysis` as a compatibility wrapper that delegates through the new flow and does not contain nonlinear conditions. Implement `NonlinearStaticProcedureExecutor` in `nonlinear_static_procedure.*` using Steps 2-8, constructing state only through `NonlinearAnalysisState::Create(...)` with one baseline per Domain node in stable internal order, forming `r = f_int - f_ext` and `K_T = K_int - K_ext`, preserving `EntityIndex` plus full `SourceEntityId` into final writer inputs, and delaying all HDF5 work until `FinalizePreparedAnalysisResult`. The app owns concrete adapters and passes them through interfaces.
## VERIFY
```powershell
cmake --fresh -S . -B .harness/build -G "Visual Studio 18 2026" -A x64 `
"-DFESA_GTEST_SOURCE_DIR=$gtestSource" `
"-DMKL_DIR=$mklDir" `
"-DTBB_DIR=$tbbDir" `
"-DHDF5_DIR=$hdf5Dir"
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug -R "LinearStaticAnalysis|NonlinearStaticProcedure|FesaApplication" --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
Recheck `.harness/config.json` before default commands.
## 상태 기록
Update only Step 10 status and one-line payload. Executor owns timestamps, commits, retry, and advancement.
## 금지사항
- Do not parse/map twice. 이유: source identity, diagnostics, and Domain lifetime must be deterministic.
- Do not reconstruct nodal identity from source labels alone. 이유: labels can repeat across instances and HDF5/reference matching requires full `SourceEntityId`.
- Do not open HDF5 before log close succeeds. 이유: io.md requires log close success before HDF5 candidate open/write/final replace.
- Do not insert nonlinear branches into `LinearStaticAnalysis` private lifecycle. 이유: new procedure owns its own lifecycle.
- Do not replace final HDF5 on failed analysis, log failure, or HDF5 failure. 이유: asymmetric preservation contract requires prior valid final preservation.
- Do not construct MKL/TBB/HDF5 backends inside procedure executors. 이유: dependencies are injected so tests can observe lifecycle and no backend type crosses analysis/core public boundaries.
@@ -0,0 +1,191 @@
# Step 11: reference-comparison-gate
## 읽어야 할 파일
- `AGENTS.md`
- `docs/TOLERANCE.md`
- `docs/nonlinear-static-newton-raphson/reference-model.md`
- `docs/nonlinear-static-newton-raphson/io.md`
- `docs/nonlinear-static-newton-raphson/numerical-review.md`
- `tests/reference/reference_tolerance_policy.h`
- `tests/reference/reference_tolerance_policy.cpp`
- `tests/reference/reference_comparison.h`
- `tests/reference/reference_comparison.cpp`
- `tests/reference/mitc4_reference_comparison.h`
- `tests/reference/mitc4_reference_comparison.cpp`
- Step 9 files: `include/fesa/results/nonlinear_results_writer.h`, `include/fesa/io/hdf5/nonlinear_hdf5_results_writer.h`
- Step 10 files: `include/fesa/analysis/prepared_analysis.h`, `src/fesa/app/fesa_application.cpp`
## 이전 Step 전제
Step 10 runs copied input files through FESA and writes authoritative HDF5 outputs after log close.
## 소유 파일
- Create: `tests/reference/nonlinear_static_reference_comparison.h`
- Create: `tests/reference/nonlinear_static_reference_comparison.cpp`
- Create: `tests/reference/nonlinear_static_reference_cases_test.cpp`
- Modify: `tests/CMakeLists.txt`
## 인터페이스
```cpp
namespace fesa::test {
struct NonlinearReferenceCase {
std::string case_id;
std::filesystem::path original_input_path;
std::filesystem::path displacement_csv_path;
std::filesystem::path reaction_csv_path;
std::filesystem::path stress_inventory_path;
std::filesystem::path execution_directory;
};
struct ArtifactSnapshot {
std::filesystem::path path;
std::string sha256;
std::uintmax_t byte_size;
std::filesystem::file_time_type last_write_time;
};
enum class NonlinearReferenceDisposition {
kBlocking,
kWarningOnly,
kExcluded
};
struct NonlinearReferenceRowKey {
std::string case_id;
std::string accepted_state;
std::string instance_name;
std::int64_t source_node_label;
std::string component;
};
struct NonlinearReferenceFamilyReport {
std::string family_identity;
std::vector<std::string> components;
NonlinearReferenceDisposition disposition;
std::size_t row_count;
ReferenceToleranceFamilyDecision tolerance;
};
struct GeneratedRunArtifacts {
std::filesystem::path copied_input_path;
std::filesystem::path generated_results_hdf5;
std::filesystem::path generated_log_path;
};
struct NonlinearReferenceComparisonReport {
std::string case_id;
std::filesystem::path original_input_path;
std::filesystem::path copied_input_path;
std::filesystem::path generated_results_hdf5;
std::filesystem::path generated_log_path;
std::vector<ArtifactSnapshot> pre_run_artifacts;
std::vector<ArtifactSnapshot> post_run_artifacts;
std::vector<NonlinearReferenceFamilyReport> families;
bool blocking_passed;
};
enum class NonlinearReferenceClassification {
kPassed,
kFailed,
kWarningOnlyDifferences
};
Result<std::vector<ArtifactSnapshot>> ArtifactCheck(
const NonlinearReferenceCase& reference_case);
Result<std::filesystem::path> CopyInputToExecutionDirectory(
const NonlinearReferenceCase& reference_case);
Result<GeneratedRunArtifacts> RunFesaApplicationOnCopiedInput(
const NonlinearReferenceCase& reference_case,
const std::filesystem::path& copied_input_path);
Result<NonlinearReferenceComparisonReport> CompareHdf5ToReferenceCsv(
const NonlinearReferenceCase& reference_case,
const std::filesystem::path& hdf5_results_path);
NonlinearReferenceClassification ClassifyReferenceComparison(
const NonlinearReferenceComparisonReport& report);
NonlinearReferenceComparisonReport BuildReferenceComparisonReport(
const NonlinearReferenceCase& reference_case,
const std::filesystem::path& hdf5_results_path);
} // namespace fesa::test
```
## RED
Add tests first.
- `NSNR-REF-001`: artifact check verifies exact pre-run SHA-256 for every declared input/CSV path.
- `NSNR-REF-002`: original `reference/shellNL/shellNL.inp` bytes are copied unchanged into a unique build-local temp case directory and only the copied `.inp` is passed to `FesaApplication`.
- `NSNR-REF-003`: original `reference/shell/shell.inp` bytes are copied unchanged into a unique build-local temp case directory and only the copied `.inp` is passed to `FesaApplication`.
- `NSNR-REF-004`: copied shellNL run produces copied-sibling `shellNL_results.h5` and `shellNL_log.txt`; copied shell run produces copied-sibling `shell_results.h5` and `shell_log.txt`.
- `NSNR-REF-005`: HDF5 source path identity matches the copied user-addressed input path, and source content identity matches the approved original input hash.
- `NSNR-REF-006`: exact post-run SHA-256, byte size, timestamp, and inventory for all original declared reference artifacts match pre-run snapshots.
- `NSNR-REF-007`: shellNL displacement/reaction rows require exact `Frame` value `Increment 10: Step Time = 1.000`.
- `NSNR-REF-008`: required CSV wide rows expand to unique `(case_id, accepted_state, instance, source_node_label, component)` keys.
- `NSNR-REF-009`: HDF5 rows and CSV rows reject missing, extra, duplicate, and nonfinite required rows before tolerance.
- `NSNR-REF-010`: `linear.translation` has 147 blocking rows.
- `NSNR-REF-011`: `linear.rotation` has 147 warning-only rows.
- `NSNR-REF-012`: `nonlinear.translation` has 147 blocking rows.
- `NSNR-REF-013`: `nonlinear.rotation` has 147 warning-only rows.
- `NSNR-REF-014`: shellNL constrained nodes select only labels `1,3,4,5,6,7,8,9,14,15,16,17,22,23,24,25,26,27,28,29,30,31,32,33`.
- `NSNR-REF-015`: `RF1/RF2` has 48 blocking rows, `RF3` has 24 blocking rows, and `RM1/RM2` has 48 blocking rows.
- `NSNR-REF-016`: `RM3` and stress quantities create no numeric comparison family.
- `NSNR-REF-017`: docs/TOLERANCE.md family policy is applied exactly and warning-only failures do not change blocking verdict.
- `NSNR-REF-018`: stress CSV files are hash-audited as nonblocking inventory artifacts and their schema/order is not a blocking verdict.
Run:
```powershell
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug -R "NonlinearStaticReference|ReferenceTolerance|Mitc4Reference" --output-on-failure
```
Expected: new tests fail. Unexpected pass stops.
## GREEN
Implement `ARTIFACT CHECK -> COPY -> RUN -> COMPARE -> CLASSIFY -> REPORT` while preserving the required public gate wording `ARTIFACT CHECK -> COMPARE -> CLASSIFY -> REPORT` in reports. The runner never passes the original reference input path to `FesaApplication`; it copies input bytes unchanged into a unique build-local temp case directory, runs the copied `.inp`, consumes copied-sibling `_results.h5` and `_log.txt`, and compares HDF5 data to original read-only CSVs. Use exact declared paths and hashes:
| path | rows | SHA-256 |
| --- | ---: | --- |
| `reference/shellNL/shellNL.inp` | input | `4BF3ECB0F7F1E8462C573E993DBC97AC5D920C91CF6F23AD4C6891D77FFBADA2` |
| `reference/shellNL/shellNL displacements.csv` | 49 | `4E0F99CA9372B1ADF7FAF102F43BC0B887DC743FDEDA378E4342D2CF8E0C0786` |
| `reference/shellNL/shellNL reactions.csv` | 49 | `001CB1541A9E94424E5E650509D46BC8724970DF4DE47184D9DB09C7938AB069` |
| `reference/shellNL/shellNL stresses.csv` | 288 | `5500E5114B1C44887528E30CEC054A1EB0F68BE3F4B8CE81FA59FC74A881483F` |
| `reference/shell/shell.inp` | input | `4005851E1AB22FD3A16AC17A8D5DA3E051233F69F37419079F3553AD134ECFCF` |
| `reference/shell/shell displacements.csv` | 49 | `C81D94E0B4A849F87AA0F79C83A79B94D5661AC79E44ED826919AB432C87746B` |
| `reference/shell/shell reactions.csv` | 49 | `0E34EEC27E700C3C0C744C1DAFD8A3B95EFEF34B8616FE96665876586FE82D41` |
| `reference/shell/shell stresses.csv` | 288 | `2B75A5B0DEB045A283C9BB7E9B1153B79F7537FF487214BF4A23316B59B660A7` |
Use docs/TOLERANCE.md exactly: family scale `S=max(abs(reference))`, near-zero band `0.01*S`, non-near relative error `<=0.05`, family `RMS(error)/S<=0.01`, zero-scale exact zero only. Original reference directory inventory, bytes, timestamps, and hashes must be unchanged after the run.
## VERIFY
```powershell
cmake --fresh -S . -B .harness/build -G "Visual Studio 18 2026" -A x64 `
"-DFESA_GTEST_SOURCE_DIR=$gtestSource" `
"-DMKL_DIR=$mklDir" `
"-DTBB_DIR=$tbbDir" `
"-DHDF5_DIR=$hdf5Dir"
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug -R "NonlinearStaticReference|ReferenceTolerance|Mitc4Reference" --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
Recheck `.harness/config.json` before default commands.
## 상태 기록
Update only Step 11 status and one-line payload. Executor owns timestamps, commits, retry, and advancement.
## 금지사항
- Do not rewrite, rename, normalize, or repair `.inp` or CSV artifacts. 이유: reference artifacts are immutable external evidence.
- Do not run `FesaApplication` on original `reference/shellNL/shellNL.inp` or `reference/shell/shell.inp`. 이유: CLI derives sibling outputs and would mutate the reference directory.
- Do not compare `RM3`. 이유: approved contract excludes stabilization-dependent drilling reaction.
- Do not numerically compare stress CSV data. 이유: stress artifacts are nonblocking inventory only in this feature.
- Do not average, omit, synthesize, or row-order match reference rows. 이유: source/component identity prechecks are mandatory.
@@ -0,0 +1,96 @@
# Step 12: execution-closure-and-evidence-docs
## 읽어야 할 파일
- `AGENTS.md`
- `docs/PRD.md`
- `docs/ARCHITECTURE.md`
- `docs/ADR.md`
- `docs/CODINGSTYLE.md`
- `docs/TOLERANCE.md`
- `docs/nonlinear-static-newton-raphson/implementation-plan.md`
- `docs/nonlinear-static-newton-raphson/requirements.md`
- `docs/nonlinear-static-newton-raphson/numerical-review.md`
- `docs/nonlinear-static-newton-raphson/reference-model.md`
- `docs/nonlinear-static-newton-raphson/io.md`
- `phases/nonlinear-static-newton-raphson/index.json`
- Step 0-11 modified source/test/CMake files
## 이전 Step 전제
Steps 0-11 have implemented and verified CLI lifecycle, Domain contract, nonlinear MITC4, controls, tangent solver, log, state, HDF5 schema v1, full prepared procedure, and reference comparison tests.
## 소유 파일
- Modify: `docs/PRD.md`
- Modify: `docs/ARCHITECTURE.md`
- Modify: `docs/ADR.md`
- Create: `docs/nonlinear-static-newton-raphson/implementation-report.md`
- Create: `docs/nonlinear-static-newton-raphson/build-test.md`
- Create: `docs/nonlinear-static-newton-raphson/reference-comparison.md`
No C++ production file is owned by this Step.
## 인터페이스
Evidence documents must record actual observed outputs:
```text
implementation-report.md: RED/GREEN/VERIFY command log, Step summaries, diagnostics, implementation-owned decisions.
build-test.md: fresh configure/build/discovery/full CTest commands, exit codes, duration, stdout/stderr tail, warning audit, failure classification.
reference-comparison.md: exact artifact inventory, HDF5 paths, projection, row prechecks, tolerance, per-family decisions, classification, no-change assertion.
```
## RED
Before writing evidence docs, run an evidence freshness audit by checking that the three evidence docs do not already contain current command outputs from this final Step.
- `NSNR-EVID-001`: missing or stale `implementation-report.md` is a failing precondition.
- `NSNR-EVID-002`: missing or stale `build-test.md` is a failing precondition.
- `NSNR-EVID-003`: missing or stale `reference-comparison.md` is a failing precondition.
- `NSNR-EVID-004`: PRD/ARCHITECTURE/ADR still contain directly superseded global CLI/procedure/output statements.
- `NSNR-EVID-005`: reference artifact pre-run SHA inventory must match Step 11 values.
Expected: evidence freshness audit fails before this Step writes docs. If it unexpectedly passes with current evidence already present, stop and report to Coordinator.
## GREEN
- Run fresh MSVC x64 Debug configure/build/discovery/full CTest.
- Run focused nonlinear reference comparison repeat.
- Run deterministic repeat/reference checks required by Step 11.
- Run warning audit from build output.
- Run `git diff --check` and `git status --short`.
- Run reference artifact post-run SHA audit and compare to pre-run values.
- Update only directly superseded PRD/ARCHITECTURE/ADR statements for CLI removal, prepared linear/nonlinear procedure boundary, output naming, log lifecycle, and nonlinear HDF5 schema.
- Create the three Stage 6 evidence docs from actual command outputs only.
## VERIFY
Recheck `.harness/config.json`. If absent, use:
```powershell
cmake --fresh -S . -B .harness/build -G "Visual Studio 18 2026" -A x64 `
"-DFESA_GTEST_SOURCE_DIR=$gtestSource" `
"-DMKL_DIR=$mklDir" `
"-DTBB_DIR=$tbbDir" `
"-DHDF5_DIR=$hdf5Dir"
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
ctest --test-dir .harness/build -C Debug -R "NonlinearStaticReference" --output-on-failure
git diff --check
git status --short
```
Record command, exit code, duration, stdout/stderr tail, and failure classification for every command in the evidence docs.
## 상태 기록
Update only Step 12 status and one-line payload. Executor owns timestamps, commits, retry, top-level phase completion, and advancement.
## 금지사항
- Do not claim success before the commands above actually pass. 이유: Stage 6 evidence docs must be output-backed.
- Do not broadly rewrite global docs. 이유: Step 12 only synchronizes directly superseded CLI/procedure/output statements.
- Do not change reference artifact content. 이유: SHA pre/post immutability is part of the acceptance evidence.
- Do not run `scripts/execute.py` from this Step. 이유: Executor already owns Harness execution.
@@ -0,0 +1,101 @@
# Step 2: finite-rotation-state
## 읽어야 할 파일
- `AGENTS.md`
- `docs/ARCHITECTURE.md`
- `docs/ADR.md`
- `docs/nonlinear-static-newton-raphson/formulation.md`
- `docs/nonlinear-static-newton-raphson/numerical-review.md`
- `docs/nonlinear-static-newton-raphson/implementation-plan.md`
- `include/fesa/math/vector3.h`
- `include/fesa/math/matrix.h`
- `tests/unit/math/vector3_test.cpp`
- `tests/unit/math/matrix_test.cpp`
- Step 1 files: `include/fesa/model/model_types.h`, `include/fesa/model/domain.h`
## 이전 Step 전제
Step 1 exposes nonlinear static semantic selection. This Step adds finite rotation math used by nonlinear MITC4 and state recovery.
## 소유 파일
- Create: `include/fesa/elements/finite_rotation.h`
- Create: `src/fesa/elements/finite_rotation.cpp`
- Create: `tests/unit/elements/finite_rotation_test.cpp`
- Modify: `src/fesa/CMakeLists.txt`
- Modify: `tests/CMakeLists.txt`
## 인터페이스
```cpp
namespace fesa {
struct FiniteRotationState {
Vector3 phi;
Matrix q;
Vector3 director;
};
Matrix ExpSkew(const Vector3& phi);
Matrix LeftJacobianSO3(const Vector3& phi);
Matrix InverseTransposeLeftJacobianSO3(const Vector3& phi);
Result<FiniteRotationState> MakeFiniteRotationState(
const Vector3& phi, const Matrix& initial_frame);
Result<FiniteRotationState> ApplyGlobalRotationIncrement(
const FiniteRotationState& committed,
const Vector3& delta_phi,
const Matrix& initial_frame);
} // namespace fesa
```
## RED
Add tests first.
- `NSNR-ROT-001`: zero `phi` returns `Q0` and `director=Q0*e3`.
- `NSNR-ROT-002`: finite `phi` satisfies `Q=exp(phi^)Q0`, `Q^T Q=I`, `det(Q)=1`, `director=Qe3`.
- `NSNR-ROT-003`: update uses `Q+ = exp((phi + delta_phi)^)Q0`.
- `NSNR-ROT-004`: principal branch margin `sqrt(epsilon_double)` rejects ambiguous rotations near `pi`.
- `NSNR-ROT-005`: `LeftJacobianSO3` and inverse-transpose are finite and derivative-consistent for small, medium, and near-branch-safe rotations.
- `NSNR-ROT-006`: nonfinite rotation components fail with `invalid-accepted-state` or the Step-introduced finite-rotation diagnostic.
Run:
```powershell
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug -R "FiniteRotation" --output-on-failure
```
Expected: tests fail because the rotation module does not exist. Unexpected pass stops.
## GREEN
Implement the SO(3) helper functions with finite checks and principal-branch validation. Use existing FESA math types and keep MKL/vendor types out of public headers.
## VERIFY
```powershell
cmake --fresh -S . -B .harness/build -G "Visual Studio 18 2026" -A x64 `
"-DFESA_GTEST_SOURCE_DIR=$gtestSource" `
"-DMKL_DIR=$mklDir" `
"-DTBB_DIR=$tbbDir" `
"-DHDF5_DIR=$hdf5Dir"
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug -R "FiniteRotation" --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
Recheck `.harness/config.json` before using default commands.
## 상태 기록
Update only Step 2 status and summary/error/blocked payload. Executor owns timestamps, commits, retry, and advancement.
## 금지사항
- Do not normalize invalid rotation matrices to make tests pass. 이유: invalid nonlinear state must fail closed.
- Do not add element residual or tangent code here. 이유: this Step owns only finite rotation state.
- Do not expose backend/vendor types. 이유: public solver core must remain backend-neutral.
@@ -0,0 +1,124 @@
# Step 3: nonlinear-mitc4-kinematics-and-recovery
## 읽어야 할 파일
- `AGENTS.md`
- `docs/ARCHITECTURE.md`
- `docs/ADR.md`
- `docs/nonlinear-static-newton-raphson/formulation.md`
- `docs/nonlinear-static-newton-raphson/numerical-review.md`
- `docs/nonlinear-static-newton-raphson/io.md`
- `include/fesa/elements/mitc4_shell.h`
- `src/fesa/elements/mitc4_shell.cpp`
- `tests/unit/elements/mitc4_shell_test.cpp`
- `include/fesa/model/shell_geometry.h`
- `src/fesa/model/shell_geometry.cpp`
- `include/fesa/model/model_types.h`
- `include/fesa/results/result_records.h`
- Step 2 files: `include/fesa/elements/finite_rotation.h`, `src/fesa/elements/finite_rotation.cpp`
## 이전 Step 전제
Step 2 provides finite rotation state and SO(3) Jacobian helpers.
## 소유 파일
- Create: `include/fesa/elements/nonlinear_mitc4_shell.h`
- Create: `src/fesa/elements/nonlinear_mitc4_shell.cpp`
- Create: `tests/unit/elements/nonlinear_mitc4_shell_test.cpp`
- Modify: `src/fesa/CMakeLists.txt`
- Modify: `tests/CMakeLists.txt`
## 인터페이스
```cpp
namespace fesa {
struct NonlinearMitc4TrialDofs {
std::array<Vector3, 4> displacement;
std::array<Vector3, 4> rotation_vector;
};
struct NonlinearMitc4RecoveryPoint {
ShellMidsurfaceLocation location;
std::array<double, 2> natural_coordinates;
Mitc4LocalFrame local_frame;
std::array<double, 8> generalized_strain;
std::array<double, 8> section_resultant;
std::array<ShellSectionStressRow, 3> stress;
};
struct NonlinearMitc4Recovery {
std::array<NonlinearMitc4RecoveryPoint, 4> gauss_points;
double physical_strain_energy;
};
class NonlinearMitc4Shell {
public:
static Result<NonlinearMitc4Shell> Create(
std::array<const Node*, 4> nodes,
std::array<ShellNodeInitialFrame, 4> initial_frames,
const ShellSection& section,
const LinearElasticMaterial& material);
Result<NonlinearMitc4Recovery> EvaluateKinematics(
const NonlinearMitc4TrialDofs& trial) const;
Result<NonlinearMitc4Recovery> RecoverState(
const NonlinearMitc4TrialDofs& trial) const;
};
} // namespace fesa
```
## RED
Add tests first.
- `NSNR-ELEM-KIN-001`: initial undeformed state produces zero generalized strain and zero material stress.
- `NSNR-ELEM-KIN-001A`: `NonlinearMitc4Shell::Create` requires exactly four `Node` pointers, four corresponding `ShellNodeInitialFrame` records, one `ShellSection`, and one `LinearElasticMaterial`; invalid or mismatched inputs fail closed.
- `NSNR-ELEM-KIN-002`: fixed-initial Total Lagrangian geometry uses initial midsurface and initial directors.
- `NSNR-ELEM-KIN-003`: current director interpolation for strain uses unnormalized interpolated director where formulation requires it.
- `NSNR-ELEM-KIN-004`: opposed or degenerate director state fails closed.
- `NSNR-ELEM-KIN-005`: small-rotation linear limit matches existing `Mitc4Shell` recovery within numerical-review tolerance.
- `NSNR-ELEM-KIN-006`: finite rigid translation/rotation produces objective zero physical strain/stress.
- `NSNR-ELEM-KIN-007`: recovery emits exactly four midsurface Gauss rows in `ShellMidsurfaceLocation` order; each row has generalized strain `[E11,E22,2E12,K11,K22,2K12,G13,G23]`, section resultant `[N11,N22,N12,M11,M22,M12,Q13,Q23]`, and stress positions `[BOTTOM,MIDDLE,TOP]` with components `[S11,S22,S12]`.
- `NSNR-ELEM-KIN-008`: recovery emits no S33, S13, S23 and no nodal extrapolated/corner/averaged stress.
Run:
```powershell
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug -R "NonlinearMitc4Shell|NonlinearMitc4Recovery" --output-on-failure
```
Expected: compile or test failure because nonlinear MITC4 files do not exist. Unexpected pass stops.
## GREEN
Implement nonlinear MITC4 creation, kinematics, and recovery using approved 2x2x2 integration, MITC4 edge-midpoint shear tying, initial shell frames, homogeneous isotropic materially linear response, fixed-size row shapes, and source-order recovery rows.
## VERIFY
```powershell
cmake --fresh -S . -B .harness/build -G "Visual Studio 18 2026" -A x64 `
"-DFESA_GTEST_SOURCE_DIR=$gtestSource" `
"-DMKL_DIR=$mklDir" `
"-DTBB_DIR=$tbbDir" `
"-DHDF5_DIR=$hdf5Dir"
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug -R "NonlinearMitc4Shell|NonlinearMitc4Recovery" --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
Recheck `.harness/config.json` before default commands.
## 상태 기록
Update only Step 3 status and one-line result payload. Executor owns timestamps, commits, retry, and advancement.
## 금지사항
- Do not change existing `Mitc4Shell` behavior. 이유: linear MITC4 reference regression must remain stable.
- Do not create stress quantities outside approved schema. 이유: I/O excludes S33/S13/S23 and nodal stress projections.
- Do not add residual/tangent solve logic here. 이유: Step 4 owns residual and tangent.
@@ -0,0 +1,99 @@
# Step 4: nonlinear-mitc4-residual-and-tangent
## 읽어야 할 파일
- `AGENTS.md`
- `docs/ARCHITECTURE.md`
- `docs/ADR.md`
- `docs/nonlinear-static-newton-raphson/formulation.md`
- `docs/nonlinear-static-newton-raphson/numerical-review.md`
- `include/fesa/elements/nonlinear_mitc4_shell.h`
- `src/fesa/elements/nonlinear_mitc4_shell.cpp`
- `tests/unit/elements/nonlinear_mitc4_shell_test.cpp`
- Step 2 files: `include/fesa/elements/finite_rotation.h`
- Step 3 files: `include/fesa/elements/nonlinear_mitc4_shell.h`
## 이전 Step 전제
Step 3 provides nonlinear MITC4 creation, kinematics, and recovery rows.
## 소유 파일
- Modify: `include/fesa/elements/nonlinear_mitc4_shell.h`
- Modify: `src/fesa/elements/nonlinear_mitc4_shell.cpp`
- Create: `tests/unit/elements/nonlinear_mitc4_shell_tangent_test.cpp`
- Modify: `tests/CMakeLists.txt`
## 인터페이스
```cpp
namespace fesa {
struct NonlinearMitc4InternalEquilibrium {
Vector internal_residual;
Matrix internal_tangent;
Vector internal_force;
NonlinearMitc4Recovery recovery;
double physical_strain_energy;
};
Result<NonlinearMitc4InternalEquilibrium> EvaluateInternalResidualAndTangent(
const NonlinearMitc4Shell& element,
const NonlinearMitc4TrialDofs& trial);
} // namespace fesa
```
## RED
Add tests first.
- `NSNR-ELEM-TAN-001`: residual and tangent are evaluated at the same trial state.
- `NSNR-ELEM-TAN-002`: directional derivative schedule uses `h={1e-3,3e-4,1e-4,3e-5,1e-5,3e-6,1e-6,3e-7}` and requires at least two observed orders `>=1.5`.
- `NSNR-ELEM-TAN-003`: one interior scaled derivative error is `<=1e-6`.
- `NSNR-ELEM-TAN-004`: zero analytical directions produce scaled absolute error `<=1e-10`.
- `NSNR-ELEM-TAN-005`: no-moment tangent satisfies scaled Frobenius symmetry `<=1e-12` after `Dq^T K_T Dq`.
- `NSNR-ELEM-TAN-006`: internal tangent contains no external fixed-load contribution; applying the same element to two incident-element load-sharing scenarios does not change internal residual/tangent.
- `NSNR-ELEM-TAN-007`: finite rigid motion keeps physical residual/objectivity invariants.
- `NSNR-ELEM-TAN-008`: patch/sign recovery identities pass relative `<=1e-9`.
- `NSNR-ELEM-TAN-009`: nonfinite trial/residual/tangent data fails closed.
Run:
```powershell
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug -R "NonlinearMitc4Residual|NonlinearMitc4Tangent|NonlinearMitc4Objectivity|NonlinearMitc4Patch" --output-on-failure
```
Expected: new tests fail. Unexpected pass stops.
## GREEN
Implement same-trial internal residual/tangent, exact rotation derivative terms through `J_l`, map Hessian terms, objective drilling contribution, and physical recovery in the element-local contract. External CLOAD vector and tangent are not element inputs and are assembled globally in Step 5.
## VERIFY
```powershell
cmake --fresh -S . -B .harness/build -G "Visual Studio 18 2026" -A x64 `
"-DFESA_GTEST_SOURCE_DIR=$gtestSource" `
"-DMKL_DIR=$mklDir" `
"-DTBB_DIR=$tbbDir" `
"-DHDF5_DIR=$hdf5Dir"
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug -R "NonlinearMitc4Residual|NonlinearMitc4Tangent|NonlinearMitc4Objectivity|NonlinearMitc4Patch" --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
Recheck `.harness/config.json` before default commands.
## 상태 기록
Update only Step 4 status and one-line payload. Executor owns timestamps, commits, retry, and advancement.
## 금지사항
- Do not symmetrize the internal tangent as a cleanup step. 이유: derivative and symmetry tests must observe the mathematically assembled operator; Step 5 owns external moment tangent nonsymmetry.
- Do not add solver factorization in this Step. 이유: Step 6 owns tangent solver backend.
- Do not pass nodal CLOAD force or moment into each incident element. 이유: it duplicates source-node loads; Step 5 owns global-once external assembly.
- Do not claim Abaqus internal equivalence. 이유: FESA only uses Abaqus CSV as external numeric reference.
@@ -0,0 +1,179 @@
# Step 5: load-boundary-path-and-convergence-gates
## 읽어야 할 파일
- `AGENTS.md`
- `docs/ARCHITECTURE.md`
- `docs/nonlinear-static-newton-raphson/requirements.md`
- `docs/nonlinear-static-newton-raphson/formulation.md`
- `docs/nonlinear-static-newton-raphson/numerical-review.md`
- `docs/nonlinear-static-newton-raphson/io.md`
- `include/fesa/core/diagnostic.h`
- `include/fesa/fem/dof_manager.h`
- `include/fesa/math/sparse_matrix.h`
- `include/fesa/math/vector3.h`
- Step 1 files: `include/fesa/model/domain.h`, `include/fesa/model/model_types.h`
- Step 4 files: `include/fesa/elements/nonlinear_mitc4_shell.h`
## 이전 Step 전제
Step 1 stores raw nonlinear static values in Domain. Step 4 provides internal-only element residual/tangent. This Step owns global-once fixed CLOAD, absolute boundary path assembly, and the external contribution sign contract used by Step 10: `r = f_int - f_ext`, `K_T = K_int - K_ext`.
## 소유 파일
- Create: `include/fesa/analysis/nonlinear_static_control.h`
- Create: `src/fesa/analysis/nonlinear_static_control.cpp`
- Create: `tests/unit/analysis/nonlinear_static_control_test.cpp`
- Modify: `src/fesa/CMakeLists.txt`
- Modify: `tests/CMakeLists.txt`
## 인터페이스
```cpp
namespace fesa {
struct LoadFactorIncrement {
std::uint32_t increment_index;
double load_factor;
bool is_factor_one;
};
enum class NewtonChannelUnit {
kForce,
kForceLength,
kLength,
kDimensionless
};
inline constexpr double kNewtonRelativeThreshold = 1.0e-2;
inline constexpr double kNewtonZeroScaleThreshold = 1.0e-3;
struct NewtonResidualChannelInput {
std::string identity;
Vector free_residual;
Vector free_internal;
Vector free_external;
};
struct NewtonCorrectionChannelInput {
std::string identity;
Vector fresh_correction;
Vector current_increment;
};
struct NewtonConvergenceInput {
NewtonResidualChannelInput force_residual;
NewtonResidualChannelInput moment_residual;
NewtonCorrectionChannelInput translation_correction;
NewtonCorrectionChannelInput rotation_correction;
};
enum class NewtonConvergenceBranch {
kRelative,
kZeroScale
};
struct NewtonChannelDecision {
std::string identity;
double numerator_norm;
double denominator_scale;
NewtonConvergenceBranch branch;
double threshold;
NewtonChannelUnit threshold_unit;
bool passed;
};
struct NewtonConvergenceResult {
NewtonChannelDecision force_residual;
NewtonChannelDecision moment_residual;
NewtonChannelDecision translation_correction;
NewtonChannelDecision rotation_correction;
bool combined_passed;
};
struct GlobalFixedLoadContribution {
Vector generalized_external_force;
SparseMatrix generalized_external_tangent;
std::vector<Diagnostic> diagnostics;
};
Result<std::vector<LoadFactorIncrement>> BuildFixedLoadFactorSequence(
const StepDefinition& step);
Result<Vector> ApplyAbsolutePrescribedDisplacementTarget(
const StepDefinition& step, double load_factor);
Result<GlobalFixedLoadContribution> AssembleGlobalFixedLoadContribution(
const Domain& domain,
const DofManager& dofs,
const Vector& trial_generalized_coordinates,
double load_factor);
Status CheckMomentAdmissibility(const Vector3& director,
const Vector3& source_moment);
NewtonConvergenceResult EvaluateNewtonConvergence(
const NewtonConvergenceInput& input);
} // namespace fesa
```
## RED
Add tests first.
- `NSNR-CTRL-001`: raw `initial_increment=0.1` and `time_period=1.0` produce factors `0.1..1.0`.
- `NSNR-CTRL-002`: final factor is assigned exact `1.0`, not accumulated past one.
- `NSNR-CTRL-003`: positive minimum/maximum values are accepted but not used for runtime stepping.
- `NSNR-CTRL-004`: nonzero `*BOUNDARY` value is absolute factor-one target from step-start committed state.
- `NSNR-CTRL-005`: constrained Newton correction remains exactly zero.
- `NSNR-CTRL-006`: `*CLOAD` force and moment directions remain fixed global dead loads and scale by factor.
- `NSNR-CTRL-007`: moment admissibility accepts `rho_M <= 1e-12` and rejects larger drilling-aligned moment.
- `NSNR-CTRL-008`: `AssembleGlobalFixedLoadContribution` contributes each aggregated source node load exactly once, independent of incident element count.
- `NSNR-CTRL-009`: source-order load rows produce deterministic global vector and tangent order.
- `NSNR-CTRL-010`: fixed-spatial moment projection and `J_l`/map-Hessian tangent terms pass directional derivative checks and may make `K_ext` nonsymmetric.
- `NSNR-CTRL-011`: global fixed-load assembly returns external quantities consumed with approved signs `r = f_int - f_ext` and `K_T = K_int - K_ext`; the fixed-moment tangent is subtracted once and is never duplicated per incident element.
- `NSNR-CTRL-012`: `NewtonConvergenceInput` has no caller-supplied threshold or unit fields; `EvaluateNewtonConvergence` owns exact immutable constants `kNewtonRelativeThreshold=1.0e-2` and `kNewtonZeroScaleThreshold=1.0e-3`.
- `NSNR-CTRL-013`: four convergence gates expose identity, `numerator_norm`, `denominator_scale`, branch, typed threshold, `threshold_unit`, pass, and combined pass.
- `NSNR-CTRL-014`: nonzero-denominator relative branches use threshold `1.0e-2` and threshold unit `kDimensionless` for all four channels.
- `NSNR-CTRL-015`: zero-scale branches use threshold `1.0e-3` with units `kForce`, `kForceLength`, `kLength`, and `kDimensionless` for residual force, residual moment, correction translation, and correction rotation respectively.
- `NSNR-CTRL-016`: empty free channels evaluate with `numerator_norm=0`, `denominator_scale=0`, branch `kZeroScale`, exact zero-scale threshold/unit, and pass.
- `NSNR-CTRL-017`: iteration numbering remains `1..100` with no iteration `101`.
Run:
```powershell
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug -R "NonlinearStaticControl|NonlinearConvergence|NonlinearLoadBoundary" --output-on-failure
```
Expected: new tests fail. Unexpected pass stops.
## GREEN
Implement factor sequence derivation, load/BC scaling, global-once fixed-load external vector `f_ext` and external tangent `K_ext` assembly, moment admissibility, and typed convergence-channel evaluation. Residual denominator scale is derived from the provided free internal/external channel values, correction denominator scale from the provided current increment channel values, and zero-scale branches use only `kZeroScale`. Thresholds and threshold units are not caller inputs; `EvaluateNewtonConvergence` assigns the exact branch/channel constants from `requirements.md` and `io.md`. Return structured diagnostics for invalid nonlinear static data, unsupported drilling load, nonfinite Newton data, and nonconvergence readiness.
## VERIFY
```powershell
cmake --fresh -S . -B .harness/build -G "Visual Studio 18 2026" -A x64 `
"-DFESA_GTEST_SOURCE_DIR=$gtestSource" `
"-DMKL_DIR=$mklDir" `
"-DTBB_DIR=$tbbDir" `
"-DHDF5_DIR=$hdf5Dir"
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug -R "NonlinearStaticControl|NonlinearConvergence|NonlinearLoadBoundary" --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
Recheck `.harness/config.json` before default commands.
## 상태 기록
Update only Step 5 status and one-line payload. Executor owns timestamps, commits, retry, and advancement.
## 금지사항
- Do not put factor sequence storage into Domain. 이유: control layer derives runtime factors.
- Do not implement cutback, line search, damping, or automatic growth. 이유: approved Full Newton path excludes them.
- Do not mutate source load vectors. 이유: fixed-global source identity must remain immutable.
- Do not distribute full source-node CLOAD into every incident element. 이유: this would multiply loads by incident element count and violate formulation §11.2.
- Do not emit convergence branch labels outside `relative` and `zero-scale`. 이유: io.md exposes exactly those two branches.
- Do not accept per-call convergence thresholds or units. 이유: NSNR-069/070 fix branch thresholds and typed units globally.
@@ -0,0 +1,105 @@
# Step 6: backend-neutral-tangent-solver
## 읽어야 할 파일
- `AGENTS.md`
- `docs/ARCHITECTURE.md`
- `docs/ADR.md`
- `docs/nonlinear-static-newton-raphson/formulation.md`
- `docs/nonlinear-static-newton-raphson/numerical-review.md`
- `include/fesa/solvers/linear/linear_solver.h`
- `include/fesa/solvers/linear/mkl_pardiso_solver.h`
- `src/fesa/solvers/linear/mkl_pardiso_solver.cpp`
- `tests/unit/solvers/linear/linear_solver_test.cpp`
- `tests/unit/solvers/linear/mkl_pardiso_solver_test.cpp`
- Step 4 files: `include/fesa/elements/nonlinear_mitc4_shell.h`
## 이전 Step 전제
Step 4 defines generally nonsymmetric nonlinear tangent matrices. Current SPD `MklPardisoSolver` must remain unchanged.
## 소유 파일
- Create: `include/fesa/solvers/linear/tangent_solver.h`
- Create: `include/fesa/solvers/linear/mkl_pardiso_tangent_solver.h`
- Create: `src/fesa/solvers/linear/mkl_pardiso_tangent_solver.cpp`
- Create: `tests/unit/solvers/linear/tangent_solver_test.cpp`
- Test: `tests/unit/solvers/linear/mkl_pardiso_solver_test.cpp`
- Modify: `src/fesa/CMakeLists.txt`
- Modify: `tests/CMakeLists.txt`
## 인터페이스
```cpp
namespace fesa {
class TangentSolver {
public:
virtual ~TangentSolver() = default;
virtual Status FactorizeFresh(const SparseMatrix& matrix) = 0;
virtual Status SolveCorrection(const Vector& rhs,
Vector& correction) const = 0;
};
class MklPardisoTangentSolver final : public TangentSolver {
public:
MklPardisoTangentSolver();
~MklPardisoTangentSolver() override;
Status FactorizeFresh(const SparseMatrix& matrix) override;
Status SolveCorrection(const Vector& rhs, Vector& correction) const override;
};
} // namespace fesa
```
The MKL tangent adapter uses unsymmetric PARDISO full CSR with `mtype=11`. Existing `MklPardisoSolver` keeps `mtype=2`, SPD symmetry validation, and upper-triangle copy unchanged.
## RED
Add tests first.
- `NSNR-SOLVER-001`: nonsymmetric 2x2 matrix factorizes and solves a known correction.
- `NSNR-SOLVER-002`: `0x0` matrix factorize/solve succeeds with zero-size vectors.
- `NSNR-SOLVER-003`: nonfinite matrix or RHS values fail without modifying output correction.
- `NSNR-SOLVER-004`: singular/factorization failure maps to deterministic solver diagnostic.
- `NSNR-SOLVER-005`: solve before successful factorization fails with solver diagnostic.
- `NSNR-SOLVER-006`: existing SPD `MklPardisoSolver` still rejects nonsymmetric public CSR and passes prior tests.
Run:
```powershell
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug -R "TangentSolver|MklPardiso" --output-on-failure
```
Expected: new tests fail. Unexpected pass stops.
## GREEN
Implement backend-neutral tangent solver boundary and MKL full-CSR adapter. Factorization is fresh per call, releases previous backend state, validates dimensions and finite values, and translates PARDISO errors to FESA `Status`.
## VERIFY
```powershell
cmake --fresh -S . -B .harness/build -G "Visual Studio 18 2026" -A x64 `
"-DFESA_GTEST_SOURCE_DIR=$gtestSource" `
"-DMKL_DIR=$mklDir" `
"-DTBB_DIR=$tbbDir" `
"-DHDF5_DIR=$hdf5Dir"
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug -R "TangentSolver|MklPardiso" --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
Recheck `.harness/config.json` before default commands.
## 상태 기록
Update only Step 6 status and one-line payload. Executor owns timestamps, commits, retry, and advancement.
## 금지사항
- Do not modify SPD `MklPardisoSolver` behavior except tests proving it is unchanged. 이유: existing linear solver contract must remain stable.
- Do not symmetrize or regularize tangent matrices. 이유: approved tangent may be nonsymmetric and failures must surface.
- Do not expose MKL types in public headers. 이유: backend types remain behind solver boundaries.
@@ -0,0 +1,132 @@
# Step 7: newton-iteration-log-writer
## 읽어야 할 파일
- `AGENTS.md`
- `docs/ARCHITECTURE.md`
- `docs/nonlinear-static-newton-raphson/io.md`
- `docs/nonlinear-static-newton-raphson/formulation.md`
- `docs/nonlinear-static-newton-raphson/implementation-plan.md`
- Step 0 files: `include/fesa/app/output_paths.h`, `src/fesa/app/output_paths.cpp`, `include/fesa/analysis/analysis.h`
- Step 5 files: `include/fesa/analysis/nonlinear_static_control.h`
## 이전 Step 전제
Step 0 gives app-owned log path and lease lifetime. Step 5 defines convergence-channel data that log records consume.
## 소유 파일
- Create: `include/fesa/analysis/newton_iteration_log.h`
- Create: `src/fesa/analysis/newton_iteration_log.cpp`
- Create: `tests/unit/analysis/newton_iteration_log_test.cpp`
- Modify: `src/fesa/CMakeLists.txt`
- Modify: `tests/CMakeLists.txt`
## 인터페이스
```cpp
namespace fesa {
enum class NewtonIterationStage {
kEntered,
kKinematicsEvaluated,
kInternalAssembled,
kExternalAssembled,
kSolvedCorrection,
kConvergenceEvaluated,
kAccepted,
kFailed
};
struct NewtonIterationFailure {
bool present;
NewtonIterationStage stage;
std::string diagnostic_code;
std::string reason;
};
struct NewtonIterationLogRecord {
std::string step_name;
std::uint32_t increment_index;
double load_factor;
std::uint32_t iteration;
NewtonIterationStage last_completed_stage;
NewtonIterationFailure failure;
std::string transition;
std::string outcome;
std::string diagnostic_code;
NewtonChannelDecision force_residual;
NewtonChannelDecision moment_residual;
NewtonChannelDecision translation_correction;
NewtonChannelDecision rotation_correction;
bool combined_passed;
};
class NewtonIterationLogWriter {
public:
Status Open(const std::filesystem::path& log_path);
Status Write(const NewtonIterationLogRecord& record);
Status Flush();
Status Close();
};
} // namespace fesa
```
The serializer, not callers, owns the exact 39 labels and fixed order from `io.md`. For evaluated convergence channels it serializes only `relative` or `zero-scale` branch labels from `NewtonConvergenceBranch`. For unevaluated typed fields it writes `not-evaluated(reason)` using `NewtonIterationFailure::reason`. Callers cannot inject arbitrary fields.
## RED
Add tests first.
- `NSNR-LOG-001`: a complete Newton iteration writes exactly one LF-terminated line.
- `NSNR-LOG-002`: line is UTF-8 without BOM, no header, no trailer.
- `NSNR-LOG-003`: line has exactly 39 TAB-separated `label=value` fields in approved order.
- `NSNR-LOG-004`: finite numeric values round-trip without locale dependence.
- `NSNR-LOG-005`: each convergence channel serializes identity, `numerator_norm`, `denominator_scale`, branch, threshold, `threshold_unit`, and pass from `NewtonChannelDecision`.
- `NSNR-LOG-006`: evaluated empty free-channel decisions serialize `numerator_norm=0`, `denominator_scale=0`, threshold `1.0e-3`, the channel-specific zero-scale `threshold_unit`, and branch `zero-scale`; no other branch label appears.
- `NSNR-LOG-007`: combined pass, transition, outcome, failure stage, and diagnostic code are serialized from explicit record fields.
- `NSNR-LOG-008`: early failure fields after the failed stage use `not-evaluated(reason)`.
- `NSNR-LOG-009`: embedded tab, LF, CR, and backslash are escaped deterministically.
- `NSNR-LOG-010`: write/flush/close failure returns `log-output-failure` and prevents success classification.
- `NSNR-LOG-011`: non-Newton controlled failure path can leave a zero-byte log owned by app lifecycle.
Run:
```powershell
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug -R "NewtonIterationLog" --output-on-failure
```
Expected: new tests fail. Unexpected pass stops.
## GREEN
Implement a small log writer with explicit open/write/flush/close state, serializer-owned 39-field order, deterministic escaping, finite numeric formatting, `relative`/`zero-scale` convergence branch mapping, typed `not-evaluated(reason)` substitution, and structured `Status` failures.
## VERIFY
```powershell
cmake --fresh -S . -B .harness/build -G "Visual Studio 18 2026" -A x64 `
"-DFESA_GTEST_SOURCE_DIR=$gtestSource" `
"-DMKL_DIR=$mklDir" `
"-DTBB_DIR=$tbbDir" `
"-DHDF5_DIR=$hdf5Dir"
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug -R "NewtonIterationLog" --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
Recheck `.harness/config.json` before default commands.
## 상태 기록
Update only Step 7 status and one-line payload. Executor owns timestamps, commits, retry, and advancement.
## 금지사항
- Do not duplicate per-iteration log lines to stderr. 이유: approved log is file-only.
- Do not accept arbitrary caller-provided field vectors. 이유: io.md requires an exact fixed schema and order.
- Do not write HDF5 trial history. 이유: log is diagnostic and HDF5 stores accepted frames only.
- Do not continue after log write/flush/close failure. 이유: log failure blocks result commit.
@@ -0,0 +1,169 @@
# Step 8: nonlinear-state-commit-rollback
## 읽어야 할 파일
- `AGENTS.md`
- `docs/ARCHITECTURE.md`
- `docs/ADR.md`
- `docs/nonlinear-static-newton-raphson/requirements.md`
- `docs/nonlinear-static-newton-raphson/formulation.md`
- `docs/nonlinear-static-newton-raphson/io.md`
- `include/fesa/analysis/analysis_state.h`
- `src/fesa/analysis/analysis_state.cpp`
- `include/fesa/core/source_identity.h`
- `include/fesa/fem/dof_manager.h`
- `include/fesa/model/domain.h`
- `include/fesa/results/result_records.h`
- Step 3 files: `include/fesa/elements/nonlinear_mitc4_shell.h`
- Step 4 files: `include/fesa/elements/nonlinear_mitc4_shell.h`
- Step 5 files: `include/fesa/analysis/nonlinear_static_control.h`
- Step 6 files: `include/fesa/solvers/linear/tangent_solver.h`
- Step 7 files: `include/fesa/analysis/newton_iteration_log.h`
## 이전 Step 전제
Steps 3-7 provide nonlinear element recovery, residual/tangent, controls, tangent solver, and Newton log record types.
## 소유 파일
- Create: `include/fesa/analysis/nonlinear_analysis_state.h`
- Create: `src/fesa/analysis/nonlinear_analysis_state.cpp`
- Create: `tests/unit/analysis/nonlinear_analysis_state_test.cpp`
- Modify: `src/fesa/CMakeLists.txt`
- Modify: `tests/CMakeLists.txt`
## 인터페이스
```cpp
namespace fesa {
struct NonlinearNodeBaseline {
EntityIndex node_index;
SourceEntityId source_id;
std::array<std::array<double, 3>, 3> triad;
std::array<double, 3> director;
};
struct NonlinearStateBaselineInput {
std::vector<NonlinearNodeBaseline> node_baselines;
};
struct NonlinearTrialState {
std::uint32_t increment_index;
double load_factor;
bool is_factor_zero_baseline;
std::vector<EntityIndex> nodal_internal_order;
std::vector<SourceEntityId> nodal_source_ids;
Vector generalized_coordinates;
Vector displacement;
Vector rotation_vector;
std::vector<std::array<std::array<double, 3>, 3>> nodal_triad;
std::vector<std::array<double, 3>> nodal_director;
Vector internal_force;
Vector external_force;
Vector residual;
Vector reaction;
std::vector<ShellResultRow> shell_results;
double physical_strain_energy;
std::array<double, 6> global_equilibrium;
};
struct AcceptedFrameState {
std::uint32_t frame_index;
std::uint32_t increment_index;
double load_factor;
std::uint32_t iteration_count;
bool is_factor_one;
std::vector<EntityIndex> nodal_internal_order;
std::vector<SourceEntityId> nodal_source_ids;
Vector generalized_coordinates;
Vector displacement;
Vector rotation_vector;
std::vector<std::array<std::array<double, 3>, 3>> nodal_triad;
std::vector<std::array<double, 3>> nodal_director;
Vector internal_force;
Vector external_force;
Vector residual;
Vector reaction;
std::vector<ShellResultRow> shell_results;
double physical_strain_energy;
std::array<double, 6> global_equilibrium;
};
class NonlinearAnalysisState {
public:
static Result<NonlinearAnalysisState> Create(
const Domain& domain,
const DofManager& dofs,
const NonlinearStateBaselineInput& baseline);
Result<NonlinearTrialState> BeginTrialFromCommitted() const;
Status CommitAcceptedFrame(const AcceptedFrameState& frame);
void DiscardTrial() noexcept;
const std::vector<AcceptedFrameState>& AcceptedFrames() const noexcept;
const NonlinearTrialState& CommittedState() const noexcept;
};
} // namespace fesa
```
## RED
Add tests first.
- `NSNR-STATE-000`: `NonlinearAnalysisState::Create` requires exactly one `NonlinearNodeBaseline` per `Domain.Nodes()` entry in stable internal order; each entry has `node_index` equal to its vector offset and `source_id` equal to `Domain.Nodes()[node_index].source_id`.
- `NSNR-STATE-001`: `NonlinearAnalysisState::Create` rejects missing, extra, duplicate, out-of-order, or instance-label mismatched node identities before any mutable state is produced.
- `NSNR-STATE-002`: `NonlinearAnalysisState::Create` validates node/DOF/frame inventory, sizes all vectors, preserves `nodal_internal_order` and `nodal_source_ids`, and creates a committed factor-zero baseline with `increment_index=0`, `load_factor=0.0`, `is_factor_zero_baseline=true`, and no accepted frames.
- `NSNR-STATE-003`: duplicate source labels across different instances remain distinct when `SourceEntityId::instance_name` differs.
- `NSNR-STATE-004`: trial state starts from committed state and can be discarded without mutation.
- `NSNR-STATE-005`: accepted frames are appended in stable accepted-factor order.
- `NSNR-STATE-006`: frame index is zero-based accepted-frame order; the factor-zero committed baseline is metadata/state only and is never appended as an accepted frame.
- `NSNR-STATE-007`: final frame at load factor `1.0` has `is_factor_one=true`.
- `NSNR-STATE-008`: residual and reaction are stored from full residual `r = f_int - f_ext`.
- `NSNR-STATE-009`: accepted frame owns generalized coordinates, displacement, rotation vector, per-node identity/order, per-node triad/director, internal/external/residual/reaction, stable `ShellResultRow` recovery, physical strain energy, and global equilibrium.
- `NSNR-STATE-010`: all accepted-frame vectors match node/DOF counts and all `ShellResultRow` rows are stable element/midsurface order.
- `NSNR-STATE-011`: commit validates finite values for every approved scalar and atomically rejects nonfinite frames with `invalid-accepted-state`.
- `NSNR-STATE-012`: failed trial preserves prior committed state.
- `NSNR-STATE-013`: no unapproved verification data is stored.
- `NSNR-STATE-014`: committed and accepted nodal identity vectors are preserved for Step 9 HDF5 node datasets and Step 11 HDF5-to-reference source mapping; source label alone is never used as identity.
Run:
```powershell
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug -R "NonlinearAnalysisState|CommitRollback" --output-on-failure
```
Expected: new tests fail. Unexpected pass stops.
## GREEN
Implement `NonlinearAnalysisState::Create` as the only construction seam for a valid nonlinear state. It uses `Domain`, `DofManager`, and `NonlinearStateBaselineInput` to require one baseline per Domain node in stable internal order, match both `EntityIndex` and full `SourceEntityId`, allocate zero generalized/displacement/rotation/internal/external/residual/reaction vectors, preserve nodal order/source identity for HDF5/reference mapping, install finite per-node triads/directors, and establish the committed factor-zero baseline without adding an accepted frame. Commit validates inventory, order, shape, identity, and finiteness before mutating committed state.
## VERIFY
```powershell
cmake --fresh -S . -B .harness/build -G "Visual Studio 18 2026" -A x64 `
"-DFESA_GTEST_SOURCE_DIR=$gtestSource" `
"-DMKL_DIR=$mklDir" `
"-DTBB_DIR=$tbbDir" `
"-DHDF5_DIR=$hdf5Dir"
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug -R "NonlinearAnalysisState|CommitRollback" --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
Recheck `.harness/config.json` before default commands.
## 상태 기록
Update only Step 8 status and one-line payload. Executor owns timestamps, commits, retry, and advancement.
## 금지사항
- Do not put equation ids into Node or Element objects. 이유: `DofManager` owns equation numbering.
- Do not identify baseline nodes by source label alone. 이유: labels are not unique across instances and cannot support stable HDF5/reference mapping.
- Do not commit trial data before convergence gates pass. 이유: rollback/preservation contract depends on committed-state isolation.
- Do not expand existing `AnalysisState` for future nonlinear features. 이유: this Step owns only approved NSNR state.
- Do not store stress projections or verification data outside approved `ShellResultRow`, physical energy, and global equilibrium fields. 이유: schema v1 has a bounded accepted-state contract.
@@ -0,0 +1,118 @@
# Step 9: nonlinear-hdf5-schema-v1-writer
## 읽어야 할 파일
- `AGENTS.md`
- `docs/ARCHITECTURE.md`
- `docs/ADR.md`
- `docs/nonlinear-static-newton-raphson/io.md`
- `docs/nonlinear-static-newton-raphson/reference-model.md`
- `include/fesa/io/hdf5/hdf5_results_writer.h`
- `include/fesa/results/results_writer.h`
- `src/fesa/io/hdf5/hdf5_results_writer.cpp`
- `src/fesa/io/hdf5/hdf5_primitives.h`
- `src/fesa/io/hdf5/hdf5_primitives.cpp`
- `src/fesa/io/hdf5/hdf5_self_check.h`
- `src/fesa/io/hdf5/hdf5_self_check.cpp`
- `tests/unit/io/hdf5/hdf5_results_writer_test.cpp`
- Step 8 files: `include/fesa/analysis/nonlinear_analysis_state.h`
## 이전 Step 전제
Step 8 provides committed nonlinear accepted-frame state. Step 0 and Step 10 own the rule that log close succeeds before this writer is invoked.
## 소유 파일
- Create: `include/fesa/io/hdf5/nonlinear_hdf5_results_writer.h`
- Create: `src/fesa/io/hdf5/nonlinear_hdf5_results_writer.cpp`
- Create: `include/fesa/results/nonlinear_results_writer.h`
- Create: `tests/unit/io/hdf5/nonlinear_hdf5_results_writer_test.cpp`
- Modify: `src/fesa/io/hdf5/hdf5_primitives.h`
- Modify: `src/fesa/io/hdf5/hdf5_primitives.cpp`
- Modify: `src/fesa/io/hdf5/hdf5_self_check.h`
- Modify: `src/fesa/io/hdf5/hdf5_self_check.cpp`
- Modify: `src/fesa/CMakeLists.txt`
- Modify: `tests/CMakeLists.txt`
## 인터페이스
```cpp
namespace fesa {
class NonlinearResultsWriter {
public:
virtual ~NonlinearResultsWriter() = default;
virtual Status Write(const std::filesystem::path& output_path,
const Domain& domain,
const NonlinearAnalysisState& state,
const std::vector<Diagnostic>& diagnostics) = 0;
};
class NonlinearHdf5ResultsWriter final : public NonlinearResultsWriter {
public:
Status Write(const std::filesystem::path& output_path,
const Domain& domain,
const NonlinearAnalysisState& state,
const std::vector<Diagnostic>& diagnostics) override;
};
} // namespace fesa
```
## RED
Add tests first.
- `NSNR-HDF5-001`: `/metadata` has `schema_version=1`, `feature_id=nonlinear-static-newton-raphson`, and approved procedure/formulation/integration attributes.
- `NSNR-HDF5-002`: `/model/nodes`, `/model/elements`, shell section/material/frame/director/constraint datasets match I/O schema.
- `NSNR-HDF5-003`: `/steps/Step-1/accepted_frames` has one row per committed increment.
- `NSNR-HDF5-004`: final row has load factor `1.0` and `is_factor_one=1`.
- `NSNR-HDF5-005`: factor zero metadata exists and factor zero is not a frame.
- `NSNR-HDF5-006`: per-frame nodal displacement, triad, director, internal, external, residual, reaction datasets have approved shapes and column ordering.
- `NSNR-HDF5-007`: reaction rotational columns store `J_l(phi)^(-T)` spatial physical moment.
- `NSNR-HDF5-008`: element shell local frame, generalized strain, section resultant, stress datasets exist with approved shape and identity.
- `NSNR-HDF5-009`: `/global/energy` and `/global/equilibrium` exist for each accepted frame.
- `NSNR-HDF5-010`: no trial history dataset is written.
- `NSNR-HDF5-011`: HDF5 candidate failure preserves prior final file.
- `NSNR-HDF5-012`: writer consumes `std::vector<Diagnostic>` and writes deterministic diagnostics.
- `NSNR-HDF5-013`: `NonlinearHdf5ResultsWriter` implements backend-neutral `NonlinearResultsWriter`, and no HDF5 handle/type appears in analysis/core public headers.
Run:
```powershell
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug -R "NonlinearHdf5|Hdf5ResultsWriter" --output-on-failure
```
Expected: new tests fail. Unexpected pass stops.
## GREEN
Implement `include/fesa/results/nonlinear_results_writer.h` as the backend-neutral boundary and implement schema-v1 nonlinear HDF5 writer using existing HDF5 RAII/primitives/self-check style. Keep HDF5 and platform types private to `src/fesa/io/hdf5`.
## VERIFY
```powershell
cmake --fresh -S . -B .harness/build -G "Visual Studio 18 2026" -A x64 `
"-DFESA_GTEST_SOURCE_DIR=$gtestSource" `
"-DMKL_DIR=$mklDir" `
"-DTBB_DIR=$tbbDir" `
"-DHDF5_DIR=$hdf5Dir"
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug -R "NonlinearHdf5|Hdf5ResultsWriter" --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
Recheck `.harness/config.json` before default commands.
## 상태 기록
Update only Step 9 status and one-line payload. Executor owns timestamps, commits, retry, and advancement.
## 금지사항
- Do not open, write, or replace HDF5 before log close succeeds. 이유: Step 10 app lifecycle enforces log-before-HDF5 finalization.
- Do not write compression, chunking, or trial history. 이유: io.md requires contiguous accepted-state storage.
- Do not make CSV an authoritative output. 이유: official solver output is HDF5.
- Do not include HDF5 headers from analysis/core public headers. 이유: output backend types stay behind writer interfaces.
+53 -2
View File
@@ -66,8 +66,12 @@ class StepExecutor:
"""Phase 디렉토리 안의 step들을 순차 실행하는 하네스."""
MAX_RETRIES = 3
CODEX_TIMEOUT_SECONDS = 1800
CODEX_SANDBOX_ENV = "FESA_HARNESS_CODEX_SANDBOX"
CODEX_SANDBOX_MODES = frozenset({"workspace-write", "danger-full-access"})
IMPLEMENTATION_AGENT_PROFILE = Path(
".codex/agents/implementation-agent.toml"
)
FEAT_MSG = "feat({phase}): step {num} - {name}"
CHORE_MSG = "chore({phase}): step {num} output"
TZ = timezone(timedelta(hours=9))
@@ -253,6 +257,35 @@ class StepExecutor:
)
return mode
def _implementation_agent_settings(self) -> tuple[str, str]:
profile_path = Path(self._root) / self.IMPLEMENTATION_AGENT_PROFILE
try:
profile_lines = profile_path.read_text(encoding="utf-8").splitlines()
except OSError as exc:
raise CodexEnvironmentError(
f"Implementation Agent profile을 읽을 수 없습니다: {profile_path}"
) from exc
settings = {}
for line in profile_lines:
key, separator, value = line.partition("=")
key = key.strip()
if separator and key in {"model", "model_reasoning_effort"}:
try:
settings[key] = json.loads(value.strip())
except json.JSONDecodeError as exc:
raise CodexEnvironmentError(
f"Implementation Agent profile의 {key} 값이 올바른 문자열이 아닙니다."
) from exc
model = settings.get("model")
reasoning_effort = settings.get("model_reasoning_effort")
if not isinstance(model, str) or not isinstance(reasoning_effort, str):
raise CodexEnvironmentError(
"Implementation Agent profile에 model과 model_reasoning_effort 문자열이 필요합니다."
)
return model, reasoning_effort
def _invoke_codex(self, step: dict, preamble: str) -> dict:
step_num, step_name = step["step"], step["name"]
step_file = self._phase_dir / f"step{step_num}.md"
@@ -262,12 +295,20 @@ class StepExecutor:
sys.exit(1)
prompt = preamble + step_file.read_text(encoding="utf-8")
sandbox_mode = self._codex_sandbox_mode()
model, reasoning_effort = self._implementation_agent_settings()
command = [
"codex",
"exec",
"--disable",
"unified_exec",
"--json",
"--model",
model,
"--config",
f"model_reasoning_effort={json.dumps(reasoning_effort)}",
"--sandbox",
self._codex_sandbox_mode(),
sandbox_mode,
"--dangerously-bypass-hook-trust",
"--cd",
self._root,
@@ -281,12 +322,22 @@ class StepExecutor:
capture_output=True,
text=True,
encoding="utf-8",
timeout=1800,
timeout=self.CODEX_TIMEOUT_SECONDS,
)
except FileNotFoundError as exc:
raise CodexEnvironmentError(
"Codex CLI를 찾을 수 없습니다. codex를 설치하고 PATH를 확인하세요."
) from exc
except subprocess.TimeoutExpired as exc:
timeout_message = f"Codex timed out after {exc.timeout} seconds."
stderr = exc.stderr or ""
if stderr:
stderr = f"{timeout_message}\n{stderr}"
else:
stderr = timeout_message
result = subprocess.CompletedProcess(
command, 124, stdout=exc.stdout or "", stderr=stderr
)
if result.returncode != 0:
print(f"\n WARN: Codex가 비정상 종료됨 (code {result.returncode})")
+1
View File
@@ -5,6 +5,7 @@ add_library(
analysis/analysis_state.cpp
analysis/linear_static_analysis.cpp
app/fesa_application.cpp
app/output_paths.cpp
assembly/load_assembler.cpp
assembly/parallel_for.cpp
assembly/sparse_assembler.cpp
+14 -26
View File
@@ -8,6 +8,7 @@
#include "fesa/analysis/analysis.h"
#include "fesa/analysis/linear_static_analysis.h"
#include "fesa/app/output_paths.h"
#include "fesa/assembly/parallel_for.h"
#include "fesa/core/diagnostic.h"
#include "fesa/io/hdf5/hdf5_results_writer.h"
@@ -23,19 +24,6 @@ constexpr int kModelExitCode = 4;
constexpr int kSolverExitCode = 5;
constexpr int kOutputExitCode = 6;
bool StartsWithOption(const std::string& argument) {
return !argument.empty() && argument.front() == '-';
}
Diagnostic UsageDiagnostic() {
return {Severity::kError,
"cli-usage",
{{}, 0U},
"",
"",
"Usage: fesa.exe <model.inp> [--output <results.h5>]."};
}
const char* SeverityName(const Severity severity) {
return severity == Severity::kWarning ? "warning" : "error";
}
@@ -72,23 +60,23 @@ int ExitCodeFor(const Status& status) {
} // namespace
int FesaApplication::Run(const std::vector<std::string>& arguments) {
const bool default_output_form = arguments.size() == 1U &&
!arguments[0U].empty() &&
!StartsWithOption(arguments[0U]);
const bool explicit_output_form =
arguments.size() == 3U && !arguments[0U].empty() &&
!StartsWithOption(arguments[0U]) && arguments[1U] == "--output" &&
!arguments[2U].empty() && !StartsWithOption(arguments[2U]);
if (!default_output_form && !explicit_output_form) {
WriteDiagnostics({UsageDiagnostic()});
const auto paths = DeriveSingleInputOutputPaths(
arguments, std::filesystem::current_path());
if (!paths.HasValue()) {
WriteDiagnostics(paths.GetStatus().Diagnostics());
return kUsageExitCode;
}
auto lease = AcquireOutputWriteLease(paths.Value());
if (!lease.HasValue()) {
WriteDiagnostics(lease.GetStatus().Diagnostics());
return kOutputExitCode;
}
AnalysisRequest request;
request.input_path = arguments[0U];
request.output_path = explicit_output_form
? std::filesystem::path{arguments[2U]}
: std::filesystem::current_path() / "results.h5";
request.input_path = paths.Value().input_path;
request.output_path = paths.Value().results_path;
request.log_path = paths.Value().log_path;
TbbParallelFor parallel_for;
MklPardisoSolver linear_solver;
+127
View File
@@ -0,0 +1,127 @@
#include "fesa/app/output_paths.h"
#include <cstddef>
#include <memory>
#include <string>
#include <utility>
#include <windows.h>
#include "fesa/core/ascii.h"
namespace fesa {
namespace {
Status UsageFailure(const std::string& identity, const std::string& message) {
return Status::Failure(
FailureCategory::kInput,
{{Severity::kError, "cli-usage", {{}, 0U}, "", identity, message}});
}
Status OutputBusyFailure(const std::filesystem::path& results_path) {
return Status::Failure(
FailureCategory::kOutput,
{{Severity::kError,
"output-busy",
{{}, 0U},
"",
results_path.generic_u8string(),
"The derived output pair is already owned by another invocation."}});
}
bool StartsWithOption(const std::string& argument) {
return !argument.empty() && argument.front() == '-';
}
std::string ArgumentIdentity(const std::size_t argument_index,
const std::string& argument) {
return "argument_index=" + std::to_string(argument_index) +
";argument=" + argument;
}
std::filesystem::path LockPathFor(const DerivedOutputPaths& paths) {
std::filesystem::path lock_path = paths.results_path;
lock_path += ".fesa.lock";
return lock_path;
}
} // namespace
class OutputWriteLease::Impl {
public:
explicit Impl(const HANDLE handle) noexcept : handle_{handle} {}
Impl(const Impl&) = delete;
Impl& operator=(const Impl&) = delete;
~Impl() {
if (handle_ != INVALID_HANDLE_VALUE) {
(void)CloseHandle(handle_);
}
}
private:
HANDLE handle_{INVALID_HANDLE_VALUE};
};
OutputWriteLease::OutputWriteLease(std::unique_ptr<Impl> impl) noexcept
: impl_{std::move(impl)} {}
OutputWriteLease::OutputWriteLease(OutputWriteLease&&) noexcept = default;
OutputWriteLease& OutputWriteLease::operator=(OutputWriteLease&&) noexcept =
default;
OutputWriteLease::~OutputWriteLease() = default;
Result<DerivedOutputPaths> DeriveSingleInputOutputPaths(
const std::vector<std::string>& arguments,
const std::filesystem::path& invocation_cwd) {
for (std::size_t index = 0U; index < arguments.size(); ++index) {
if (arguments[index].find("--output") != std::string::npos) {
return Result<DerivedOutputPaths>::Failure(UsageFailure(
ArgumentIdentity(index, arguments[index]),
"The --output option is not supported."));
}
}
if (arguments.size() != 1U || arguments.front().empty() ||
StartsWithOption(arguments.front())) {
return Result<DerivedOutputPaths>::Failure(
UsageFailure("", "Usage: fesa.exe <model.inp>."));
}
std::filesystem::path input_path{arguments.front()};
if (input_path.is_relative()) {
input_path = invocation_cwd / input_path;
}
input_path = input_path.lexically_normal();
if (!AsciiCaseInsensitiveEquals(input_path.extension().string(), ".inp")) {
return Result<DerivedOutputPaths>::Failure(
UsageFailure(input_path.generic_u8string(),
"The input path must end in .inp."));
}
const std::filesystem::path stem = input_path.stem();
const std::filesystem::path output_directory = input_path.parent_path();
return Result<DerivedOutputPaths>::Success(
{input_path, output_directory / (stem.string() + "_results.h5"),
output_directory / (stem.string() + "_log.txt")});
}
Result<OutputWriteLease> AcquireOutputWriteLease(
const DerivedOutputPaths& paths) {
const std::filesystem::path lock_path = LockPathFor(paths);
const HANDLE lock_handle = CreateFileW(
lock_path.c_str(), GENERIC_READ | GENERIC_WRITE, 0U, nullptr, CREATE_NEW,
FILE_ATTRIBUTE_HIDDEN | FILE_FLAG_DELETE_ON_CLOSE, nullptr);
if (lock_handle == INVALID_HANDLE_VALUE) {
return Result<OutputWriteLease>::Failure(
OutputBusyFailure(paths.results_path));
}
return Result<OutputWriteLease>::Success(
OutputWriteLease{std::make_unique<OutputWriteLease::Impl>(lock_handle)});
}
} // namespace fesa
+1
View File
@@ -9,6 +9,7 @@ add_executable(
unit/assembly/parallel_for_test.cpp
unit/assembly/load_assembler_test.cpp
unit/assembly/sparse_assembler_test.cpp
unit/app/output_paths_test.cpp
unit/constraints/boundary_condition_test.cpp
unit/constraints/essential_constraints_test.cpp
unit/core/ascii_test.cpp
+89 -33
View File
@@ -1,5 +1,7 @@
#include "fesa/app/fesa_application.h"
#include "fesa/app/output_paths.h"
#include <algorithm>
#include <gtest/gtest.h>
#include <hdf5.h>
@@ -9,6 +11,7 @@
#include <cstddef>
#include <filesystem>
#include <fstream>
#include <iterator>
#include <stdexcept>
#include <string>
#include <utility>
@@ -332,32 +335,37 @@ void ExpectDiagnosticFieldOrder(const std::string& text) {
}
}
std::vector<std::string> ExplicitOutputArguments(
const std::filesystem::path& input, const std::filesystem::path& output) {
// FesaApplication receives argv[0]-excluded operands and options.
return {input.string(), "--output", output.string()};
struct FileSnapshot {
std::string contents;
std::filesystem::file_time_type write_time;
};
FileSnapshot SnapshotFile(const std::filesystem::path& path) {
std::ifstream stream{path, std::ios::binary};
if (!stream) {
throw std::runtime_error{"Unable to open an app output fixture."};
}
return {{std::istreambuf_iterator<char>{stream},
std::istreambuf_iterator<char>{}},
std::filesystem::last_write_time(path)};
}
} // namespace
TEST(LinearStaticCli, DefaultAndExplicitOutputProduceFesaHdf5) {
// NSNR-CLI-008: the application no longer uses a CWD-global results.h5.
TEST(LinearStaticCli, DefaultOutputUsesInputSiblingDerivedName) {
TempDirectory directory{"paths"};
const auto input = directory.Path() / "model.inp";
const auto input = directory.Path() / "Beam.Model.INP";
WriteText(input, AxialDeck(true, false, false));
const auto default_output = directory.Path() / "results.h5";
const auto default_output = directory.Path() / "Beam.Model_results.h5";
{
CurrentDirectoryGuard current_directory{directory.Path()};
const auto result = RunApplication({input.string()});
ASSERT_EQ(result.exit_code, 0) << result.standard_error;
}
ExpectFesaHdf5Identity(default_output, input);
const auto explicit_output = directory.Path() / "named-output.h5";
const auto result =
RunApplication(ExplicitOutputArguments(input, explicit_output));
ASSERT_EQ(result.exit_code, 0) << result.standard_error;
ExpectFesaHdf5Identity(explicit_output, input);
EXPECT_FALSE(std::filesystem::exists(directory.Path() / "results.h5"));
}
TEST(LinearStaticCli, ReturnsEveryExactExitCodeAndOrderedDiagnostic) {
@@ -369,8 +377,7 @@ TEST(LinearStaticCli, ReturnsEveryExactExitCodeAndOrderedDiagnostic) {
WriteText(model_input, AxialDeck(true, true, false));
WriteText(solver_input, AxialDeck(false, false, false));
const auto success = RunApplication(
ExplicitOutputArguments(valid_input, directory.Path() / "success.h5"));
const auto success = RunApplication({valid_input.string()});
const auto usage = RunApplication({});
const auto missing_input = directory.Path() / "missing.inp";
const auto input = RunApplication({missing_input.string()});
@@ -378,25 +385,19 @@ TEST(LinearStaticCli, ReturnsEveryExactExitCodeAndOrderedDiagnostic) {
RunApplication({missing_input.string(), "--output", "--output"});
const auto unknown_output_option =
RunApplication({missing_input.string(), "--output", "--bogus"});
const auto model = RunApplication(ExplicitOutputArguments(
model_input, directory.Path() / "model-failure.h5"));
const auto solver = RunApplication(ExplicitOutputArguments(
solver_input, directory.Path() / "solver-failure.h5"));
const auto output = RunApplication(ExplicitOutputArguments(
valid_input, directory.Path() / "nonexistent-parent" / "results.h5"));
const auto model = RunApplication({model_input.string()});
const auto solver = RunApplication({solver_input.string()});
EXPECT_EQ(success.exit_code, 0) << success.standard_error;
EXPECT_EQ(usage.exit_code, 2);
EXPECT_EQ(input.exit_code, 3);
EXPECT_EQ(model.exit_code, 4);
EXPECT_EQ(solver.exit_code, 5);
EXPECT_EQ(output.exit_code, 6);
ExpectDiagnosticFieldOrder(usage.standard_error);
ExpectDiagnosticFieldOrder(input.standard_error);
ExpectDiagnosticFieldOrder(model.standard_error);
ExpectDiagnosticFieldOrder(solver.standard_error);
ExpectDiagnosticFieldOrder(output.standard_error);
EXPECT_EQ(repeated_output.exit_code, 2);
ExpectDiagnosticFieldOrder(repeated_output.standard_error);
EXPECT_NE(repeated_output.standard_error.find("code=cli-usage"),
@@ -407,24 +408,79 @@ TEST(LinearStaticCli, ReturnsEveryExactExitCodeAndOrderedDiagnostic) {
std::string::npos);
}
// NSNR-CLI-003 and NSNR-CLI-007: usage failure precedes every output side
// effect, including replacement of existing derived files.
TEST(LinearStaticCli, OutputSubstringRejectionLeavesDerivedFilesUnchanged) {
TempDirectory directory{"usage-no-output"};
const auto input = directory.Path() / "model.inp";
const auto results = directory.Path() / "model_results.h5";
const auto log = directory.Path() / "model_log.txt";
WriteText(input, AxialDeck(true, false, false));
WriteText(results, "previous-results");
WriteText(log, "previous-log");
const FileSnapshot previous_results = SnapshotFile(results);
const FileSnapshot previous_log = SnapshotFile(log);
for (const char* argument :
{"abc--outputdef", "--output-path", "--output=foo", "--output"}) {
const auto result = RunApplication({input.string(), argument});
EXPECT_EQ(result.exit_code, 2) << argument;
EXPECT_EQ(
std::count(result.standard_error.begin(), result.standard_error.end(), '\n'),
1U)
<< result.standard_error;
EXPECT_NE(result.standard_error.find("code=cli-usage"),
std::string::npos);
EXPECT_EQ(SnapshotFile(results).contents, previous_results.contents);
EXPECT_EQ(SnapshotFile(results).write_time, previous_results.write_time);
EXPECT_EQ(SnapshotFile(log).contents, previous_log.contents);
EXPECT_EQ(SnapshotFile(log).write_time, previous_log.write_time);
}
}
// NSNR-CLI-006: a held lease blocks the application before any public output
// is opened, truncated, or replaced.
TEST(LinearStaticCli, BusyOutputLeaseLeavesDerivedFilesUnchanged) {
TempDirectory directory{"busy-output"};
const auto input = directory.Path() / "model.inp";
const auto results = directory.Path() / "model_results.h5";
const auto log = directory.Path() / "model_log.txt";
WriteText(input, AxialDeck(true, false, false));
WriteText(results, "previous-results");
WriteText(log, "previous-log");
const FileSnapshot previous_results = SnapshotFile(results);
const FileSnapshot previous_log = SnapshotFile(log);
const fesa::DerivedOutputPaths paths{input, results, log};
auto lease = fesa::AcquireOutputWriteLease(paths);
ASSERT_TRUE(lease.HasValue()) << lease.GetStatus().Diagnostics().size();
const auto result = RunApplication({input.string()});
EXPECT_EQ(result.exit_code, 6) << result.standard_error;
EXPECT_NE(result.standard_error.find("code=output-busy"),
std::string::npos);
EXPECT_EQ(SnapshotFile(results).contents, previous_results.contents);
EXPECT_EQ(SnapshotFile(results).write_time, previous_results.write_time);
EXPECT_EQ(SnapshotFile(log).contents, previous_log.contents);
EXPECT_EQ(SnapshotFile(log).write_time, previous_log.write_time);
}
TEST(LinearStaticCli, OutputRequestsDoNotFilterMandatoryResults) {
TempDirectory directory{"output-requests"};
const auto plain_input = directory.Path() / "plain.inp";
const auto requested_input = directory.Path() / "requested.inp";
const auto plain_output = directory.Path() / "plain.h5";
const auto requested_output = directory.Path() / "requested.h5";
WriteText(plain_input, AxialDeck(true, false, false));
WriteText(requested_input, AxialDeck(true, false, true));
const auto plain =
RunApplication(ExplicitOutputArguments(plain_input, plain_output));
const auto requested = RunApplication(
ExplicitOutputArguments(requested_input, requested_output));
const auto plain = RunApplication({plain_input.string()});
const auto requested = RunApplication({requested_input.string()});
ASSERT_EQ(plain.exit_code, 0) << plain.standard_error;
ASSERT_EQ(requested.exit_code, 0) << requested.standard_error;
const auto plain_file = OpenFile(plain_output);
const auto requested_file = OpenFile(requested_output);
const auto plain_file =
OpenFile(plain_input.parent_path() / "plain_results.h5");
const auto requested_file =
OpenFile(requested_input.parent_path() / "requested_results.h5");
ExpectMandatoryInventory(plain_file.Get());
ExpectMandatoryInventory(requested_file.Get());
@@ -449,10 +505,10 @@ TEST(LinearStaticCli, OutputRequestsDoNotFilterMandatoryResults) {
TEST(Mitc4ShellCli, WritesShellHdf5ThroughTheExistingApplicationRoute) {
TempDirectory directory{"shell-route"};
const auto input = directory.Path() / "shell.inp";
const auto output = directory.Path() / "shell-results.h5";
const auto output = directory.Path() / "shell_results.h5";
WriteText(input, AllConstrainedShellDeck());
const auto result = RunApplication(ExplicitOutputArguments(input, output));
const auto result = RunApplication({input.string()});
ASSERT_EQ(result.exit_code, 0) << result.standard_error;
ExpectShellHdf5Identity(output, input);
}
@@ -153,7 +153,8 @@ TEST(B33ReferenceComparison, GeneratesAuthoritativeHdf5AndComparisonEvidence) {
const auto input = reference_directory / "cantilever beam.inp";
const auto output_directory =
binary_root / "reference" / "cantilever-beam-b33";
const auto results = output_directory / "results.h5";
const auto execution_input = output_directory / input.filename();
const auto results = output_directory / "cantilever beam_results.h5";
const auto comparison = output_directory / "comparison.json";
// Only the exact build-local evidence directory is reset; the approved
@@ -173,16 +174,18 @@ TEST(B33ReferenceComparison, GeneratesAuthoritativeHdf5AndComparisonEvidence) {
std::filesystem::path{"cantilever beam reactions.csv"});
EXPECT_EQ(reference_before[3U].relative_path,
std::filesystem::path{"cantilever beam.inp"});
ASSERT_TRUE(std::filesystem::copy_file(input, execution_input, error));
ASSERT_FALSE(error);
fesa::FesaApplication application;
// FesaApplication receives application operands/options; main strips argv[0].
ASSERT_EQ(application.Run({input.string(), "--output", results.string()}), 0);
ASSERT_EQ(application.Run({execution_input.string()}), 0);
ASSERT_TRUE(std::filesystem::is_regular_file(results));
ASSERT_GT(H5Fis_hdf5(results.string().c_str()), 0);
EXPECT_GT(StressRowCount(results), 0U);
auto comparison_result =
fesa::test::ReferenceComparison::Compare(results, reference_directory);
fesa::test::ReferenceComparison::Compare(results, reference_directory,
execution_input);
ASSERT_TRUE(comparison_result.HasValue());
const auto& report = comparison_result.Value();
ASSERT_TRUE(report.passed);
@@ -248,7 +251,9 @@ TEST(B33ReferenceComparison, GeneratesAuthoritativeHdf5AndComparisonEvidence) {
}
std::sort(generated_names.begin(), generated_names.end());
EXPECT_EQ(generated_names,
(std::vector<std::string>{"comparison.json", "results.h5"}));
(std::vector<std::string>{"cantilever beam.inp",
"cantilever beam_results.h5",
"comparison.json"}));
ExpectTreeUnchanged(reference_before, SnapshotTree(reference_directory));
}
+11 -4
View File
@@ -75,14 +75,19 @@ CaseEvidence RunCase(const std::string& case_id,
if (!std::filesystem::create_directories(output_directory, error) || error) {
throw std::runtime_error{"Unable to create MITC4 evidence directory."};
}
const auto results = output_directory / "results.h5";
const auto execution_input = output_directory / input.filename();
if (!std::filesystem::copy_file(input, execution_input, error) || error) {
throw std::runtime_error{"Unable to copy MITC4 input for execution."};
}
const auto results = output_directory /
(execution_input.stem().string() + "_results.h5");
const auto comparison = output_directory / "comparison.json";
fesa::FesaApplication application;
EXPECT_EQ(application.Run({input.string(), "--output", results.string()}), 0);
EXPECT_EQ(application.Run({execution_input.string()}), 0);
EXPECT_TRUE(std::filesystem::is_regular_file(results));
auto comparison_result = fesa::test::Mitc4ReferenceComparison::Compare(
{case_id, source_element_type, input, csv, results});
{case_id, source_element_type, execution_input, csv, results});
if (!comparison_result.HasValue()) {
std::string diagnostics;
for (const auto& diagnostic : comparison_result.GetStatus().Diagnostics()) {
@@ -104,7 +109,9 @@ CaseEvidence RunCase(const std::string& case_id,
}
std::sort(generated.begin(), generated.end());
EXPECT_EQ(generated,
(std::vector<std::string>{"comparison.json", "results.h5"}));
(std::vector<std::string>{"comparison.json",
input.filename().string(),
results.filename().string()}));
EXPECT_TRUE(std::filesystem::is_directory(reference_directory));
ExpectUnchanged(input, input_before);
ExpectUnchanged(csv, csv_before);
+12 -3
View File
@@ -1345,10 +1345,18 @@ bool FiniteReport(const ComparisonReport& report) {
Result<ComparisonReport> ReferenceComparison::Compare(
const std::filesystem::path& results_hdf5,
const std::filesystem::path& legacy_reference_directory) {
return Compare(results_hdf5, legacy_reference_directory,
legacy_reference_directory / kInputName);
}
Result<ComparisonReport> ReferenceComparison::Compare(
const std::filesystem::path& results_hdf5,
const std::filesystem::path& legacy_reference_directory,
const std::filesystem::path& execution_input_path) {
try {
RequireExactArtifactInventory(legacy_reference_directory);
const auto input = legacy_reference_directory / kInputName;
Domain domain = ReadApprovedDomain(input);
const auto reference_input = legacy_reference_directory / kInputName;
Domain domain = ReadApprovedDomain(reference_input);
const ReferenceTable displacement =
ReadReferenceCsv(legacy_reference_directory / kDisplacementName,
{"Frame", "Part Instance Name", "Node Label", "U-U1",
@@ -1359,7 +1367,8 @@ Result<ComparisonReport> ReferenceComparison::Compare(
"RF-RF2", "RF-RF3", "RM-RM1", "RM-RM2", "RM-RM3"});
const SectionReferenceTable section =
ReadSectionReferenceCsv(legacy_reference_directory / kSectionName);
HdfProjection hdf = ReadHdfProjection(results_hdf5, input, domain);
HdfProjection hdf =
ReadHdfProjection(results_hdf5, execution_input_path, domain);
const auto displacement_rows = OrderedRows(displacement, hdf.nodes);
const auto reaction_rows = OrderedRows(reaction, hdf.nodes);
const auto section_rows = OrderedSectionRows(section, hdf);
+9
View File
@@ -84,6 +84,15 @@ class ReferenceComparison {
static Result<ComparisonReport> Compare(
const std::filesystem::path& results_hdf5,
const std::filesystem::path& legacy_reference_directory);
/// @brief Compares results using a separately copied execution input path.
/// @param execution_input_path Input path recorded by the solver in HDF5.
/// @note Reference inputs and CSV files remain in legacy_reference_directory.
static Result<ComparisonReport> Compare(
const std::filesystem::path& results_hdf5,
const std::filesystem::path& legacy_reference_directory,
const std::filesystem::path& execution_input_path);
static Status WriteDeterministicJson(
const ComparisonReport& report, const std::filesystem::path& output_json);
};
+125
View File
@@ -6,6 +6,17 @@ import pytest
from scripts import execute
def write_implementation_agent_profile(
root, *, model="gpt-5.6-terra", reasoning="xhigh"
):
profile = root / ".codex" / "agents" / "implementation-agent.toml"
profile.parent.mkdir(parents=True)
profile.write_text(
f'model = "{model}"\nmodel_reasoning_effort = "{reasoning}"\n',
encoding="utf-8",
)
def test_invoke_codex_uses_utf8_for_unicode_prompt(tmp_path, monkeypatch):
phase_dir = tmp_path / "phases" / "unicode-phase"
phase_dir.mkdir(parents=True)
@@ -20,6 +31,7 @@ def test_invoke_codex_uses_utf8_for_unicode_prompt(tmp_path, monkeypatch):
encoding="utf-8",
)
(phase_dir / "step0.md").write_text("Euler–Bernoulli 보", encoding="utf-8")
write_implementation_agent_profile(tmp_path)
invocation = {}
@@ -40,6 +52,44 @@ def test_invoke_codex_uses_utf8_for_unicode_prompt(tmp_path, monkeypatch):
assert invocation["command"][sandbox_index + 1] == "workspace-write"
def test_invoke_codex_uses_implementation_agent_command_contract(
tmp_path, monkeypatch
):
phase_dir = tmp_path / "phases" / "agent-phase"
phase_dir.mkdir(parents=True)
(phase_dir / "index.json").write_text(
json.dumps(
{
"project": "FESA Structural Solver",
"phase": "agent-phase",
"steps": [{"step": 0, "name": "agent", "status": "pending"}],
}
),
encoding="utf-8",
)
(phase_dir / "step0.md").write_text("agent routing", encoding="utf-8")
write_implementation_agent_profile(tmp_path)
invocation = {}
def capture_run(command, **kwargs):
invocation["command"] = command
return subprocess.CompletedProcess(command, 0, stdout="", stderr="")
monkeypatch.setattr(execute, "ROOT", tmp_path)
monkeypatch.setattr(execute.subprocess, "run", capture_run)
executor = execute.StepExecutor("agent-phase")
executor._invoke_codex({"step": 0, "name": "agent"}, "")
model_index = invocation["command"].index("--model")
config_index = invocation["command"].index("--config")
assert invocation["command"][model_index + 1] == "gpt-5.6-terra"
assert invocation["command"][config_index + 1] == 'model_reasoning_effort="xhigh"'
adjacent_arguments = list(zip(invocation["command"], invocation["command"][1:]))
assert ("--disable", "unified_exec") in adjacent_arguments
def test_invoke_codex_accepts_explicit_danger_full_access_override(
tmp_path, monkeypatch
):
@@ -56,6 +106,7 @@ def test_invoke_codex_accepts_explicit_danger_full_access_override(
encoding="utf-8",
)
(phase_dir / "step0.md").write_text("sandbox override", encoding="utf-8")
write_implementation_agent_profile(tmp_path)
invocation = {}
@@ -74,6 +125,80 @@ def test_invoke_codex_accepts_explicit_danger_full_access_override(
assert invocation["command"][sandbox_index + 1] == "danger-full-access"
def test_invoke_codex_timeout_writes_structured_failure(tmp_path, monkeypatch):
phase_dir = tmp_path / "phases" / "timeout-phase"
phase_dir.mkdir(parents=True)
(phase_dir / "index.json").write_text(
json.dumps(
{
"project": "FESA Structural Solver",
"phase": "timeout-phase",
"steps": [{"step": 0, "name": "timeout", "status": "pending"}],
}
),
encoding="utf-8",
)
(phase_dir / "step0.md").write_text("timeout", encoding="utf-8")
write_implementation_agent_profile(tmp_path)
def timeout_run(command, **kwargs):
raise subprocess.TimeoutExpired(
command, kwargs["timeout"], output="partial stdout", stderr="partial stderr"
)
monkeypatch.setattr(execute, "ROOT", tmp_path)
monkeypatch.setattr(execute.subprocess, "run", timeout_run)
executor = execute.StepExecutor("timeout-phase")
output = executor._invoke_codex({"step": 0, "name": "timeout"}, "")
assert output["exitCode"] == 124
assert output["stdout"] == "partial stdout"
assert "Codex timed out after 1800 seconds." in output["stderr"]
stored = json.loads((phase_dir / "step0-output.json").read_text(encoding="utf-8"))
assert stored == output
def test_execute_single_step_retries_structured_codex_timeout(tmp_path, monkeypatch):
phase_dir = tmp_path / "phases" / "retry-phase"
phase_dir.mkdir(parents=True)
(phase_dir / "index.json").write_text(
json.dumps(
{
"project": "FESA Structural Solver",
"phase": "retry-phase",
"steps": [{"step": 0, "name": "retry", "status": "pending"}],
}
),
encoding="utf-8",
)
(phase_dir / "step0.md").write_text("retry", encoding="utf-8")
write_implementation_agent_profile(tmp_path)
attempts = []
def timeout_run(command, **kwargs):
attempts.append(command)
raise subprocess.TimeoutExpired(command, kwargs["timeout"])
monkeypatch.setattr(execute, "ROOT", tmp_path)
monkeypatch.setattr(execute.subprocess, "run", timeout_run)
executor = execute.StepExecutor("retry-phase")
executor.MAX_RETRIES = 2
monkeypatch.setattr(executor, "_commit_step", lambda *args: None)
monkeypatch.setattr(executor, "_update_top_index", lambda *args: None)
with pytest.raises(SystemExit, match="1"):
executor._execute_single_step(
{"step": 0, "name": "retry", "status": "pending"}, ""
)
assert len(attempts) == 2
index = json.loads((phase_dir / "index.json").read_text(encoding="utf-8"))
assert index["steps"][0]["status"] == "error"
assert "Codex timed out after 1800 seconds." in index["steps"][0]["error_message"]
def test_invoke_codex_rejects_unknown_sandbox_override(tmp_path, monkeypatch):
phase_dir = tmp_path / "phases" / "sandbox-phase"
phase_dir.mkdir(parents=True)
+141
View File
@@ -0,0 +1,141 @@
#include "fesa/app/output_paths.h"
#include <chrono>
#include <filesystem>
#include <stdexcept>
#include <string>
#include <vector>
#include <gtest/gtest.h>
#include "fesa/analysis/analysis.h"
namespace {
class TempDirectory {
public:
explicit TempDirectory(const std::string& label) {
const auto tick =
std::chrono::steady_clock::now().time_since_epoch().count();
path_ = std::filesystem::temp_directory_path() /
("fesa-output-paths-" + label + "-" + std::to_string(tick));
std::error_code error;
if (!std::filesystem::create_directory(path_, error) || error) {
throw std::runtime_error{"Unable to create an output-path test fixture."};
}
}
TempDirectory(const TempDirectory&) = delete;
TempDirectory& operator=(const TempDirectory&) = delete;
~TempDirectory() {
std::error_code ignored;
std::filesystem::remove_all(path_, ignored);
}
const std::filesystem::path& Path() const noexcept { return path_; }
private:
std::filesystem::path path_;
};
void ExpectFailureCode(const fesa::Status& status, const char* code) {
ASSERT_FALSE(status.IsOk());
ASSERT_EQ(status.Diagnostics().size(), 1U);
EXPECT_EQ(status.Diagnostics().front().code, code);
}
// NSNR-CLI-001 and NSNR-CLI-002: a token containing the literal substring
// must fail before input path validation or output derivation.
TEST(OutputPaths, RejectsFirstTokenContainingOutputSubstring) {
const auto paths = fesa::DeriveSingleInputOutputPaths(
{"abc--outputdef", "model.inp", "--output=ignored"},
std::filesystem::path{"C:/invocation"});
ASSERT_FALSE(paths.HasValue());
ExpectFailureCode(paths.GetStatus(), "cli-usage");
EXPECT_EQ(paths.GetStatus().Diagnostics().front().entity_identity,
"argument_index=0;argument=abc--outputdef");
}
TEST(OutputPaths, RejectsEveryOutputSubstringVariant) {
for (const char* argument :
{"abc--outputdef", "--output-path", "--output=foo", "--output"}) {
const auto paths = fesa::DeriveSingleInputOutputPaths(
{"model.inp", argument}, std::filesystem::path{"C:/invocation"});
ASSERT_FALSE(paths.HasValue()) << argument;
ExpectFailureCode(paths.GetStatus(), "cli-usage");
}
}
// NSNR-CLI-004: derivation is lexical and does not inspect the filesystem.
TEST(OutputPaths, DerivesNormalizedSiblingNamesFromRelativeInput) {
const auto paths = fesa::DeriveSingleInputOutputPaths(
{"inputs/../models/Beam.Model.INP"},
std::filesystem::path{"C:/invocation/current"});
ASSERT_TRUE(paths.HasValue()) << paths.GetStatus().Diagnostics().size();
EXPECT_EQ(
paths.Value().input_path,
std::filesystem::path{"C:/invocation/current/models/Beam.Model.INP"});
EXPECT_EQ(paths.Value().results_path,
std::filesystem::path{
"C:/invocation/current/models/Beam.Model_results.h5"});
EXPECT_EQ(paths.Value().log_path,
std::filesystem::path{
"C:/invocation/current/models/Beam.Model_log.txt"});
}
// NSNR-CLI-005: only the final, case-insensitive input extension is removed.
TEST(OutputPaths, PreservesBasenameCaseAndPrecedingDots) {
const auto paths = fesa::DeriveSingleInputOutputPaths(
{"C:/models/.Beam.v2.iNp"}, std::filesystem::path{"C:/unused"});
ASSERT_TRUE(paths.HasValue());
EXPECT_EQ(paths.Value().results_path,
std::filesystem::path{"C:/models/.Beam.v2_results.h5"});
EXPECT_EQ(paths.Value().log_path,
std::filesystem::path{"C:/models/.Beam.v2_log.txt"});
}
TEST(OutputPaths, RejectsInputWithoutInpFinalExtension) {
const auto paths = fesa::DeriveSingleInputOutputPaths(
{"model.inp.bak"}, std::filesystem::path{"C:/invocation"});
ASSERT_FALSE(paths.HasValue());
ExpectFailureCode(paths.GetStatus(), "cli-usage");
}
// NSNR-CLI-006: the lease is exclusive and does not create public outputs.
TEST(OutputPaths, LeaseCollisionPreservesPublicOutputPaths) {
TempDirectory directory{"lease"};
const fesa::DerivedOutputPaths paths{
directory.Path() / "model.inp", directory.Path() / "model_results.h5",
directory.Path() / "model_log.txt"};
auto first = fesa::AcquireOutputWriteLease(paths);
ASSERT_TRUE(first.HasValue()) << first.GetStatus().Diagnostics().size();
EXPECT_FALSE(std::filesystem::exists(paths.results_path));
EXPECT_FALSE(std::filesystem::exists(paths.log_path));
const auto second = fesa::AcquireOutputWriteLease(paths);
ASSERT_FALSE(second.HasValue());
ExpectFailureCode(second.GetStatus(), "output-busy");
EXPECT_FALSE(std::filesystem::exists(paths.results_path));
EXPECT_FALSE(std::filesystem::exists(paths.log_path));
}
// NSNR-CLI-009: procedure calls receive all derived output identities.
TEST(OutputPaths, AnalysisRequestCarriesInputResultAndLogPaths) {
const fesa::AnalysisRequest request{
std::filesystem::path{"C:/models/model.inp"},
std::filesystem::path{"C:/models/model_results.h5"},
std::filesystem::path{"C:/models/model_log.txt"}};
EXPECT_EQ(request.input_path, "C:/models/model.inp");
EXPECT_EQ(request.output_path, "C:/models/model_results.h5");
EXPECT_EQ(request.log_path, "C:/models/model_log.txt");
}
} // namespace