Add frozen physical shape-field compensation diagnostics and controlled order study plan

This commit is contained in:
2026-09-18 13:20:03 -04:00
parent db854c0f7c
commit d79db9445b
4 changed files with 777 additions and 3 deletions

View File

@@ -30,6 +30,7 @@ import mean_field;
#include "plateau_gravity_application_diagnostics.hpp"
#include "plateau_positivity_strategy_diagnostics.hpp"
#include "plateau_polynomial_certificate.hpp"
#include "shape_field_weak_diagnostics.hpp"
using namespace mean_field;
namespace {
@@ -40,6 +41,7 @@ struct Options {
bool probes = false, noCentral = false;
bool strategyProbe = false, positivityProbe = false, positivityCertificate = false;
bool preconditionerProbe = false, nonlinearStepProbe = false;
bool weakShapeProbe = false, weakShapeFinal = false;
bool coupledTrialProbe = false, coupledSeedControl = false;
bool dampedCoupledProbe = false;
std::string coupledSearch = "near";
@@ -113,6 +115,10 @@ Options Parse(int argc, char **argv) {
o.preconditionerProbe = true;
else if (a == "--nonlinear-step-probe")
o.nonlinearStepProbe = true;
else if (a == "--weak-shape-probe")
o.weakShapeProbe = true;
else if (a == "--weak-shape-final")
o.weakShapeFinal = true;
else if (a == "--damped-coupled-probe")
o.dampedCoupledProbe = true;
else if (a == "--coupled-search")
@@ -171,6 +177,16 @@ Options Parse(int argc, char **argv) {
}
if (o.output.empty() || o.n < 1 || o.n >= 5 || o.maxNewton < 0 || o.maxLinear < 1 || o.restart < 1)
throw std::invalid_argument("Invalid options");
if (o.weakShapeProbe || o.weakShapeFinal) {
if ((o.weakShapeProbe && o.weakShapeFinal) || o.probes || o.pressureProbe || o.shapeCurvature ||
o.surfaceTrace || o.strategyProbe || o.positivityProbe || o.positivityCertificate ||
o.preconditionerProbe || o.nonlinearStepProbe || o.coupledTrialProbe || o.dampedCoupledProbe ||
!o.replayCandidate.empty() || !o.captureIterations.empty() ||
(o.weakShapeProbe && (o.maxNewton != 0 || o.strategy != "baseline")) ||
(o.weakShapeFinal && (o.maxNewton == 0 || !o.probeState.empty() || !o.probeDirection.empty())) ||
!std::isfinite(o.linearTolerance) || o.linearTolerance <= 0.)
throw std::invalid_argument("Weak-shape diagnostics require a standalone frozen probe or a final live endpoint probe");
}
if (o.probeRestart != 40 && o.probeRestart != 160)
throw std::invalid_argument("--probe-restart must be 40 or 160");
if ((o.pressureProbe || o.shapeCurvature || o.surfaceTrace || o.strategyProbe || o.positivityProbe || o.coupledTrialProbe || o.dampedCoupledProbe) && (o.probeState.empty() || o.probeDirection.empty()))
@@ -218,8 +234,8 @@ Options Parse(int argc, char **argv) {
throw std::invalid_argument("Newton preconditioner variants are independent, gravity-schur, stellar-ldu, or stellar-ldu-gravity-schur");
if (o.preconditionerVariant != "independent") {
if (o.probes || o.pressureProbe || o.shapeCurvature || o.surfaceTrace || o.strategyProbe ||
o.positivityProbe || o.positivityCertificate || (!o.probeState.empty() && !o.nonlinearStepProbe && !o.coupledTrialProbe && !o.dampedCoupledProbe) ||
(!o.probeDirection.empty() && !o.coupledTrialProbe && !o.dampedCoupledProbe) ||
o.positivityProbe || o.positivityCertificate || (!o.probeState.empty() && !o.nonlinearStepProbe && !o.coupledTrialProbe && !o.dampedCoupledProbe && !o.weakShapeProbe) ||
(!o.probeDirection.empty() && !o.coupledTrialProbe && !o.dampedCoupledProbe && !o.weakShapeProbe) ||
!o.replayCandidate.empty())
throw std::invalid_argument("A custom Newton preconditioner cannot be combined with frozen or certificate probes");
if (o.strategy != "baseline" && o.strategy != "positivity" && o.strategy != "curvature" &&
@@ -513,7 +529,8 @@ int RunContext(Context &context, const Options &o, const Scales &scales) {
<< "\nrestart=" << o.restart << "\nprobe_restart=" << o.probeRestart
<< "\nfrozen_probe_backend=" << (o.preconditionerProbe ? "direct_mfem_fgmres_preconditioner_benchmark" :
(o.coupledTrialProbe || o.dampedCoupledProbe) ? "supplied_outer_direction_verified_with_full_J_and_auxiliary_fgmres" :
o.nonlinearStepProbe ? "prepared_fgmres_cold_with_independent_true_gate" :
(o.nonlinearStepProbe || ((o.weakShapeProbe || o.weakShapeFinal) && o.probeDirection.empty()))
? "prepared_fgmres_cold_with_independent_true_gate" :
o.positivityCertificate ? "polynomial_certificate_no_linear_solve" :
o.probeDirection.empty() ? "direct_mfem_fgmres_cold" : "supplied_direction_no_linear_solve")
<< "\nlinear_tol=" << o.linearTolerance << "\nmax_linear=" << o.maxLinear
@@ -522,6 +539,7 @@ int RunContext(Context &context, const Options &o, const Scales &scales) {
<< "\ngravity_iterations=" << o.gravityIterations << "\ngravity_restart=" << o.gravityRestart
<< "\npreconditioner_probe=" << o.preconditionerProbe
<< "\nnonlinear_step_probe=" << o.nonlinearStepProbe
<< "\nweak_shape_probe=" << o.weakShapeProbe << "\nweak_shape_final=" << o.weakShapeFinal
<< "\ndamped_coupled_probe=" << o.dampedCoupledProbe
<< "\ncoupled_search=" << o.coupledSearch
<< "\ncoupled_beta_steps=" << o.coupledBetaSteps
@@ -541,7 +559,29 @@ int RunContext(Context &context, const Options &o, const Scales &scales) {
<< "\ncontext_gravity_schur_relaxation=" << (contextUsesGravitySchur ? o.schurRelaxation : 0.0)
<< "\nschur_correction_sweeps=" << o.schurCorrectionSweeps << "\nschur_relaxation=" << o.schurRelaxation
<< "\ncompiler=" << __VERSION__ << "\ncompiled=" << __DATE__ << ' ' << __TIME__ << '\n';
if (o.weakShapeProbe || o.weakShapeFinal)
metadata << "weak_shape_direction_space=normalized_current_factors\n"
<< "weak_shape_operator=full_monolithic\n"
<< "weak_shape_trial_policy=raw_prepare_only\n";
metadata.flush();
if (o.weakShapeProbe) {
metadata << "weak_shape_input=" << (o.probeState.empty() ? "lane_emden_seed" : "physical_snapshot") << '\n'
<< "probe_state=" << o.probeState << "\nprobe_direction=" << o.probeDirection << '\n';
metadata.flush();
solver::detail::StellarEquilibriumContextDiagnostics::WithState(context, [&](auto &s, const fem::FEM &f) {
mfem::Vector base(s.acceptedNormalizedState), direction;
if (!o.probeState.empty()) {
const auto physical = LoadVector(o.probeState, s.AcceptedPhysicalState().Size());
s.normalizedOperator->NormalizeState(physical, base);
}
if (!o.probeDirection.empty()) direction = LoadVector(o.probeDirection, base.Size());
experiment::plateau_diagnostics::ProbeWeakShapeField(s, f, base,
o.probeDirection.empty() ? nullptr : &direction, o.output, {
.linear = {.relativeTolerance = o.linearTolerance, .absoluteTolerance = 0.,
.maximumIterations = o.maxLinear}, .restartLength = o.restart});
});
return 0;
}
if (o.dampedCoupledProbe) {
metadata << "coupled_trial_input=physical_snapshot_and_supplied_normalized_direction\n"
<< "coupled_trial_admissibility=sampled_enthalpy_without_repair\n"
@@ -979,6 +1019,10 @@ int RunContext(Context &context, const Options &o, const Scales &scales) {
experiment::plateau_diagnostics::InspectPreconditioner(s, o.output);
FrozenProbes(s, f, o);
}
if (o.weakShapeFinal)
experiment::plateau_diagnostics::ProbeWeakShapeField(s, f, s.acceptedNormalizedState, nullptr, o.output, {
.linear = {.relativeTolerance = o.linearTolerance, .absoluteTolerance = 0.,
.maximumIterations = o.maxLinear}, .restartLength = o.restart});
});
return converged ? 0 : 3;
}