Integrate Refactor solver sources and dual MSVC CMake builds

This commit is contained in:
KOKO\Mimi
2026-10-18 02:10:51 +09:00
parent 7ee32e5837
commit 12d51480de
218 changed files with 17842 additions and 9689 deletions
+275 -245
View File
@@ -1,11 +1,15 @@
#include "fesa/analysis/nonlinear_static_procedure.h"
#include "equilibrium_algorithm.h"
#include "analysis/nonlinear_static_core.h"
#include <algorithm>
#include <array>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <limits>
#include <memory>
#include <optional>
#include <string>
#include <utility>
@@ -17,6 +21,7 @@
#include "fesa/assembly/parallel_for.h"
#include "fesa/assembly/surface_pressure_assembler.h"
#include "fesa/constraints/essential_constraint_policy.h"
#include "fesa/elements/element_capabilities.h"
#include "fesa/elements/finite_rotation.h"
#include "fesa/elements/mitc4_shell.h"
#include "fesa/elements/nonlinear_mitc4_shell.h"
@@ -25,9 +30,16 @@
#include "fesa/properties/shell_section.h"
#include "fesa/solvers/linear/tangent_solver.h"
#include "assembly/ordered_contribution_internal.h"
#include "math/finite_values.h"
#include "elements/shell_kernel_values.h"
namespace fesa {
namespace {
using shell_kernel_internal::FrameMatrix;
using math_internal::IsFinite;
constexpr std::size_t kDofsPerNode = 6U;
constexpr std::size_t kTranslationsPerNode = 3U;
constexpr std::size_t kShellDofCount = 24U;
@@ -36,7 +48,8 @@ constexpr std::uint32_t kMaximumNewtonIterations = 100U;
struct RuntimeShell {
EntityIndex element_index;
std::array<std::size_t, kShellDofCount> scatter;
NonlinearMitc4Shell element;
std::unique_ptr<NonlinearMitc4Shell> kernel;
std::unique_ptr<ShellTrialElement> element;
};
struct InternalAssembly {
@@ -124,16 +137,6 @@ Status RecordFailure(NewtonIterationLogWriter& log,
return log_status.IsOk() ? failure : log_status;
}
Matrix InitialFrame(const ShellNodeInitialFrame& frame) {
Matrix result{3U, 3U};
for (std::size_t row = 0U; row < kTranslationsPerNode; ++row) {
result(row, 0U) = frame.tangent_a[row];
result(row, 1U) = frame.tangent_b[row];
result(row, 2U) = frame.director[row];
}
return result;
}
Result<DofManager> BuildDofManager(const Domain& domain) {
Result<AnalysisModel> model = AnalysisModel::Create(domain);
if (!model.HasValue()) {
@@ -239,9 +242,20 @@ Result<std::vector<RuntimeShell>> BuildRuntimeShells(const Domain& domain,
return Result<std::vector<RuntimeShell>>::Failure(shell.GetStatus());
}
const EntityIndex element_index = static_cast<EntityIndex>(index);
auto kernel =
std::make_unique<NonlinearMitc4Shell>(std::move(shell.Value()));
auto element = std::make_unique<Mitc4TrialAdapter>(
ElementDofLayout{definition->SourceId(), definition->NodeIndices(),
{DofComponent::kUx, DofComponent::kUy, DofComponent::kUz,
DofComponent::kUrx, DofComponent::kUry, DofComponent::kUrz}},
*kernel);
auto mapped = dofs.ElementScatter(element->DofLayout());
if (!mapped.HasValue())
return Result<std::vector<RuntimeShell>>::Failure(mapped.GetStatus());
std::array<std::size_t, kShellDofCount> scatter{};
std::copy(mapped.Value().begin(), mapped.Value().end(), scatter.begin());
shells.push_back(
{element_index, dofs.ShellElementScatter(element_index),
std::move(shell.Value())});
{element_index, scatter, std::move(kernel), std::move(element)});
}
return Result<std::vector<RuntimeShell>>::Success(std::move(shells));
}
@@ -269,7 +283,7 @@ Status PopulateNodalKinematics(const Domain& domain,
trial->generalized_coordinates[first + 4U],
trial->generalized_coordinates[first + 5U]};
Result<FiniteRotationState> rotation = MakeFiniteRotationState(
phi, InitialFrame(domain.ShellNodeInitialFrames()[node]));
phi, FrameMatrix(domain.ShellNodeInitialFrames()[node]));
if (!rotation.HasValue()) {
return rotation.GetStatus();
}
@@ -304,26 +318,6 @@ NonlinearMitc4TrialDofs ExtractElementTrial(
return trial;
}
bool IsFinite(const Vector& values) {
for (std::size_t index = 0U; index < values.Size(); ++index) {
if (!std::isfinite(values[index])) {
return false;
}
}
return true;
}
bool IsFinite(const Matrix& values) {
for (std::size_t row = 0U; row < values.Rows(); ++row) {
for (std::size_t column = 0U; column < values.Columns(); ++column) {
if (!std::isfinite(values(row, column))) {
return false;
}
}
}
return true;
}
Result<InternalAssembly> AssembleInternal(
const std::vector<RuntimeShell>& shells, const DofManager& dofs,
const Vector& coordinates, const ParallelFor& parallel_for) {
@@ -332,9 +326,8 @@ Result<InternalAssembly> AssembleInternal(
std::vector<std::optional<Status>> failures(shells.size());
parallel_for.Execute(shells.size(), [&](const std::size_t index) {
Result<NonlinearMitc4InternalEquilibrium> result =
EvaluateInternalResidualAndTangent(shells[index].element,
ExtractElementTrial(shells[index],
coordinates));
shells[index].element->EvaluateTrial(
ExtractElementTrial(shells[index], coordinates));
if (!result.HasValue()) {
failures[index] = result.GetStatus();
return;
@@ -363,12 +356,9 @@ Result<InternalAssembly> AssembleInternal(
}
for (std::size_t row = 0U; row < kShellDofCount; ++row) {
force[shells[index].scatter[row]] += local[index]->internal_residual[row];
for (std::size_t column = 0U; column < kShellDofCount; ++column) {
contributions.push_back(
{shells[index].scatter[row], shells[index].scatter[column],
local[index]->internal_tangent(row, column), index,
row * kShellDofCount + column});
}
assembly_internal::AppendLocalMatrixRow(
local[index]->internal_tangent, shells[index].scatter, row, index,
contributions);
}
for (const NonlinearMitc4RecoveryPoint& point :
local[index]->recovery.gauss_points) {
@@ -573,19 +563,6 @@ Vector CurrentIncrementComponents(const Vector& current, const Vector& start,
return SelectFreeComponents(difference, dofs, rotations);
}
Vector3 SpatialMoment(const Matrix& transform,
const std::array<double, 3>& generalized) {
return {transform(0U, 0U) * generalized[0U] +
transform(0U, 1U) * generalized[1U] +
transform(0U, 2U) * generalized[2U],
transform(1U, 0U) * generalized[0U] +
transform(1U, 1U) * generalized[1U] +
transform(1U, 2U) * generalized[2U],
transform(2U, 0U) * generalized[0U] +
transform(2U, 1U) * generalized[1U] +
transform(2U, 2U) * generalized[2U]};
}
/// @brief Computes accepted-state applied-plus-reaction balance evidence.
Result<std::array<double, 6>> GlobalEquilibrium(
const Domain& domain, const DofManager& dofs,
@@ -634,7 +611,6 @@ Result<std::array<double, 6>> GlobalEquilibrium(
constrained[first] ? trial.residual[first] : 0.0,
constrained[first + 1U] ? trial.residual[first + 1U] : 0.0,
constrained[first + 2U] ? trial.residual[first + 2U] : 0.0};
const Matrix transform = InverseTransposeLeftJacobianSO3(phi);
const std::array<double, 3> applied_generalized{
trial.external_force[first + 3U], trial.external_force[first + 4U],
trial.external_force[first + 5U]};
@@ -642,9 +618,16 @@ Result<std::array<double, 6>> GlobalEquilibrium(
constrained[first + 3U] ? trial.residual[first + 3U] : 0.0,
constrained[first + 4U] ? trial.residual[first + 4U] : 0.0,
constrained[first + 5U] ? trial.residual[first + 5U] : 0.0};
const Vector3 applied_moment = SpatialMoment(transform, applied_generalized);
const Vector3 reaction_moment =
SpatialMoment(transform, reaction_generalized);
const auto applied = SpatialMomentSO3(phi, Vector3(applied_generalized));
const auto reaction = SpatialMomentSO3(phi, Vector3(reaction_generalized));
if (!applied.HasValue() || !reaction.HasValue())
return Result<std::array<double, 6>>::Failure(ProcedureFailure(
FailureCategory::kSolver, "nonfinite-newton-data",
{domain.SourcePath(), 0U}, "NONLINEAR_STATIC_PROCEDURE",
domain.SourceContentIdentity(),
"Nonlinear global equilibrium balance is nonfinite."));
const Vector3 applied_moment = applied.Value();
const Vector3 reaction_moment = reaction.Value();
applied_force_resultant = applied_force_resultant + applied_force;
applied_moment_resultant =
applied_moment_resultant + position.Cross(applied_force) + applied_moment;
@@ -694,11 +677,11 @@ Status ApplyIncrementConstraints(const StepDefinition& step,
return Status::Ok();
}
AcceptedFrameState AcceptedFrame(const NonlinearAnalysisState& state,
AcceptedFrameState AcceptedFrame(const std::uint32_t frame_index,
const NonlinearTrialState& trial,
const LoadFactorIncrement& increment,
const std::uint32_t iteration) {
return {static_cast<std::uint32_t>(state.AcceptedFrames().size()),
return {frame_index,
increment.increment_index,
increment.load_factor,
iteration,
@@ -728,6 +711,15 @@ NonlinearStaticProcedureExecutor::NonlinearStaticProcedureExecutor(
Result<NonlinearStaticExecutionResult>
NonlinearStaticProcedureExecutor::Execute(
const Domain& domain, NewtonIterationLogWriter& log) const {
NewtonStepAlgorithm algorithm;
return ExecuteNonlinearStaticCore(domain, log, parallel_for_, tangent_solver_,
algorithm);
}
Result<NonlinearStaticExecutionResult> ExecuteNonlinearStaticCore(
const Domain& domain, NewtonIterationLogWriter& log,
const ParallelFor& parallel_for, TangentSolver& tangent_solver,
EquilibriumAlgorithm& algorithm) {
if (domain.Steps().Size() != 1U || !domain.Steps()[0U].IsNonlinearStatic()) {
return Result<NonlinearStaticExecutionResult>::Failure(ProcedureFailure(
FailureCategory::kInput, "invalid-nonlinear-static-data",
@@ -782,199 +774,237 @@ NonlinearStaticProcedureExecutor::Execute(
return Result<NonlinearStaticExecutionResult>::Failure(constraint_status);
}
for (std::uint32_t iteration = 1U; iteration <= kMaximumNewtonIterations;
++iteration) {
NewtonIterationLogRecord record =
NewLogRecord(step, increment, iteration);
trial.Value().increment_index = increment.increment_index;
trial.Value().load_factor = increment.load_factor;
trial.Value().is_factor_zero_baseline = false;
struct ShellStepCandidate {
AcceptedFrameState frame;
NewtonIterationLogRecord record;
};
const auto next_frame_index =
static_cast<std::uint32_t>(state.Value().AcceptedFrames().size());
const auto report_failure = [&](NewtonIterationLogRecord* record,
const Status& failure,
NewtonIterationStage stage) {
return RecordFailure(log, record, failure, stage);
};
const auto write_iteration = [&](const NewtonIterationLogRecord& record) {
return WriteAndFlush(log, record);
};
ShellFullNewtonStep<ShellStepCandidate> iteration_step(
[&](std::uint32_t iteration)
-> Result<std::optional<ShellStepCandidate>> {
NewtonIterationLogRecord record =
NewLogRecord(step, increment, iteration);
trial.Value().increment_index = increment.increment_index;
trial.Value().load_factor = increment.load_factor;
trial.Value().is_factor_zero_baseline = false;
Status kinematics = PopulateNodalKinematics(domain, &trial.Value());
if (!kinematics.IsOk()) {
return Result<NonlinearStaticExecutionResult>::Failure(
RecordFailure(log, &record, kinematics,
NewtonIterationStage::kKinematicsEvaluated));
}
record.last_completed_stage = NewtonIterationStage::kKinematicsEvaluated;
Status kinematics = PopulateNodalKinematics(domain, &trial.Value());
if (!kinematics.IsOk()) {
return Result<std::optional<ShellStepCandidate>>::Failure(
report_failure(&record, kinematics,
NewtonIterationStage::kKinematicsEvaluated));
}
record.last_completed_stage =
NewtonIterationStage::kKinematicsEvaluated;
Result<InternalAssembly> internal = AssembleInternal(
shells.Value(), dofs.Value(), trial.Value().generalized_coordinates,
parallel_for_);
if (!internal.HasValue()) {
return Result<NonlinearStaticExecutionResult>::Failure(RecordFailure(
log, &record, internal.GetStatus(),
NewtonIterationStage::kInternalAssembled));
}
record.last_completed_stage = NewtonIterationStage::kInternalAssembled;
Result<InternalAssembly> internal = AssembleInternal(
shells.Value(), dofs.Value(),
trial.Value().generalized_coordinates, parallel_for);
if (!internal.HasValue()) {
return Result<std::optional<ShellStepCandidate>>::Failure(
report_failure(&record, internal.GetStatus(),
NewtonIterationStage::kInternalAssembled));
}
record.last_completed_stage =
NewtonIterationStage::kInternalAssembled;
Result<GlobalFixedLoadContribution> fixed =
AssembleGlobalFixedLoadContribution(
domain, dofs.Value(), trial.Value().generalized_coordinates,
increment.load_factor);
if (!fixed.HasValue()) {
return Result<NonlinearStaticExecutionResult>::Failure(
RecordFailure(log, &record, fixed.GetStatus(),
NewtonIterationStage::kExternalAssembled));
}
Result<SurfacePressureAssemblyCandidate> pressure =
AssembleSurfacePressure(
analysis_model.Value(), dofs.Value(),
trial.Value().generalized_coordinates, increment.load_factor,
SurfacePressureConfiguration::kCurrent, parallel_for_);
if (!pressure.HasValue()) {
return Result<NonlinearStaticExecutionResult>::Failure(
RecordFailure(log, &record, pressure.GetStatus(),
NewtonIterationStage::kExternalAssembled));
}
Result<GlobalFixedLoadContribution> external =
CombineExternalContributions(fixed.Value(), pressure.Value(),
dofs.Value());
if (!external.HasValue()) {
return Result<NonlinearStaticExecutionResult>::Failure(
RecordFailure(log, &record, external.GetStatus(),
NewtonIterationStage::kExternalAssembled));
}
record.last_completed_stage = NewtonIterationStage::kExternalAssembled;
Result<GlobalFixedLoadContribution> fixed =
AssembleGlobalFixedLoadContribution(
domain, dofs.Value(), trial.Value().generalized_coordinates,
increment.load_factor);
if (!fixed.HasValue()) {
return Result<std::optional<ShellStepCandidate>>::Failure(
report_failure(&record, fixed.GetStatus(),
NewtonIterationStage::kExternalAssembled));
}
Result<SurfacePressureAssemblyCandidate> pressure =
AssembleSurfacePressure(
analysis_model.Value(), dofs.Value(),
trial.Value().generalized_coordinates, increment.load_factor,
SurfacePressureConfiguration::kCurrent, parallel_for);
if (!pressure.HasValue()) {
return Result<std::optional<ShellStepCandidate>>::Failure(
report_failure(&record, pressure.GetStatus(),
NewtonIterationStage::kExternalAssembled));
}
Result<GlobalFixedLoadContribution> external =
CombineExternalContributions(fixed.Value(), pressure.Value(),
dofs.Value());
if (!external.HasValue()) {
return Result<std::optional<ShellStepCandidate>>::Failure(
report_failure(&record, external.GetStatus(),
NewtonIterationStage::kExternalAssembled));
}
record.last_completed_stage =
NewtonIterationStage::kExternalAssembled;
Result<Vector> residual =
Difference(internal.Value().force,
external.Value().generalized_external_force);
if (!residual.HasValue()) {
return Result<NonlinearStaticExecutionResult>::Failure(RecordFailure(
log, &record, residual.GetStatus(),
NewtonIterationStage::kExternalAssembled));
}
Result<SparseMatrix> tangent =
Difference(internal.Value().tangent,
external.Value().generalized_external_tangent,
dofs.Value());
if (!tangent.HasValue()) {
return Result<NonlinearStaticExecutionResult>::Failure(RecordFailure(
log, &record, tangent.GetStatus(),
NewtonIterationStage::kExternalAssembled));
}
trial.Value().internal_force = std::move(internal.Value().force);
trial.Value().external_force =
std::move(external.Value().generalized_external_force);
trial.Value().residual = std::move(residual.Value());
trial.Value().reaction = trial.Value().residual;
trial.Value().shell_results = std::move(internal.Value().shell_rows);
trial.Value().physical_strain_energy =
internal.Value().physical_strain_energy;
Result<std::array<double, 6>> global_equilibrium =
GlobalEquilibrium(domain, dofs.Value(), trial.Value());
if (!global_equilibrium.HasValue()) {
return Result<NonlinearStaticExecutionResult>::Failure(RecordFailure(
log, &record, global_equilibrium.GetStatus(),
NewtonIterationStage::kExternalAssembled));
}
trial.Value().global_equilibrium = global_equilibrium.Value();
Result<Vector> residual =
Difference(internal.Value().force,
external.Value().generalized_external_force);
if (!residual.HasValue()) {
return Result<std::optional<ShellStepCandidate>>::Failure(
report_failure(&record, residual.GetStatus(),
NewtonIterationStage::kExternalAssembled));
}
Result<SparseMatrix> tangent = Difference(
internal.Value().tangent,
external.Value().generalized_external_tangent, dofs.Value());
if (!tangent.HasValue()) {
return Result<std::optional<ShellStepCandidate>>::Failure(
report_failure(&record, tangent.GetStatus(),
NewtonIterationStage::kExternalAssembled));
}
trial.Value().internal_force = std::move(internal.Value().force);
trial.Value().external_force =
std::move(external.Value().generalized_external_force);
trial.Value().residual = std::move(residual.Value());
trial.Value().reaction = trial.Value().residual;
trial.Value().shell_results = std::move(internal.Value().shell_rows);
trial.Value().physical_strain_energy =
internal.Value().physical_strain_energy;
Result<std::array<double, 6>> global_equilibrium =
GlobalEquilibrium(domain, dofs.Value(), trial.Value());
if (!global_equilibrium.HasValue()) {
return Result<std::optional<ShellStepCandidate>>::Failure(
report_failure(&record, global_equilibrium.GetStatus(),
NewtonIterationStage::kExternalAssembled));
}
trial.Value().global_equilibrium = global_equilibrium.Value();
Result<PartitionedStiffness> partition =
constraints.Partition(tangent.Value(), dofs.Value());
if (!partition.HasValue()) {
return Result<NonlinearStaticExecutionResult>::Failure(RecordFailure(
log, &record, partition.GetStatus(),
NewtonIterationStage::kExternalAssembled));
}
const Status factorization = tangent_solver_.FactorizeFresh(
partition.Value().k_ff);
if (!factorization.IsOk()) {
return Result<NonlinearStaticExecutionResult>::Failure(RecordFailure(
log, &record, factorization,
NewtonIterationStage::kSolvedCorrection));
}
Result<PartitionedStiffness> partition =
constraints.Partition(tangent.Value(), dofs.Value());
if (!partition.HasValue()) {
return Result<std::optional<ShellStepCandidate>>::Failure(
report_failure(&record, partition.GetStatus(),
NewtonIterationStage::kExternalAssembled));
}
const Status factorization =
tangent_solver.FactorizeFresh(partition.Value().k_ff);
if (!factorization.IsOk()) {
return Result<std::optional<ShellStepCandidate>>::Failure(
report_failure(&record, factorization,
NewtonIterationStage::kSolvedCorrection));
}
Vector correction_rhs = constraints.GatherFree(trial.Value().residual,
dofs.Value());
for (std::size_t index = 0U; index < correction_rhs.Size(); ++index) {
correction_rhs[index] = -correction_rhs[index];
}
Vector correction{dofs.Value().FreeDofCount()};
const Status solve =
tangent_solver_.SolveCorrection(correction_rhs, correction);
if (!solve.IsOk()) {
return Result<NonlinearStaticExecutionResult>::Failure(RecordFailure(
log, &record, solve, NewtonIterationStage::kSolvedCorrection));
}
record.last_completed_stage = NewtonIterationStage::kSolvedCorrection;
Vector correction_rhs =
constraints.GatherFree(trial.Value().residual, dofs.Value());
for (std::size_t index = 0U; index < correction_rhs.Size(); ++index) {
correction_rhs[index] = -correction_rhs[index];
}
Vector correction{dofs.Value().FreeDofCount()};
const Status solve =
tangent_solver.SolveCorrection(correction_rhs, correction);
if (!solve.IsOk()) {
return Result<std::optional<ShellStepCandidate>>::Failure(
report_failure(&record, solve,
NewtonIterationStage::kSolvedCorrection));
}
record.last_completed_stage = NewtonIterationStage::kSolvedCorrection;
const NewtonConvergenceResult convergence = EvaluateNewtonConvergence({
{"residual_force", SelectFreeComponents(trial.Value().residual,
dofs.Value(), false),
SelectFreeComponents(trial.Value().internal_force, dofs.Value(),
false),
SelectFreeComponents(trial.Value().external_force, dofs.Value(),
false)},
{"residual_moment", SelectFreeComponents(trial.Value().residual,
dofs.Value(), true),
SelectFreeComponents(trial.Value().internal_force, dofs.Value(),
true),
SelectFreeComponents(trial.Value().external_force, dofs.Value(),
true)},
{"correction_translation",
SelectCorrectionComponents(correction, dofs.Value(), false),
CurrentIncrementComponents(trial.Value().generalized_coordinates,
increment_start, dofs.Value(), false)},
{"correction_rotation",
SelectCorrectionComponents(correction, dofs.Value(), true),
CurrentIncrementComponents(trial.Value().generalized_coordinates,
increment_start, dofs.Value(), true)}});
record.force_residual = convergence.force_residual;
record.moment_residual = convergence.moment_residual;
record.translation_correction = convergence.translation_correction;
record.rotation_correction = convergence.rotation_correction;
record.combined_passed = convergence.combined_passed;
record.last_completed_stage = NewtonIterationStage::kConvergenceEvaluated;
const NewtonConvergenceResult convergence = EvaluateNewtonConvergence(
{{"residual_force",
SelectFreeComponents(trial.Value().residual, dofs.Value(),
false),
SelectFreeComponents(trial.Value().internal_force, dofs.Value(),
false),
SelectFreeComponents(trial.Value().external_force, dofs.Value(),
false)},
{"residual_moment",
SelectFreeComponents(trial.Value().residual, dofs.Value(),
true),
SelectFreeComponents(trial.Value().internal_force, dofs.Value(),
true),
SelectFreeComponents(trial.Value().external_force, dofs.Value(),
true)},
{"correction_translation",
SelectCorrectionComponents(correction, dofs.Value(), false),
CurrentIncrementComponents(
trial.Value().generalized_coordinates, increment_start,
dofs.Value(), false)},
{"correction_rotation",
SelectCorrectionComponents(correction, dofs.Value(), true),
CurrentIncrementComponents(
trial.Value().generalized_coordinates, increment_start,
dofs.Value(), true)}});
record.force_residual = convergence.force_residual;
record.moment_residual = convergence.moment_residual;
record.translation_correction = convergence.translation_correction;
record.rotation_correction = convergence.rotation_correction;
record.combined_passed = convergence.combined_passed;
record.last_completed_stage =
NewtonIterationStage::kConvergenceEvaluated;
if (convergence.combined_passed) {
const Status committed = state.Value().CommitAcceptedFrame(
AcceptedFrame(state.Value(), trial.Value(), increment, iteration));
if (!committed.IsOk()) {
return Result<NonlinearStaticExecutionResult>::Failure(RecordFailure(
log, &record, committed, NewtonIterationStage::kAccepted));
}
record.last_completed_stage = NewtonIterationStage::kAccepted;
record.transition = "accepted";
record.outcome = "accepted";
const Status log_status = WriteAndFlush(log, record);
if (!log_status.IsOk()) {
return Result<NonlinearStaticExecutionResult>::Failure(log_status);
}
break;
}
if (convergence.combined_passed) {
return Result<std::optional<ShellStepCandidate>>::Success(
ShellStepCandidate{AcceptedFrame(next_frame_index,
trial.Value(), increment,
iteration),
record});
}
if (iteration == kMaximumNewtonIterations) {
const Status failure = ProcedureFailure(
FailureCategory::kSolver, "nonlinear-nonconvergence",
step.Location(), "STATIC", step.Name(),
"The nonlinear procedure did not converge within 100 iterations.");
return Result<NonlinearStaticExecutionResult>::Failure(RecordFailure(
log, &record, failure,
NewtonIterationStage::kConvergenceEvaluated));
}
if (iteration == kMaximumNewtonIterations) {
const Status failure = ProcedureFailure(
FailureCategory::kSolver, "nonlinear-nonconvergence",
step.Location(), "STATIC", step.Name(),
"The nonlinear procedure did not converge within 100 "
"iterations.");
return Result<std::optional<ShellStepCandidate>>::Failure(
report_failure(&record, failure,
NewtonIterationStage::kConvergenceEvaluated));
}
for (std::size_t equation = 0U; equation < dofs.Value().FreeDofs().size();
++equation) {
const std::size_t full_dof = dofs.Value().FreeDofs()[equation];
trial.Value().generalized_coordinates[full_dof] += correction[equation];
if (!std::isfinite(trial.Value().generalized_coordinates[full_dof])) {
const Status failure = ProcedureFailure(
FailureCategory::kSolver, "nonfinite-newton-data", {},
"NONLINEAR_STATIC_PROCEDURE", std::to_string(full_dof),
"A nonlinear free-coordinate correction is nonfinite.");
return Result<NonlinearStaticExecutionResult>::Failure(RecordFailure(
log, &record, failure, NewtonIterationStage::kSolvedCorrection));
}
}
record.transition = "continue";
record.outcome = "not-converged";
const Status log_status = WriteAndFlush(log, record);
if (!log_status.IsOk()) {
return Result<NonlinearStaticExecutionResult>::Failure(log_status);
}
for (std::size_t equation = 0U;
equation < dofs.Value().FreeDofs().size(); ++equation) {
const std::size_t full_dof = dofs.Value().FreeDofs()[equation];
trial.Value().generalized_coordinates[full_dof] +=
correction[equation];
if (!std::isfinite(
trial.Value().generalized_coordinates[full_dof])) {
const Status failure = ProcedureFailure(
FailureCategory::kSolver, "nonfinite-newton-data", {},
"NONLINEAR_STATIC_PROCEDURE", std::to_string(full_dof),
"A nonlinear free-coordinate correction is nonfinite.");
return Result<std::optional<ShellStepCandidate>>::Failure(
report_failure(&record, failure,
NewtonIterationStage::kSolvedCorrection));
}
}
record.transition = "continue";
record.outcome = "not-converged";
const Status log_status = write_iteration(record);
if (!log_status.IsOk()) {
return Result<std::optional<ShellStepCandidate>>::Failure(
log_status);
}
return Result<std::optional<ShellStepCandidate>>::Success(
std::nullopt);
},
kMaximumNewtonIterations);
const Status solved = iteration_step.Solve(algorithm);
if (!solved.IsOk())
return Result<NonlinearStaticExecutionResult>::Failure(solved);
auto candidate = iteration_step.TakeCandidate();
auto& record = candidate.record;
const Status committed = state.Value().CommitAcceptedFrame(candidate.frame);
if (!committed.IsOk()) {
return Result<NonlinearStaticExecutionResult>::Failure(RecordFailure(
log, &record, committed, NewtonIterationStage::kAccepted));
}
record.last_completed_stage = NewtonIterationStage::kAccepted;
record.transition = "accepted";
record.outcome = "accepted";
const Status log_status = WriteAndFlush(log, record);
if (!log_status.IsOk())
return Result<NonlinearStaticExecutionResult>::Failure(log_status);
}
std::vector<Diagnostic> diagnostics = domain.Warnings();
@@ -983,4 +1013,4 @@ NonlinearStaticProcedureExecutor::Execute(
{std::move(state.Value()), std::move(diagnostics)});
}
} // namespace fesa
} // namespace fesa