Record reproducible plateau campaigns and selected-direction probes
This commit is contained in:
@@ -23,7 +23,7 @@ namespace {
|
||||
using Clock = std::chrono::steady_clock;
|
||||
struct Options {
|
||||
double n = 1., angularMomentum = 0., atol = 0., rtol = 1e-8, linearTolerance = .03;
|
||||
int maxNewton = 12, maxLinear = 200, restart = 40;
|
||||
int maxNewton = 12, maxLinear = 200, restart = 40, probeRestart = 40;
|
||||
bool probes = false, noCentral = false;
|
||||
std::string mesh = "sandbox.smesh";
|
||||
std::filesystem::path output, probeState;
|
||||
@@ -51,6 +51,8 @@ Options Parse(int argc, char **argv) {
|
||||
o.maxLinear = std::stoi(v());
|
||||
else if (a == "--restart")
|
||||
o.restart = std::stoi(v());
|
||||
else if (a == "--probe-restart")
|
||||
o.probeRestart = std::stoi(v());
|
||||
else if (a == "--linear-tol")
|
||||
o.linearTolerance = std::stod(v());
|
||||
else if (a == "--atol")
|
||||
@@ -68,6 +70,8 @@ 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.probeRestart != 40 && o.probeRestart != 160)
|
||||
throw std::invalid_argument("--probe-restart must be 40 or 160");
|
||||
if (std::filesystem::exists(o.output))
|
||||
throw std::runtime_error("Output directory already exists");
|
||||
std::filesystem::create_directories(o.output);
|
||||
@@ -130,7 +134,9 @@ void FrozenProbes(State &s, const fem::FEM &f, const Options &o, const mfem::Vec
|
||||
histories << "restart,tolerance,iteration,reported_norm,final\n";
|
||||
auto blocks = File(o.output / "frozen_blocks.csv");
|
||||
blocks << "restart,tolerance,block,F_norm,Jp_plus_F_norm,global_correction_norm\n";
|
||||
mfem::Vector best, baselineAction(base.Size());
|
||||
mfem::Vector selectedCorrection, baselineAction(base.Size());
|
||||
// These are two cold direct MFEM solves, not the configured production
|
||||
// backend or any recycled Krylov history.
|
||||
for (int restart : {40, 160}) {
|
||||
mfem::FGMRESSolver linear(MPI_COMM_WORLD);
|
||||
solver::ResidualHistoryMonitor monitor;
|
||||
@@ -164,17 +170,18 @@ void FrozenProbes(State &s, const fem::FEM &f, const Options &o, const mfem::Vec
|
||||
<< ',' << Norm(action, r.offset, r.size) << ',' << p.Norml2() << '\n';
|
||||
blocks.flush();
|
||||
std::cout << "Frozen restart=" << restart << " true=" << rel << " seconds=" << seconds << std::endl;
|
||||
if (restart == 40)
|
||||
best = p;
|
||||
if (restart == o.probeRestart)
|
||||
selectedCorrection = p;
|
||||
}
|
||||
s.normalizedCorrection = best;
|
||||
s.normalizedOperator->Mult(best, baselineAction);
|
||||
std::cout << "Frozen probe direction restart=" << o.probeRestart << std::endl;
|
||||
s.normalizedCorrection = selectedCorrection;
|
||||
s.normalizedOperator->Mult(selectedCorrection, baselineAction);
|
||||
auto positivity = File(o.output / "enthalpy_step_bound.csv");
|
||||
positivity << "metric,value\n";
|
||||
for (const auto &[key, value] : experiment::plateau_diagnostics::MeasureEnthalpyStep(s, f, o.n, physicalBase))
|
||||
positivity << key << ',' << value << '\n';
|
||||
positivity.flush();
|
||||
SaveVector(o.output / "probe_normalized_correction.txt", best);
|
||||
SaveVector(o.output / "probe_normalized_correction.txt", selectedCorrection);
|
||||
auto fd = File(o.output / "finite_differences.csv");
|
||||
fd << "epsilon,admissible,block,absolute_error,relative_to_Jp,action_norm\n";
|
||||
const auto safe = s.EstimateLargestSafeStepSize(1., .9);
|
||||
@@ -186,7 +193,7 @@ void FrozenProbes(State &s, const fem::FEM &f, const Options &o, const mfem::Vec
|
||||
for (double a : {1., .5, .1, .01, .001, .0001, .00001}) {
|
||||
const double epsilon = std::min(1., safe.stepSize) * a;
|
||||
s.trialNormalizedState = frozenState;
|
||||
s.trialNormalizedState.Add(epsilon, best);
|
||||
s.trialNormalizedState.Add(epsilon, selectedCorrection);
|
||||
const auto prep = s.PrepareTrial();
|
||||
if (!prep) {
|
||||
trials << epsilon << ",0," << int(prep.error().reason) << ",nan,nan\n";
|
||||
@@ -217,7 +224,9 @@ template <class Context> int RunContext(Context &context, const Options &o, cons
|
||||
auto metadata = File(o.output / "metadata.txt");
|
||||
metadata << "n=" << o.n << "\nK=" << scales.K << "\nrho_c=" << scales.rho << "\nJ=" << o.angularMomentum
|
||||
<< "\nM=1\nR_reference=1\nxi1=" << scales.xi << "\nmu1=" << scales.mu << "\ncentral_phase=" << !o.noCentral
|
||||
<< "\nrestart=" << o.restart << "\nlinear_tol=" << o.linearTolerance << "\nmax_linear=" << o.maxLinear
|
||||
<< "\nrestart=" << o.restart << "\nprobe_restart=" << o.probeRestart
|
||||
<< "\nfrozen_probe_backend=direct_mfem_fgmres_cold"
|
||||
<< "\nlinear_tol=" << o.linearTolerance << "\nmax_linear=" << o.maxLinear
|
||||
<< "\nmax_newton=" << o.maxNewton << "\natol=" << o.atol << "\nrtol=" << o.rtol
|
||||
<< "\ncompiler=" << __VERSION__ << "\ncompiled=" << __DATE__ << ' ' << __TIME__ << '\n';
|
||||
metadata.flush();
|
||||
@@ -289,7 +298,8 @@ template <class Context> int RunContext(Context &context, const Options &o, cons
|
||||
});
|
||||
auto history = File(o.output / "newton.csv");
|
||||
history << "iteration,accepted,F,alpha,trials,linear_status,linear_iterations,linear_true,seconds,linear_seconds,"
|
||||
"prepare_seconds,refresh_seconds,geometry_limited,geometry_safe_step,central_border,unbordered_F\n";
|
||||
"prepare_seconds,refresh_seconds,geometry_limited,geometry_safe_step,central_border,unbordered_F,"
|
||||
"linear_initial_residual,linear_rhs_norm,linear_initial_over_rhs\n";
|
||||
auto blocklog = File(o.output / "blocks.csv");
|
||||
blocklog << "iteration,stage,block,normalized_norm,physical_norm,max_abs_normalized\n";
|
||||
auto triallog = File(o.output / "trials.csv");
|
||||
@@ -327,6 +337,13 @@ template <class Context> int RunContext(Context &context, const Options &o, cons
|
||||
unbordered(i) = e.normalizedResidual[i];
|
||||
for (int i : centralRows)
|
||||
unbordered(i) -= residualFactors(i) * border;
|
||||
const double linearInitial = e.linearSolve ? e.linearSolve->initialResidualNorm : NAN;
|
||||
const double linearRhs = e.linearSolve ? e.linearSolve->rightHandSideNorm : NAN;
|
||||
double linearInitialRelative = NAN;
|
||||
if (linearRhs > 0.)
|
||||
linearInitialRelative = linearInitial / linearRhs;
|
||||
else if (linearRhs == 0. && std::isfinite(linearInitial))
|
||||
linearInitialRelative = linearInitial == 0. ? 0. : std::numeric_limits<double>::infinity();
|
||||
history << e.iteration << ',' << e.stepAccepted << ',' << e.residualNorm << ',' << e.acceptedStepLength
|
||||
<< ',' << e.lineSearchTrials << ',' << (e.linearSolve ? int(e.linearSolve->status) : -1) << ','
|
||||
<< (e.linearSolve ? e.linearSolve->iterations : 0) << ','
|
||||
@@ -335,7 +352,8 @@ template <class Context> int RunContext(Context &context, const Options &o, cons
|
||||
<< ',' << e.preconditionerRefreshSeconds << ','
|
||||
<< (e.geometryPreflight ? e.geometryPreflight->limitedByGeometry : false) << ','
|
||||
<< (e.geometryPreflight ? e.geometryPreflight->stepSize : NAN) << ',' << border << ','
|
||||
<< unbordered.Norml2() << '\n';
|
||||
<< unbordered.Norml2() << ',' << linearInitial << ',' << linearRhs << ','
|
||||
<< linearInitialRelative << '\n';
|
||||
history.flush();
|
||||
std::cout << " alpha=" << e.acceptedStepLength << " F=" << e.residualNorm
|
||||
<< " linear=" << (e.linearSolve ? e.linearSolve->relativeTrueResidualNorm : NAN)
|
||||
|
||||
Reference in New Issue
Block a user