diff --git a/examples/closed_coil/Main.cpp b/examples/closed_coil/Main.cpp index d7118c0c1..11cf01ebd 100644 --- a/examples/closed_coil/Main.cpp +++ b/examples/closed_coil/Main.cpp @@ -132,15 +132,13 @@ main(int argc, char * argv[]) hephaestus::Outputs outputs = defineOutputs(); problem_builder->SetOutputs(outputs); - hephaestus::InputParameters solver_options; - solver_options.SetParam("Tolerance", float(1.0e-13)); - solver_options.SetParam("AbsTolerance", float(1.0e-16)); - solver_options.SetParam("MaxIter", (unsigned int)500); - problem_builder->SetSolverOptions(solver_options); - problem_builder->FinalizeProblem(); auto problem = problem_builder->ReturnProblem(); + + problem->GetOperator()->SetSolverOptions( + {._tolerance = 1.0e-13, ._abs_tolerance = 1.0e-16, ._max_iteration = 500}); + hephaestus::InputParameters exec_params; exec_params.SetParam("VisualisationSteps", int(1)); exec_params.SetParam("UseGLVis", true); diff --git a/examples/complex_team7/Main.cpp b/examples/complex_team7/Main.cpp index 5adf63c35..29402d00f 100644 --- a/examples/complex_team7/Main.cpp +++ b/examples/complex_team7/Main.cpp @@ -225,15 +225,12 @@ main(int argc, char * argv[]) linesamplerwriter->SetPriority(5); problem_builder->AddPostprocessor("LineSamplerWriter", linesamplerwriter); - hephaestus::InputParameters solver_options; - solver_options.SetParam("Tolerance", float(1.0e-16)); - solver_options.SetParam("MaxIter", (unsigned int)1000); - problem_builder->SetSolverOptions(solver_options); - problem_builder->FinalizeProblem(); auto problem = problem_builder->ReturnProblem(); + problem->GetOperator()->SetSolverOptions({._tolerance = 1.0e-16, ._max_iteration = 1000}); + hephaestus::InputParameters exec_params; exec_params.SetParam("Problem", static_cast(problem.get())); diff --git a/examples/magnetostatic/Main.cpp b/examples/magnetostatic/Main.cpp index 7cef1fd23..53441e181 100644 --- a/examples/magnetostatic/Main.cpp +++ b/examples/magnetostatic/Main.cpp @@ -160,14 +160,12 @@ main(int argc, char * argv[]) hephaestus::Outputs outputs = defineOutputs(); problem_builder->SetOutputs(outputs); - hephaestus::InputParameters solver_options; - solver_options.SetParam("Tolerance", float(1.0e-16)); - solver_options.SetParam("MaxIter", (unsigned int)1000); - problem_builder->SetSolverOptions(solver_options); - problem_builder->FinalizeProblem(); auto problem = problem_builder->ReturnProblem(); + + problem->GetOperator()->SetSolverOptions({._tolerance = 1.0e-16, ._max_iteration = 1000}); + hephaestus::InputParameters exec_params; exec_params.SetParam("VisualisationSteps", int(1)); exec_params.SetParam("UseGLVis", true); diff --git a/examples/open_coil/Main.cpp b/examples/open_coil/Main.cpp index 1cc1966dc..85654d4d5 100644 --- a/examples/open_coil/Main.cpp +++ b/examples/open_coil/Main.cpp @@ -159,15 +159,13 @@ main(int argc, char * argv[]) hephaestus::Outputs outputs = defineOutputs(); problem_builder->SetOutputs(outputs); - hephaestus::InputParameters solver_options; - solver_options.SetParam("Tolerance", float(1.0e-10)); - solver_options.SetParam("AbsTolerance", float(1.0e-10)); - solver_options.SetParam("MaxIter", (unsigned int)1000); - problem_builder->SetSolverOptions(solver_options); - problem_builder->FinalizeProblem(); auto problem = problem_builder->ReturnProblem(); + + problem->GetOperator()->SetSolverOptions( + {._tolerance = 1.0e-10, ._abs_tolerance = 1.0e-10, ._max_iteration = 1000}); + hephaestus::InputParameters exec_params; exec_params.SetParam("VisualisationSteps", int(1)); exec_params.SetParam("UseGLVis", true); diff --git a/examples/team4/Main.cpp b/examples/team4/Main.cpp index 7d6e35de9..5cc3259d6 100644 --- a/examples/team4/Main.cpp +++ b/examples/team4/Main.cpp @@ -153,15 +153,13 @@ main(int argc, char * argv[]) fluxmonitor->SetPriority(2); problem_builder->AddPostprocessor("FluxMonitor", fluxmonitor); - hephaestus::InputParameters solver_options; - solver_options.SetParam("AbsTolerance", float(1.0e-20)); - solver_options.SetParam("Tolerance", float(1.0e-20)); - solver_options.SetParam("MaxIter", (unsigned int)500); - problem_builder->SetSolverOptions(solver_options); - problem_builder->FinalizeProblem(); auto problem = problem_builder->ReturnProblem(); + + problem->GetOperator()->SetSolverOptions( + {._tolerance = 1.0e-20, ._abs_tolerance = 1.0e-20, ._max_iteration = 500}); + hephaestus::InputParameters exec_params; exec_params.SetParam("TimeStep", float(0.001)); exec_params.SetParam("StartTime", float(0.00)); diff --git a/examples/team7/Main.cpp b/examples/team7/Main.cpp index 4fa8d52f4..a19125d64 100644 --- a/examples/team7/Main.cpp +++ b/examples/team7/Main.cpp @@ -214,14 +214,12 @@ main(int argc, char * argv[]) linesamplerwriter->SetPriority(5); problem_builder->AddPostprocessor("LineSamplerWriter", linesamplerwriter); - hephaestus::InputParameters solver_options; - solver_options.SetParam("Tolerance", float(1.0e-16)); - solver_options.SetParam("MaxIter", (unsigned int)1000); - problem_builder->SetSolverOptions(solver_options); - problem_builder->FinalizeProblem(); auto problem = problem_builder->ReturnProblem(); + + problem->GetOperator()->SetSolverOptions({._tolerance = 1.0e-16, ._max_iteration = 1000}); + hephaestus::InputParameters exec_params; exec_params.SetParam("TimeStep", float(0.001)); exec_params.SetParam("StartTime", float(0.00)); diff --git a/src/equation_systems/equation_system.hpp b/src/equation_systems/equation_system.hpp index 613bbe706..d1278b242 100644 --- a/src/equation_systems/equation_system.hpp +++ b/src/equation_systems/equation_system.hpp @@ -97,9 +97,6 @@ class EquationSystem : public mfem::Operator virtual void RecoverFEMSolution(mfem::BlockVector & trueX, hephaestus::GridFunctions & gridfunctions); - /// Returns a reference to the jacobian operator handle. - [[nodiscard]] mfem::OperatorHandle & JacobianOperatorHandle() { return _jacobian; } - std::vector> _ess_tdof_lists; protected: diff --git a/src/formulations/ComplexMaxwell/complex_maxwell_formulation.cpp b/src/formulations/ComplexMaxwell/complex_maxwell_formulation.cpp index 238ca0c36..6d60953e5 100644 --- a/src/formulations/ComplexMaxwell/complex_maxwell_formulation.cpp +++ b/src/formulations/ComplexMaxwell/complex_maxwell_formulation.cpp @@ -24,12 +24,6 @@ ComplexMaxwellFormulation::ComplexMaxwellFormulation(std::string alpha_coef_name { } -void -ComplexMaxwellFormulation::ConstructJacobianSolver() -{ - ConstructJacobianSolverWithOptions(SolverType::SUPER_LU); -} - void ComplexMaxwellFormulation::ConstructOperator() { @@ -168,8 +162,8 @@ ComplexMaxwellOperator::Init() void ComplexMaxwellOperator::Update() { - _u->Update(); ProblemOperator::Update(); + _u->Update(); } void @@ -226,4 +220,10 @@ ComplexMaxwellOperator::Solve(mfem::Vector & X) _problem._gridfunctions.GetRef(_trial_var_names.at(1)) = _u->imag(); } +void +ComplexMaxwellOperator::ConstructJacobianSolver() +{ + _jacobian_solver = std::make_unique(_problem._comm); +} + } // namespace hephaestus diff --git a/src/formulations/ComplexMaxwell/complex_maxwell_formulation.hpp b/src/formulations/ComplexMaxwell/complex_maxwell_formulation.hpp index 5246fa18c..710b31108 100644 --- a/src/formulations/ComplexMaxwell/complex_maxwell_formulation.hpp +++ b/src/formulations/ComplexMaxwell/complex_maxwell_formulation.hpp @@ -38,8 +38,6 @@ class ComplexMaxwellFormulation : public hephaestus::FrequencyDomainEMFormulatio ~ComplexMaxwellFormulation() override = default; - void ConstructJacobianSolver() override; - void ConstructOperator() override; void RegisterGridFunctions() override; @@ -88,6 +86,11 @@ class ComplexMaxwellOperator : public ProblemOperator mfem::Coefficient * _loss_coef{nullptr}; // omega sigma mfem::Array _ess_bdr_tdofs; + +protected: + void ApplySolverOptions() override {} + + void ConstructJacobianSolver() override; }; } // namespace hephaestus diff --git a/src/formulations/Dual/dual_formulation.cpp b/src/formulations/Dual/dual_formulation.cpp index 56a21370c..b9c6cfd70 100644 --- a/src/formulations/Dual/dual_formulation.cpp +++ b/src/formulations/Dual/dual_formulation.cpp @@ -58,20 +58,6 @@ DualFormulation::DualFormulation(std::string alpha_coef_name, { } -void -DualFormulation::ConstructJacobianSolver() -{ - auto precond = - std::make_unique(GetProblem()->GetEquationSystem()->_test_pfespaces.at(0)); - - precond->SetSingularProblem(); - precond->SetPrintLevel(-1); - - GetProblem()->GetOperator()->SetJacobianPreconditioner(std::move(precond)); - - ConstructJacobianSolverWithOptions(SolverType::HYPRE_PCG, {._max_iteration = 1000}); -} - void DualFormulation::ConstructOperator() { @@ -213,12 +199,39 @@ DualOperator::Init() void DualOperator::Update() { + // 0. Call superclass' update method. TimeDomainEquationSystemProblemOperator::Update(); _curl->Update(); _curl->Assemble(); } +void +DualOperator::ConstructJacobianSolver() +{ + auto precond = std::make_unique(GetEquationSystem()->_test_pfespaces.at(0)); + + precond->SetSingularProblem(); + precond->SetPrintLevel(-1); + + auto solver = std::make_unique(_problem._comm); + solver->SetPreconditioner(*precond); + + _jacobian_preconditioner = std::move(precond); + _jacobian_solver = std::move(solver); +} + +void +DualOperator::ApplySolverOptions() +{ + auto & solver = static_cast(*_jacobian_solver); + + solver.SetTol(GetSolverOptions()._tolerance); + solver.SetAbsTol(GetSolverOptions()._abs_tolerance); + solver.SetMaxIter(GetSolverOptions()._max_iteration); + solver.SetPrintLevel(GetSolverOptions()._print_level); +} + void DualOperator::ImplicitSolve(const double dt, const mfem::Vector & X, mfem::Vector & dX_dt) { diff --git a/src/formulations/Dual/dual_formulation.hpp b/src/formulations/Dual/dual_formulation.hpp index 5a09f8923..51988024a 100644 --- a/src/formulations/Dual/dual_formulation.hpp +++ b/src/formulations/Dual/dual_formulation.hpp @@ -16,8 +16,6 @@ class DualFormulation : public TimeDomainEMFormulation ~DualFormulation() override = default; - void ConstructJacobianSolver() override; - void ConstructOperator() override; void RegisterGridFunctions() override; @@ -72,6 +70,10 @@ class DualOperator : public TimeDomainEquationSystemProblemOperator mfem::ParGridFunction * _dv{nullptr}; // HDiv vector field protected: + void ConstructJacobianSolver() override; + + void ApplySolverOptions() override; + int GetSolutionVectorSize() const override; std::unique_ptr _curl; diff --git a/src/formulations/HCurl/hcurl_formulation.cpp b/src/formulations/HCurl/hcurl_formulation.cpp index bdb5acee0..dc0442a0f 100644 --- a/src/formulations/HCurl/hcurl_formulation.cpp +++ b/src/formulations/HCurl/hcurl_formulation.cpp @@ -62,24 +62,10 @@ HCurlFormulation::ConstructOperator() auto equation_system = std::make_unique(weak_form_params); - GetProblem()->SetOperator(std::make_unique( + GetProblem()->SetOperator(std::make_unique( *GetProblem(), std::move(equation_system))); } -void -HCurlFormulation::ConstructJacobianSolver() -{ - auto precond = - std::make_unique(GetProblem()->GetEquationSystem()->_test_pfespaces.at(0)); - - precond->SetSingularProblem(); - precond->SetPrintLevel(-1); - - GetProblem()->GetOperator()->SetJacobianPreconditioner(std::move(precond)); - - ConstructJacobianSolverWithOptions(SolverType::HYPRE_PCG); -} - void HCurlFormulation::RegisterGridFunctions() { @@ -102,6 +88,32 @@ HCurlFormulation::RegisterGridFunctions() TimeDomainEquationSystemProblemBuilder::RegisterGridFunctions(); }; +void +HCurlProblemOperator::ApplySolverOptions() +{ + auto & solver = static_cast(*_jacobian_solver); + + solver.SetTol(GetSolverOptions()._tolerance); + solver.SetAbsTol(GetSolverOptions()._abs_tolerance); + solver.SetMaxIter(GetSolverOptions()._max_iteration); + solver.SetPrintLevel(GetSolverOptions()._print_level); +} + +void +HCurlProblemOperator::ConstructJacobianSolver() +{ + auto precond = std::make_unique(GetEquationSystem()->_test_pfespaces.at(0)); + + precond->SetSingularProblem(); + precond->SetPrintLevel(-1); + + auto solver = std::make_unique(_problem._comm); + solver->SetPreconditioner(*precond); + + _jacobian_preconditioner = std::move(precond); + _jacobian_solver = std::move(solver); +} + CurlCurlEquationSystem::CurlCurlEquationSystem(const hephaestus::InputParameters & params) : _h_curl_var_name(params.GetParam("HCurlVarName")), _alpha_coef_name(params.GetParam("AlphaCoefName")), diff --git a/src/formulations/HCurl/hcurl_formulation.hpp b/src/formulations/HCurl/hcurl_formulation.hpp index dc9e491a1..25c86b69d 100644 --- a/src/formulations/HCurl/hcurl_formulation.hpp +++ b/src/formulations/HCurl/hcurl_formulation.hpp @@ -18,8 +18,6 @@ class HCurlFormulation : public TimeDomainEMFormulation void ConstructOperator() override; - void ConstructJacobianSolver() override; - void RegisterGridFunctions() override; void RegisterCoefficients() override; @@ -30,6 +28,21 @@ class HCurlFormulation : public TimeDomainEMFormulation const std::string _h_curl_var_name; }; +class HCurlProblemOperator : public TimeDomainEquationSystemProblemOperator +{ +public: + HCurlProblemOperator(hephaestus::Problem & problem, + std::unique_ptr equation_system) + : TimeDomainEquationSystemProblemOperator(problem, std::move(equation_system)) + { + } + +protected: + void ApplySolverOptions() override; + + void ConstructJacobianSolver() override; +}; + class CurlCurlEquationSystem : public TimeDependentEquationSystem { public: diff --git a/src/formulations/Magnetostatic/statics_formulation.cpp b/src/formulations/Magnetostatic/statics_formulation.cpp index 25ddd21e5..4335b3389 100644 --- a/src/formulations/Magnetostatic/statics_formulation.cpp +++ b/src/formulations/Magnetostatic/statics_formulation.cpp @@ -37,21 +37,6 @@ StaticsFormulation::StaticsFormulation(std::string alpha_coef_name, std::string { } -void -StaticsFormulation::ConstructJacobianSolver() -{ - auto precond = std::make_unique( - GetProblem()->_gridfunctions.Get(_h_curl_var_name)->ParFESpace()); - - precond->SetSingularProblem(); - precond->SetPrintLevel(-1); - - GetProblem()->GetOperator()->SetJacobianPreconditioner(std::move(precond)); - - ConstructJacobianSolverWithOptions(SolverType::HYPRE_FGMRES, - {._max_iteration = 100, ._k_dim = 10}); -} - void StaticsFormulation::ConstructOperator() { @@ -113,6 +98,33 @@ StaticsOperator::Init() ProblemOperator::Init(); } +void +StaticsOperator::ConstructJacobianSolver() +{ + auto precond = + std::make_unique(_problem._gridfunctions.Get(_h_curl_var_name)->ParFESpace()); + + precond->SetSingularProblem(); + precond->SetPrintLevel(-1); + + auto solver = std::make_unique(_problem._comm); + solver->SetPreconditioner(*precond); + + _jacobian_preconditioner = std::move(precond); + _jacobian_solver = std::move(solver); +} + +void +StaticsOperator::ApplySolverOptions() +{ + auto & solver = static_cast(*_jacobian_solver); + + solver.SetTol(GetSolverOptions()._tolerance); + solver.SetMaxIter(GetSolverOptions()._max_iteration); + solver.SetKDim(GetSolverOptions()._k_dim); + solver.SetPrintLevel(GetSolverOptions()._print_level); +} + /* This is the main method that solves for u. diff --git a/src/formulations/Magnetostatic/statics_formulation.hpp b/src/formulations/Magnetostatic/statics_formulation.hpp index b0a901695..2f3f78eab 100644 --- a/src/formulations/Magnetostatic/statics_formulation.hpp +++ b/src/formulations/Magnetostatic/statics_formulation.hpp @@ -14,8 +14,6 @@ class StaticsFormulation : public SteadyStateEMFormulation ~StaticsFormulation() override = default; - void ConstructJacobianSolver() override; - void ConstructOperator() override; void RegisterGridFunctions() override; @@ -40,6 +38,11 @@ class StaticsOperator : public ProblemOperator void Init() override; void Solve(mfem::Vector & X) override; +protected: + void ApplySolverOptions() override; + + void ConstructJacobianSolver() override; + private: std::string _h_curl_var_name, _stiffness_coef_name; diff --git a/src/problem_builders/problem_builder_base.cpp b/src/problem_builders/problem_builder_base.cpp index d5e4ef8dd..a125a5e24 100644 --- a/src/problem_builders/problem_builder_base.cpp +++ b/src/problem_builders/problem_builder_base.cpp @@ -82,25 +82,6 @@ ProblemBuilder::SetOutputs(hephaestus::Outputs & outputs) GetProblem()->_outputs = outputs; } -void -ProblemBuilder::SetSolverOptions(hephaestus::InputParameters & solver_options) -{ - logger.info("Setting Solver Options"); - GetProblem()->_solver_options = solver_options; -} - -void -ProblemBuilder::SetJacobianPreconditioner(std::unique_ptr preconditioner) -{ - GetProblem()->GetOperator()->SetJacobianPreconditioner(std::move(preconditioner)); -} - -void -ProblemBuilder::SetJacobianSolver(std::unique_ptr jacobian_solver) -{ - GetProblem()->GetOperator()->SetJacobianSolver(std::move(jacobian_solver)); -} - void ProblemBuilder::SetCoefficients(hephaestus::Coefficients & coefficients) { @@ -215,121 +196,6 @@ ProblemBuilder::AddSource(std::string source_name, std::shared_ptr_sources.Register(source_name, std::move(source)); } -void -ProblemBuilder::ConstructJacobianSolver() -{ - auto precond = std::make_unique(); - precond->SetPrintLevel(GetGlobalPrintLevel()); - - GetProblem()->GetOperator()->SetJacobianPreconditioner(std::move(precond)); - - ConstructJacobianSolverWithOptions(SolverType::HYPRE_GMRES); -} - -void -ProblemBuilder::ConstructJacobianSolverWithOptions(SolverType type, SolverParams default_params) -{ - const auto & solver_options = GetProblem()->_solver_options; - - const auto tolerance = - solver_options.GetOptionalParam("Tolerance", default_params._tolerance); - const auto abs_tolerance = - solver_options.GetOptionalParam("AbsTolerance", default_params._abs_tolerance); - const auto max_iter = - solver_options.GetOptionalParam("MaxIter", default_params._max_iteration); - const auto print_level = - solver_options.GetOptionalParam("PrintLevel", default_params._print_level); - const auto k_dim = solver_options.GetOptionalParam("KDim", default_params._k_dim); - - auto preconditioner = GetProblem()->GetOperator()->JacobianPreconditioner(); - - switch (type) - { - case SolverType::HYPRE_PCG: - { - auto solver = std::make_unique(GetProblem()->_comm); - - solver->SetTol(tolerance); - solver->SetAbsTol(abs_tolerance); - solver->SetMaxIter(max_iter); - solver->SetPrintLevel(print_level); - - if (preconditioner) - solver->SetPreconditioner(*preconditioner); - - GetProblem()->GetOperator()->SetJacobianSolver(std::move(solver)); - break; - } - case SolverType::HYPRE_GMRES: - { - auto solver = std::make_unique(GetProblem()->_comm); - - solver->SetTol(tolerance); - solver->SetAbsTol(abs_tolerance); - solver->SetMaxIter(max_iter); - solver->SetKDim(k_dim); - solver->SetPrintLevel(print_level); - - if (preconditioner) - solver->SetPreconditioner(*preconditioner); - - GetProblem()->GetOperator()->SetJacobianSolver(std::move(solver)); - break; - } - case SolverType::HYPRE_FGMRES: - { - auto solver = std::make_unique(GetProblem()->_comm); - - solver->SetTol(tolerance); - solver->SetMaxIter(max_iter); - solver->SetKDim(k_dim); - solver->SetPrintLevel(print_level); - - if (preconditioner) - solver->SetPreconditioner(*preconditioner); - - GetProblem()->GetOperator()->SetJacobianSolver(std::move(solver)); - break; - } - case SolverType::HYPRE_AMG: - { - auto solver = std::make_unique(); - - solver->SetTol(tolerance); - solver->SetMaxIter(max_iter); - solver->SetPrintLevel(print_level); - - GetProblem()->GetOperator()->SetJacobianSolver(std::move(solver)); - break; - } - case SolverType::SUPER_LU: - { - auto solver = std::make_unique(GetProblem()->_comm); - - GetProblem()->GetOperator()->SetJacobianSolver(std::move(solver)); - break; - } - default: - { - MFEM_ABORT("Unsupported solver type specified."); - break; - } - } -} - -void -ProblemBuilder::ConstructNonlinearSolver() -{ - auto nl_solver = std::make_unique(GetProblem()->_comm); - - // Defaults to one iteration, without further nonlinear iterations - nl_solver->SetRelTol(0.0); - nl_solver->SetAbsTol(0.0); - nl_solver->SetMaxIter(1); - - GetProblem()->GetOperator()->SetNonlinearSolver(std::move(nl_solver)); -} - void ProblemBuilder::InitializeSources() { @@ -375,11 +241,6 @@ ProblemBuilder::FinalizeProblem(bool build_operator) InitializeAuxSolvers(); InitializeSources(); InitializeOperator(); - - ConstructJacobianSolver(); - ConstructNonlinearSolver(); - - ConstructTimestepper(); InitializeOutputs(); } diff --git a/src/problem_builders/problem_builder_base.hpp b/src/problem_builders/problem_builder_base.hpp index 39d85ac62..1778d84e6 100644 --- a/src/problem_builders/problem_builder_base.hpp +++ b/src/problem_builders/problem_builder_base.hpp @@ -28,7 +28,6 @@ class Problem hephaestus::AuxSolvers _postprocessors; hephaestus::Sources _sources; hephaestus::Outputs _outputs; - hephaestus::InputParameters _solver_options; hephaestus::FECollections _fecs; hephaestus::FESpaces _fespaces; @@ -41,9 +40,6 @@ class Problem /// Returns a pointer to the operator. See derived classes. [[nodiscard]] virtual hephaestus::ProblemOperatorBase * GetOperator() const = 0; - /// Virtual method to construct the operator. Call for default problems. - virtual void ConstructOperator() = 0; - /// Call to update on mesh change. virtual void Update(); }; @@ -72,9 +68,6 @@ class ProblemBuilder void SetPostprocessors(hephaestus::AuxSolvers & postprocessors); void SetSources(hephaestus::Sources & sources); void SetOutputs(hephaestus::Outputs & outputs); - void SetSolverOptions(hephaestus::InputParameters & solver_options); - void SetJacobianPreconditioner(std::unique_ptr preconditioner); - void SetJacobianSolver(std::unique_ptr solver); void SetCoefficients(hephaestus::Coefficients & coefficients); void AddFESpace(std::string fespace_name, @@ -93,11 +86,7 @@ class ProblemBuilder virtual void RegisterAuxSolvers() = 0; virtual void RegisterCoefficients() = 0; - virtual void ConstructJacobianSolver(); - virtual void ConstructNonlinearSolver(); - virtual void ConstructOperator() = 0; - virtual void ConstructTimestepper() = 0; virtual void InitializeSources(); @@ -115,39 +104,6 @@ class ProblemBuilder /// Protected constructor. Derived classes must call this constructor. ProblemBuilder(hephaestus::Problem * problem) : _problem{problem} {} - /// Supported Jacobian solver types. - enum class SolverType - { - HYPRE_PCG, - HYPRE_GMRES, - HYPRE_FGMRES, - HYPRE_AMG, - SUPER_LU - }; - - /// Structure containing default parameters which can be passed to @a ConstructJacobianSolverWithOptions. - /// These will be used if the user has not supplied their own values. - struct SolverParams - { - double _tolerance; - double _abs_tolerance; - - unsigned int _max_iteration; - - int _print_level; - int _k_dim; - }; - - /// Called in @a ConstructJacobianSolver. This will create a solver of the chosen type and use the user's input - /// parameters if they have been provided. - void ConstructJacobianSolverWithOptions(SolverType type, - SolverParams default_params = { - ._tolerance = 1e-16, - ._abs_tolerance = 1e-16, - ._max_iteration = 1000, - ._print_level = GetGlobalPrintLevel(), - ._k_dim = 10}); - /// Overridden in derived classes. [[nodiscard]] virtual hephaestus::Problem * GetProblem() const = 0; diff --git a/src/problem_builders/steady_state_equation_system_problem_builder.cpp b/src/problem_builders/steady_state_equation_system_problem_builder.cpp new file mode 100644 index 000000000..0c0f94557 --- /dev/null +++ b/src/problem_builders/steady_state_equation_system_problem_builder.cpp @@ -0,0 +1,16 @@ +#include "steady_state_equation_system_problem_builder.hpp" + +namespace hephaestus +{ + +void +SteadyStateEquationSystemProblemBuilder::ConstructOperator() +{ + auto equation_system = std::make_unique(); + auto problem_operator = std::make_unique( + *GetProblem(), std::move(equation_system)); + + GetProblem()->SetOperator(std::move(problem_operator)); +} + +} // namespace hephaestus diff --git a/src/problem_builders/steady_state_equation_system_problem_builder.hpp b/src/problem_builders/steady_state_equation_system_problem_builder.hpp index 32c4c57cb..37d1484ea 100644 --- a/src/problem_builders/steady_state_equation_system_problem_builder.hpp +++ b/src/problem_builders/steady_state_equation_system_problem_builder.hpp @@ -24,15 +24,6 @@ class SteadyStateEquationSystemProblem : public SteadyStateProblem, public Equat SteadyStateProblem::SetOperator(std::move(problem_operator)); } - void ConstructOperator() override - { - auto equation_system = std::make_unique(); - auto problem_operator = std::make_unique( - *this, std::move(equation_system)); - - SetOperator(std::move(problem_operator)); - } - [[nodiscard]] hephaestus::EquationSystem * GetEquationSystem() const override { return GetOperator()->GetEquationSystem(); @@ -54,6 +45,8 @@ class SteadyStateEquationSystemProblemBuilder : public SteadyStateProblemBuilder auto ReturnProblem() { return ProblemBuilder::ReturnProblem(); } + void ConstructOperator() override; + protected: [[nodiscard]] hephaestus::SteadyStateEquationSystemProblem * GetProblem() const override { diff --git a/src/problem_builders/steady_state_problem_builder.cpp b/src/problem_builders/steady_state_problem_builder.cpp index a9fbe8ecd..60eca97bd 100644 --- a/src/problem_builders/steady_state_problem_builder.cpp +++ b/src/problem_builders/steady_state_problem_builder.cpp @@ -6,7 +6,8 @@ namespace hephaestus void SteadyStateProblemBuilder::ConstructOperator() { - GetProblem()->ConstructOperator(); + auto problem_operator = std::make_unique(*GetProblem()); + GetProblem()->SetOperator(std::move(problem_operator)); } } // namespace hephaestus diff --git a/src/problem_builders/steady_state_problem_builder.hpp b/src/problem_builders/steady_state_problem_builder.hpp index 994676aff..9765fe975 100644 --- a/src/problem_builders/steady_state_problem_builder.hpp +++ b/src/problem_builders/steady_state_problem_builder.hpp @@ -27,12 +27,6 @@ class SteadyStateProblem : public Problem _problem_operator = std::move(problem_operator); } - void ConstructOperator() override - { - _problem_operator.reset(); - _problem_operator = std::make_unique(*this); - } - private: std::unique_ptr _problem_operator{nullptr}; }; @@ -56,8 +50,6 @@ class SteadyStateProblemBuilder : public ProblemBuilder void ConstructOperator() override; - void ConstructTimestepper() override {} - protected: // NB: constructor for derived classes. SteadyStateProblemBuilder(hephaestus::SteadyStateProblem * problem) : ProblemBuilder(problem) {} diff --git a/src/problem_builders/time_domain_equation_system_problem_builder.cpp b/src/problem_builders/time_domain_equation_system_problem_builder.cpp new file mode 100644 index 000000000..b26680b0c --- /dev/null +++ b/src/problem_builders/time_domain_equation_system_problem_builder.cpp @@ -0,0 +1,15 @@ +#include "time_domain_equation_system_problem_builder.hpp" + +namespace hephaestus +{ +void +TimeDomainEquationSystemProblemBuilder::ConstructOperator() +{ + auto equation_system = std::make_unique(); + auto problem_operator = std::make_unique( + *GetProblem(), std::move(equation_system)); + + GetProblem()->SetOperator(std::move(problem_operator)); +} + +} // namespace hephaestus diff --git a/src/problem_builders/time_domain_equation_system_problem_builder.hpp b/src/problem_builders/time_domain_equation_system_problem_builder.hpp index a96620911..dc436199a 100644 --- a/src/problem_builders/time_domain_equation_system_problem_builder.hpp +++ b/src/problem_builders/time_domain_equation_system_problem_builder.hpp @@ -25,15 +25,6 @@ class TimeDomainEquationSystemProblem : public TimeDomainProblem, public Equatio TimeDomainProblem::SetOperator(std::move(problem_operator)); } - void ConstructOperator() override - { - auto equation_system = std::make_unique(); - auto problem_operator = std::make_unique( - *this, std::move(equation_system)); - - SetOperator(std::move(problem_operator)); - } - [[nodiscard]] TimeDependentEquationSystem * GetEquationSystem() const override { return GetOperator()->GetEquationSystem(); @@ -55,6 +46,8 @@ class TimeDomainEquationSystemProblemBuilder : public TimeDomainProblemBuilder, auto ReturnProblem() { return ProblemBuilder::ReturnProblem(); } + void ConstructOperator() override; + protected: [[nodiscard]] hephaestus::TimeDomainEquationSystemProblem * GetProblem() const override { diff --git a/src/problem_builders/time_domain_problem_builder.cpp b/src/problem_builders/time_domain_problem_builder.cpp index 916857a8f..8ebe4e105 100644 --- a/src/problem_builders/time_domain_problem_builder.cpp +++ b/src/problem_builders/time_domain_problem_builder.cpp @@ -35,7 +35,8 @@ TimeDomainProblemBuilder::RegisterGridFunctions() void TimeDomainProblemBuilder::ConstructOperator() { - GetProblem()->ConstructOperator(); + auto problem_operator = std::make_unique(*GetProblem()); + GetProblem()->SetOperator(std::move(problem_operator)); } void @@ -45,13 +46,4 @@ TimeDomainProblemBuilder::InitializeOperator() GetProblem()->GetOperator()->SetTime(0.0); } -void -TimeDomainProblemBuilder::ConstructTimestepper() -{ - auto ode_solver = std::make_unique(); - ode_solver->Init(*GetProblem()->GetOperator()); - - GetProblem()->GetOperator()->SetODESolver(std::move(ode_solver)); -} - } // namespace hephaestus diff --git a/src/problem_builders/time_domain_problem_builder.hpp b/src/problem_builders/time_domain_problem_builder.hpp index 231b20586..d21cd422c 100644 --- a/src/problem_builders/time_domain_problem_builder.hpp +++ b/src/problem_builders/time_domain_problem_builder.hpp @@ -25,12 +25,6 @@ class TimeDomainProblem : public Problem _problem_operator = std::move(problem_operator); } - void ConstructOperator() override - { - _problem_operator.reset(); - _problem_operator = std::make_unique(*this); - } - private: std::unique_ptr _problem_operator{nullptr}; }; @@ -61,8 +55,6 @@ class TimeDomainProblemBuilder : public ProblemBuilder void InitializeOperator() override; - void ConstructTimestepper() override; - protected: /// NB: constructor called in derived classes. TimeDomainProblemBuilder(hephaestus::TimeDomainProblem * problem) : ProblemBuilder(problem) {} diff --git a/src/problem_operators/equation_system_problem_operator.cpp b/src/problem_operators/equation_system_problem_operator.cpp index 0a2a4793c..7d7d944f8 100644 --- a/src/problem_operators/equation_system_problem_operator.cpp +++ b/src/problem_operators/equation_system_problem_operator.cpp @@ -25,8 +25,6 @@ EquationSystemProblemOperator::Update() { GetEquationSystem()->Update(_problem._bc_map, _problem._sources); - // TODO: - rebuild jacobian, jacobian_solver, etc... - ProblemOperator::Update(); } diff --git a/src/problem_operators/problem_operator_base.cpp b/src/problem_operators/problem_operator_base.cpp index 55aeeb746..965b837db 100644 --- a/src/problem_operators/problem_operator_base.cpp +++ b/src/problem_operators/problem_operator_base.cpp @@ -3,9 +3,67 @@ namespace hephaestus { -ProblemOperatorBase::ProblemOperatorBase(hephaestus::Problem & problem) : _problem{problem} +ProblemOperatorBase::ProblemOperatorBase(hephaestus::Problem & problem) : _problem{problem} {} + +ProblemOperatorBase::SolverOptions +ProblemOperatorBase::DefaultSolverOptions() const { - _block_vector = std::make_unique(); + return {._tolerance = 1e-16, + ._abs_tolerance = 1e-16, + ._max_iteration = 1000, + ._print_level = GetGlobalPrintLevel(), + ._k_dim = 10}; +} + +void +ProblemOperatorBase::ConstructJacobianSolver() +{ + auto precond = std::make_unique(); + precond->SetPrintLevel(GetGlobalPrintLevel()); + + auto solver = std::make_unique(_problem._comm); + solver->SetPreconditioner(*precond); + + _jacobian_preconditioner = std::move(precond); + _jacobian_solver = std::move(solver); +} + +void +ProblemOperatorBase::ConstructJacobianSolverAndApplyOptions() +{ + ConstructJacobianSolver(); + ApplySolverOptions(); +} + +void +ProblemOperatorBase::SetSolverOptions(SolverOptions options) +{ + // Store the options for future. + _solver_options = std::move(options); + ApplySolverOptions(); +} + +void +ProblemOperatorBase::ApplySolverOptions() +{ + auto & solver = static_cast(*_jacobian_solver); + + solver.SetTol(GetSolverOptions()._tolerance); + solver.SetAbsTol(GetSolverOptions()._abs_tolerance); + solver.SetMaxIter(GetSolverOptions()._max_iteration); + solver.SetKDim(GetSolverOptions()._k_dim); + solver.SetPrintLevel(GetSolverOptions()._print_level); +} + +void +ProblemOperatorBase::ConstructNonlinearSolver() +{ + _nonlinear_solver = std::make_unique(_problem._comm); + + // Defaults to one iteration, without further nonlinear iterations + _nonlinear_solver->SetRelTol(0.0); + _nonlinear_solver->SetAbsTol(0.0); + _nonlinear_solver->SetMaxIter(1); } void @@ -81,6 +139,12 @@ ProblemOperatorBase::UpdateBlockVector(mfem::BlockVector & X) void ProblemOperatorBase::Init() { + _block_vector = std::make_unique(); + _solver_options = DefaultSolverOptions(); + + ConstructJacobianSolverAndApplyOptions(); + ConstructNonlinearSolver(); + SetTrialVariables(); UpdateOffsets(); @@ -96,6 +160,9 @@ ProblemOperatorBase::Update() UpdateOffsets(); UpdateBlockVector(*_block_vector); + + // Update the Jacobian solver. + ConstructJacobianSolverAndApplyOptions(); } } \ No newline at end of file diff --git a/src/problem_operators/problem_operator_base.hpp b/src/problem_operators/problem_operator_base.hpp index 323c373ab..ae7ce5c13 100644 --- a/src/problem_operators/problem_operator_base.hpp +++ b/src/problem_operators/problem_operator_base.hpp @@ -19,30 +19,20 @@ class ProblemOperatorBase /// Update the problem operator after a mesh change. virtual void Update(); - /// Set the Jacobian preconditioner. - void SetJacobianPreconditioner(std::unique_ptr preconditioner) + /// A structure for setting solver options. + struct SolverOptions { - _jacobian_preconditioner = std::move(preconditioner); - } + double _tolerance; + double _abs_tolerance; - /// Set the Jacobian solver. - void SetJacobianSolver(std::unique_ptr solver) - { - _jacobian_solver = std::move(solver); - } + unsigned int _max_iteration; - /// Set the nonlinear solver. - void SetNonlinearSolver(std::unique_ptr nl_solver) - { - _nonlinear_solver = std::move(nl_solver); - } + int _print_level; + int _k_dim; + }; - /// Accessor for Jacobian preconditioner. - template - TSolver * JacobianPreconditioner() const - { - return static_cast(_jacobian_preconditioner.get()); - } + /// Sets the solver's options. Then calls ApplySolverOptions. + void SetSolverOptions(SolverOptions options); protected: /// Use of protected constructor to only allow construction by derived classes. @@ -50,6 +40,21 @@ class ProblemOperatorBase /// be possible to use directly. explicit ProblemOperatorBase(hephaestus::Problem & problem); + /// Override in derived classes to set default solver options. These will be + /// applied following solver construction. + virtual SolverOptions DefaultSolverOptions() const; + + /// Applies the current solver options. Override in derived classes. + virtual void ApplySolverOptions(); + + /// Override in derived classes to construct the Jacobian solver. Called in the + /// Init method. + virtual void ConstructJacobianSolver(); + + /// Override in derived classes to construct the non-linear solver. Called in + /// the Init method. + virtual void ConstructNonlinearSolver(); + /// Set trial variables names. Override in derived classes. virtual void SetTrialVariableNames() {} @@ -69,6 +74,9 @@ class ProblemOperatorBase /// Returns the number of trial variables. int GetTrialVariablesSize() const; + /// Solver options accessor. + const SolverOptions & GetSolverOptions() const { return _solver_options; } + // Reference to the current problem. hephaestus::Problem & _problem; @@ -98,10 +106,17 @@ class ProblemOperatorBase std::unique_ptr _block_vector{nullptr}; private: + /// Calls ConstructJacobianSolver followed by ApplySolverOptions. This ensures + /// that ApplySolverOptions is always called! + void ConstructJacobianSolverAndApplyOptions(); + /// Update the block vectors and offsets after a mesh change. void UpdateOffsets(); /// Update a block vector. Should be called after the offsets have been updated. void UpdateBlockVector(mfem::BlockVector & X); + + /// The current solver options. + SolverOptions _solver_options; }; } \ No newline at end of file diff --git a/src/problem_operators/time_domain_equation_system_problem_operator.cpp b/src/problem_operators/time_domain_equation_system_problem_operator.cpp index ccc210c42..86588af50 100644 --- a/src/problem_operators/time_domain_equation_system_problem_operator.cpp +++ b/src/problem_operators/time_domain_equation_system_problem_operator.cpp @@ -39,37 +39,9 @@ TimeDomainEquationSystemProblemOperator::Init() void TimeDomainEquationSystemProblemOperator::Update() { - GetEquationSystem()->Update(_problem._bc_map, _problem._sources); - TimeDomainProblemOperator::Update(); - // TODO: - we need to update the size of the jacobian_solver here after the parent class' Update - // method is called which ensures that we've updated the _true_x, _true_rhs. This is a hacky first - // attempt to avoid a segfault with test_mesh_updates. This is very bad code and basically - // copies methods from the AFormulation problem builder used. We need to generalize this. - // Note that this approach will only work for this specific problem! Static pointer casts - // have been used to ensure that this will fail if used on a different problem. - { - GetEquationSystem()->BuildJacobian(_true_x, _true_rhs); - - // Rebuild the jacobian preconditioner. - auto first_pfespace = GetEquationSystem()->_test_pfespaces.at(0); - - auto precond = std::make_unique(first_pfespace); - - precond->SetSingularProblem(); - precond->SetPrintLevel(-1); - - _jacobian_preconditioner = std::move(precond); - - // Set new preconditioner. - static_cast(_jacobian_solver.get()) - ->SetPreconditioner(*static_cast(_jacobian_preconditioner.get())); - - // Set Jacobian matrix. - auto * matrix = GetEquationSystem()->JacobianOperatorHandle().As(); - _jacobian_solver->SetOperator(*matrix); - } + GetEquationSystem()->Update(_problem._bc_map, _problem._sources); } void diff --git a/src/problem_operators/time_domain_problem_operator.cpp b/src/problem_operators/time_domain_problem_operator.cpp index a4ffa7211..78ee2b096 100644 --- a/src/problem_operators/time_domain_problem_operator.cpp +++ b/src/problem_operators/time_domain_problem_operator.cpp @@ -20,6 +20,25 @@ GetTimeDerivativeNames(std::vector gridfunction_names) return time_derivative_names; } +TimeDomainProblemOperator::TimeDomainProblemOperator(hephaestus::Problem & problem) + : ProblemOperatorBase(problem) +{ +} + +void +TimeDomainProblemOperator::ConstructTimestepper() +{ + _ode_solver = std::make_unique(); + _ode_solver->Init(*this); +} + +void +TimeDomainProblemOperator::Init() +{ + ProblemOperatorBase::Init(); + ConstructTimestepper(); +} + void TimeDomainProblemOperator::Update() { @@ -27,10 +46,7 @@ TimeDomainProblemOperator::Update() // The dimensions of the problem operator have now changed. We must call the // ODE solver's Init method to resize its internal vector. - if (_ode_solver) - { - _ode_solver->Init(*this); - } + _ode_solver->Init(*this); } } // namespace hephaestus \ No newline at end of file diff --git a/src/problem_operators/time_domain_problem_operator.hpp b/src/problem_operators/time_domain_problem_operator.hpp index d36f17365..e12c5f27f 100644 --- a/src/problem_operators/time_domain_problem_operator.hpp +++ b/src/problem_operators/time_domain_problem_operator.hpp @@ -16,29 +16,28 @@ std::vector GetTimeDerivativeNames(std::vector gridfun class TimeDomainProblemOperator : public mfem::TimeDependentOperator, public ProblemOperatorBase { public: - TimeDomainProblemOperator(hephaestus::Problem & problem) : ProblemOperatorBase(problem) {} + TimeDomainProblemOperator(hephaestus::Problem & problem); ~TimeDomainProblemOperator() override = default; void ImplicitSolve(const double dt, const mfem::Vector & X, mfem::Vector & dX_dt) override {} - /// Set the ODE solver. - void SetODESolver(std::unique_ptr ode_solver) - { - _ode_solver = std::move(ode_solver); - } - /// Wrapper around the ODE solver's Step method using the block vector. virtual void Step(mfem::real_t & t, mfem::real_t & dt) { _ode_solver->Step(*_block_vector, t, dt); } + void Init() override; + void Update() override; protected: int & Width() final { return mfem::TimeDependentOperator::width; } int & Height() final { return mfem::TimeDependentOperator::height; } + /// Construct the ODE solver. Called in constructor. Override in derived classes. + virtual void ConstructTimestepper(); + private: /// Store the ODE solver. std::unique_ptr _ode_solver{nullptr}; diff --git a/test/integration/test_aform_source.cpp b/test/integration/test_aform_source.cpp index b60093299..def039144 100644 --- a/test/integration/test_aform_source.cpp +++ b/test/integration/test_aform_source.cpp @@ -110,10 +110,6 @@ class TestAFormSource current_solver_options, false)); - hephaestus::InputParameters solver_options; - solver_options.SetParam("Tolerance", float(1.0e-16)); - solver_options.SetParam("MaxIter", (unsigned int)1000); - hephaestus::InputParameters params; params.SetParam("Mesh", mfem::ParMesh(MPI_COMM_WORLD, mesh)); params.SetParam("BoundaryConditions", bc_map); @@ -121,7 +117,6 @@ class TestAFormSource params.SetParam("PostProcessors", postprocessors); params.SetParam("Outputs", outputs); params.SetParam("Sources", sources); - params.SetParam("SolverOptions", solver_options); return params; } @@ -156,8 +151,6 @@ TEST_CASE_METHOD(TestAFormSource, "TestAForm", "[CheckRun]") auto postprocessors(params.GetParam("PostProcessors")); auto sources(params.GetParam("Sources")); auto outputs(params.GetParam("Outputs")); - auto solver_options(params.GetOptionalParam( - "SolverOptions", hephaestus::InputParameters())); problem_builder->SetMesh(pmesh); problem_builder->AddFESpace(std::string("HCurl"), std::string("ND_3D_P2")); @@ -169,12 +162,13 @@ TEST_CASE_METHOD(TestAFormSource, "TestAForm", "[CheckRun]") problem_builder->SetPostprocessors(postprocessors); problem_builder->SetSources(sources); problem_builder->SetOutputs(outputs); - problem_builder->SetSolverOptions(solver_options); problem_builder->FinalizeProblem(); auto problem = problem_builder->ReturnProblem(); + problem->GetOperator()->SetSolverOptions({._tolerance = 1.0e-16, ._max_iteration = 1000}); + hephaestus::InputParameters exec_params; exec_params.SetParam("TimeStep", float(0.05)); exec_params.SetParam("StartTime", float(0.00)); diff --git a/test/integration/test_avform_rod.cpp b/test/integration/test_avform_rod.cpp index 84c09cb20..926c90bd6 100644 --- a/test/integration/test_avform_rod.cpp +++ b/test/integration/test_avform_rod.cpp @@ -118,8 +118,6 @@ TEST_CASE_METHOD(TestAVFormRod, "TestAVFormRod", "[CheckRun]") auto postprocessors(params.GetParam("PostProcessors")); auto sources(params.GetParam("Sources")); auto outputs(params.GetParam("Outputs")); - auto solver_options(params.GetOptionalParam( - "SolverOptions", hephaestus::InputParameters())); problem_builder->SetMesh(pmesh); problem_builder->SetBoundaryConditions(bc_map); @@ -128,7 +126,6 @@ TEST_CASE_METHOD(TestAVFormRod, "TestAVFormRod", "[CheckRun]") problem_builder->SetPostprocessors(postprocessors); problem_builder->SetSources(sources); problem_builder->SetOutputs(outputs); - problem_builder->SetSolverOptions(solver_options); problem_builder->FinalizeProblem(); diff --git a/test/integration/test_avform_source.cpp b/test/integration/test_avform_source.cpp index 2b2026812..2aedc08c2 100644 --- a/test/integration/test_avform_source.cpp +++ b/test/integration/test_avform_source.cpp @@ -171,8 +171,6 @@ TEST_CASE_METHOD(TestAVFormSource, "TestAVFormSource", "[CheckRun]") auto postprocessors(params.GetParam("PostProcessors")); auto sources(params.GetParam("Sources")); auto outputs(params.GetParam("Outputs")); - auto solver_options(params.GetOptionalParam( - "SolverOptions", hephaestus::InputParameters())); problem_builder->SetMesh(pmesh); problem_builder->AddFESpace(std::string("HCurl"), std::string("ND_3D_P2")); @@ -185,7 +183,6 @@ TEST_CASE_METHOD(TestAVFormSource, "TestAVFormSource", "[CheckRun]") problem_builder->SetPostprocessors(postprocessors); problem_builder->SetSources(sources); problem_builder->SetOutputs(outputs); - problem_builder->SetSolverOptions(solver_options); problem_builder->FinalizeProblem(); diff --git a/test/integration/test_complex_aform_rod.cpp b/test/integration/test_complex_aform_rod.cpp index 12280df4f..6d43ea30a 100644 --- a/test/integration/test_complex_aform_rod.cpp +++ b/test/integration/test_complex_aform_rod.cpp @@ -108,10 +108,6 @@ class TestComplexAFormRod -1, current_solver_options)); - hephaestus::InputParameters solver_options; - solver_options.SetParam("Tolerance", float(1.0e-9)); - solver_options.SetParam("MaxIter", (unsigned int)1000); - hephaestus::InputParameters params; params.SetParam("UseGLVis", true); params.SetParam("Mesh", mfem::ParMesh(MPI_COMM_WORLD, mesh)); @@ -122,7 +118,6 @@ class TestComplexAFormRod params.SetParam("PostProcessors", postprocessors); params.SetParam("Sources", sources); params.SetParam("Outputs", outputs); - params.SetParam("SolverOptions", solver_options); return params; } @@ -149,8 +144,6 @@ TEST_CASE_METHOD(TestComplexAFormRod, "TestComplexAFormRod", "[CheckRun]") auto postprocessors(params.GetParam("PostProcessors")); auto sources(params.GetParam("Sources")); auto outputs(params.GetParam("Outputs")); - auto solver_options(params.GetOptionalParam( - "SolverOptions", hephaestus::InputParameters())); problem_builder->SetMesh(pmesh); problem_builder->AddFESpace(std::string("HCurl"), std::string("ND_3D_P1")); @@ -187,12 +180,13 @@ TEST_CASE_METHOD(TestComplexAFormRod, "TestComplexAFormRod", "[CheckRun]") problem_builder->SetSources(sources); problem_builder->SetOutputs(outputs); - problem_builder->SetSolverOptions(solver_options); problem_builder->FinalizeProblem(); auto problem = problem_builder->ReturnProblem(); + problem->GetOperator()->SetSolverOptions({._tolerance = 1.0e-9, ._max_iteration = 1000}); + hephaestus::InputParameters exec_params; exec_params.SetParam("Problem", static_cast(problem.get())); diff --git a/test/integration/test_complex_ermes_mouse.cpp b/test/integration/test_complex_ermes_mouse.cpp index ddac16f11..ffdafb2a5 100644 --- a/test/integration/test_complex_ermes_mouse.cpp +++ b/test/integration/test_complex_ermes_mouse.cpp @@ -101,10 +101,6 @@ class TestComplexERMESMouse hephaestus::AuxSolvers preprocessors; hephaestus::Sources sources; - hephaestus::InputParameters solver_options; - solver_options.SetParam("Tolerance", float(1.0e-16)); - solver_options.SetParam("MaxIter", (unsigned int)1000); - hephaestus::InputParameters params; params.SetParam("UseGLVis", true); @@ -117,7 +113,6 @@ class TestComplexERMESMouse params.SetParam("PostProcessors", postprocessors); params.SetParam("Outputs", outputs); params.SetParam("Sources", sources); - params.SetParam("SolverOptions", solver_options); return params; } @@ -144,8 +139,6 @@ TEST_CASE_METHOD(TestComplexERMESMouse, "TestComplexERMESMouse", "[CheckRun]") auto postprocessors(params.GetParam("PostProcessors")); auto sources(params.GetParam("Sources")); auto outputs(params.GetParam("Outputs")); - auto solver_options(params.GetOptionalParam( - "SolverOptions", hephaestus::InputParameters())); problem_builder->SetMesh(pmesh); problem_builder->SetBoundaryConditions(bc_map); @@ -154,12 +147,13 @@ TEST_CASE_METHOD(TestComplexERMESMouse, "TestComplexERMESMouse", "[CheckRun]") problem_builder->SetPostprocessors(postprocessors); problem_builder->SetSources(sources); problem_builder->SetOutputs(outputs); - problem_builder->SetSolverOptions(solver_options); problem_builder->FinalizeProblem(); auto problem = problem_builder->ReturnProblem(); + problem->GetOperator()->SetSolverOptions({._tolerance = 1.0e-16, ._max_iteration = 1000}); + hephaestus::InputParameters exec_params; exec_params.SetParam("Problem", static_cast(problem.get())); diff --git a/test/integration/test_complex_iris_wg.cpp b/test/integration/test_complex_iris_wg.cpp index e2611cd7c..7b06130ba 100644 --- a/test/integration/test_complex_iris_wg.cpp +++ b/test/integration/test_complex_iris_wg.cpp @@ -99,10 +99,6 @@ class TestComplexIrisWaveguide hephaestus::AuxSolvers preprocessors; hephaestus::Sources sources; - hephaestus::InputParameters solver_options; - solver_options.SetParam("Tolerance", float(1.0e-16)); - solver_options.SetParam("MaxIter", (unsigned int)1000); - hephaestus::InputParameters params; params.SetParam("UseGLVis", true); @@ -115,7 +111,6 @@ class TestComplexIrisWaveguide params.SetParam("PostProcessors", postprocessors); params.SetParam("Outputs", outputs); params.SetParam("Sources", sources); - params.SetParam("SolverOptions", solver_options); return params; } @@ -142,8 +137,6 @@ TEST_CASE_METHOD(TestComplexIrisWaveguide, "TestComplexIrisWaveguide", "[CheckRu auto postprocessors(params.GetParam("PostProcessors")); auto sources(params.GetParam("Sources")); auto outputs(params.GetParam("Outputs")); - auto solver_options(params.GetOptionalParam( - "SolverOptions", hephaestus::InputParameters())); problem_builder->SetMesh(pmesh); problem_builder->SetBoundaryConditions(bc_map); @@ -172,12 +165,13 @@ TEST_CASE_METHOD(TestComplexIrisWaveguide, "TestComplexIrisWaveguide", "[CheckRu problem_builder->SetPostprocessors(postprocessors); problem_builder->SetSources(sources); problem_builder->SetOutputs(outputs); - problem_builder->SetSolverOptions(solver_options); problem_builder->FinalizeProblem(); auto problem = problem_builder->ReturnProblem(); + problem->GetOperator()->SetSolverOptions({._tolerance = 1.0e-16, ._max_iteration = 1000}); + hephaestus::InputParameters exec_params; exec_params.SetParam("Problem", static_cast(problem.get())); diff --git a/test/integration/test_complex_team7.cpp b/test/integration/test_complex_team7.cpp index 923390be9..4d57f6f08 100644 --- a/test/integration/test_complex_team7.cpp +++ b/test/integration/test_complex_team7.cpp @@ -135,10 +135,6 @@ class TestComplexTeam7 std::make_shared( "source", "source", "HCurl", "H1", "electric_potential", current_solver_options)); - hephaestus::InputParameters solver_options; - solver_options.SetParam("Tolerance", float(1.0e-16)); - solver_options.SetParam("MaxIter", (unsigned int)1000); - hephaestus::InputParameters params; params.SetParam("UseGLVis", true); @@ -147,7 +143,6 @@ class TestComplexTeam7 params.SetParam("Coefficients", coefficients); params.SetParam("Outputs", outputs); params.SetParam("Sources", sources); - params.SetParam("SolverOptions", solver_options); hephaestus::logger.info("Created params "); return params; } @@ -166,8 +161,6 @@ TEST_CASE_METHOD(TestComplexTeam7, "TestComplexTeam7", "[CheckRun]") auto coefficients(params.GetParam("Coefficients")); auto sources(params.GetParam("Sources")); auto outputs(params.GetParam("Outputs")); - auto solver_options(params.GetOptionalParam( - "SolverOptions", hephaestus::InputParameters())); auto problem_builder = std::make_unique("magnetic_reluctivity", @@ -192,7 +185,6 @@ TEST_CASE_METHOD(TestComplexTeam7, "TestComplexTeam7", "[CheckRun]") problem_builder->SetCoefficients(coefficients); problem_builder->SetSources(sources); problem_builder->SetOutputs(outputs); - problem_builder->SetSolverOptions(solver_options); // Call LineSampler to save values std::string gridfunction_name("magnetic_flux_density_real"); @@ -220,6 +212,8 @@ TEST_CASE_METHOD(TestComplexTeam7, "TestComplexTeam7", "[CheckRun]") auto problem = problem_builder->ReturnProblem(); + problem->GetOperator()->SetSolverOptions({._tolerance = 1.0e-16, ._max_iteration = 1000}); + hephaestus::InputParameters exec_params; exec_params.SetParam("Problem", static_cast(problem.get())); diff --git a/test/integration/test_ebform_coupled.cpp b/test/integration/test_ebform_coupled.cpp index a1ee79e86..9178a28c7 100644 --- a/test/integration/test_ebform_coupled.cpp +++ b/test/integration/test_ebform_coupled.cpp @@ -125,10 +125,6 @@ class TestEBFormCoupled -1, current_solver_options)); - hephaestus::InputParameters solver_options; - solver_options.SetParam("Tolerance", float(1.0e-9)); - solver_options.SetParam("MaxIter", (unsigned int)1000); - hephaestus::InputParameters params; params.SetParam("Mesh", mfem::ParMesh(MPI_COMM_WORLD, mesh)); params.SetParam("BoundaryConditions", bc_map); @@ -139,7 +135,6 @@ class TestEBFormCoupled params.SetParam("PostProcessors", postprocessors); params.SetParam("Sources", sources); params.SetParam("Outputs", outputs); - params.SetParam("SolverOptions", solver_options); return params; } @@ -161,8 +156,6 @@ TEST_CASE_METHOD(TestEBFormCoupled, "TestEBFormCoupled", "[CheckRun]") auto postprocessors(params.GetParam("PostProcessors")); auto sources(params.GetParam("Sources")); auto outputs(params.GetParam("Outputs")); - auto solver_options(params.GetOptionalParam( - "SolverOptions", hephaestus::InputParameters())); std::shared_ptr pmesh = std::make_shared(params.GetParam("Mesh")); @@ -185,11 +178,13 @@ TEST_CASE_METHOD(TestEBFormCoupled, "TestEBFormCoupled", "[CheckRun]") problem_builder->SetPostprocessors(postprocessors); problem_builder->SetSources(sources); problem_builder->SetOutputs(outputs); - problem_builder->SetSolverOptions(solver_options); problem_builder->FinalizeProblem(); auto problem = problem_builder->ReturnProblem(); + + problem->GetOperator()->SetSolverOptions({._tolerance = 1.0e-9, ._max_iteration = 1000}); + hephaestus::InputParameters exec_params; exec_params.SetParam("TimeStep", float(0.5)); exec_params.SetParam("StartTime", float(0.00)); diff --git a/test/integration/test_ebform_rod.cpp b/test/integration/test_ebform_rod.cpp index d9a7bed54..f8d026c07 100644 --- a/test/integration/test_ebform_rod.cpp +++ b/test/integration/test_ebform_rod.cpp @@ -103,10 +103,6 @@ class TestEBFormRod -1, current_solver_options)); - hephaestus::InputParameters solver_options; - solver_options.SetParam("Tolerance", float(1.0e-9)); - solver_options.SetParam("MaxIter", (unsigned int)1000); - hephaestus::InputParameters params; params.SetParam("Mesh", mfem::ParMesh(MPI_COMM_WORLD, mesh)); params.SetParam("BoundaryConditions", bc_map); @@ -116,7 +112,6 @@ class TestEBFormRod params.SetParam("PostProcessors", postprocessors); params.SetParam("Sources", sources); params.SetParam("Outputs", outputs); - params.SetParam("SolverOptions", solver_options); return params; } @@ -138,8 +133,6 @@ TEST_CASE_METHOD(TestEBFormRod, "TestEBFormRod", "[CheckRun]") auto postprocessors(params.GetParam("PostProcessors")); auto sources(params.GetParam("Sources")); auto outputs(params.GetParam("Outputs")); - auto solver_options(params.GetOptionalParam( - "SolverOptions", hephaestus::InputParameters())); std::shared_ptr pmesh = std::make_shared(params.GetParam("Mesh")); @@ -153,11 +146,13 @@ TEST_CASE_METHOD(TestEBFormRod, "TestEBFormRod", "[CheckRun]") problem_builder->SetPostprocessors(postprocessors); problem_builder->SetSources(sources); problem_builder->SetOutputs(outputs); - problem_builder->SetSolverOptions(solver_options); problem_builder->FinalizeProblem(); auto problem = problem_builder->ReturnProblem(); + + problem->GetOperator()->SetSolverOptions({._tolerance = 1.0e-9, ._max_iteration = 1000}); + hephaestus::InputParameters exec_params; exec_params.SetParam("TimeStep", float(0.5)); exec_params.SetParam("StartTime", float(0.00)); diff --git a/test/integration/test_hform_rod.cpp b/test/integration/test_hform_rod.cpp index 74e163773..8444df3e9 100644 --- a/test/integration/test_hform_rod.cpp +++ b/test/integration/test_hform_rod.cpp @@ -88,10 +88,6 @@ class TestHFormRod outputs.Register("ParaViewDataCollection", std::make_shared("HFormParaView")); - hephaestus::InputParameters solver_options; - solver_options.SetParam("Tolerance", float(1.0e-16)); - solver_options.SetParam("MaxIter", (unsigned int)1000); - hephaestus::GridFunctions gridfunctions; hephaestus::AuxSolvers preprocessors; hephaestus::AuxSolvers postprocessors; @@ -118,7 +114,6 @@ class TestHFormRod params.SetParam("PostProcessors", postprocessors); params.SetParam("Outputs", outputs); params.SetParam("Sources", sources); - params.SetParam("SolverOptions", solver_options); return params; } @@ -141,8 +136,6 @@ TEST_CASE_METHOD(TestHFormRod, "TestHFormRod", "[CheckRun]") auto postprocessors(params.GetParam("PostProcessors")); auto sources(params.GetParam("Sources")); auto outputs(params.GetParam("Outputs")); - auto solver_options(params.GetOptionalParam( - "SolverOptions", hephaestus::InputParameters())); problem_builder->SetMesh(pmesh); problem_builder->AddFESpace(std::string("H1"), std::string("H1_3D_P2")); @@ -152,11 +145,13 @@ TEST_CASE_METHOD(TestHFormRod, "TestHFormRod", "[CheckRun]") problem_builder->SetPostprocessors(postprocessors); problem_builder->SetSources(sources); problem_builder->SetOutputs(outputs); - problem_builder->SetSolverOptions(solver_options); problem_builder->FinalizeProblem(); auto problem = problem_builder->ReturnProblem(); + + problem->GetOperator()->SetSolverOptions({._tolerance = 1.0e-16, ._max_iteration = 1000}); + hephaestus::InputParameters exec_params; exec_params.SetParam("TimeStep", float(0.5)); exec_params.SetParam("StartTime", float(0.00)); diff --git a/test/integration/test_hform_source.cpp b/test/integration/test_hform_source.cpp index dbf26f531..604036bc9 100644 --- a/test/integration/test_hform_source.cpp +++ b/test/integration/test_hform_source.cpp @@ -116,10 +116,6 @@ class TestHFormSource current_solver_options, false)); - hephaestus::InputParameters solver_options; - solver_options.SetParam("Tolerance", float(1.0e-16)); - solver_options.SetParam("MaxIter", (unsigned int)1000); - hephaestus::InputParameters params; params.SetParam("TimeStep", float(0.05)); params.SetParam("StartTime", float(0.00)); @@ -134,7 +130,6 @@ class TestHFormSource params.SetParam("PostProcessors", postprocessors); params.SetParam("Sources", sources); params.SetParam("Outputs", outputs); - params.SetParam("SolverOptions", solver_options); return params; } @@ -171,8 +166,6 @@ TEST_CASE_METHOD(TestHFormSource, "TestHFormSource", "[CheckRun]") auto postprocessors(params.GetParam("PostProcessors")); auto sources(params.GetParam("Sources")); auto outputs(params.GetParam("Outputs")); - auto solver_options(params.GetOptionalParam( - "SolverOptions", hephaestus::InputParameters())); problem_builder->SetMesh(pmesh); problem_builder->AddFESpace(std::string("HCurl"), std::string("ND_3D_P2")); @@ -184,12 +177,13 @@ TEST_CASE_METHOD(TestHFormSource, "TestHFormSource", "[CheckRun]") problem_builder->SetPostprocessors(postprocessors); problem_builder->SetSources(sources); problem_builder->SetOutputs(outputs); - problem_builder->SetSolverOptions(solver_options); problem_builder->FinalizeProblem(); auto problem = problem_builder->ReturnProblem(); + problem->GetOperator()->SetSolverOptions({._tolerance = 1.0e-16, ._max_iteration = 1000}); + hephaestus::InputParameters exec_params; exec_params.SetParam("TimeStep", float(0.05)); exec_params.SetParam("StartTime", float(0.00)); diff --git a/test/integration/test_mesh_updates.cpp b/test/integration/test_mesh_updates.cpp index 277488a19..d15982c98 100644 --- a/test/integration/test_mesh_updates.cpp +++ b/test/integration/test_mesh_updates.cpp @@ -112,10 +112,6 @@ class TestMeshUpdates current_solver_options, false)); - hephaestus::InputParameters solver_options; - solver_options.SetParam("Tolerance", float(1.0e-16)); - solver_options.SetParam("MaxIter", (unsigned int)1000); - hephaestus::InputParameters params; params.SetParam("Mesh", mfem::ParMesh(MPI_COMM_WORLD, mesh)); params.SetParam("BoundaryConditions", bc_map); @@ -123,7 +119,6 @@ class TestMeshUpdates params.SetParam("PostProcessors", postprocessors); params.SetParam("Outputs", outputs); params.SetParam("Sources", sources); - params.SetParam("SolverOptions", solver_options); return params; } @@ -146,8 +141,6 @@ TEST_CASE_METHOD(TestMeshUpdates, "TestMeshUpdates", "[CheckRun]") auto postprocessors(params.GetParam("PostProcessors")); auto sources(params.GetParam("Sources")); auto outputs(params.GetParam("Outputs")); - auto solver_options(params.GetOptionalParam( - "SolverOptions", hephaestus::InputParameters())); problem_builder->SetMesh(pmesh); problem_builder->AddFESpace(std::string("HCurl"), std::string("ND_3D_P2")); @@ -158,12 +151,13 @@ TEST_CASE_METHOD(TestMeshUpdates, "TestMeshUpdates", "[CheckRun]") problem_builder->SetPostprocessors(postprocessors); problem_builder->SetSources(sources); problem_builder->SetOutputs(outputs); - problem_builder->SetSolverOptions(solver_options); problem_builder->FinalizeProblem(); auto problem = problem_builder->ReturnProblem(); + problem->GetOperator()->SetSolverOptions({._tolerance = 1.0e-16, ._max_iteration = 1000}); + hephaestus::InputParameters exec_params; // Single timestep. diff --git a/test/integration/test_team4_hform.cpp b/test/integration/test_team4_hform.cpp index 8c226d203..63813bc30 100644 --- a/test/integration/test_team4_hform.cpp +++ b/test/integration/test_team4_hform.cpp @@ -147,15 +147,13 @@ TEST_CASE_METHOD(TestTEAM4HForm, "TestTEAM4HForm", "[CheckRun]") fluxmonitor->SetPriority(2); problem_builder->AddPostprocessor("FluxMonitor", fluxmonitor); - hephaestus::InputParameters solver_options; - solver_options.SetParam("AbsTolerance", float(1.0e-20)); - solver_options.SetParam("Tolerance", float(1.0e-20)); - solver_options.SetParam("MaxIter", (unsigned int)500); - problem_builder->SetSolverOptions(solver_options); - problem_builder->FinalizeProblem(); auto problem = problem_builder->ReturnProblem(); + + problem->GetOperator()->SetSolverOptions( + {._tolerance = 1.0e-20, ._abs_tolerance = 1.0e-20, ._max_iteration = 500}); + hephaestus::InputParameters exec_params; exec_params.SetParam("TimeStep", float(0.001)); exec_params.SetParam("StartTime", float(0.00));