Files
FESADev/phases/nonlinear-static-newton-raphson/step5.md
T

8.0 KiB

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

인터페이스

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:

cmake --build --preset windows-msvc-ninja-debug
ctest --preset windows-msvc-ninja-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

cmake --preset windows-msvc-ninja-debug
cmake --build --preset windows-msvc-ninja-debug
ctest --preset windows-msvc-ninja-debug -R "NonlinearStaticControl|NonlinearConvergence|NonlinearLoadBoundary" --output-on-failure
ctest --preset windows-msvc-ninja-debug --show-only=json-v1
ctest --preset windows-msvc-ninja-debug --output-on-failure

Use the ignored .harness/config.json preset contract. The Harness process must inherit VsDevCmd x64 and FESA_GTEST_SOURCE_DIR, MKL_DIR, TBB_DIR, and HDF5_DIR from its parent launch environment.

상태 기록

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.