LifeV
lifev/electrophysiology/testsuite/test_restart/main.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 Test to restart a simulation from an hdf5 exported solution
30 
31  @date 03 - 2014
32  @author Simone Rossi <simone.rossi@epfl.ch>
33 
34  @contributor
35  @mantainer Simone Rossi <simone.rossi@epfl.ch>
36  */
37 
38 // Tell the compiler to ignore specific kind of warnings:
39 #pragma GCC diagnostic ignored "-Wunused-variable"
40 #pragma GCC diagnostic ignored "-Wunused-parameter"
41 
42 #include <Epetra_ConfigDefs.h>
43 #ifdef EPETRA_MPI
44 #include <mpi.h>
45 #include <Epetra_MpiComm.h>
46 #else
47 #include <Epetra_SerialComm.h>
48 #endif
49 
50 //Tell the compiler to restore the warning previously silented
51 #pragma GCC diagnostic warning "-Wunused-variable"
52 #pragma GCC diagnostic warning "-Wunused-parameter"
53 
54 //We use this to transform the mesh from [0,1]x[0,1] to [0,5]x[0,5]
55 #include <lifev/core/mesh/MeshUtility.hpp>
56 
57 //We will use the ETAMonodomainSolver
58 #include <lifev/electrophysiology/solver/ElectroETAMonodomainSolver.hpp>
59 
60 //We will use the Aliev Panfilov model for simplicity
61 #include <lifev/electrophysiology/solver/IonicModels/IonicAlievPanfilov.hpp>
62 
63 //Include LifeV
64 #include <lifev/core/LifeV.hpp>
65 
66 //this is useful to save the out in a separate folder
67 #include <sys/stat.h>
68 
69 using namespace LifeV;
70 
71 //Forward declaration of the function defining the fiber direction.
72 //See the end of the file for the implementation
73 Real cut (const Real& /*t*/, const Real& /*x*/, const Real& y, const Real& /*z*/, const ID& /*i*/);
74 Real initialCondition ( const Real& /*t*/, const Real& x, const Real& /*y*/, const Real& /*z*/, const ID& /*id*/);
75 
76 //Forward declaration of the function defining the fiber direction.
77 //See the end of the file for the implementation
78 Int main ( Int argc, char** argv )
79 {
80 
81  //! Initializing Epetra communicator
82  MPI_Init (&argc, &argv);
83  std::shared_ptr<Epetra_Comm> Comm ( new Epetra_MpiComm (MPI_COMM_WORLD) );
84  if ( Comm->MyPID() == 0 )
85  {
86  std::cout << "% using MPI" << std::endl;
87  }
88 
89  //*********************************************//
90  // creating output folder
91  //*********************************************//
92 
93  GetPot commandLine ( argc, argv );
94  std::string problemFolder = commandLine.follow ( "Output", 2, "-o", "--output" );
95  // Create the problem folder
96  if ( problemFolder.compare ("./") )
97  {
98  problemFolder += "/";
99 
100  if ( Comm->MyPID() == 0 )
101  {
102  mkdir ( problemFolder.c_str(), 0777 );
103  }
104  }
105 
106  //********************************************//
107  // Some typedefs //
108  //********************************************//
109 
110  typedef RegionMesh<LinearTetra> mesh_Type;
111 
112  typedef std::function < Real (const Real& /*t*/,
113  const Real & x,
114  const Real & y,
115  const Real& /*z*/,
116  const ID& /*i*/ ) > function_Type;
117 
118  typedef ElectroETAMonodomainSolver< mesh_Type, IonicAlievPanfilov > monodomainSolver_Type;
119  typedef std::shared_ptr< monodomainSolver_Type > monodomainSolverPtr_Type;
120 
121  typedef VectorEpetra vector_Type;
122  typedef std::shared_ptr<vector_Type> vectorPtr_Type;
123 
124  //********************************************//
125  // Import parameters from an xml list. Use //
126  // Teuchos to create a list from a given file //
127  // in the execution directory. //
128  //********************************************//
129 
130  if ( Comm->MyPID() == 0 )
131  {
132  std::cout << "Importing parameters list...";
133  }
134  Teuchos::ParameterList monodomainList = * ( Teuchos::getParametersFromXmlFile ( "MonodomainSolverParamList.xml" ) );
135  if ( Comm->MyPID() == 0 )
136  {
137  std::cout << " Done!" << std::endl;
138  }
139 
140  //********************************************//
141  // Creates a new model object representing the//
142  // model from Aliev and Panfilov 1996. The //
143  // model input are the parameters. Pass the //
144  // parameter list in the constructor //
145  //********************************************//
146  if ( Comm->MyPID() == 0 )
147  {
148  std::cout << "Building Constructor for Minimal Model with parameters ... ";
149  }
150  std::shared_ptr<IonicAlievPanfilov> model ( new IonicAlievPanfilov() );
151  if ( Comm->MyPID() == 0 )
152  {
153  std::cout << " Done!" << std::endl;
154  }
155 
156 
157  //********************************************//
158  // In the parameter list we need to specify //
159  // the mesh name and the mesh path. //
160  //********************************************//
161  std::string meshName = monodomainList.get ("mesh_name", "lid16.mesh");
162  std::string meshPath = monodomainList.get ("mesh_path", "./");
163 
164  //********************************************//
165  // We need the GetPot datafile for to setup //
166  // the preconditioner. //
167  //********************************************//
168 
169  GetPot dataFile (argc, argv);
170 
171  //********************************************//
172  // We create the monodomain solver //
173  //********************************************//
174  if ( Comm->MyPID() == 0 )
175  {
176  std::cout << "Building Monodomain Solvers... ";
177  }
178 
179  monodomainSolverPtr_Type monodomain ( new monodomainSolver_Type ( meshName, meshPath, dataFile, model ) );
180  if ( Comm->MyPID() == 0 )
181  {
182  std::cout << " Splitting solver done... ";
183  }
184 
185  //********************************************//
186  // We transform the mesh to get a larger //
187  // domain. //
188  //********************************************//
189  std::vector<Real> scale (3, 1.0);
190  scale[2] = 5.0;
191  scale[1] = 5.0;
192  std::vector<Real> rotate (3, 0.0);
193  std::vector<Real> translate (3, 0.0);
194  MeshUtility::MeshTransformer<mesh_Type> transformer (* (monodomain -> localMeshPtr() ) );
195  transformer.transformMesh (scale, rotate, translate);
196 
197 
198  //********************************************//
199  // Computing the norm of the precomputed at //
200  // final time //
201  //********************************************//
202  std::string prefix = monodomainList.get ("importPrefix", "ciccia");
203  std::string dir = monodomainList.get ("importDir", "./");
204  monodomain -> importSolution (prefix, dir, 100.0);
205  Real solutionNorm = monodomain -> potentialPtr() -> norm2();
206 
207  //********************************************//
208  // Setting up the initial condition form //
209  // importing the old solution //
210  //********************************************//
211 
212  if ( Comm->MyPID() == 0 )
213  {
214  std::cout << "\nInitializing potential: " ;
215  }
216 
217  Real initialTime = monodomainList.get ("importTime", 0.0);
218  monodomain -> importSolution (prefix, dir, initialTime);
219 
220  if ( Comm->MyPID() == 0 )
221  {
222  std::cout << "Done! \n" ;
223  }
224 
225  //********************************************//
226  // Setting up the monodomain solver //
227  //********************************************//
228 
229  monodomain -> setParameters ( monodomainList );
230 
231  //********************************************//
232  // fiber direction //
233  //********************************************//
234 
235  if ( Comm->MyPID() == 0 )
236  {
237  std::cout << "\nImporting fibers: " ;
238  }
239 
240  VectorSmall<3> fibers;
241  fibers[0] = monodomainList.get ("fibers_X", 0.0);
242  fibers[1] = monodomainList.get ("fibers_Y", 0.0);
243  fibers[2] = monodomainList.get ("fibers_Z", 1.0);
244 
245  monodomain -> setupFibers (fibers);
246  if ( Comm->MyPID() == 0 )
247  {
248  std::cout << "Done! \n" ;
249  }
250 
251  //********************************************//
252  // Saving Fiber direction to file //
253  //********************************************//
254 
255  monodomain -> exportFiberDirection (problemFolder);
256 
257  //********************************************//
258  // Create the global matrix: mass + stiffness //
259  //********************************************//
260 
261  if ( Comm->MyPID() == 0 )
262  {
263  std::cout << "\nSetup operators: " ;
264  }
265  monodomain -> setupLumpedMassMatrix();
266  monodomain -> setupStiffnessMatrix();
267  monodomain -> setupGlobalMatrix();
268  if ( Comm->MyPID() == 0 )
269  {
270  std::cout << "Done! \n" ;
271  }
272 
273  //********************************************//
274  // Creating exporters to save the solution //
275  //********************************************//
276 
277  ExporterHDF5< RegionMesh <LinearTetra> > exporter;
278  monodomain -> setupExporter ( exporter, monodomainList.get ("OutputFile", "Solution"), problemFolder );
279  monodomain -> exportSolution ( exporter, initialTime);
280 
281  //********************************************//
282  // Solving the system //
283  //********************************************//
284 
285  if ( Comm->MyPID() == 0 )
286  {
287  std::cout << "\nstart solving: " ;
288  }
289 
290  Real dt = monodomain -> timeStep();
291  Real cutTime = monodomainList.get ("cutTime", 150.0);
292  //Uncomment for proper use
293  Real TF = monodomain -> endTime();
294  //Real TF = 100.0;
295  Int iter = monodomainList.get ("saveStep", 1.0) / dt;
296 
297 
298  //********************************************//
299  // Defining the cut for generating the spiral //
300  //********************************************//
301  vectorPtr_Type spiral ( new vector_Type ( ( monodomain -> globalSolution().at (0) ) -> map() ) );
302  function_Type f = &cut;
303  monodomain -> feSpacePtr() -> interpolate (
304  static_cast<FESpace<RegionMesh<LinearTetra>, MapEpetra>::function_Type> (f),
305  *spiral, 0.0);
306 
307 
308  //********************************************//
309  // Loop over time solving with L-ICI //
310  //********************************************//
311  int loop = 0;
312  for (Real t = initialTime; t < (TF - dt * 1e-4);) // the -dt*1e-4 is needed or you do an additional iteration
313  {
314  loop++;
315  t += dt;
316 
317  if (t >= cutTime && t <= cutTime + dt)
318  {
319  * (monodomain -> potentialPtr() ) *= *spiral;
320  }
321  monodomain -> solveOneStepGatingVariablesFE();
322  monodomain -> solveOneICIStep();
323  if (loop % iter == 0 )
324  {
325  exporter.postProcess (t);
326  }
327  }
328  //********************************************//
329  // Close the exporter //
330  //********************************************//
331 
332  exporter.closeFile();
333 
334 
335  //********************************************//
336  // Check if the test failed //
337  //********************************************//
338 
339  Real newSolutionNorm = monodomain -> potentialPtr() -> norm2();
340 
341  monodomain.reset();
342  MPI_Barrier (MPI_COMM_WORLD);
343  MPI_Finalize();
344 
345  Real err = std::abs (newSolutionNorm - solutionNorm) / std::abs (solutionNorm);
346  std::cout << std::setprecision (20) << "\nError: " << err << "\nSolution Norm: " << newSolutionNorm << "\n";
347  std::cout << std::setprecision (20) << "\nImported solution Norm: " << solutionNorm << "\n";
348  if ( err > 1e-8 )
349  {
350  std::cout << "\nTest Failed: " << err << "\n" << "\nSolution Norm: " << newSolutionNorm << "\n";
351  return EXIT_FAILURE; // Norm of solution did not match
352  }
353  else
354  {
355  return EXIT_SUCCESS;
356  }
357 }
358 
359 
360 
361 // Function to cut the spiral
362 Real cut (const Real& /*t*/, const Real& /*x*/, const Real& y, const Real& /*z*/, const ID& /*i*/)
363 {
364  if ( y >= 2.5)
365  {
366  return 1.0;
367  }
368  else
369  {
370  return 0.0;
371  }
372 }
373 
374 //Initial condition used for the precomputed solution
375 Real initialCondition ( const Real& /*t*/, const Real& /*x*/, const Real& /*y*/, const Real& z, const ID& /*id*/)
376 {
377  if ( z <= 0.4 )
378  {
379  return 1.0;
380  }
381  else
382  {
383  return 0;
384  }
385 }
VectorEpetra - The Epetra Vector format Wrapper.
Real initialCondition(const Real &, const Real &x, const Real &, const Real &, const ID &)
Real cut(const Real &, const Real &, const Real &y, const Real &, const ID &)
GetPot(const int argc_, char **argv_, const char *FieldSeparator=0x0)
Definition: GetPot.hpp:507
int32_type Int
Generic integer data.
Definition: LifeV.hpp:188
uint32_type ID
IDs.
Definition: LifeV.hpp:194
double Real
Generic real data.
Definition: LifeV.hpp:175
int main(int argc, char **argv)
const std::string follow(const char *Default, unsigned No, const char *Option,...)
Definition: GetPot.hpp:1510