LifeV
MultiscaleSolver.cpp
Go to the documentation of this file.
1 //@HEADER
2 /*
3 *******************************************************************************
4 
5  Copyright (C) 2004, 2005, 2007 EPFL, Politecnico di Milano, INRIA
6  Copyright (C) 2010 EPFL, Politecnico di Milano, Emory University
7 
8  This file is part of LifeV.
9 
10  LifeV is free software; you can redistribute it and/or modify
11  it under the terms of the GNU Lesser General Public License as published by
12  the Free Software Foundation, either version 3 of the License, or
13  (at your option) any later version.
14 
15  LifeV is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  Lesser General Public License for more details.
19 
20  You should have received a copy of the GNU Lesser General Public License
21  along with LifeV. If not, see <http://www.gnu.org/licenses/>.
22 
23 *******************************************************************************
24 */
25 //@HEADER
26 
27 /*!
28  * @file
29  * @brief File containing the Multiscale Solver
30  *
31  * @date 28-09-2009
32  * @author Cristiano Malossi <cristiano.malossi@epfl.ch>
33  *
34  * @maintainer Cristiano Malossi <cristiano.malossi@epfl.ch>
35  */
36 
37 #include <lifev/multiscale/framework/MultiscaleSolver.hpp>
38 
39 namespace LifeV
40 {
41 namespace Multiscale
42 {
43 
45 std::string multiscaleProblemFolder = "./";
46 std::string multiscaleProblemPrefix = "Multiscale";
49 bool multiscaleExitFlag = EXIT_SUCCESS;
50 
51 // ===================================================
52 // Constructors
53 // ===================================================
55  M_model (),
57  M_comm ()
58 {
59 
60 #ifdef HAVE_LIFEV_DEBUG
61  debugStream ( 8000 ) << "MultiscaleSolver::MultiscaleSolver() \n";
62 #endif
63 
64  //Define the maps of Multiscale objects
66 
67  //Register the available models
68  multiscaleModelFactory_Type::instance().registerProduct ( Multiscale, &createMultiscaleModelMultiscale );
69 #if defined(LIFEV_HAS_NAVIERSTOKES)
70  multiscaleModelFactory_Type::instance().registerProduct ( Fluid3D, &createMultiscaleModelFluid3D );
71 #endif
72 #if defined(LIFEV_HAS_FSI)
73  multiscaleModelFactory_Type::instance().registerProduct ( FSI3D, &createMultiscaleModelFSI3D );
74 #endif
75 #if defined(LIFEV_HAS_ONEDFSI)
76  multiscaleModelFactory_Type::instance().registerProduct ( FSI1D, &createMultiscaleModelFSI1D );
77 #endif
78 #if defined(LIFEV_HAS_ZERODIMENSIONAL)
79  multiscaleModelFactory_Type::instance().registerProduct ( Windkessel0D, &createMultiscaleModelWindkessel0D );
80  multiscaleModelFactory_Type::instance().registerProduct ( ZeroDimensional, &createMultiscaleModelZeroDimensional );
81 #endif
82 }
83 
84 // ===================================================
85 // Methods
86 // ===================================================
87 void
88 MultiscaleSolver::setupProblem ( const std::string& fileName, const std::string& problemFolder, const UInt& coresPerNode )
89 {
90 
91 #ifdef HAVE_LIFEV_DEBUG
92  debugStream ( 8000 ) << "MultiscaleSolver::setupData( fileName, problemFolder ) \n";
93 #endif
94 
95  // Load data file
96  GetPot dataFile ( fileName );
97 
98  // Define the folder containing the problem
99  multiscaleProblemFolder = problemFolder;
100 
101  // Define the number of cores on each node for the machine
102  multiscaleCoresPerNode = coresPerNode;
103 
104  // Define the step of the problem
105  if ( dataFile ( "Solver/Restart/Restart", false ) )
106  {
107  multiscaleProblemStep = dataFile ( "Solver/Restart/RestartFromStepNumber", 0 ) + 1;
108  }
109 
110  // Define the filename prefix for the multiscale output
111  multiscaleProblemPrefix = dataFile ( "Solver/Output/ProblemPrefix", "Multiscale" );
112 
113  // Define how many time step between two calls of the saveSolution() method
114  multiscaleSaveEachNTimeSteps = dataFile ( "Solver/Output/SaveEach", 1 );
115 
116  // Create the main model and set the communicator
117  M_model = multiscaleModelPtr_Type ( multiscaleModelFactory_Type::instance().createObject ( multiscaleModelsMap[ dataFile ( "Problem/ProblemType", "Multiscale" ) ], multiscaleModelsMap ) );
118 
119  M_model->setID ( 0 );
120  M_model->setCommunicator ( M_comm );
121 
122  // Setup data
123  M_globalData->readData ( dataFile );
124  M_model->setGlobalData ( M_globalData );
125  M_model->setupData ( dataFile ( "Problem/ProblemFile", "./MultiscaleDatabase/Models/NoModel" ) + ".dat" );
126 
127  // Setup Models
128  if ( multiscaleProblemStep )
129  {
131  }
132  M_model->setupModel();
133 
134  // Save the initial solution if it is the very first time step
135  if ( !multiscaleProblemStep )
136  {
137  M_model->saveSolution();
138  }
139 
140  // Move to the "true" first time-step (needed to perform initializations of the different models/couplings/algorithms)
141  M_globalData->dataTime()->updateTime();
142  M_globalData->dataTime()->setInitialTime ( M_globalData->dataTime()->time() );
143 }
144 
145 bool
146 MultiscaleSolver::solveProblem ( const Real& referenceSolution, const Real& tolerance )
147 {
148 
149 #ifdef HAVE_LIFEV_DEBUG
150  debugStream ( 8000 ) << "MultiscaleSolver::solveProblem() \n";
151 #endif
152 
153  // Chrono definitions
154  LifeChrono buildUpdateChrono;
155  LifeChrono solveChrono;
156  LifeChrono saveChrono;
157  LifeChrono updateSolutionChrono;
158  LifeChrono globalChrono;
159  Real totalSimulationTime (0);
160  Real timeStepTime (0);
161 
162  for ( ; M_globalData->dataTime()->canAdvance(); M_globalData->dataTime()->updateTime() )
163  {
164  // Global chrono start
165  globalChrono.start();
166 
167  if ( M_comm->MyPID() == 0 )
168  {
169  std::cout << std::endl;
170  std::cout << "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$" << std::endl;
171  std::cout << " MULTISCALE FRAMEWORK" << std::endl;
172  std::cout << " time = " << M_globalData->dataTime()->time() << " s;"
173  << " time step number = " << M_globalData->dataTime()->timeStepNumber() << std::endl;
174  std::cout << "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$" << std::endl << std::endl;
175  }
176 
177  // Build or Update System
178  buildUpdateChrono.start();
179  if ( M_globalData->dataTime()->isFirstTimeStep() )
180  {
181  M_model->buildModel();
182  }
183  else
184  {
185  M_model->updateModel();
186  }
187  buildUpdateChrono.stop();
188 
189  // Solve the model
190  solveChrono.start();
191  M_model->solveModel();
192  solveChrono.stop();
193 
194  // Update solution
195  updateSolutionChrono.start();
196  M_model->updateSolution();
197  updateSolutionChrono.stop();
198 
199  // Save the solution
200  saveChrono.start();
201  if ( M_globalData->dataTime()->timeStepNumber() % multiscaleSaveEachNTimeSteps == 0 || M_globalData->dataTime()->isLastTimeStep() )
202  {
203  M_model->saveSolution();
204  }
205  saveChrono.stop();
206 
207  // Global chrono stop
208  globalChrono.stop();
209 
210  // Compute time step time
211  timeStepTime = globalChrono.globalDiff ( *M_comm );
212 
213  // Updating total simulation time
214  totalSimulationTime += timeStepTime;
215 
216  if ( M_comm->MyPID() == 0 )
217  {
218  std::cout << " MS- Total iteration time: " << timeStepTime << " s" << std::endl;
219  std::cout << " MS- Total simulation time: " << totalSimulationTime << " s" << std::endl;
220  }
221 
222  // Save CPU time
223  saveCPUTime ( timeStepTime, buildUpdateChrono.globalDiff ( *M_comm ), solveChrono.globalDiff ( *M_comm ),
224  updateSolutionChrono.globalDiff ( *M_comm ), saveChrono.globalDiff ( *M_comm ) );
225  }
226 
227  // Numerical check of the last iteration solution (used for the night testsuite check)
228  Real computedSolution ( M_model->checkSolution() );
229  Real relativeError ( std::abs ( ( referenceSolution - computedSolution ) / referenceSolution ) );
230  if ( referenceSolution >= 0. && relativeError > tolerance )
231  multiscaleErrorCheck ( Solution, "Problem solution: " + number2string ( computedSolution ) +
232  " (Reference solution: " + number2string ( referenceSolution ) +
233  "; Relative error: " + number2string ( relativeError ) + ")\n", M_comm->MyPID() == 0 );
234 
235  return multiscaleExitFlag;
236 }
237 
238 void
240 {
241  if ( M_comm->MyPID() == 0 )
242  {
243  std::cout << std::endl << std::endl
244  << "=============== Multiscale Solver Information ===============" << std::endl << std::endl;
245 
246  std::cout << "Cores per node = " << multiscaleCoresPerNode << std::endl
247  << "Problem folder = " << multiscaleProblemFolder << std::endl
248  << "Problem prefix = " << multiscaleProblemPrefix << std::endl
249  << "Problem step = " << multiscaleProblemStep << std::endl
250  << "Save each = " << multiscaleSaveEachNTimeSteps << " time steps" << std::endl << std::endl;
251 
252  M_globalData->showMe();
253 
254  std::cout << std::endl << std::endl;
255  }
256 
257  M_model->showMe();
258 
259  if ( M_comm->MyPID() == 0 )
260  {
261  std::cout << "=============================================================" << std::endl << std::endl;
262  }
263 }
264 
265 
266 // ===================================================
267 // Private Methods
268 // ===================================================
269 void
270 MultiscaleSolver::saveCPUTime ( const Real& totalCPUTime, const Real& buildUpdateCPUTime, const Real& solveCPUTime,
271  const Real& updateSolutionCPUTime, const Real& saveCPUTime ) const
272 {
273  if ( M_comm->MyPID() == 0 )
274  {
275  std::ofstream outputFile;
276  outputFile << std::scientific << std::setprecision ( 15 );
277 
278  std::string filename = multiscaleProblemFolder + multiscaleProblemPrefix + "_CPUTime_" + number2string ( multiscaleProblemStep ) + ".mfile";
279 
280  if ( M_globalData->dataTime()->isFirstTimeStep() )
281  {
282  outputFile.open ( filename.c_str(), std::ios::trunc );
283  outputFile << "% ITERATION TIME TOTAL BUILD/UPDATE "
284  "SOLVE UPDATE SOLUTION SAVE" << std::endl;
285  }
286  else
287  {
288  outputFile.open ( filename.c_str(), std::ios::app );
289  }
290  outputFile << " " << number2string ( M_globalData->dataTime()->timeStepNumber() )
291  << " " << M_globalData->dataTime()->time()
292  << " " << totalCPUTime << " " << buildUpdateCPUTime << " " << solveCPUTime
293  << " " << updateSolutionCPUTime << " " << saveCPUTime << std::endl;
294  outputFile.close();
295  }
296 }
297 
298 void
300 {
301  // Initialize the iteration number
302  Int iterationNumber ( 0 );
303  Real initialTime ( 0. );
304 
305  if ( M_comm->MyPID() == 0 )
306  {
307  std::string fileName = multiscaleProblemFolder + multiscaleProblemPrefix + "_CPUTime_" + number2string ( multiscaleProblemStep - 1 ) + ".mfile";
308 
309  std::ifstream inputFile;
310  inputFile.open ( fileName.c_str(), std::ios::in );
311 
312  if ( inputFile.is_open() )
313  {
314  // Define some variables
315  std::string line;
316  std::vector<std::string> stringsVector;
317  std::vector< std::pair< Int, Real > > iterationAndTime;
318  std::pair< Int, Real > selectedIterationAndTime;
319 
320  // Read the first line with comments
321  std::getline ( inputFile, line, '\n' );
322 
323  // Read one-by-one all the other lines of the file
324  while ( std::getline ( inputFile, line, '\n' ) )
325  {
326  boost::split ( stringsVector, line, boost::is_any_of ( " " ), boost::token_compress_on );
327  if ( string2number ( stringsVector[7] ) > 0 ) // check if we have saved the data
328  {
329  iterationAndTime.push_back ( std::make_pair ( string2number ( stringsVector[1] ), string2number ( stringsVector[2] ) ) );
330  }
331  }
332 
333  // Close file
334  inputFile.close();
335 
336  // Find the closest time step
337  selectedIterationAndTime = iterationAndTime.front();
338  for ( std::vector< std::pair< Int, Real > >::const_iterator i = iterationAndTime.begin(); i < iterationAndTime.end() ; ++i )
339  if ( std::fabs ( selectedIterationAndTime.second - M_globalData->dataTime()->time() ) >= std::fabs ( (*i).second - M_globalData->dataTime()->time() ) )
340  {
341  selectedIterationAndTime = *i;
342  }
343 
344  // Select the iteration number
345  iterationNumber = selectedIterationAndTime.first;
346  initialTime = selectedIterationAndTime.second;
347  }
348  else
349  {
350  std::cerr << " !!! Error: cannot open file: " << fileName.c_str() << " !!!" << std::endl;
351  }
352  }
353 
354  // Share the values with the other processes
355  M_comm->Broadcast ( &iterationNumber, 1, 0 );
356  M_comm->Broadcast ( &initialTime, 1, 0 );
357 
358  // Set the iteration number and the initial time on the basis of the available saved data
359  M_globalData->dataTime()->setTimeStepNumber ( iterationNumber );
360  M_globalData->dataTime()->setInitialTime ( initialTime );
361  M_globalData->dataTime()->setTime ( initialTime );
362 }
363 
364 } // Namespace multiscale
365 } // Namespace LifeV
void showMe() const
Display some information about the Multiscale problem (should be called after setupProblem) ...
std::string multiscaleProblemFolder
int32_type Int
Generic integer data.
Definition: LifeV.hpp:188
void importIterationNumber()
Import iteration number from the CPU file.
void multiscaleMapsDefinition()
Define the map of the MS objects.
void updateInverseJacobian(const UInt &iQuadPt)
bool solveProblem(const Real &referenceSolution=-1., const Real &tolerance=1e-8)
Run the time-loop to solve the Multiscale problem.
void saveCPUTime(const Real &totalCPUTime, const Real &buildUpdateCPUTime, const Real &solveCPUTime, const Real &updateSolutionCPUTime, const Real &saveCPUTime) const
Save CPU time at each time step.
std::string multiscaleProblemPrefix
double Real
Generic real data.
Definition: LifeV.hpp:175
void setupProblem(const std::string &fileName, const std::string &problemName, const UInt &coresPerNode)
Setup the problem.
MultiscaleSolver - The Multiscale solver.
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191