Line data Source code
1 : // The libMesh Finite Element Library. 2 : // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 : 4 : // This library is free software; you can redistribute it and/or 5 : // modify it under the terms of the GNU Lesser General Public 6 : // License as published by the Free Software Foundation; either 7 : // version 2.1 of the License, or (at your option) any later version. 8 : 9 : // This library is distributed in the hope that it will be useful, 10 : // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 : // Lesser General Public License for more details. 13 : 14 : // You should have received a copy of the GNU Lesser General Public 15 : // License along with this library; if not, write to the Free Software 16 : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 : 18 : 19 : 20 : #ifndef LIBMESH_ADAPTIVE_TIME_SOLVER_H 21 : #define LIBMESH_ADAPTIVE_TIME_SOLVER_H 22 : 23 : // Local includes 24 : #include "libmesh/system_norm.h" 25 : #include "libmesh/first_order_unsteady_solver.h" 26 : 27 : // C++ includes 28 : 29 : namespace libMesh 30 : { 31 : 32 : // Forward declarations 33 : class System; 34 : 35 : /** 36 : * This class wraps another UnsteadySolver derived class, and compares 37 : * the results of timestepping with deltat and timestepping with 38 : * 2*deltat to adjust future timestep lengths. 39 : * 40 : * Currently this class only works on fully coupled Systems 41 : * 42 : * This class is part of the new DifferentiableSystem framework, 43 : * which is still experimental. Users of this framework should 44 : * beware of bugs and future API changes. 45 : * 46 : * \author Roy H. Stogner 47 : * \date 2007 48 : */ 49 24 : class AdaptiveTimeSolver : public FirstOrderUnsteadySolver 50 : { 51 : public: 52 : /** 53 : * The parent class 54 : */ 55 : typedef FirstOrderUnsteadySolver Parent; 56 : 57 : /** 58 : * Constructor. Requires a reference to the system 59 : * to be solved. 60 : */ 61 : explicit 62 : AdaptiveTimeSolver (sys_type & s); 63 : 64 : /** 65 : * Destructor. 66 : */ 67 : virtual ~AdaptiveTimeSolver (); 68 : 69 : virtual void init() override; 70 : 71 : virtual void reinit() override; 72 : 73 : virtual void solve() override = 0; 74 : 75 : virtual std::pair<unsigned int, Real> adjoint_solve (const QoISet & qoi_indices) override = 0; 76 : 77 : virtual void advance_timestep() override; 78 : 79 : virtual void adjoint_advance_timestep() override; 80 : 81 : virtual void retrieve_timestep() override; 82 : 83 : virtual void integrate_qoi_timestep() override = 0; 84 : 85 : virtual void integrate_adjoint_sensitivity(const QoISet & qois, const ParameterVector & parameter_vector, SensitivityData & sensitivities) override = 0; 86 : 87 : #ifdef LIBMESH_ENABLE_AMR 88 : virtual void integrate_adjoint_refinement_error_estimate(AdjointRefinementEstimator & adjoint_refinement_error_estimator, ErrorVector & QoI_elementwise_error) override = 0; 89 : #endif // LIBMESH_ENABLE_AMR 90 : 91 21140 : virtual Real last_completed_timestep_size() override { return completed_timestep_size; }; 92 : 93 : /** 94 : * This method is passed on to the core_time_solver 95 : */ 96 : virtual Real error_order () const override; 97 : 98 : /** 99 : * This method is passed on to the core_time_solver 100 : */ 101 : virtual bool element_residual (bool get_jacobian, 102 : DiffContext &) override; 103 : 104 : /** 105 : * This method is passed on to the core_time_solver 106 : */ 107 : virtual bool side_residual (bool get_jacobian, 108 : DiffContext &) override; 109 : 110 : /** 111 : * This method is passed on to the core_time_solver 112 : */ 113 : virtual bool nonlocal_residual (bool get_jacobian, 114 : DiffContext &) override; 115 : 116 : /** 117 : * An implicit linear or nonlinear solver to use at each timestep. 118 : */ 119 : virtual std::unique_ptr<DiffSolver> & diff_solver() override; 120 : 121 : /** 122 : * An implicit linear solver to use for adjoint and sensitivity 123 : * problems. 124 : */ 125 : virtual std::unique_ptr<LinearSolver<Number>> & linear_solver() override; 126 : 127 : /** 128 : * This object is used to take timesteps 129 : */ 130 : std::unique_ptr<UnsteadySolver> core_time_solver; 131 : 132 : /** 133 : * Error calculations are done in this norm, DISCRETE_L2 by default. 134 : */ 135 : SystemNorm component_norm; 136 : 137 : /** 138 : * If component_norms is non-empty, each variable's contribution to the error 139 : * of a system will also be scaled by component_scale[var], unless 140 : * component_scale is empty in which case all variables will be weighted 141 : * equally. 142 : */ 143 : std::vector<float> component_scale; 144 : 145 : /** 146 : * This tolerance is the target relative error between an exact 147 : * time integration and a single time step output, scaled by deltat. 148 : * integrator, scaled by deltat. If the estimated error exceeds or 149 : * undershoots the target error tolerance, future timesteps will be 150 : * run with deltat shrunk or grown to compensate. 151 : * 152 : * The default value is 1.0e-2; obviously users should select their 153 : * own tolerance. 154 : * 155 : * If a *negative* target_tolerance is specified, then its absolute 156 : * value is used to scale the estimated error from the first 157 : * simulation time step, and this becomes the target tolerance of 158 : * all future time steps. 159 : */ 160 : Real target_tolerance; 161 : 162 : /** 163 : * This tolerance is the maximum relative error between an exact 164 : * time integration and a single time step output, scaled by deltat. 165 : * If this error tolerance is exceeded by the estimated error of the 166 : * current time step, that time step will be repeated with a smaller 167 : * deltat. 168 : * 169 : * If you use the default upper_tolerance=0.0, then the current 170 : * time step will not be repeated regardless of estimated error. 171 : * 172 : * If a *negative* upper_tolerance is specified, then its absolute 173 : * value is used to scale the estimated error from the first 174 : * simulation time step, and this becomes the upper tolerance of 175 : * all future time steps. 176 : */ 177 : Real upper_tolerance; 178 : 179 : /** 180 : * Do not allow the adaptive time solver to select deltat > max_deltat. 181 : * If you use the default max_deltat=0.0, then deltat is unlimited. 182 : */ 183 : Real max_deltat; 184 : 185 : /** 186 : * Do not allow the adaptive time solver to select deltat < min_deltat. 187 : * The default value is 0.0. 188 : */ 189 : Real min_deltat; 190 : 191 : /** 192 : * Do not allow the adaptive time solver to select 193 : * a new deltat greater than max_growth times the old deltat. 194 : * If you use the default max_growth=0.0, then the deltat growth is 195 : * unlimited. 196 : */ 197 : Real max_growth; 198 : 199 : /** 200 : * The adaptive time solver's have two notions of deltat. The deltat the solver 201 : * ended up using for the completed timestep. And the deltat the solver determined 202 : * would be workable for the coming timestep. The latter gets set as system.deltat. 203 : * We need a variable to save the deltat used for the completed timestep. 204 : * */ 205 : Real completed_timestep_size; 206 : 207 : /** 208 : * This flag, which is true by default, grows (shrinks) the timestep 209 : * based on the expected global accuracy of the timestepping scheme. 210 : * Global in this sense means the cumulative final-time accuracy of 211 : * the scheme. For example, the backward Euler scheme's truncation 212 : * error is locally of order 2, so that after N timesteps of size 213 : * deltat, the result is first-order accurate. If you set this to 214 : * false, you can grow (shrink) your timestep based on the local 215 : * accuracy rather than the global accuracy of the core TimeSolver. 216 : * 217 : * \note By setting this value to false you may fail to achieve 218 : * the predicted convergence in time of the underlying method, however 219 : * it may be possible to get more fine-grained control over step sizes 220 : * as well. 221 : */ 222 : bool global_tolerance; 223 : 224 : protected: 225 : 226 : /** 227 : * A helper function to calculate error norms 228 : */ 229 : virtual Real calculate_norm(System &, NumericVector<Number> &); 230 : }; 231 : 232 : 233 : } // namespace libMesh 234 : 235 : 236 : #endif // LIBMESH_ADAPTIVE_TIME_SOLVER_H