Line data Source code
1 : //* This file is part of the MOOSE framework 2 : //* https://mooseframework.inl.gov 3 : //* 4 : //* All rights reserved, see COPYRIGHT for full restrictions 5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT 6 : //* 7 : //* Licensed under LGPL 2.1, please see LICENSE for details 8 : //* https://www.gnu.org/licenses/lgpl-2.1.html 9 : 10 : #ifdef MOOSE_MFEM_ENABLED 11 : 12 : #include "MFEMTransient.h" 13 : #include "MFEMProblem.h" 14 : #include "TimeDependentEquationSystemProblemOperator.h" 15 : #include "TimeStepper.h" 16 : 17 : registerMooseObject("MooseApp", MFEMTransient); 18 : 19 : InputParameters 20 2784 : MFEMTransient::validParams() 21 : { 22 2784 : InputParameters params = MFEMProblemSolve::validParams(); 23 2784 : params += TransientBase::validParams(); 24 2784 : params.addClassDescription("Executioner for transient MFEM problems."); 25 2784 : return params; 26 0 : } 27 : 28 329 : MFEMTransient::MFEMTransient(const InputParameters & params) 29 : : TransientBase(params), 30 329 : _mfem_problem(dynamic_cast<MFEMProblem &>(feProblem())), 31 329 : _mfem_problem_data(_mfem_problem.getProblemData()), 32 658 : _mfem_problem_solve(*this, getProblemOperators()) 33 : { 34 : // If no ProblemOperators have been added by the user, add a default 35 329 : if (getProblemOperators().empty()) 36 : { 37 329 : _mfem_problem_data.eqn_system = std::make_shared<Moose::MFEM::TimeDependentEquationSystem>( 38 329 : _mfem_problem_data.time_derivative_map); 39 : auto problem_operator = 40 329 : std::make_shared<Moose::MFEM::TimeDependentEquationSystemProblemOperator>(_mfem_problem); 41 329 : addProblemOperator(std::move(problem_operator)); 42 329 : } 43 329 : } 44 : 45 : void 46 329 : MFEMTransient::init() 47 : { 48 329 : TransientBase::init(); 49 : 50 : // verify that the requested time integration scheme is actually supported by MFEM transient 51 329 : if (getTimeScheme() != Moose::TimeIntegratorType::TI_IMPLICIT_EULER) 52 2 : paramError("scheme", 53 2 : "Time Integration scheme \"" + stringify(getTimeScheme()) + 54 : "\" is not supported by MFEMTransient Executioner."); 55 : 56 327 : if (_mfem_problem_data.nonlinear_solver) 57 30 : _mfem_problem_data.eqn_system->SetSolverRequiresGradient( 58 30 : _mfem_problem_data.nonlinear_solver->RequiresGradient()); 59 : 60 327 : _mfem_problem_data.eqn_system->SetCoefficientManager(_mfem_problem_data.coefficients); 61 : 62 : // Set up initial conditions 63 327 : _mfem_problem_data.eqn_system->Init( 64 327 : _mfem_problem_data.gridfunctions, 65 327 : _mfem_problem_data.cmplx_gridfunctions, 66 981 : getParam<MooseEnum>("assembly_level").getEnum<mfem::AssemblyLevel>()); 67 : 68 654 : for (const auto & problem_operator : getProblemOperators()) 69 : { 70 327 : problem_operator->SetGridFunctions(); 71 327 : problem_operator->Init(_mfem_problem_data.true_solution); 72 : } 73 327 : } 74 : 75 : void 76 1872 : MFEMTransient::takeStep(Real input_dt) 77 : { 78 1872 : _dt_old = _dt; 79 : 80 1872 : if (input_dt == -1.0) 81 1594 : _dt = computeConstrainedDT(); 82 : else 83 278 : _dt = input_dt; 84 : 85 1872 : _time_stepper->preSolve(); 86 : 87 : // Unfortunately, time needs to be temporarily incremented so we get 88 : // meaningful console output in timestepSetup(). We decrement it back 89 : // immediately after so step() below behaves as expected. 90 1872 : _time += _dt; 91 1872 : _problem.timestepSetup(); 92 1872 : _time -= _dt; 93 : 94 1872 : _problem.onTimestepBegin(); 95 1872 : _problem.execTransfers(EXEC_TIMESTEP_BEGIN); 96 1872 : if (!_problem.execMultiApps(EXEC_TIMESTEP_BEGIN, true)) 97 : { 98 0 : _last_solve_converged = false; 99 0 : return; 100 : } 101 1872 : _problem.execute(EXEC_TIMESTEP_BEGIN); 102 : 103 : // Advance time step of the MFEM problem. Time is also updated here, and 104 : // _problem_operator->SetTime is called inside the ode_solver->Step method to 105 : // update the time used by time dependent (function) coefficients. 106 1872 : _time_stepper->step(); 107 : 108 : // Continue with usual TransientBase::takeStep() finalisation 109 1872 : _last_solve_converged = _time_stepper->converged(); 110 : 111 1872 : if (!lastSolveConverged()) 112 : { 113 0 : _console << "Aborting as solve did not converge" << std::endl; 114 0 : return; 115 : } 116 : 117 1872 : _problem.execute(EXEC_TIMESTEP_END); 118 1872 : _problem.execTransfers(EXEC_TIMESTEP_END); 119 1872 : _problem.execMultiApps(EXEC_TIMESTEP_END, true); 120 : 121 1872 : if (lastSolveConverged()) 122 1872 : _time_stepper->acceptStep(); 123 : else 124 0 : _time_stepper->rejectStep(); 125 : 126 : // Set time to time old, since final time is updated in TransientBase::endStep() 127 1872 : _time = _time_old; 128 : 129 1872 : _time_stepper->postSolve(); 130 : } 131 : 132 : #endif