#include #include #include #include #include #include #include "serif/runtime.hpp" #include "serif/model/finite_elements.hpp" #include "serif/backend/mfem/serialize/configuration.hpp" #include "serif/solver/equilibrium.hpp" #include "serif/solver/seed/state.hpp" #include "serif/solver/seed/polytrope.hpp" #include "polytropic_model.hpp" #include "serif/utils/serialize/archive.hpp" #include "serif/utils/serialize/solver.hpp" namespace { /** @brief Keep this example's error reporting separate from its save-and-resume workflow. */ template T checked(std::expected result) { if (!result) { if constexpr (requires { result.error().path; result.error().message; }) { serif::utils::errors::serif_ensure(false, "{}: {}", result.error().path, result.error().message); } else { serif::utils::errors::serif_ensure(false, "{}", result.error()); } } if constexpr (!std::is_void_v) { return std::move(*result); } } } /** @brief Stop at an accepted Newton boundary, save the star, and continue with newly reconstructed resources. */ int main(int argc, char** argv) { namespace solver = serif::solver; namespace serialization = serif::utils::serialize; namespace configuration_io = serif::utils::serialize; serif::initialize(); // const std::filesystem::path path = argc > 1 ? argv[1] : "stellar_checkpoint.serif"; // // const auto star = serif::examples::make_polytropic_model(); // const auto radial = checked(solver::seed::make_polytropic_seed(star)); // const auto finite_elements = serif::model::make_stellar_discretization(star, // {.radius = radial.scales.radius}, // serif::geometry::deformation::DomainDeformation{ // .surface = {.maximum_degree = 0}, .stellar_interior = {}, .vacuum = {}}); // const auto initial = checked(solver::seed::make_polytropic_state(star, finite_elements, radial)); // const solver::normalization::NormalizationOptions normalization{ // .scheme = checked(solver::normalization::prepare_stellar_reference_scales( // serif::dimensions::MassValue{1.0}, serif::dimensions::LengthValue{1.0}))}; // const auto configuration = serif::model::make_discretization(serif::model::DiscretizationOptions{ // .model = star, .finite_elements = finite_elements, .normalization = normalization}); // const solver::SolverOptions options{ // .linear_solver = { // .print_level = 1 // } // }; // const auto stop_after_step = [](const solver::SolveEvent& event, const auto&, const auto&) { // return event.kind == solver::EventKind::accepted ? solver::SolveControl::stop : solver::SolveControl::continue_solve; // }; // const auto stopped = solver::solve_equilibrium(configuration, initial, options, stop_after_step); // // // Each component remains independently readable. No cache, Jacobian or preconditioner is written. // checked(serialization::write(path, serialization::pack(configuration, options, stopped), // {.author = "SERiF example", .comment = "Accepted Newton step; ready to continue"})); // // auto reader = checked(serialization::Reader::open(path)); // using Configuration = std::remove_cvref_t; // const auto restored = checked(configuration_io::restore_configuration(checked(reader.node("configuration")))); // const auto checkpoint = checked(reader.read("solution/checkpoint")); // const auto restored_options = checked(reader.read>()); // const auto resumed = solver::resume_equilibrium(restored, checkpoint, restored_options); // std::println("{} ({} accepted iterations, including those before saving)", resumed.message(), resumed.diagnostics().accepted_iterations); // return resumed.converged() ? 0 : 1; auto result = serif::utils::serialize::Reader::open("stellar_checkpoint.serif"); if (result.has_value()) { std::println("Opened checkpoint from SERiF version: {}", result->serif_version()); } else { std::println("Failed to open checkpoint: {} ({})", result.error().message, result.error().path); } }