IFEM  90A354
SIMSolverTS.h
Go to the documentation of this file.
1 // $Id$
2 //==============================================================================
12 //==============================================================================
13 
14 #ifndef _SIM_SOLVER_TS_H_
15 #define _SIM_SOLVER_TS_H_
16 
17 #include "SIMSolver.h"
18 
19 
30 template<class T1> class SIMSolverTS : public SIMSolver<T1>
31 {
32 public:
34  SIMSolverTS(T1& s1) : SIMSolver<T1>(s1)
35  {
36  nForward = nPredict = maxPred = 1;
37  maxRef = 2;
38  preRef = 0;
39  refTol = 0.0;
40  minFrac = 0.1;
41  aStart = beta = -1.0;
42  dumpGrid = 0;
43  lastRLev = -1;
44  }
45 
47  virtual ~SIMSolverTS() {}
48 
50  virtual bool read(const char* file)
51  {
52  if (!this->SIMadmin::read(file))
53  return false;
54  else if (preRef < 1)
55  return true;
56 
57  // Perform some pre-refinement to resolve geometric features, etc.
58  return this->S1.preRefine(maxRef,preRef,refTol);
59  }
60 
62  virtual int solveProblem(char* infile, const char* heading)
63  {
64  if (this->tp.step == 0)
65  {
66  // Perform some initial refinement to resolve geometric features, etc.
67  if (maxRef > preRef && !this->S1.initialRefine(beta,minFrac,maxRef))
68  return 4;
69 
70  // Dump the initial (refined) mesh
71  if (maxRef > preRef || preRef > 0)
72  this->dumpMesh(infile,false);
73  }
74 
75  // Save the initial FE model (and state) to VTF and HDF5 for visualization
76  int geoBlk = 0, nBlock = 0;
77  if (!this->saveState(geoBlk,nBlock,true,infile,preRef<1))
78  return 2;
79 
80  this->printHeading(heading);
81 
82  // Pre-adaptive loop, solve for a certain time period on the initial mesh
83  while (this->tp.time.t < aStart-1.0e-12 && this->advanceStep())
84  if (!this->S1.solveStep(this->tp))
85  return 3;
86  else if (!this->saveState(geoBlk,nBlock))
87  return 2;
88 
89  // Activate printing of time level for result dumps
91 
92  // Adaptive loop
93  while (!this->tp.finished())
94  {
95  this->S1.saveState(); // Save current solution state internally
96  int tranStep = this->tp.step; // Time step of next solution transfer
97  int lastRef = 1, refElms = 0;
98 
99  // Prediction cycle loop, disable staggering cycles
100  if (maxPred < 0) this->S1.enableStaggering(false);
101  for (int iPred = 0; iPred < abs(maxPred) && lastRef > 0; iPred++)
102  {
103  lastRef = 0;
104  if (iPred > 0)
105  {
106  // Reset time step counter to the last saved state
107  this->tp.reset(tranStep);
108  // Save current solution state internally for the refined mesh
109  this->S1.saveState();
110  }
111 
112  // Solve for (up to) nPredict steps without saving results on disk
113  for (size_t i = 0; i < nPredict && this->advanceStep(); i++)
114  if (!this->S1.solveStep(this->tp))
115  return 3;
116 
117  if (maxPred > 0 && this->S1.stopped())
118  break; // Terminated due to other user-criterion
119  else if (this->tp.finished())
120  break; // Stop time reached
121 
122  // Adapt the mesh based on current solution, and
123  // transfer the old solution variables onto the new mesh
124  IFEM::cout <<"\n >>> Paused for mesh refinement at time="
125  << this->tp.time.t << std::endl;
126  if ((lastRef = this->S1.adaptMesh(beta,minFrac,maxRef)))
127  this->dumpMesh(infile,false);
128 
129  refElms += lastRef; // Total number of refined elements
130  }
131 
132  if (lastRef < 0)
133  return 4; // Something went wrong, bailing
134  else if (refElms == 0 && !this->tp.finished() && !this->S1.stopped())
135  IFEM::cout <<" No refinement, resume from current state"<< std::endl;
136 
137  if (lastRef == 0 && maxPred > 0)
138  {
139  // The mesh is sufficiently refined at this state.
140  // Save the current results to VTF and HDF5, and continue.
141  // Note: We then miss the results from the preceding nPredict-1 steps.
142  if (!this->saveState(geoBlk,nBlock,refElms > 0))
143  return 2;
144  }
145  else
146  {
147  // Either the mesh was refined or we were doing prediction steps
148  // without staggering cycles. Now continue (at most) nForward steps
149  // without checking for further refinement at those steps.
150  this->tp.reset(tranStep);
151  IFEM::cout <<"\n >>> Resuming simulation from time="<< this->tp.time.t;
152  if (lastRef > 0)
153  {
154  IFEM::cout <<" on the new mesh."<< std::endl;
156  lastRLev = SIMSolver<T1>::restartAdm->getTimeLevel()+1;
157  }
158  else
159  {
160  IFEM::cout <<" on current mesh."<< std::endl;
161  this->S1.restoreState(); // Solution transfer was not performed
162  }
163 
164  // Solve for each time step up to final time,
165  // but only up to nForward steps on this mesh
166  this->S1.enableStaggering(true);
167  for (size_t j = 0; j < nForward && this->advanceStep(); j++)
168  if (!this->S1.solveStep(this->tp))
169  return 3;
170  else if (!this->saveState(geoBlk,nBlock,j < 1))
171  return 2;
172  }
173  }
174 
175  return this->dumpMesh(infile) ? 0 : 2;
176  }
177 
181  {
182  if (lastRLev < 0 && SIMSolver<T1>::restartAdm && this->S1.getRefined())
183  lastRLev = SIMSolver<T1>::restartAdm->getTimeLevel()+1;
184 
185  if (lastRLev >= 0)
186  data[this->S1.getName()+"::basis"] = std::to_string(lastRLev);
187  return this->SIMSolver<T1>::serialize(data);
188  }
189 
190 protected:
191  using SIMSolver<T1>::parse;
193  virtual bool parse(const tinyxml2::XMLElement* elem)
194  {
195  if (strcasecmp(elem->Value(),"adaptive"))
196  return this->SIMSolver<T1>::parse(elem);
197 
198  utl::getAttribute(elem,"start",aStart);
199  utl::getAttribute(elem,"dump",dumpGrid);
201 
202  const char* value = nullptr;
203  const tinyxml2::XMLElement* child = elem->FirstChildElement();
204  for (; child; child = child->NextSiblingElement())
205  if ((value = utl::getValue(child,"forward_steps")))
206  nForward = atoi(value);
207  else if ((value = utl::getValue(child,"predict_steps")))
208  nPredict = atoi(value);
209  else if ((value = utl::getValue(child,"beta")))
210  beta = atof(value);
211  else if ((value = utl::getValue(child,"nrefinements")))
212  maxRef = atoi(value);
213  else if ((value = utl::getValue(child,"max_prediction")))
214  maxPred = atoi(value);
215  else if ((value = utl::getValue(child,"min_frac")))
216  minFrac = atof(value);
217  else if (this->S1.getRefined())
218  continue; // ignore pre-refinement tags if mesh already refined
219  else if ((value = utl::getValue(child,"prerefine")))
220  {
221  if (utl::getAttribute(child,"levels",preRef))
222  this->S1.parsePreref(child);
223  else
224  preRef = atoi(value);
225  utl::getAttribute(child,"tol",refTol);
226  }
227  else if (!strcasecmp(child->Value(),"prerefine"))
228  {
229  utl::getAttribute(child,"levels",preRef);
230  utl::getAttribute(child,"tol",refTol);
231  }
232 
233  if (preRef > 0)
234  IFEM::cout <<"\tNumber of pre-refinement cycles: "<< preRef
235  <<"\n\tPre-refinement tolerance: "<< refTol <<"\n";
236  IFEM::cout <<"\tNumber of trial steps before refinement: "<< nPredict
237  <<"\n\tNumber of steps between each refinement: "<< nForward
238  <<"\n\tMax. number of trial cycles at refinement: "<< maxPred
239  <<"\n\tMax. number of refinements of an element: "<< maxRef
240  <<"\n\tRelative refinement threshold: "<< minFrac;
241  if (beta > 0.0)
242  IFEM::cout <<"\n\tPercentage of elements to refine: "<< beta;
243  if (aStart > 0.0)
244  IFEM::cout <<"\n\tMesh adaptation starting at time: "<< aStart;
245 
246  IFEM::cout << std::endl;
247  return true;
248  }
249 
251  bool dumpMesh(char* infile, bool done = true) const
252  {
253  if (dumpGrid < 1)
254  return true;
255  else if (dumpGrid == 1) // Dump the final grid only
256  return done ? this->S1.dumpMesh(strcat(strtok(infile,"."),".lr")) : true;
257  else if (done)
258  return true;
259 
260  // Dump grid after each refinement step
261  char fileName[128];
262  static int gridNo = 1;
263  sprintf(fileName,"%s_m%d.lr",strtok(infile,"."),++gridNo);
264  return this->S1.dumpMesh(fileName);
265  }
266 
267 private:
268  size_t nForward;
269  size_t nPredict;
270  int maxPred;
271  int maxRef;
272  int preRef;
273  double refTol;
274  double minFrac;
275  double beta;
276  double aStart;
277  char dumpGrid;
278  int lastRLev;
279 };
280 
281 #endif
SIM solver class template.
static const double T1[2]
1-point rule coordinates.
Definition: TriangleQuadrature.C:19
std::map< std::string, std::string > SerializeData
Convenience type.
Definition: HDF5Restart.h:34
static utl::LogStream cout
Combined standard out for parallel processes.
Definition: IFEM.h:62
T1 & S1
The actual solver.
Definition: SIMSolver.h:109
void printHeading(const char *heading)
Writes an application-specific heading, if provided.
Definition: SIMSolver.h:69
Template class for time-slab adaptive simulator drivers.
Definition: SIMSolverTS.h:31
int maxPred
Maximum number of prediction cycles.
Definition: SIMSolverTS.h:270
virtual int solveProblem(char *infile, const char *heading)
Solves the problem up to the final time.
Definition: SIMSolverTS.h:62
virtual ~SIMSolverTS()
Empty destructor.
Definition: SIMSolverTS.h:47
double refTol
Pre-refinement threshold.
Definition: SIMSolverTS.h:273
int maxRef
Number of refinements to allow for a single element.
Definition: SIMSolverTS.h:271
virtual bool read(const char *file)
Reads solver data from the specified input file.
Definition: SIMSolverTS.h:50
bool dumpMesh(char *infile, bool done=true) const
Dumps the refined LR-mesh to file.
Definition: SIMSolverTS.h:251
virtual bool serialize(HDF5Restart::SerializeData &data)
Serialize internal state for restarting purposes.
Definition: SIMSolverTS.h:180
int preRef
Number of pre-refinement cycles.
Definition: SIMSolverTS.h:272
virtual bool parse(const tinyxml2::XMLElement *elem)
Parses a data section from an XML element.
Definition: SIMSolverTS.h:193
size_t nForward
Number of steps to advance on new mesh.
Definition: SIMSolverTS.h:268
size_t nPredict
Number of steps to use for prediction.
Definition: SIMSolverTS.h:269
double aStart
Time from where to check for mesh adaptation.
Definition: SIMSolverTS.h:276
char dumpGrid
Option for mesh output: 0=none, 1=last, 2=all.
Definition: SIMSolverTS.h:277
double beta
Percentage of elements to refine.
Definition: SIMSolverTS.h:275
SIMSolverTS(T1 &s1)
The constructor forwards to the parent class constructor.
Definition: SIMSolverTS.h:34
int lastRLev
Restart time level for last mesh refinement.
Definition: SIMSolverTS.h:278
double minFrac
Element-level refinement threshold.
Definition: SIMSolverTS.h:274
Template class for transient simulator drivers.
Definition: SIMSolver.h:123
bool advanceStep()
Advances the time step one step forward.
Definition: SIMSolver.h:144
TimeStep tp
Time stepping information.
Definition: SIMSolver.h:304
virtual bool serialize(HDF5Restart::SerializeData &data)
Serialize internal state for restarting purposes.
Definition: SIMSolver.h:196
bool saveState(int &geoBlk, int &nBlock, bool newMesh=false, char *infile=nullptr, bool saveRes=true)
Saves geometry and results to VTF and HDF5 for current time step.
Definition: SIMSolver.h:229
virtual bool parse(char *keyw, std::istream &is)
Parses a data section from an input stream.
Definition: SIMSolver.h:210
virtual bool read(const char *fileName)
Reads model data from the specified input file *fileName.
Definition: SIMadmin.C:68
int step
Time step counter.
Definition: TimeStep.h:72
bool reset(int istep=0)
Resets the time step to the specified step.
Definition: TimeStep.C:203
bool finished() const
Returns true if the end of the simulation has been reached.
Definition: TimeStep.C:331
TimeDomain time
Time domain data.
Definition: TimeStep.h:74
const char * getValue(const tinyxml2::XMLNode *xml, const char *tag)
Returns the value (if any) of the specified XML-node.
Definition: Utilities.C:319
int getAttribute(const tinyxml2::XMLElement *xml, const char *att, bool &val)
Extracts a boolean attribute value from the specified XML-element.
Definition: Utilities.C:188
double t
Current time (or pseudo time, load parameter)
Definition: TimeDomain.h:24