Connect HHT field convergence to production acceptance and v2 logs

This commit is contained in:
KOKO\Mimi
2026-10-19 02:49:53 +09:00
parent 0e392a7364
commit dd54b0ae1e
9 changed files with 811 additions and 23 deletions
+91 -19
View File
@@ -150,7 +150,7 @@ void ResidualRecord(const DofManager& dofs,
frame.free_residual_metrics[1U] <= 1e-10;
}
void CorrectionRecord(const Vector& coordinate, const Vector& velocity,
bool CorrectionRecord(const Vector& coordinate, const Vector& velocity,
const Vector& acceleration,
const Vector& full_algorithmic,
const Vector& reduced_algorithmic,
@@ -189,12 +189,14 @@ void CorrectionRecord(const Vector& coordinate, const Vector& velocity,
if (reduced_algorithmic.Size() != chart.p_columns.size() ||
reduced_physical.Size() != chart.p_columns.size()) {
record->correction_pass = false;
return;
return false;
}
bool private_pass = true;
for (std::size_t i = 0U; i < chart.p_dofs.size(); ++i)
record->correction_pass = record->correction_pass &&
PrivateCorrectionEqual(chart, i, full_algorithmic,
reduced_algorithmic, reduced_physical, alpha);
private_pass = private_pass && PrivateCorrectionEqual(
chart, i, full_algorithmic, reduced_algorithmic, reduced_physical, alpha);
record->correction_pass = record->correction_pass && private_pass;
return private_pass;
}
bool ExactlyEqual(const Vector& left, const Vector& right) {
@@ -433,7 +435,8 @@ Result<DynamicExecutionResult> ExecuteReducedHht(
auto length_result = ReferenceLength(domain);
if (!length_result.HasValue()) return Result<DynamicExecutionResult>::Failure(length_result.GetStatus());
const double length = length_result.Value();
auto loads = AssembleLoads(domain, dofs);
std::array<std::vector<hht_field_convergence::FluxOccurrence>, 2> load_flux;
auto loads = AssembleLoads(domain, dofs, &load_flux);
if (!loads.HasValue()) return Result<DynamicExecutionResult>::Failure(loads.GetStatus());
auto parameters_result = MakeHhtParameters(domain.Dynamic()->alpha);
if (!parameters_result.HasValue()) return Result<DynamicExecutionResult>::Failure(parameters_result.GetStatus());
@@ -699,9 +702,11 @@ Result<DynamicExecutionResult> ExecuteReducedHht(
status = log.Write(record); if (status.IsOk()) status = log.Flush();
if (!status.IsOk()) return Result<DynamicExecutionResult>::Failure(status);
std::array<hht_field_convergence::History, 2> flux_history{};
struct ReducedStepCandidate {
DynamicAcceptedFrameState frame;
ReducedHistory history;
std::array<hht_field_convergence::History, 2> flux_history;
};
for (std::uint32_t increment = 1U;
increment <= domain.Dynamic()->increment_count; ++increment) {
@@ -711,9 +716,14 @@ Result<DynamicExecutionResult> ExecuteReducedHht(
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;
record.accepted = false;
const auto cause = std::find_if(
failure.Diagnostics().begin(), failure.Diagnostics().end(),
[](const Diagnostic& diagnostic) {
return diagnostic.code != "dynamic-procedure-context";
});
record.failure_code = cause == failure.Diagnostics().end()
? "dynamic-solver-failure" : cause->code;
const Status written = log.Write(record);
return written.IsOk() ? contextual : written;
};
@@ -744,6 +754,10 @@ Result<DynamicExecutionResult> ExecuteReducedHht(
record.increment_index = increment;
record.time = trial_frame.time;
record.correction_pass = true;
record.policy_id = hht_field_convergence::kPolicyId;
record.step_name = domain.Dynamic()->source_step_name_raw;
std::optional<Vector> previous_selected_q;
std::array<std::optional<double>, 2> previous_residual, older_residual;
bool translation_private_algorithmic_pass = true;
bool copy_translation_rates = false;
Vector retained_velocity{history.p.Size()};
@@ -755,6 +769,9 @@ Result<DynamicExecutionResult> ExecuteReducedHht(
};
ReducedShellHhtStep<ReducedStepCandidate> iteration_step(
[&](std::uint32_t iteration) -> StepResult {
record.fields = {};
record.field_pass.reset();
record.strict_residual_evaluated = false;
record.iteration_index = iteration;
record.stage = "evaluation";
record.outcome = "candidate";
@@ -896,7 +913,53 @@ Result<DynamicExecutionResult> ExecuteReducedHht(
if (!operators.HasValue())
return fail(operators.GetStatus());
ResidualRecord(dofs, candidate, &record);
if (record.residual_pass && record.correction_pass) {
record.strict_residual_evaluated = true;
auto measured_fields = MeasureEndpointFields(dofs, candidate, old, previous_selected_q);
if (!measured_fields.HasValue()) return fail(measured_fields.GetStatus());
auto field_inputs = std::move(measured_fields.Value());
for (std::size_t c = 0; c < 2; ++c) {
field_inputs[c].flux = trial.Value().assembly.field_flux[c];
field_inputs[c].flux.insert(field_inputs[c].flux.end(),
load_flux[c].begin(), load_flux[c].end());
field_inputs[c].previous_residual = previous_residual[c];
field_inputs[c].older_residual = older_residual[c];
}
const auto field_evaluation = hht_field_convergence::Evaluate(
field_inputs, flux_history, iteration, length);
for (std::size_t c = 0; c < 2; ++c) {
auto& e = record.fields[c];
const auto& in = field_inputs[c];
const auto& out = field_evaluation.fields[c];
if (in.active) {
e.residual_numerator = in.residual;
e.increment_norm = in.increment;
e.correction_numerator = in.correction;
}
e.residual_scale = out.residual_scale;
e.spatial_flux = out.spatial_flux;
e.time_average_flux = out.time_average_flux;
e.estimated_correction = out.estimated_correction;
e.residual_threshold = out.residual_threshold;
e.correction_threshold = out.correction_threshold;
e.residual_pass = out.residual_pass;
e.correction_pass = out.correction_pass;
e.field_pass = out.field_pass;
using Branch = hht_field_convergence::Branch;
switch (out.branch) {
case Branch::kNotEvaluated: e.branch = "not-evaluated"; break;
case Branch::kLinear: e.branch = "linear"; break;
case Branch::kZeroFlux: e.branch = "zero-flux"; break;
case Branch::kNonquadratic: e.branch = "nonquadratic"; break;
case Branch::kNormal: e.branch = "normal"; break;
}
}
if (!field_evaluation.status.IsOk()) return fail(field_evaluation.status);
record.field_pass = field_evaluation.field_pass;
previous_selected_q = candidate.generalized_coordinates;
older_residual = previous_residual;
for (std::size_t c = 0; c < 2; ++c)
previous_residual[c] = field_inputs[c].residual;
if (field_evaluation.field_pass) {
status = CompleteConstraintEvidence(
domain, dofs, trial.Value().assembly, length, null_nodes,
positive_solver, tangent_solver, &candidate);
@@ -932,7 +995,7 @@ Result<DynamicExecutionResult> ExecuteReducedHht(
return StepResult::Success(ReducedStepCandidate{
std::move(candidate),
{trial_p, trial_v, trial_a, trial_algorithmic,
trial.Value().root.z}});
trial.Value().root.z}, field_evaluation.pending});
}
if (!CanApplyOuterCorrection(iteration)) {
double full_hidden = 0.0;
@@ -1059,11 +1122,15 @@ Result<DynamicExecutionResult> ExecuteReducedHht(
correction.Value().p[i] / (parameters.beta * h * h);
reduced_physical[i] = acceleration_rate * correction.Value().p[i];
}
CorrectionRecord(correction.Value().coordinate,
const bool private_correction_pass = CorrectionRecord(correction.Value().coordinate,
correction.Value().velocity,
correction.Value().acceleration, full_algorithmic,
reduced_algorithmic, reduced_physical, chart.Value(),
dofs, length, h, parameters.alpha, &record);
record.strict_correction_evaluated = true;
if (!private_correction_pass)
return fail(Failure(domain, "reduced-dynamic-update-inconsistency",
"The full/private correction acceleration arithmetic is inconsistent."));
translation_private_algorithmic_pass = true;
for (std::size_t i = 0U; i < chart.Value().p_dofs.size(); ++i)
if (PhysicalCoordinateChannel(chart.Value(), i) == 0U)
@@ -1115,16 +1182,21 @@ Result<DynamicExecutionResult> ExecuteReducedHht(
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);
// Stage the complete accepted history. Output failure discards all
// three snapshots; publication below consists only of noexcept moves.
auto staged_state = state;
status = staged_state.CommitAcceptedFrame(accepted_candidate.frame);
if (!status.IsOk()) return report_failure(status, "accepted");
record.stage = "accepted";
record.outcome = "accepted";
record.accepted = true;
status = log.Write(record);
if (status.IsOk())
status = log.Flush();
return status;
if (status.IsOk()) status = log.Flush();
if (!status.IsOk()) return status;
state = std::move(staged_state);
history = std::move(accepted_candidate.history);
flux_history = accepted_candidate.flux_history;
return Status::Ok();
});
if (!status.IsOk()) return Result<DynamicExecutionResult>::Failure(status);
}