Integrate Refactor solver sources and dual MSVC CMake builds
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
#include "analysis/hht_reduced_procedure.h"
|
||||
#include "analysis/hht_reduced_integrator.h"
|
||||
|
||||
#include "equilibrium_algorithm.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
@@ -296,12 +299,83 @@ Status CheckReducedUpdates(const Domain& domain,
|
||||
return Status::Ok();
|
||||
}
|
||||
|
||||
struct ReducedHistory {
|
||||
Vector p{0U};
|
||||
Vector velocity{0U};
|
||||
Vector acceleration{0U};
|
||||
Vector algorithmic_acceleration{0U};
|
||||
Vector z{0U};
|
||||
// Private nonvirtual primitive: keep velocity assignment before acceleration
|
||||
// evaluation, including per-index position retries. No accepted state changes.
|
||||
void EvaluateReducedShellRate(double predictor_velocity,
|
||||
double algorithmic_acceleration,
|
||||
double old_acceleration, double h,
|
||||
const HhtParameters& parameters,
|
||||
double* velocity, double* acceleration) {
|
||||
*velocity = predictor_velocity + parameters.gamma * h * algorithmic_acceleration;
|
||||
*acceleration = (algorithmic_acceleration + parameters.alpha * old_acceleration) /
|
||||
(1.0 + parameters.alpha);
|
||||
}
|
||||
|
||||
class ReducedCoordinateShellHhtIntegrator final : public ShellHhtIntegrator {
|
||||
public:
|
||||
ReducedShellPredictor
|
||||
Predict(const ReducedHistory& history, double h,
|
||||
const HhtParameters& parameters) const override {
|
||||
Vector pp{history.p.Size()}, vpp{history.p.Size()};
|
||||
for (std::size_t i = 0U; i < history.p.Size(); ++i) {
|
||||
pp[i] =
|
||||
history.p[i] + h * history.velocity[i] +
|
||||
h * h * (0.5 - parameters.beta) * history.algorithmic_acceleration[i];
|
||||
vpp[i] = history.velocity[i] + h * (1.0 - parameters.gamma) *
|
||||
history.algorithmic_acceleration[i];
|
||||
}
|
||||
Vector coordinate_low{history.p.Size()};
|
||||
Vector increment_trace{history.p.Size()};
|
||||
Vector increment_trace_compensation{history.p.Size()};
|
||||
Vector increment_trace_absolute_sum{history.p.Size()};
|
||||
for (std::size_t i = 0U; i < history.p.Size(); ++i) {
|
||||
const double velocity_term = h * history.velocity[i];
|
||||
const double old_acceleration_term =
|
||||
h * h * (0.5 - parameters.beta) * history.algorithmic_acceleration[i];
|
||||
const double first_sum = history.p[i] + velocity_term;
|
||||
coordinate_low[i] =
|
||||
AdditionLowPart(history.p[i], velocity_term, first_sum) +
|
||||
AdditionLowPart(first_sum, old_acceleration_term, pp[i]);
|
||||
AddIncrementTraceTerm(velocity_term, &increment_trace[i],
|
||||
&increment_trace_compensation[i]);
|
||||
AddIncrementTraceTerm(old_acceleration_term, &increment_trace[i],
|
||||
&increment_trace_compensation[i]);
|
||||
increment_trace_absolute_sum[i] =
|
||||
std::abs(velocity_term) + std::abs(old_acceleration_term);
|
||||
}
|
||||
return {std::move(pp),
|
||||
std::move(vpp),
|
||||
std::move(coordinate_low),
|
||||
std::move(increment_trace),
|
||||
std::move(increment_trace_compensation),
|
||||
std::move(increment_trace_absolute_sum)};
|
||||
}
|
||||
void EvaluateRates(const ReducedShellRateRequest& request,
|
||||
Vector& trial_v, Vector& trial_a) const override {
|
||||
const auto& history = request.history;
|
||||
const auto& trial_algorithmic = request.trial_algorithmic;
|
||||
const auto& vpp = request.vpp;
|
||||
const auto& parameters = request.parameters;
|
||||
const double h = request.h;
|
||||
for (std::size_t i = 0U; i < history.p.Size(); ++i) {
|
||||
if (request.copy_translation_rates &&
|
||||
PhysicalCoordinateChannel(request.chart, i) == 0U) {
|
||||
trial_v[i] = request.retained_velocity[i];
|
||||
trial_a[i] = request.retained_acceleration[i];
|
||||
} else {
|
||||
EvaluateReducedShellRate(
|
||||
vpp[i], trial_algorithmic[i], history.acceleration[i], h, parameters,
|
||||
&trial_v[i], &trial_a[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
Result<ReconstructedRates>
|
||||
ReconstructPhysicalRates(const FixedChart& chart, const EmbeddingRoot& root,
|
||||
const Vector& velocity, const Vector& acceleration,
|
||||
TangentSolver& solver) const override {
|
||||
return hht_reduced_internal::ReconstructPhysicalRates(chart, root, velocity,
|
||||
acceleration, solver);
|
||||
}
|
||||
};
|
||||
|
||||
struct Trial {
|
||||
@@ -320,6 +394,17 @@ Result<DynamicExecutionResult> ExecuteReducedHht(
|
||||
const Domain& domain, NewtonIterationLogWriter& log,
|
||||
const ParallelFor& parallel_for, LinearSolver& positive_solver,
|
||||
TangentSolver& tangent_solver) {
|
||||
const ReducedCoordinateShellHhtIntegrator integrator;
|
||||
NewtonStepAlgorithm algorithm;
|
||||
return ExecuteReducedHht(domain, log, parallel_for, positive_solver,
|
||||
tangent_solver, integrator, algorithm);
|
||||
}
|
||||
|
||||
Result<DynamicExecutionResult> ExecuteReducedHht(
|
||||
const Domain& domain, NewtonIterationLogWriter& log,
|
||||
const ParallelFor& parallel_for, LinearSolver& positive_solver,
|
||||
TangentSolver& tangent_solver, const ShellHhtIntegrator& integrator,
|
||||
EquilibriumAlgorithm& algorithm) {
|
||||
if (domain.Dynamic() == nullptr)
|
||||
return Result<DynamicExecutionResult>::Failure(Status::Failure(
|
||||
FailureCategory::kModel, {{Severity::kError, "invalid-dynamic-step", {},
|
||||
@@ -433,7 +518,7 @@ Result<DynamicExecutionResult> ExecuteReducedHht(
|
||||
tangent_solver);
|
||||
if (!root0.HasValue()) return Result<DynamicExecutionResult>::Failure(
|
||||
WithProcedureContext(domain, root0.GetStatus(), "inner-position", 0U, 0.0));
|
||||
auto rates0 = ReconstructPhysicalRates(chart.Value(), root0.Value(), history.velocity,
|
||||
auto rates0 = integrator.ReconstructPhysicalRates(chart.Value(), root0.Value(), history.velocity,
|
||||
history.acceleration, tangent_solver);
|
||||
if (!rates0.HasValue()) return Result<DynamicExecutionResult>::Failure(
|
||||
WithProcedureContext(domain, rates0.GetStatus(), "inner-rates", 0U, 0.0));
|
||||
@@ -604,343 +689,434 @@ Result<DynamicExecutionResult> ExecuteReducedHht(
|
||||
status = log.Write(record); if (status.IsOk()) status = log.Flush();
|
||||
if (!status.IsOk()) return Result<DynamicExecutionResult>::Failure(status);
|
||||
|
||||
for (std::uint32_t increment = 1U; increment <= domain.Dynamic()->increment_count; ++increment) {
|
||||
struct ReducedStepCandidate {
|
||||
DynamicAcceptedFrameState frame;
|
||||
ReducedHistory history;
|
||||
};
|
||||
for (std::uint32_t increment = 1U;
|
||||
increment <= domain.Dynamic()->increment_count; ++increment) {
|
||||
const auto& old = state.CommittedState();
|
||||
Vector pp{history.p.Size()}, vpp{history.p.Size()};
|
||||
for (std::size_t i = 0U; i < history.p.Size(); ++i) {
|
||||
pp[i] = history.p[i] + h * history.velocity[i] + h * h * (0.5 - parameters.beta) * history.algorithmic_acceleration[i];
|
||||
vpp[i] = history.velocity[i] + h * (1.0 - parameters.gamma) * history.algorithmic_acceleration[i];
|
||||
}
|
||||
DynamicAcceptedFrameState trial_frame = old;
|
||||
trial_frame.is_initial = false; trial_frame.frame_index = increment;
|
||||
trial_frame.increment_index = increment; trial_frame.time = static_cast<double>(increment) * h;
|
||||
trial_frame.time_integration_formulation = DynamicTimeIntegrationFormulation::kReducedCoordinateHht;
|
||||
Vector trial_algorithmic{history.p.Size()};
|
||||
Vector trial_p = pp;
|
||||
Vector coordinate_low{history.p.Size()};
|
||||
Vector chosen_start_p = pp;
|
||||
Vector increment_trace{history.p.Size()};
|
||||
Vector increment_trace_compensation{history.p.Size()};
|
||||
Vector increment_trace_absolute_sum{history.p.Size()};
|
||||
for (std::size_t i = 0U; i < history.p.Size(); ++i) {
|
||||
const double velocity_term = h * history.velocity[i];
|
||||
const double old_acceleration_term =
|
||||
h * h * (0.5 - parameters.beta) * history.algorithmic_acceleration[i];
|
||||
const double first_sum = history.p[i] + velocity_term;
|
||||
coordinate_low[i] = AdditionLowPart(history.p[i], velocity_term, first_sum) +
|
||||
AdditionLowPart(first_sum, old_acceleration_term, pp[i]);
|
||||
AddIncrementTraceTerm(velocity_term, &increment_trace[i],
|
||||
&increment_trace_compensation[i]);
|
||||
AddIncrementTraceTerm(old_acceleration_term, &increment_trace[i],
|
||||
&increment_trace_compensation[i]);
|
||||
increment_trace_absolute_sum[i] =
|
||||
std::abs(velocity_term) + std::abs(old_acceleration_term);
|
||||
}
|
||||
Vector seed = history.z;
|
||||
record = {}; record.increment_index = increment; record.time = trial_frame.time; record.correction_pass = true;
|
||||
bool translation_private_algorithmic_pass = true;
|
||||
bool copy_translation_rates = false;
|
||||
Vector retained_velocity{history.p.Size()};
|
||||
Vector retained_acceleration{history.p.Size()};
|
||||
bool accepted = false;
|
||||
for (std::uint32_t iteration = 0U;
|
||||
iteration <= kMaximumOuterCorrections; ++iteration) {
|
||||
record.iteration_index = iteration; record.stage = "evaluation"; record.outcome = "candidate";
|
||||
const auto fail = [&](const Status& failure,
|
||||
const char* stage = "outer") -> Result<DynamicExecutionResult> {
|
||||
const Status contextual = WithProcedureContext(
|
||||
domain, failure, stage, increment, trial_frame.time);
|
||||
record.stage = stage; record.outcome = "failed";
|
||||
record.failure_code = contextual.Diagnostics().empty()
|
||||
? "dynamic-solver-failure"
|
||||
: contextual.Diagnostics().front().code;
|
||||
const Status written = log.Write(record);
|
||||
return Result<DynamicExecutionResult>::Failure(
|
||||
written.IsOk() ? contextual : written);
|
||||
};
|
||||
Vector trial_v{history.p.Size()}, trial_a{history.p.Size()};
|
||||
for (std::size_t i = 0U; i < trial_p.Size(); ++i) {
|
||||
if (copy_translation_rates && PhysicalCoordinateChannel(chart.Value(), i) == 0U) {
|
||||
trial_v[i] = retained_velocity[i];
|
||||
trial_a[i] = retained_acceleration[i];
|
||||
} else {
|
||||
trial_v[i] = vpp[i] + parameters.gamma * h * trial_algorithmic[i];
|
||||
trial_a[i] = (trial_algorithmic[i] + parameters.alpha * history.acceleration[i]) / (1.0 + parameters.alpha);
|
||||
}
|
||||
}
|
||||
const auto evaluate_trial = [&](const Vector& physical_p,
|
||||
const Vector& physical_v,
|
||||
const Vector& physical_a,
|
||||
const Vector& root_seed) -> Result<Trial> {
|
||||
auto root = SolveEmbeddingRoot(chart.Value(), physical_p, root_seed,
|
||||
[&](const Vector& q) { return position_operators(trial_frame, q); },
|
||||
tangent_solver);
|
||||
if (!root.HasValue()) return Result<Trial>::Failure(
|
||||
WithProcedureContext(domain, root.GetStatus(), "inner-position",
|
||||
increment, trial_frame.time));
|
||||
auto rates = ReconstructPhysicalRates(chart.Value(), root.Value(), physical_v,
|
||||
physical_a, tangent_solver);
|
||||
if (!rates.HasValue()) return Result<Trial>::Failure(
|
||||
WithProcedureContext(domain, rates.GetStatus(), "inner-rates",
|
||||
increment, trial_frame.time));
|
||||
auto candidate = trial_frame;
|
||||
candidate.generalized_coordinates = root.Value().q;
|
||||
candidate.velocity = rates.Value().velocity;
|
||||
candidate.acceleration = rates.Value().acceleration;
|
||||
candidate.algorithmic_acceleration = Vector(dofs.FullDofCount());
|
||||
for (std::size_t i = 0U; i < candidate.algorithmic_acceleration.Size(); ++i)
|
||||
candidate.algorithmic_acceleration[i] =
|
||||
(1.0 + parameters.alpha) * candidate.acceleration[i] -
|
||||
parameters.alpha * old.acceleration[i];
|
||||
candidate.iteration_count = iteration;
|
||||
auto assembly = EvaluateAssembly(domain, dofs, shells.Value(), candidate,
|
||||
loads.Value()[1U], h, parameters,
|
||||
parallel_for, true);
|
||||
if (!assembly.HasValue()) return Result<Trial>::Failure(
|
||||
WithProcedureContext(domain, assembly.GetStatus(), "outer",
|
||||
increment, trial_frame.time));
|
||||
assembly.Value().frame.time_integration_formulation =
|
||||
DynamicTimeIntegrationFormulation::kReducedCoordinateHht;
|
||||
return Result<Trial>::Success(
|
||||
{std::move(assembly.Value()), std::move(root.Value()), physical_p,
|
||||
physical_v, physical_a, trial_algorithmic,
|
||||
std::move(rates.Value().z_velocity), std::move(rates.Value().z_acceleration)});
|
||||
};
|
||||
position_geometry_failure = false;
|
||||
auto trial = evaluate_trial(trial_p, trial_v, trial_a, seed);
|
||||
if (!trial.HasValue() && iteration == 0U && position_geometry_failure) {
|
||||
for (std::size_t i = 0U; i < trial_p.Size(); ++i) {
|
||||
trial_algorithmic[i] =
|
||||
(history.p[i] - pp[i]) / (parameters.beta * h * h);
|
||||
trial_p[i] = history.p[i];
|
||||
chosen_start_p[i] = history.p[i];
|
||||
coordinate_low[i] = 0.0;
|
||||
increment_trace[i] = 0.0;
|
||||
increment_trace_compensation[i] = 0.0;
|
||||
increment_trace_absolute_sum[i] = 0.0;
|
||||
trial_v[i] = vpp[i] + parameters.gamma * h * trial_algorithmic[i];
|
||||
trial_a[i] = (trial_algorithmic[i] +
|
||||
parameters.alpha * history.acceleration[i]) /
|
||||
(1.0 + parameters.alpha);
|
||||
}
|
||||
trial = evaluate_trial(trial_p, trial_v, trial_a, seed);
|
||||
}
|
||||
if (!trial.HasValue()) return fail(trial.GetStatus());
|
||||
if (iteration == 0U && !ExactlyEqual(trial_p, history.p)) {
|
||||
Vector old_algorithmic{trial_p.Size()};
|
||||
Vector old_velocity{trial_p.Size()};
|
||||
Vector old_acceleration{trial_p.Size()};
|
||||
for (std::size_t i = 0U; i < trial_p.Size(); ++i) {
|
||||
old_algorithmic[i] = (history.p[i] - pp[i]) / (parameters.beta * h * h);
|
||||
old_velocity[i] = vpp[i] + parameters.gamma * h * old_algorithmic[i];
|
||||
old_acceleration[i] = (old_algorithmic[i] + parameters.alpha * history.acceleration[i]) /
|
||||
(1.0 + parameters.alpha);
|
||||
}
|
||||
auto old_trial = evaluate_trial(history.p, old_velocity, old_acceleration, seed);
|
||||
if (!old_trial.HasValue()) return fail(old_trial.GetStatus());
|
||||
const auto reduced_residual = [&](const Trial& value) {
|
||||
double norm = 0.0;
|
||||
for (const auto full : dofs.FreeDofs()) {
|
||||
const double scale = full % 6U < 3U ? length : 1.0;
|
||||
norm = (std::max)(norm,
|
||||
scale * std::abs(value.assembly.frame.residual[full]));
|
||||
}
|
||||
if (!std::isfinite(norm)) return std::numeric_limits<double>::infinity();
|
||||
return norm;
|
||||
};
|
||||
const double old_residual = reduced_residual(old_trial.Value());
|
||||
const double predictor_residual = reduced_residual(trial.Value());
|
||||
if (!std::isfinite(old_residual) || !std::isfinite(predictor_residual))
|
||||
return fail(Failure(domain, "dynamic-invalid-state",
|
||||
"The scaled initial reduced residual is nonfinite."));
|
||||
if (old_residual < predictor_residual) {
|
||||
trial = std::move(old_trial);
|
||||
trial_p = history.p;
|
||||
chosen_start_p = history.p;
|
||||
coordinate_low = Vector(history.p.Size());
|
||||
increment_trace = Vector(history.p.Size());
|
||||
increment_trace_compensation = Vector(history.p.Size());
|
||||
increment_trace_absolute_sum = Vector(history.p.Size());
|
||||
trial_v = old_velocity;
|
||||
trial_a = old_acceleration;
|
||||
trial_algorithmic = old_algorithmic;
|
||||
}
|
||||
}
|
||||
auto candidate = trial.Value().assembly.frame;
|
||||
auto operators = EvaluateConstraintOperators(domain, dofs, shells.Value(),
|
||||
trial.Value().assembly, chart.Value(), zero, zero);
|
||||
if (!operators.HasValue()) return fail(operators.GetStatus());
|
||||
ResidualRecord(dofs, candidate, &record);
|
||||
if (record.residual_pass && record.correction_pass) {
|
||||
status = CompleteConstraintEvidence(domain, dofs, trial.Value().assembly, length, null_nodes,
|
||||
positive_solver, tangent_solver, &candidate);
|
||||
if (!status.IsOk()) return fail(status, "accepted");
|
||||
status = CompleteEquilibrium(domain, dofs, trial.Value().assembly, &candidate);
|
||||
if (!status.IsOk()) return fail(status, "accepted");
|
||||
graph_regularity = CheckGraphRegularity(trial.Value().assembly,
|
||||
chart.Value(), operators.Value(),
|
||||
tangent_solver);
|
||||
if (!graph_regularity.HasValue())
|
||||
return fail(graph_regularity.GetStatus(), "accepted");
|
||||
status = CheckReducedUpdates(domain, old, candidate, pp, vpp, trial_p, trial_v,
|
||||
trial_a, trial.Value().root.z,
|
||||
trial.Value().algebraic_velocity,
|
||||
trial.Value().algebraic_acceleration,
|
||||
trial_algorithmic, history.p, history.velocity,
|
||||
history.acceleration,
|
||||
history.algorithmic_acceleration,
|
||||
increment_trace,
|
||||
increment_trace_compensation,
|
||||
increment_trace_absolute_sum,
|
||||
chart.Value(), chosen_start_p, coordinate_low,
|
||||
parameters, h);
|
||||
if (!status.IsOk()) return fail(status, "accepted");
|
||||
candidate.external_work = 0.0;
|
||||
for (std::size_t i = 0U; i < dofs.FullDofCount(); ++i)
|
||||
candidate.external_work += candidate.external_force[i] * candidate.generalized_coordinates[i];
|
||||
candidate.energy_defect = candidate.kinetic_energy + candidate.physical_strain_energy +
|
||||
candidate.drilling_energy - initial_energy - candidate.external_work;
|
||||
status = state.CommitAcceptedFrame(candidate);
|
||||
if (!status.IsOk()) return fail(status, "accepted");
|
||||
history = {trial_p, trial_v, trial_a, trial_algorithmic, trial.Value().root.z};
|
||||
record.stage = "accepted"; record.outcome = "accepted";
|
||||
status = log.Write(record); if (status.IsOk()) status = log.Flush();
|
||||
if (!status.IsOk()) return Result<DynamicExecutionResult>::Failure(status);
|
||||
accepted = true; break;
|
||||
}
|
||||
if (!CanApplyOuterCorrection(iteration)) {
|
||||
double full_hidden = 0.0;
|
||||
double analytic_hidden = 0.0;
|
||||
double inertia_hidden = 0.0;
|
||||
double consistency = 0.0;
|
||||
for (std::size_t row = 0U; row < chart.Value().null_nodes.size(); ++row) {
|
||||
const auto node = chart.Value().null_nodes[row];
|
||||
const auto& null = trial.Value().assembly.rotations[node].drill_null;
|
||||
double full = 0.0;
|
||||
double inertia = 0.0;
|
||||
for (std::size_t component = 0U; component < 3U; ++component) {
|
||||
const auto full_dof = 6U * node + 3U + component;
|
||||
full += null[component] * candidate.residual[full_dof];
|
||||
inertia += null[component] * candidate.inertia_force[full_dof];
|
||||
}
|
||||
const double analytic = operators.Value().rows[row].value;
|
||||
full_hidden = (std::max)(full_hidden, std::abs(full));
|
||||
analytic_hidden = (std::max)(analytic_hidden, std::abs(analytic));
|
||||
inertia_hidden = (std::max)(inertia_hidden, std::abs(inertia));
|
||||
consistency = (std::max)(consistency, std::abs(full - analytic - inertia));
|
||||
}
|
||||
std::ostringstream message;
|
||||
const auto maximum = [](const Vector& values) {
|
||||
double result = 0.0;
|
||||
for (std::size_t i = 0U; i < values.Size(); ++i)
|
||||
result = (std::max)(result, std::abs(values[i]));
|
||||
return result;
|
||||
};
|
||||
Vector position_correction{trial_algorithmic.Size()};
|
||||
Vector velocity_correction{trial_algorithmic.Size()};
|
||||
for (std::size_t i = 0U; i < trial_algorithmic.Size(); ++i) {
|
||||
position_correction[i] = parameters.beta * h * h * trial_algorithmic[i];
|
||||
velocity_correction[i] = parameters.gamma * h * trial_algorithmic[i];
|
||||
}
|
||||
message << "HHT exhausted 100 corrections without satisfying every endpoint check; "
|
||||
<< "stage=outer, outer_iteration=" << iteration
|
||||
<< ", graph_iteration=" << trial.Value().root.graph_iteration_count
|
||||
<< ", graph_residual=" << trial.Value().root.graph_residual_infinity
|
||||
<< ", graph_relative=" << trial.Value().root.graph_residual_relative
|
||||
<< ", graph_correction=" << trial.Value().root.graph_correction_infinity
|
||||
<< ", max_NtE=" << full_hidden
|
||||
<< ", max_analytic_psi=" << analytic_hidden
|
||||
<< ", max_NtInertia=" << inertia_hidden
|
||||
<< ", max_NtE_minus_psi_minus_NtInertia=" << consistency
|
||||
<< ", max_pp=" << maximum(pp)
|
||||
<< ", max_beta_h2_trial_Ar=" << maximum(position_correction)
|
||||
<< ", max_trial_p=" << maximum(trial_p)
|
||||
<< ", max_vp_predictor=" << maximum(vpp)
|
||||
<< ", max_gamma_h_trial_Ar=" << maximum(velocity_correction)
|
||||
<< ", max_trial_v=" << maximum(trial_v)
|
||||
<< ", max_physical_v=" << maximum(trial.Value().velocity) << ".";
|
||||
return fail(Failure(domain, "dynamic-nonconvergence", message.str()));
|
||||
}
|
||||
status = log.Write(record);
|
||||
if (!status.IsOk()) return Result<DynamicExecutionResult>::Failure(status);
|
||||
const double velocity_rate = parameters.gamma / (parameters.beta * h);
|
||||
const double acceleration_rate = 1.0 / ((1.0 + parameters.alpha) * parameters.beta * h * h);
|
||||
auto system = AssembleAugmentedReducedSystem(trial.Value().assembly, chart.Value(), operators.Value(), velocity_rate, acceleration_rate, length, h);
|
||||
if (!system.HasValue()) return fail(system.GetStatus());
|
||||
const bool angular_only = ShouldRefineAngular(
|
||||
chart.Value(), candidate.free_residual_metrics,
|
||||
{record.coordinate_correction[0U], record.velocity_correction[0U],
|
||||
record.acceleration_correction[0U], record.algorithmic_correction[0U]},
|
||||
translation_private_algorithmic_pass);
|
||||
auto selected = SelectAugmentedSolve(system.Value(), chart.Value(), angular_only);
|
||||
if (!selected.HasValue()) return fail(selected.GetStatus());
|
||||
const auto linear_failure = [&](const Status& failure) {
|
||||
return fail(failure, angular_only ? "angular-newton-linear-solve"
|
||||
: "full-newton-linear-solve");
|
||||
};
|
||||
Vector selected_solution{selected.Value().rhs.Size()};
|
||||
if (selected_solution.Size() > 0U) {
|
||||
status = tangent_solver.FactorizeFresh(selected.Value().tangent);
|
||||
if (!status.IsOk()) return linear_failure(status);
|
||||
status = tangent_solver.SolveCorrection(selected.Value().rhs, selected_solution);
|
||||
if (!status.IsOk()) return linear_failure(status);
|
||||
status = CheckLinearSolve(selected.Value().tangent, selected.Value().rhs, selected_solution);
|
||||
if (!status.IsOk()) return linear_failure(status);
|
||||
}
|
||||
auto solution = EmbedAugmentedSolution(selected.Value(), selected_solution,
|
||||
system.Value().rhs.Size());
|
||||
if (!solution.HasValue()) return fail(solution.GetStatus());
|
||||
auto correction = MapAugmentedCorrection(chart.Value(), system.Value(), solution.Value(), velocity_rate, acceleration_rate);
|
||||
if (!correction.HasValue()) return fail(correction.GetStatus());
|
||||
Vector full_algorithmic{dofs.FullDofCount()};
|
||||
Vector reduced_algorithmic{correction.Value().p.Size()};
|
||||
Vector reduced_physical{correction.Value().p.Size()};
|
||||
for (std::size_t i = 0U; i < full_algorithmic.Size(); ++i)
|
||||
full_algorithmic[i] =
|
||||
(1.0 + parameters.alpha) * correction.Value().acceleration[i];
|
||||
for (std::size_t i = 0U; i < reduced_algorithmic.Size(); ++i) {
|
||||
reduced_algorithmic[i] = correction.Value().p[i] /
|
||||
(parameters.beta * h * h);
|
||||
reduced_physical[i] = acceleration_rate * correction.Value().p[i];
|
||||
}
|
||||
CorrectionRecord(correction.Value().coordinate, correction.Value().velocity,
|
||||
correction.Value().acceleration, full_algorithmic,
|
||||
reduced_algorithmic, reduced_physical, chart.Value(), dofs, length, h,
|
||||
parameters.alpha,
|
||||
&record);
|
||||
translation_private_algorithmic_pass = true;
|
||||
for (std::size_t i = 0U; i < chart.Value().p_dofs.size(); ++i)
|
||||
if (PhysicalCoordinateChannel(chart.Value(), i) == 0U)
|
||||
translation_private_algorithmic_pass =
|
||||
translation_private_algorithmic_pass &&
|
||||
PrivateCorrectionEqual(chart.Value(), i, full_algorithmic,
|
||||
reduced_algorithmic, reduced_physical, parameters.alpha);
|
||||
copy_translation_rates = angular_only;
|
||||
if (angular_only) {
|
||||
retained_velocity = trial_v;
|
||||
retained_acceleration = trial_a;
|
||||
}
|
||||
for (std::size_t i = 0U; i < trial_algorithmic.Size(); ++i) {
|
||||
if (angular_only && PhysicalCoordinateChannel(chart.Value(), i) == 0U) continue;
|
||||
trial_algorithmic[i] += reduced_algorithmic[i];
|
||||
}
|
||||
for (std::size_t i = 0U; i < trial_p.Size(); ++i) {
|
||||
if (angular_only && PhysicalCoordinateChannel(chart.Value(), i) == 0U) continue;
|
||||
AdvanceCoordinate(correction.Value().p[i], &trial_p[i], &coordinate_low[i]);
|
||||
}
|
||||
for (std::size_t i = 0U; i < increment_trace.Size(); ++i) {
|
||||
if (angular_only && PhysicalCoordinateChannel(chart.Value(), i) == 0U) continue;
|
||||
AddIncrementTraceTerm(correction.Value().p[i], &increment_trace[i],
|
||||
&increment_trace_compensation[i]);
|
||||
increment_trace_absolute_sum[i] += std::abs(correction.Value().p[i]);
|
||||
}
|
||||
seed = trial.Value().root.z;
|
||||
for (std::size_t i = 0U; i < seed.Size(); ++i)
|
||||
seed[i] += correction.Value().z[i];
|
||||
}
|
||||
if (!accepted) return Result<DynamicExecutionResult>::Failure(
|
||||
Failure(domain, "dynamic-nonconvergence", "Dynamic increment was not accepted."));
|
||||
const auto report_failure = [&](const Status& failure, const char* stage) {
|
||||
const Status contextual = WithProcedureContext(
|
||||
domain, failure, stage, increment, record.time);
|
||||
record.stage = stage;
|
||||
record.outcome = "failed";
|
||||
record.failure_code = contextual.Diagnostics().empty()
|
||||
? "dynamic-solver-failure"
|
||||
: contextual.Diagnostics().front().code;
|
||||
const Status written = log.Write(record);
|
||||
return written.IsOk() ? contextual : written;
|
||||
};
|
||||
status = RunReducedHhtStep(
|
||||
integrator, history, h, parameters,
|
||||
[&](const ShellHhtIntegrator& step_integrator,
|
||||
ReducedShellPredictor predictor) -> Result<ReducedStepCandidate> {
|
||||
Vector pp = std::move(predictor.pp);
|
||||
Vector vpp = std::move(predictor.vpp);
|
||||
DynamicAcceptedFrameState trial_frame = old;
|
||||
trial_frame.is_initial = false;
|
||||
trial_frame.frame_index = increment;
|
||||
trial_frame.increment_index = increment;
|
||||
trial_frame.time = static_cast<double>(increment) * h;
|
||||
trial_frame.time_integration_formulation =
|
||||
DynamicTimeIntegrationFormulation::kReducedCoordinateHht;
|
||||
Vector trial_algorithmic{history.p.Size()};
|
||||
Vector trial_p = pp;
|
||||
Vector coordinate_low = std::move(predictor.coordinate_low);
|
||||
Vector chosen_start_p = pp;
|
||||
Vector increment_trace = std::move(predictor.increment_trace);
|
||||
Vector increment_trace_compensation =
|
||||
std::move(predictor.increment_trace_compensation);
|
||||
Vector increment_trace_absolute_sum =
|
||||
std::move(predictor.increment_trace_absolute_sum);
|
||||
Vector seed = history.z;
|
||||
record = {};
|
||||
record.increment_index = increment;
|
||||
record.time = trial_frame.time;
|
||||
record.correction_pass = true;
|
||||
bool translation_private_algorithmic_pass = true;
|
||||
bool copy_translation_rates = false;
|
||||
Vector retained_velocity{history.p.Size()};
|
||||
Vector retained_acceleration{history.p.Size()};
|
||||
using StepResult = Result<std::optional<ReducedStepCandidate>>;
|
||||
const auto write_iteration =
|
||||
[&](const DynamicNewtonIterationLogRecord& value) {
|
||||
return log.Write(value);
|
||||
};
|
||||
ReducedShellHhtStep<ReducedStepCandidate> iteration_step(
|
||||
[&](std::uint32_t iteration) -> StepResult {
|
||||
record.iteration_index = iteration;
|
||||
record.stage = "evaluation";
|
||||
record.outcome = "candidate";
|
||||
const auto fail = [&](const Status& failure,
|
||||
const char* stage = "outer") -> StepResult {
|
||||
return StepResult::Failure(report_failure(failure, stage));
|
||||
};
|
||||
ReducedShellTrialRates reduced_rates{
|
||||
Vector{history.p.Size()}, Vector{history.p.Size()}};
|
||||
step_integrator.EvaluateRates(
|
||||
{chart.Value(), history, trial_algorithmic, vpp,
|
||||
copy_translation_rates, retained_velocity, retained_acceleration,
|
||||
h, parameters}, reduced_rates.velocity,
|
||||
reduced_rates.acceleration);
|
||||
Vector trial_v = std::move(reduced_rates.velocity);
|
||||
Vector trial_a = std::move(reduced_rates.acceleration);
|
||||
const auto evaluate_trial =
|
||||
[&](const Vector& physical_p, const Vector& physical_v,
|
||||
const Vector& physical_a,
|
||||
const Vector& root_seed) -> Result<Trial> {
|
||||
auto root = SolveEmbeddingRoot(
|
||||
chart.Value(), physical_p, root_seed,
|
||||
[&](const Vector& q) {
|
||||
return position_operators(trial_frame, q);
|
||||
},
|
||||
tangent_solver);
|
||||
if (!root.HasValue())
|
||||
return Result<Trial>::Failure(WithProcedureContext(
|
||||
domain, root.GetStatus(), "inner-position", increment,
|
||||
trial_frame.time));
|
||||
auto rates = step_integrator.ReconstructPhysicalRates(
|
||||
chart.Value(), root.Value(), physical_v, physical_a,
|
||||
tangent_solver);
|
||||
if (!rates.HasValue())
|
||||
return Result<Trial>::Failure(
|
||||
WithProcedureContext(domain, rates.GetStatus(), "inner-rates",
|
||||
increment, trial_frame.time));
|
||||
auto candidate = trial_frame;
|
||||
candidate.generalized_coordinates = root.Value().q;
|
||||
candidate.velocity = rates.Value().velocity;
|
||||
candidate.acceleration = rates.Value().acceleration;
|
||||
candidate.algorithmic_acceleration = Vector(dofs.FullDofCount());
|
||||
for (std::size_t i = 0U;
|
||||
i < candidate.algorithmic_acceleration.Size(); ++i)
|
||||
candidate.algorithmic_acceleration[i] =
|
||||
(1.0 + parameters.alpha) * candidate.acceleration[i] -
|
||||
parameters.alpha * old.acceleration[i];
|
||||
candidate.iteration_count = iteration;
|
||||
auto assembly = EvaluateAssembly(domain, dofs, shells.Value(),
|
||||
candidate, loads.Value()[1U], h,
|
||||
parameters, parallel_for, true);
|
||||
if (!assembly.HasValue())
|
||||
return Result<Trial>::Failure(
|
||||
WithProcedureContext(domain, assembly.GetStatus(), "outer",
|
||||
increment, trial_frame.time));
|
||||
assembly.Value().frame.time_integration_formulation =
|
||||
DynamicTimeIntegrationFormulation::kReducedCoordinateHht;
|
||||
return Result<Trial>::Success(
|
||||
{std::move(assembly.Value()), std::move(root.Value()),
|
||||
physical_p, physical_v, physical_a, trial_algorithmic,
|
||||
std::move(rates.Value().z_velocity),
|
||||
std::move(rates.Value().z_acceleration)});
|
||||
};
|
||||
position_geometry_failure = false;
|
||||
auto trial = evaluate_trial(trial_p, trial_v, trial_a, seed);
|
||||
if (!trial.HasValue() && iteration == 0U &&
|
||||
position_geometry_failure) {
|
||||
for (std::size_t i = 0U; i < trial_p.Size(); ++i) {
|
||||
trial_algorithmic[i] =
|
||||
(history.p[i] - pp[i]) / (parameters.beta * h * h);
|
||||
trial_p[i] = history.p[i];
|
||||
chosen_start_p[i] = history.p[i];
|
||||
coordinate_low[i] = 0.0;
|
||||
increment_trace[i] = 0.0;
|
||||
increment_trace_compensation[i] = 0.0;
|
||||
increment_trace_absolute_sum[i] = 0.0;
|
||||
}
|
||||
step_integrator.EvaluateRates(
|
||||
{chart.Value(), history, trial_algorithmic, vpp, false,
|
||||
retained_velocity, retained_acceleration, h, parameters},
|
||||
trial_v, trial_a);
|
||||
trial = evaluate_trial(trial_p, trial_v, trial_a, seed);
|
||||
}
|
||||
if (!trial.HasValue())
|
||||
return fail(trial.GetStatus());
|
||||
if (iteration == 0U && !ExactlyEqual(trial_p, history.p)) {
|
||||
Vector old_algorithmic{trial_p.Size()};
|
||||
Vector old_velocity{trial_p.Size()};
|
||||
Vector old_acceleration{trial_p.Size()};
|
||||
for (std::size_t i = 0U; i < trial_p.Size(); ++i) {
|
||||
old_algorithmic[i] =
|
||||
(history.p[i] - pp[i]) / (parameters.beta * h * h);
|
||||
}
|
||||
step_integrator.EvaluateRates(
|
||||
{chart.Value(), history, old_algorithmic, vpp, false,
|
||||
retained_velocity, retained_acceleration, h, parameters},
|
||||
old_velocity, old_acceleration);
|
||||
auto old_trial =
|
||||
evaluate_trial(history.p, old_velocity, old_acceleration, seed);
|
||||
if (!old_trial.HasValue())
|
||||
return fail(old_trial.GetStatus());
|
||||
const auto reduced_residual = [&](const Trial& value) {
|
||||
double norm = 0.0;
|
||||
for (const auto full : dofs.FreeDofs()) {
|
||||
const double scale = full % 6U < 3U ? length : 1.0;
|
||||
norm = (std::max)(norm,
|
||||
scale *
|
||||
std::abs(
|
||||
value.assembly.frame.residual[full]));
|
||||
}
|
||||
if (!std::isfinite(norm))
|
||||
return std::numeric_limits<double>::infinity();
|
||||
return norm;
|
||||
};
|
||||
const double old_residual = reduced_residual(old_trial.Value());
|
||||
const double predictor_residual = reduced_residual(trial.Value());
|
||||
if (!std::isfinite(old_residual) ||
|
||||
!std::isfinite(predictor_residual))
|
||||
return fail(
|
||||
Failure(domain, "dynamic-invalid-state",
|
||||
"The scaled initial reduced residual is nonfinite."));
|
||||
if (old_residual < predictor_residual) {
|
||||
trial = std::move(old_trial);
|
||||
trial_p = history.p;
|
||||
chosen_start_p = history.p;
|
||||
coordinate_low = Vector(history.p.Size());
|
||||
increment_trace = Vector(history.p.Size());
|
||||
increment_trace_compensation = Vector(history.p.Size());
|
||||
increment_trace_absolute_sum = Vector(history.p.Size());
|
||||
trial_v = old_velocity;
|
||||
trial_a = old_acceleration;
|
||||
trial_algorithmic = old_algorithmic;
|
||||
}
|
||||
}
|
||||
auto candidate = trial.Value().assembly.frame;
|
||||
auto operators = EvaluateConstraintOperators(
|
||||
domain, dofs, shells.Value(), trial.Value().assembly,
|
||||
chart.Value(), zero, zero);
|
||||
if (!operators.HasValue())
|
||||
return fail(operators.GetStatus());
|
||||
ResidualRecord(dofs, candidate, &record);
|
||||
if (record.residual_pass && record.correction_pass) {
|
||||
status = CompleteConstraintEvidence(
|
||||
domain, dofs, trial.Value().assembly, length, null_nodes,
|
||||
positive_solver, tangent_solver, &candidate);
|
||||
if (!status.IsOk())
|
||||
return fail(status, "accepted");
|
||||
status = CompleteEquilibrium(domain, dofs, trial.Value().assembly,
|
||||
&candidate);
|
||||
if (!status.IsOk())
|
||||
return fail(status, "accepted");
|
||||
graph_regularity =
|
||||
CheckGraphRegularity(trial.Value().assembly, chart.Value(),
|
||||
operators.Value(), tangent_solver);
|
||||
if (!graph_regularity.HasValue())
|
||||
return fail(graph_regularity.GetStatus(), "accepted");
|
||||
status = CheckReducedUpdates(
|
||||
domain, old, candidate, pp, vpp, trial_p, trial_v, trial_a,
|
||||
trial.Value().root.z, trial.Value().algebraic_velocity,
|
||||
trial.Value().algebraic_acceleration, trial_algorithmic,
|
||||
history.p, history.velocity, history.acceleration,
|
||||
history.algorithmic_acceleration, increment_trace,
|
||||
increment_trace_compensation, increment_trace_absolute_sum,
|
||||
chart.Value(), chosen_start_p, coordinate_low, parameters, h);
|
||||
if (!status.IsOk())
|
||||
return fail(status, "accepted");
|
||||
candidate.external_work = 0.0;
|
||||
for (std::size_t i = 0U; i < dofs.FullDofCount(); ++i)
|
||||
candidate.external_work += candidate.external_force[i] *
|
||||
candidate.generalized_coordinates[i];
|
||||
candidate.energy_defect = candidate.kinetic_energy +
|
||||
candidate.physical_strain_energy +
|
||||
candidate.drilling_energy -
|
||||
initial_energy - candidate.external_work;
|
||||
return StepResult::Success(ReducedStepCandidate{
|
||||
std::move(candidate),
|
||||
{trial_p, trial_v, trial_a, trial_algorithmic,
|
||||
trial.Value().root.z}});
|
||||
}
|
||||
if (!CanApplyOuterCorrection(iteration)) {
|
||||
double full_hidden = 0.0;
|
||||
double analytic_hidden = 0.0;
|
||||
double inertia_hidden = 0.0;
|
||||
double consistency = 0.0;
|
||||
for (std::size_t row = 0U; row < chart.Value().null_nodes.size();
|
||||
++row) {
|
||||
const auto node = chart.Value().null_nodes[row];
|
||||
const auto& null =
|
||||
trial.Value().assembly.rotations[node].drill_null;
|
||||
double full = 0.0;
|
||||
double inertia = 0.0;
|
||||
for (std::size_t component = 0U; component < 3U; ++component) {
|
||||
const auto full_dof = 6U * node + 3U + component;
|
||||
full += null[component] * candidate.residual[full_dof];
|
||||
inertia += null[component] * candidate.inertia_force[full_dof];
|
||||
}
|
||||
const double analytic = operators.Value().rows[row].value;
|
||||
full_hidden = (std::max)(full_hidden, std::abs(full));
|
||||
analytic_hidden = (std::max)(analytic_hidden, std::abs(analytic));
|
||||
inertia_hidden = (std::max)(inertia_hidden, std::abs(inertia));
|
||||
consistency =
|
||||
(std::max)(consistency, std::abs(full - analytic - inertia));
|
||||
}
|
||||
std::ostringstream message;
|
||||
const auto maximum = [](const Vector& values) {
|
||||
double result = 0.0;
|
||||
for (std::size_t i = 0U; i < values.Size(); ++i)
|
||||
result = (std::max)(result, std::abs(values[i]));
|
||||
return result;
|
||||
};
|
||||
Vector position_correction{trial_algorithmic.Size()};
|
||||
Vector velocity_correction{trial_algorithmic.Size()};
|
||||
for (std::size_t i = 0U; i < trial_algorithmic.Size(); ++i) {
|
||||
position_correction[i] =
|
||||
parameters.beta * h * h * trial_algorithmic[i];
|
||||
velocity_correction[i] =
|
||||
parameters.gamma * h * trial_algorithmic[i];
|
||||
}
|
||||
message << "HHT exhausted 100 corrections without satisfying every "
|
||||
"endpoint check; "
|
||||
<< "stage=outer, outer_iteration=" << iteration
|
||||
<< ", graph_iteration="
|
||||
<< trial.Value().root.graph_iteration_count
|
||||
<< ", graph_residual="
|
||||
<< trial.Value().root.graph_residual_infinity
|
||||
<< ", graph_relative="
|
||||
<< trial.Value().root.graph_residual_relative
|
||||
<< ", graph_correction="
|
||||
<< trial.Value().root.graph_correction_infinity
|
||||
<< ", max_NtE=" << full_hidden
|
||||
<< ", max_analytic_psi=" << analytic_hidden
|
||||
<< ", max_NtInertia=" << inertia_hidden
|
||||
<< ", max_NtE_minus_psi_minus_NtInertia=" << consistency
|
||||
<< ", max_pp=" << maximum(pp)
|
||||
<< ", max_beta_h2_trial_Ar=" << maximum(position_correction)
|
||||
<< ", max_trial_p=" << maximum(trial_p)
|
||||
<< ", max_vp_predictor=" << maximum(vpp)
|
||||
<< ", max_gamma_h_trial_Ar=" << maximum(velocity_correction)
|
||||
<< ", max_trial_v=" << maximum(trial_v)
|
||||
<< ", max_physical_v=" << maximum(trial.Value().velocity)
|
||||
<< ".";
|
||||
return fail(
|
||||
Failure(domain, "dynamic-nonconvergence", message.str()));
|
||||
}
|
||||
status = write_iteration(record);
|
||||
if (!status.IsOk())
|
||||
return StepResult::Failure(status);
|
||||
const double velocity_rate = parameters.gamma / (parameters.beta * h);
|
||||
const double acceleration_rate =
|
||||
1.0 / ((1.0 + parameters.alpha) * parameters.beta * h * h);
|
||||
auto system = AssembleAugmentedReducedSystem(
|
||||
trial.Value().assembly, chart.Value(), operators.Value(),
|
||||
velocity_rate, acceleration_rate, length, h);
|
||||
if (!system.HasValue())
|
||||
return fail(system.GetStatus());
|
||||
const bool angular_only = ShouldRefineAngular(
|
||||
chart.Value(), candidate.free_residual_metrics,
|
||||
{record.coordinate_correction[0U], record.velocity_correction[0U],
|
||||
record.acceleration_correction[0U],
|
||||
record.algorithmic_correction[0U]},
|
||||
translation_private_algorithmic_pass);
|
||||
auto selected =
|
||||
SelectAugmentedSolve(system.Value(), chart.Value(), angular_only);
|
||||
if (!selected.HasValue())
|
||||
return fail(selected.GetStatus());
|
||||
const auto linear_failure = [&](const Status& failure) {
|
||||
return fail(failure, angular_only ? "angular-newton-linear-solve"
|
||||
: "full-newton-linear-solve");
|
||||
};
|
||||
Vector selected_solution{selected.Value().rhs.Size()};
|
||||
if (selected_solution.Size() > 0U) {
|
||||
status = tangent_solver.FactorizeFresh(selected.Value().tangent);
|
||||
if (!status.IsOk())
|
||||
return linear_failure(status);
|
||||
status = tangent_solver.SolveCorrection(selected.Value().rhs,
|
||||
selected_solution);
|
||||
if (!status.IsOk())
|
||||
return linear_failure(status);
|
||||
status = CheckLinearSolve(selected.Value().tangent,
|
||||
selected.Value().rhs, selected_solution);
|
||||
if (!status.IsOk())
|
||||
return linear_failure(status);
|
||||
}
|
||||
auto solution = EmbedAugmentedSolution(
|
||||
selected.Value(), selected_solution, system.Value().rhs.Size());
|
||||
if (!solution.HasValue())
|
||||
return fail(solution.GetStatus());
|
||||
auto correction = MapAugmentedCorrection(
|
||||
chart.Value(), system.Value(), solution.Value(), velocity_rate,
|
||||
acceleration_rate);
|
||||
if (!correction.HasValue())
|
||||
return fail(correction.GetStatus());
|
||||
Vector full_algorithmic{dofs.FullDofCount()};
|
||||
Vector reduced_algorithmic{correction.Value().p.Size()};
|
||||
Vector reduced_physical{correction.Value().p.Size()};
|
||||
for (std::size_t i = 0U; i < full_algorithmic.Size(); ++i)
|
||||
full_algorithmic[i] =
|
||||
(1.0 + parameters.alpha) * correction.Value().acceleration[i];
|
||||
for (std::size_t i = 0U; i < reduced_algorithmic.Size(); ++i) {
|
||||
reduced_algorithmic[i] =
|
||||
correction.Value().p[i] / (parameters.beta * h * h);
|
||||
reduced_physical[i] = acceleration_rate * correction.Value().p[i];
|
||||
}
|
||||
CorrectionRecord(correction.Value().coordinate,
|
||||
correction.Value().velocity,
|
||||
correction.Value().acceleration, full_algorithmic,
|
||||
reduced_algorithmic, reduced_physical, chart.Value(),
|
||||
dofs, length, h, parameters.alpha, &record);
|
||||
translation_private_algorithmic_pass = true;
|
||||
for (std::size_t i = 0U; i < chart.Value().p_dofs.size(); ++i)
|
||||
if (PhysicalCoordinateChannel(chart.Value(), i) == 0U)
|
||||
translation_private_algorithmic_pass =
|
||||
translation_private_algorithmic_pass &&
|
||||
PrivateCorrectionEqual(chart.Value(), i, full_algorithmic,
|
||||
reduced_algorithmic, reduced_physical,
|
||||
parameters.alpha);
|
||||
copy_translation_rates = angular_only;
|
||||
if (angular_only) {
|
||||
retained_velocity = trial_v;
|
||||
retained_acceleration = trial_a;
|
||||
}
|
||||
for (std::size_t i = 0U; i < trial_algorithmic.Size(); ++i) {
|
||||
if (angular_only &&
|
||||
PhysicalCoordinateChannel(chart.Value(), i) == 0U)
|
||||
continue;
|
||||
trial_algorithmic[i] += reduced_algorithmic[i];
|
||||
}
|
||||
for (std::size_t i = 0U; i < trial_p.Size(); ++i) {
|
||||
if (angular_only &&
|
||||
PhysicalCoordinateChannel(chart.Value(), i) == 0U)
|
||||
continue;
|
||||
AdvanceCoordinate(correction.Value().p[i], &trial_p[i],
|
||||
&coordinate_low[i]);
|
||||
}
|
||||
for (std::size_t i = 0U; i < increment_trace.Size(); ++i) {
|
||||
if (angular_only &&
|
||||
PhysicalCoordinateChannel(chart.Value(), i) == 0U)
|
||||
continue;
|
||||
AddIncrementTraceTerm(correction.Value().p[i], &increment_trace[i],
|
||||
&increment_trace_compensation[i]);
|
||||
increment_trace_absolute_sum[i] +=
|
||||
std::abs(correction.Value().p[i]);
|
||||
}
|
||||
seed = trial.Value().root.z;
|
||||
for (std::size_t i = 0U; i < seed.Size(); ++i)
|
||||
seed[i] += correction.Value().z[i];
|
||||
return StepResult::Success(std::nullopt);
|
||||
},
|
||||
kMaximumOuterCorrections);
|
||||
const Status solved = iteration_step.Solve(algorithm);
|
||||
if (!solved.IsOk())
|
||||
return Result<ReducedStepCandidate>::Failure(solved);
|
||||
if (!iteration_step.HasCandidate()) return Result<ReducedStepCandidate>::Failure(
|
||||
Failure(domain, "dynamic-nonconvergence", "Dynamic increment was not accepted."));
|
||||
return Result<ReducedStepCandidate>::Success(
|
||||
iteration_step.TakeCandidate());
|
||||
},
|
||||
[&](ReducedStepCandidate&& accepted_candidate) -> Status {
|
||||
status = state.CommitAcceptedFrame(accepted_candidate.frame);
|
||||
if (!status.IsOk())
|
||||
return report_failure(status, "accepted");
|
||||
history = std::move(accepted_candidate.history);
|
||||
record.stage = "accepted";
|
||||
record.outcome = "accepted";
|
||||
status = log.Write(record);
|
||||
if (status.IsOk())
|
||||
status = log.Flush();
|
||||
return status;
|
||||
});
|
||||
if (!status.IsOk()) return Result<DynamicExecutionResult>::Failure(status);
|
||||
}
|
||||
return Result<DynamicExecutionResult>::Success({std::move(state), domain.Warnings()});
|
||||
return Result<DynamicExecutionResult>::Success(
|
||||
{std::move(state), domain.Warnings()});
|
||||
}
|
||||
} // namespace fesa
|
||||
} // namespace fesa
|
||||
|
||||
Reference in New Issue
Block a user