Add frozen smooth-surface restriction study with physical dual maps

This commit is contained in:
2026-09-18 15:45:05 -04:00
parent 6ceda61bdd
commit 21cdbda224
6 changed files with 1767 additions and 4 deletions

View File

@@ -31,6 +31,7 @@ import mean_field;
#include "plateau_positivity_strategy_diagnostics.hpp"
#include "plateau_polynomial_certificate.hpp"
#include "shape_field_weak_diagnostics.hpp"
#include "reduced_surface_diagnostics.hpp"
using namespace mean_field;
namespace {
@@ -42,6 +43,8 @@ struct Options {
bool strategyProbe = false, positivityProbe = false, positivityCertificate = false;
bool preconditionerProbe = false, nonlinearStepProbe = false;
bool weakShapeProbe = false, weakShapeFinal = false;
bool reducedSurfaceProbe = false, reducedSurfaceAlgebraCheck = false;
int surfaceDegree = 4;
bool coupledTrialProbe = false, coupledSeedControl = false;
bool dampedCoupledProbe = false;
std::string coupledSearch = "near";
@@ -115,6 +118,12 @@ Options Parse(int argc, char **argv) {
o.preconditionerProbe = true;
else if (a == "--nonlinear-step-probe")
o.nonlinearStepProbe = true;
else if (a == "--reduced-surface-probe")
o.reducedSurfaceProbe = true;
else if (a == "--reduced-surface-algebra-check")
o.reducedSurfaceAlgebraCheck = true;
else if (a == "--surface-degree")
o.surfaceDegree = std::stoi(v());
else if (a == "--weak-shape-probe")
o.weakShapeProbe = true;
else if (a == "--weak-shape-final")
@@ -177,6 +186,18 @@ 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.reducedSurfaceProbe || o.reducedSurfaceAlgebraCheck) {
if ((o.reducedSurfaceProbe && o.reducedSurfaceAlgebraCheck) || o.maxNewton != 0 ||
o.strategy != "baseline" || o.probes || o.pressureProbe || o.shapeCurvature ||
o.surfaceTrace || o.strategyProbe || o.positivityProbe || o.positivityCertificate ||
o.preconditionerProbe || o.nonlinearStepProbe || o.coupledTrialProbe || o.dampedCoupledProbe ||
o.weakShapeProbe || o.weakShapeFinal || !o.probeDirection.empty() ||
!o.replayCandidate.empty() || !o.captureIterations.empty() || !o.noCentral ||
(o.surfaceDegree != 0 && o.surfaceDegree != 2 && o.surfaceDegree != 4 &&
o.surfaceDegree != 6 && o.surfaceDegree != 8) ||
!std::isfinite(o.linearTolerance) || o.linearTolerance <= 0.)
throw std::invalid_argument("Reduced-surface study requires a standalone unbordered frozen probe; degree 0 is the full control");
}
if (o.weakShapeProbe || o.weakShapeFinal) {
if ((o.weakShapeProbe && o.weakShapeFinal) || o.probes || o.pressureProbe || o.shapeCurvature ||
o.surfaceTrace || o.strategyProbe || o.positivityProbe || o.positivityCertificate ||
@@ -234,8 +255,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.weakShapeProbe) ||
(!o.probeDirection.empty() && !o.coupledTrialProbe && !o.dampedCoupledProbe && !o.weakShapeProbe) ||
o.positivityProbe || o.positivityCertificate || (!o.probeState.empty() && !o.nonlinearStepProbe && !o.coupledTrialProbe && !o.dampedCoupledProbe && !o.weakShapeProbe && !o.reducedSurfaceProbe) ||
(!o.probeDirection.empty() && !o.coupledTrialProbe && !o.dampedCoupledProbe && !o.weakShapeProbe && !o.reducedSurfaceProbe) ||
!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" &&
@@ -529,7 +550,7 @@ 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 || ((o.weakShapeProbe || o.weakShapeFinal) && o.probeDirection.empty()))
(o.reducedSurfaceProbe || 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")
@@ -539,6 +560,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
<< "\nreduced_surface_probe=" << o.reducedSurfaceProbe << "\nsurface_degree=" << o.surfaceDegree
<< "\nweak_shape_probe=" << o.weakShapeProbe << "\nweak_shape_final=" << o.weakShapeFinal
<< "\ndamped_coupled_probe=" << o.dampedCoupledProbe
<< "\ncoupled_search=" << o.coupledSearch
@@ -564,6 +586,23 @@ int RunContext(Context &context, const Options &o, const Scales &scales) {
<< "weak_shape_operator=full_monolithic\n"
<< "weak_shape_trial_policy=raw_prepare_only\n";
metadata.flush();
if (o.reducedSurfaceProbe) {
metadata << "reduced_surface_input=" << (o.probeState.empty() ? "lane_emden_seed" : "physical_snapshot") << '\n'
<< "reduced_surface_trial_policy=raw_prepare_only_no_commit\n"
<< "probe_state=" << o.probeState << '\n';
metadata.flush();
solver::detail::StellarEquilibriumContextDiagnostics::WithState(context, [&](auto &s, const fem::FEM &f) {
mfem::Vector base(s.acceptedNormalizedState);
if (!o.probeState.empty()) {
const auto physical = LoadVector(o.probeState, s.AcceptedPhysicalState().Size());
s.normalizedOperator->NormalizeState(physical, base);
}
experiment::plateau_diagnostics::ProbeReducedSurface(s, f, base, o.output, o.surfaceDegree, o.n, scales.K, {
.linear = {.relativeTolerance = o.linearTolerance, .absoluteTolerance = 0.,
.maximumIterations = o.maxLinear}, .restartLength = o.restart});
});
return 0;
}
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';
@@ -1088,7 +1127,14 @@ int main(int argc, char **argv) {
throw std::runtime_error("Single rank only");
mfem::Device device("cpu");
std::cout << std::setprecision(12);
result = Run(Parse(argc, argv));
const auto options = Parse(argc, argv);
if (options.reducedSurfaceAlgebraCheck) {
const auto checks = experiment::plateau_diagnostics::RunReducedSurfaceAlgebraSelfCheck(MPI_COMM_WORLD);
std::cout << "Reduced surface algebra self-check passed: " << checks.checks
<< " checks, maximum error " << checks.maximumError << std::endl;
} else {
result = Run(options);
}
} catch (const std::exception &e) {
std::cerr << "Diagnostic failure: " << e.what() << std::endl;
result = 2;