fvbaseproblem.hh
Go to the documentation of this file.
1 // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 // vi: set et ts=4 sw=4 sts=4:
3 /*
4  Copyright (C) 2008-2013 by Andreas Lauser
5  Copyright (C) 2010-2011 by Markus Wolff
6 
7  This file is part of the Open Porous Media project (OPM).
8 
9  OPM is free software: you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 2 of the License, or
12  (at your option) any later version.
13 
14  OPM is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with OPM. If not, see <http://www.gnu.org/licenses/>.
21 */
27 #ifndef EWOMS_FV_BASE_PROBLEM_HH
28 #define EWOMS_FV_BASE_PROBLEM_HH
29 
30 #include "fvbaseproperties.hh"
31 
33 #include <ewoms/io/restart.hh>
34 #include <dune/common/fvector.hh>
35 
36 #include <iostream>
37 #include <limits>
38 #include <string>
39 
40 namespace Ewoms {
41 
51 template<class TypeTag>
53 {
54 private:
55  typedef typename GET_PROP_TYPE(TypeTag, Problem) Implementation;
56  typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
57 
58  static const int vtkOutputFormat = GET_PROP_VALUE(TypeTag, VtkOutputFormat);
60 
61  typedef typename GET_PROP_TYPE(TypeTag, Model) Model;
62  typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
63  typedef typename GET_PROP_TYPE(TypeTag, Simulator) Simulator;
64  typedef typename GET_PROP_TYPE(TypeTag, ThreadManager) ThreadManager;
65  typedef typename GET_PROP_TYPE(TypeTag, NewtonMethod) NewtonMethod;
66 
67  typedef typename GET_PROP_TYPE(TypeTag, VertexMapper) VertexMapper;
68  typedef typename GET_PROP_TYPE(TypeTag, ElementMapper) ElementMapper;
69 
70  typedef typename GET_PROP_TYPE(TypeTag, RateVector) RateVector;
71  typedef typename GET_PROP_TYPE(TypeTag, BoundaryRateVector) BoundaryRateVector;
72  typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
73  typedef typename GET_PROP_TYPE(TypeTag, Constraints) Constraints;
74 
75  enum {
76  dim = GridView::dimension,
77  dimWorld = GridView::dimensionworld
78  };
79 
80  typedef typename GridView::template Codim<0>::Entity Element;
81  typedef typename GridView::template Codim<dim>::Entity Vertex;
82  typedef typename GridView::template Codim<dim>::Iterator VertexIterator;
83 
84  typedef typename GridView::Grid::ctype CoordScalar;
85  typedef Dune::FieldVector<CoordScalar, dimWorld> GlobalPosition;
86 
87  // copying a problem is not a good idea
88  FvBaseProblem(const FvBaseProblem &) = delete;
89 
90 public:
99  : gridView_(simulator.gridView())
100  , elementMapper_(gridView_)
101  , vertexMapper_(gridView_)
102  , boundingBoxMin_(std::numeric_limits<double>::max())
103  , boundingBoxMax_(-std::numeric_limits<double>::max())
104  , simulator_(simulator)
105  , defaultVtkWriter_(0)
106  {
107  // calculate the bounding box of the local partition of the grid view
108  VertexIterator vIt = gridView_.template begin<dim>();
109  const VertexIterator vEndIt = gridView_.template end<dim>();
110  for (; vIt!=vEndIt; ++vIt) {
111  for (int i=0; i<dim; i++) {
112  boundingBoxMin_[i] = std::min(boundingBoxMin_[i], vIt->geometry().corner(0)[i]);
113  boundingBoxMax_[i] = std::max(boundingBoxMax_[i], vIt->geometry().corner(0)[i]);
114  }
115  }
116 
117  // communicate to get the bounding box of the whole domain
118  for (int i = 0; i < dim; ++i) {
119  boundingBoxMin_[i] = gridView_.comm().min(boundingBoxMin_[i]);
120  boundingBoxMax_[i] = gridView_.comm().max(boundingBoxMax_[i]);
121  }
122 
123  if (enableVtkOutput_())
124  defaultVtkWriter_ = new VtkMultiWriter(gridView_, asImp_().name());
125  }
126 
131  static void registerParameters()
132  {
133  Model::registerParameters();
134  EWOMS_REGISTER_PARAM(TypeTag, Scalar, MaxTimeStepSize,
135  "The maximum size to which all time steps are limited to [s]");
136  EWOMS_REGISTER_PARAM(TypeTag, Scalar, MinTimeStepSize,
137  "The minimum size to which all time steps are limited to [s]");
138  EWOMS_REGISTER_PARAM(TypeTag, unsigned, MaxTimeStepDivisions,
139  "The maximum number of divisions by two of the timestep size "
140  "before the simulation bails out");
141  }
142 
148  void finishInit()
149  {
150  linearizeTime_ = 0.0;
151  solveTime_ = 0.0;
152  updateTime_ = 0.0;
153  }
154 
159  Scalar solveTime() const
160  { return solveTime_; }
161 
166  Scalar updateTime() const
167  { return updateTime_; }
168 
178  template <class Context>
179  void boundary(BoundaryRateVector &values,
180  const Context &context,
181  int spaceIdx, int timeIdx) const
182  { OPM_THROW(std::logic_error, "Problem does not provide a boundary() method"); }
183 
194  template <class Context>
195  void constraints(Constraints &constraints,
196  const Context &context,
197  int spaceIdx, int timeIdx) const
198  { OPM_THROW(std::logic_error, "Problem does not provide a constraints() method"); }
199 
212  template <class Context>
213  void source(RateVector &rate,
214  const Context &context,
215  int spaceIdx, int timeIdx) const
216  { OPM_THROW(std::logic_error, "Problem does not provide a source() method"); }
217 
228  template <class Context>
229  void initial(PrimaryVariables &values,
230  const Context &context,
231  int spaceIdx, int timeIdx) const
232  { OPM_THROW(std::logic_error, "Problem does not provide a initial() method"); }
233 
249  template <class Context>
250  Scalar extrusionFactor(const Context &context,
251  int spaceIdx, int timeIdx) const
252  { return asImp_().extrusionFactor(); }
253 
254  Scalar extrusionFactor() const
255  { return 1.0; }
256 
262  {}
263 
268  { }
269 
274  { }
275 
280  { }
281 
286  { }
287 
294  void endTimeStep()
295  { }
296 
302  void endEpisode()
303  {
304  std::cerr << "The end of episode " << simulator().episodeIndex() + 1 << " has been "
305  << "reached, but the problem does not override the endEpisode() method. "
306  << "Doing nothing!\n";
307  }
308 
312  void finalize()
313  {
314  const auto& timer = simulator().timer();
315  Scalar simulationTime = timer.realTimeElapsed();
316  Scalar setupTime = simulator().setupTime();
317  Scalar prePostProcessTime = simulator().prePostProcessTime();
318  Scalar localCpuTime = timer.cpuTimeElapsed();
319  Scalar globalCpuTime = timer.globalCpuTimeElapsed();
320  Scalar totalWriteTime = simulator().totalWriteTime();
321  int numProcesses = this->gridView().comm().size();
322  int threadsPerProcess = ThreadManager::maxThreads();
323  if (gridView().comm().rank() == 0) {
324  std::cout << std::setprecision(3)
325  << "Simulation of problem '" << asImp_().name() << "' finished.\n"
326  << "\n"
327  << "------------------------ Timing receipt ------------------------\n"
328  << "Setup time: "<< Simulator::humanReadableTime(setupTime, /*isAmendment=*/false)
329  << ", " << setupTime/(simulationTime + setupTime)*100 << "%\n"
330  << "Simulation time: "<< Simulator::humanReadableTime(simulationTime, /*isAmendment=*/false)
331  << ", " << simulationTime/(simulationTime + setupTime)*100 << "%\n"
332  << " Linearization time: "<< Simulator::humanReadableTime(linearizeTime_, /*isAmendment=*/false)
333  << ", " << linearizeTime_/simulationTime*100 << "%\n"
334  << " Linear solve time: " << Simulator::humanReadableTime(solveTime_, /*isAmendment=*/false)
335  << ", " << solveTime_/simulationTime*100 << "%\n"
336  << " Newton update time: " << Simulator::humanReadableTime(updateTime_, /*isAmendment=*/false)
337  << ", " << updateTime_/simulationTime*100 << "%\n"
338  << " Pre/postprocess time: " << Simulator::humanReadableTime(prePostProcessTime, /*isAmendment=*/false)
339  << ", " << prePostProcessTime/simulationTime*100 << "%\n"
340  << " Output write time: " << Simulator::humanReadableTime(totalWriteTime, /*isAmendment=*/false)
341  << ", " << totalWriteTime/simulationTime*100 << "%\n"
342  << "First process' simulation CPU time: " << Simulator::humanReadableTime(localCpuTime, /*isAmendment=*/false) << "\n"
343  << "Number of processes: " << numProcesses << "\n"
344  << "Threads per processes: " << threadsPerProcess << "\n"
345  << "Total CPU time: " << Simulator::humanReadableTime(globalCpuTime, /*isAmendment=*/false) << "\n"
346  << "\n"
347  << "Note 1: If not stated otherwise, all times are wall clock times\n"
348  << "Note 2: Taxes and administrative overhead are "
349  << (simulationTime - (linearizeTime_+solveTime_+updateTime_+prePostProcessTime+totalWriteTime))/simulationTime*100
350  << "%\n"
351  << "\n"
352  << "Our simulation hours are 24/7. Thank you for choosing us.\n"
353  << "----------------------------------------------------------------\n"
354  << "\n"
355  << std::flush;
356  }
357  }
358 
364  {
365  int maxFails = EWOMS_GET_PARAM(TypeTag, unsigned, MaxTimeStepDivisions);
366  Scalar minTimeStepSize = EWOMS_GET_PARAM(TypeTag, Scalar, MinTimeStepSize);
367 
368  // if the time step size of the simulator is smaller than
369  // the specified minimum size and we're not going to finish
370  // the simulation or an episode, try with the minimum size.
371  if (simulator().timeStepSize() < minTimeStepSize &&
372  !simulator().episodeWillBeOver() &&
373  !simulator().willBeFinished())
374  {
375  simulator().setTimeStepSize(minTimeStepSize);
376  }
377 
378  for (int i = 0; i < maxFails; ++i) {
379  bool converged = model().update(newtonMethod());
380 
381  linearizeTime_ += newtonMethod().linearizeTime();
382  solveTime_ += newtonMethod().solveTime();
383  updateTime_ += newtonMethod().updateTime();
384 
385  if (converged)
386  return;
387 
388  Scalar dt = simulator().timeStepSize();
389  Scalar nextDt = dt / 2;
390  if (nextDt < minTimeStepSize)
391  break; // give up: we can't make the time step smaller anymore!
392  simulator().setTimeStepSize(nextDt);
393 
394  // update failed
395  if (gridView().comm().rank() == 0)
396  std::cout << "Newton solver did not converge with "
397  << "dt=" << dt << " seconds. Retrying with time step of "
398  << nextDt << " seconds\n" << std::flush;
399  }
400 
401  OPM_THROW(std::runtime_error,
402  "Newton solver didn't converge after "
403  << maxFails << " time-step divisions. dt="
404  << simulator().timeStepSize());
405  }
406 
413  {
414  Scalar dtNext = std::min(EWOMS_GET_PARAM(TypeTag, Scalar, MaxTimeStepSize),
415  newtonMethod().suggestTimeStepSize(simulator().timeStepSize()));
416 
417  if (dtNext < simulator().maxTimeStepSize()
418  && simulator().maxTimeStepSize() < dtNext*2)
419  {
420  dtNext = simulator().maxTimeStepSize()/2 * 1.01;
421  }
422 
423  return dtNext;
424  }
425 
435  {
436  return simulator().timeStepIndex() > 0 &&
437  (simulator().timeStepIndex() % 10 == 0);
438  }
439 
448  bool shouldWriteOutput() const
449  { return true; }
450 
457  { model().advanceTimeLevel(); }
458 
466  std::string name() const
467  { return "sim"; }
468 
472  const GridView &gridView() const
473  { return gridView_; }
474 
479  const GlobalPosition &boundingBoxMin() const
480  { return boundingBoxMin_; }
481 
486  const GlobalPosition &boundingBoxMax() const
487  { return boundingBoxMax_; }
488 
492  const VertexMapper &vertexMapper() const
493  { return vertexMapper_; }
494 
498  const ElementMapper &elementMapper() const
499  { return elementMapper_; }
500 
504  Simulator &simulator()
505  { return simulator_; }
506 
510  const Simulator &simulator() const
511  { return simulator_; }
512 
516  Model &model()
517  { return simulator_.model(); }
518 
522  const Model &model() const
523  { return simulator_.model(); }
524 
528  NewtonMethod &newtonMethod()
529  { return model().newtonMethod(); }
530 
534  const NewtonMethod &newtonMethod() const
535  { return model().newtonMethod(); }
536  // \}
537 
551  template <class Restarter>
552  void serialize(Restarter &res)
553  {
554  if (enableVtkOutput_())
555  defaultVtkWriter_->serialize(res);
556  }
557 
568  template <class Restarter>
569  void deserialize(Restarter &res)
570  {
571  if (enableVtkOutput_())
572  defaultVtkWriter_->deserialize(res);
573  }
574 
581  void writeOutput(bool verbose = true)
582  {
583  if (verbose && gridView().comm().rank() == 0)
584  std::cout << "Writing visualization results for the current time step.\n"
585  << std::flush;
586 
587  // calculate the time _after_ the time was updated
588  Scalar t = simulator().time() + simulator().timeStepSize();
589 
590  if (enableVtkOutput_())
591  defaultVtkWriter_->beginWrite(t);
592 
593  model().prepareOutputFields();
594 
595  if (enableVtkOutput_()) {
596  model().appendOutputFields(*defaultVtkWriter_);
597  defaultVtkWriter_->endWrite();
598  }
599  }
600 
605  VtkMultiWriter &defaultVtkWriter() const
606  { return defaultVtkWriter_; }
607 
608 private:
609  bool enableVtkOutput_() const
610  { return EWOMS_GET_PARAM(TypeTag, bool, EnableVtkOutput); }
611 
613  Implementation &asImp_()
614  { return *static_cast<Implementation *>(this); }
615 
617  const Implementation &asImp_() const
618  { return *static_cast<const Implementation *>(this); }
619 
620  // Grid management stuff
621  const GridView gridView_;
622  ElementMapper elementMapper_;
623  VertexMapper vertexMapper_;
624  GlobalPosition boundingBoxMin_;
625  GlobalPosition boundingBoxMax_;
626 
627  // Attributes required for the actual simulation
628  Simulator &simulator_;
629  mutable VtkMultiWriter *defaultVtkWriter_;
630 
631  // CPU time keeping
632  Scalar linearizeTime_;
633  Scalar solveTime_;
634  Scalar updateTime_;
635 };
636 
637 } // namespace Ewoms
638 
639 #endif
Load or save a state of a problem to/from the harddisk.
FvBaseProblem(Simulator &simulator)
Definition: fvbaseproblem.hh:98
void initial(PrimaryVariables &values, const Context &context, int spaceIdx, int timeIdx) const
Evaluate the initial value for a control volume.
Definition: fvbaseproblem.hh:229
const Model & model() const
Returns numerical model used for the problem.
Definition: fvbaseproblem.hh:522
void endEpisode()
Called when the end of an simulation episode is reached.
Definition: fvbaseproblem.hh:302
bool shouldWriteRestartFile() const
Returns true if a restart file should be written to disk.
Definition: fvbaseproblem.hh:434
Scalar timeStepSize() const
Returns the time step length so that we don't miss the beginning of the next episode or cross the en...
Definition: simulator.hh:296
bool shouldWriteOutput() const
Returns true if the current solution should be written to disk (i.e. as a VTK file) ...
Definition: fvbaseproblem.hh:448
void deserialize(Restarter &res)
This method restores the complete state of the problem from disk.
Definition: fvbaseproblem.hh:569
Scalar prePostProcessTime() const
Definition: simulator.hh:620
void endTimeStep()
Called by the simulator after each time integration.
Definition: fvbaseproblem.hh:294
void initialSolutionApplied()
Callback used by the model to indicate that the initial solution has been determined for all degrees ...
Definition: fvbaseproblem.hh:261
const Ewoms::Timer & timer() const
Returns the current wall time required by actually running the simulation.
Definition: simulator.hh:262
Scalar solveTime() const
Returns the wall time spend so far for solving the linear systems for all iterations of the current t...
Definition: newtonmethod.hh:472
Declare the properties used by the infrastructure code of the finite volume discretizations.
Scalar nextTimeStepSize()
Called by Ewoms::Simulator whenever a solution for a time step has been computed and the simulation t...
Definition: fvbaseproblem.hh:412
The multi-dimensional Newton method.
Definition: newtonmethod.hh:54
void beginEpisode()
Called at the beginning of an simulation episode.
Definition: fvbaseproblem.hh:267
#define GET_PROP_VALUE(TypeTag, PropTagName)
Access the value attribute of a property for a type tag.
Definition: propertysystem.hh:468
VtkMultiWriter & defaultVtkWriter() const
Method to retrieve the VTK writer which should be used to write the default ouput after each time ste...
Definition: fvbaseproblem.hh:605
void serialize(Restarter &res)
Write the multi-writer's state to a restart file.
Definition: vtkmultiwriter.hh:377
void writeOutput(bool verbose=true)
Write the relevant secondary variables of the current solution into an VTK output file...
Definition: fvbaseproblem.hh:581
Simulator & simulator()
Returns Simulator object used by the simulation.
Definition: fvbaseproblem.hh:504
Scalar extrusionFactor() const
Definition: fvbaseproblem.hh:254
void serialize(Restarter &res)
This method writes the complete state of the problem to the harddisk.
Definition: fvbaseproblem.hh:552
void source(RateVector &rate, const Context &context, int spaceIdx, int timeIdx) const
Evaluate the source term for all phases within a given sub-control-volume.
Definition: fvbaseproblem.hh:213
void beginIteration()
Called by the simulator before each Newton-Raphson iteration.
Definition: fvbaseproblem.hh:279
const GridView & gridView() const
The GridView which used by the problem.
Definition: fvbaseproblem.hh:472
Simplifies multi-threaded capabilities.
Definition: threadmanager.hh:48
Scalar solveTime() const
Returns the total wall time spend on solving the system [s].
Definition: fvbaseproblem.hh:159
Base class for all problems which use a finite volume spatial discretization.
Definition: fvbaseproblem.hh:52
STL namespace.
const VertexMapper & vertexMapper() const
Returns the mapper for vertices to indices.
Definition: fvbaseproblem.hh:492
int timeStepIndex() const
Returns number of time steps which have been executed since the beginning of the simulation.
Definition: simulator.hh:309
Scalar extrusionFactor(const Context &context, int spaceIdx, int timeIdx) const
Return how much the domain is extruded at a given sub-control volume.
Definition: fvbaseproblem.hh:250
void setTimeStepSize(Scalar timeStepSize)
Set the current time step size to a given value.
Definition: simulator.hh:288
void advanceTimeLevel()
Called by the simulator after everything which can be done about the current time step is finished an...
Definition: fvbaseproblem.hh:456
Scalar totalWriteTime() const
Returns total wall clock time required to write the visualization and restart files over the course o...
Definition: simulator.hh:269
Simplifies writing multi-file VTK datasets.
Manages the initializing and running of time dependent problems.
Definition: simulator.hh:73
const Simulator & simulator() const
Returns Simulator object used by the simulation.
Definition: fvbaseproblem.hh:510
Definition: baseauxiliarymodule.hh:35
Model & model()
Returns numerical model used for the problem.
Definition: fvbaseproblem.hh:516
Scalar maxTimeStepSize() const
Aligns the time step size to the episode boundary and to the end time of the simulation.
Definition: simulator.hh:351
void boundary(BoundaryRateVector &values, const Context &context, int spaceIdx, int timeIdx) const
Evaluate the boundary conditions for a boundary segment.
Definition: fvbaseproblem.hh:179
static int maxThreads()
Return the maximum number of threads of the current process.
Definition: threadmanager.hh:117
const GlobalPosition & boundingBoxMin() const
The coordinate of the corner of the GridView's bounding box with the smallest values.
Definition: fvbaseproblem.hh:479
#define EWOMS_REGISTER_PARAM(TypeTag, ParamType, ParamName, Description)
Register a run-time parameter.
Definition: parametersystem.hh:64
std::string name() const
The problem name.
Definition: fvbaseproblem.hh:466
void beginWrite(double t)
Called whenever a new time step must be written.
Definition: vtkmultiwriter.hh:128
void timeIntegration()
Called by Ewoms::Simulator in order to do a time integration on the model.
Definition: fvbaseproblem.hh:363
Model & model()
Return the physical model used in the simulation.
Definition: simulator.hh:176
static std::string humanReadableTime(Scalar timeInSeconds, bool isAmendment=true)
Given a time step size in seconds, return it in a format which is more easily parsable by humans...
Definition: simulator.hh:632
void endIteration()
Called by the simulator after each Newton-Raphson update.
Definition: fvbaseproblem.hh:285
Scalar time() const
Return the number of seconds of simulated time which have elapsed since the start time...
Definition: simulator.hh:241
void finishInit()
Called by the Ewoms::Simulator in order to initialize the problem.
Definition: fvbaseproblem.hh:148
Scalar updateTime() const
Returns the wall time spend so far for updating the iterative solutions of the non-linear system for ...
Definition: newtonmethod.hh:480
NewtonMethod & newtonMethod()
Returns object which implements the Newton method.
Definition: fvbaseproblem.hh:528
const NewtonMethod & newtonMethod() const
Returns object which implements the Newton method.
Definition: fvbaseproblem.hh:534
void finalize()
Called after the simulation has been run sucessfully.
Definition: fvbaseproblem.hh:312
void constraints(Constraints &constraints, const Context &context, int spaceIdx, int timeIdx) const
Evaluate the constraints for a control volume.
Definition: fvbaseproblem.hh:195
void beginTimeStep()
Called by the simulator before each time integration.
Definition: fvbaseproblem.hh:273
const GlobalPosition & boundingBoxMax() const
The coordinate of the corner of the GridView's bounding box with the largest values.
Definition: fvbaseproblem.hh:486
Scalar updateTime() const
Returns the total wall time spend on updating the iterative solutions [s].
Definition: fvbaseproblem.hh:166
double realTimeElapsed() const
Return the real time [s] elapsed.
Definition: timer.hh:100
void deserialize(Restarter &res)
Read the multi-writer's state from a restart file.
Definition: vtkmultiwriter.hh:411
static void registerParameters()
Registers all available parameters for the problem and the model.
Definition: fvbaseproblem.hh:131
int episodeIndex() const
Returns the index of the current episode.
Definition: simulator.hh:400
double setupTime() const
Returns the wall time required by setting up and initializing the simulation.
Definition: simulator.hh:275
const ElementMapper & elementMapper() const
Returns the mapper for elements to indices.
Definition: fvbaseproblem.hh:498
void endWrite(bool onlyDiscard=false)
Finalizes the current writer.
Definition: vtkmultiwriter.hh:339
Simplifies writing multi-file VTK datasets.
Definition: vtkmultiwriter.hh:61
Scalar linearizeTime() const
Returns the wall time spend so far for linearizing the non-linear system for all iterations of the cu...
Definition: newtonmethod.hh:464
#define EWOMS_GET_PARAM(TypeTag, ParamType, ParamName)
Retrieve a runtime parameter.
Definition: parametersystem.hh:95