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 : #include "SolutionTimeAdaptiveDT.h" 11 : #include "FEProblem.h" 12 : #include "Transient.h" 13 : 14 : #include <chrono> 15 : 16 : registerMooseObject("MooseApp", SolutionTimeAdaptiveDT); 17 : 18 : InputParameters 19 14317 : SolutionTimeAdaptiveDT::validParams() 20 : { 21 14317 : InputParameters params = TimeStepper::validParams(); 22 14317 : params.addClassDescription("Compute simulation timestep based on actual solution time."); 23 42951 : params.addParam<Real>( 24 28634 : "percent_change", 0.1, "Fraction to change the timestep by. Should be between 0 and 1"); 25 42951 : params.addParam<int>( 26 28634 : "initial_direction", 1, "Direction for the first step. 1 for up... -1 for down. "); 27 14317 : params.addParam<bool>("adapt_log", false, "Output adaptive time step log"); 28 14317 : params.addRequiredParam<Real>("dt", "The timestep size between solves"); 29 : 30 14317 : return params; 31 0 : } 32 : 33 26 : SolutionTimeAdaptiveDT::SolutionTimeAdaptiveDT(const InputParameters & parameters) 34 : : TimeStepper(parameters), 35 26 : _direction(getParam<int>("initial_direction")), 36 26 : _percent_change(getParam<Real>("percent_change")), 37 26 : _older_sol_time_vs_dt(std::numeric_limits<Real>::max()), 38 26 : _old_sol_time_vs_dt(std::numeric_limits<Real>::max()), 39 26 : _sol_time_vs_dt(std::numeric_limits<Real>::max()), 40 52 : _adapt_log(getParam<bool>("adapt_log")) 41 : 42 : { 43 26 : if ((_adapt_log) && (processor_id() == 0)) 44 : { 45 0 : static const std::string log("adaptive_log"); 46 0 : _adaptive_log.open(log); 47 0 : if (_adaptive_log.fail()) 48 0 : mooseError("Unable to open file ", log); 49 0 : _adaptive_log << "Adaptive Times Step Log" << std::endl; 50 : } 51 26 : } 52 : 53 44 : SolutionTimeAdaptiveDT::~SolutionTimeAdaptiveDT() { _adaptive_log.close(); } 54 : 55 : void 56 172 : SolutionTimeAdaptiveDT::step() 57 : { 58 172 : auto solve_start = std::chrono::system_clock::now(); 59 : 60 172 : TimeStepper::step(); 61 : 62 172 : if (converged()) 63 : { 64 172 : auto solve_end = std::chrono::system_clock::now(); 65 : auto elapsed_time = 66 172 : std::chrono::duration_cast<std::chrono::milliseconds>(solve_end - solve_start).count(); 67 : 68 : // Take the maximum time over all processors so all processors compute and use the same dt 69 172 : TimeStepper::_communicator.max(elapsed_time); 70 : 71 172 : _older_sol_time_vs_dt = _old_sol_time_vs_dt; 72 172 : _old_sol_time_vs_dt = _sol_time_vs_dt; 73 172 : _sol_time_vs_dt = elapsed_time / _dt; 74 : } 75 172 : } 76 : 77 : Real 78 50 : SolutionTimeAdaptiveDT::computeInitialDT() 79 : { 80 50 : return getParam<Real>("dt"); 81 : } 82 : 83 : Real 84 171 : SolutionTimeAdaptiveDT::computeDT() 85 : { 86 : // Ratio grew so switch direction 87 171 : if (_sol_time_vs_dt > _old_sol_time_vs_dt && _sol_time_vs_dt > _older_sol_time_vs_dt) 88 : { 89 21 : _direction *= -1; 90 : 91 : // Make sure we take at least two steps in this new direction 92 21 : _old_sol_time_vs_dt = std::numeric_limits<Real>::max(); 93 21 : _older_sol_time_vs_dt = std::numeric_limits<Real>::max(); 94 : } 95 : 96 171 : Real local_dt = _dt + _dt * _percent_change * _direction; 97 : 98 171 : if ((_adapt_log) && (processor_id() == 0)) 99 : { 100 0 : Real out_dt = getCurrentDT(); 101 0 : if (out_dt > _dt_max) 102 0 : out_dt = _dt_max; 103 : 104 0 : _adaptive_log << "***Time step: " << _t_step << ", time = " << _time + out_dt 105 0 : << "\nCur DT: " << out_dt << "\nOlder Ratio: " << _older_sol_time_vs_dt 106 0 : << "\nOld Ratio: " << _old_sol_time_vs_dt << "\nNew Ratio: " << _sol_time_vs_dt 107 0 : << std::endl; 108 : } 109 : 110 171 : return local_dt; 111 : } 112 : 113 : void 114 0 : SolutionTimeAdaptiveDT::rejectStep() 115 : { 116 0 : _console << "Solve failed... cutting timestep" << std::endl; 117 0 : if (_adapt_log) 118 0 : _adaptive_log << "Solve failed... cutting timestep" << std::endl; 119 : 120 0 : TimeStepper::rejectStep(); 121 0 : }