LifeV
lifev/electrophysiology/testsuite/test_ventricle/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 on an idealized ventricle
30 
31  In this test I solve the monodomain on the idealized ventricle
32  setting with the minimal model and SVI.
33  To initiate the excitation I set the initial condition of
34  the potential to one on the endocardium.
35  The fiber field is loaded from file.
36 
37  Note that the given mesh is super coarse.
38  Using SVI the propagation will be super fast.
39  Please refine the mesh and run this test again.
40  You can create a fiber field using the test_fibers
41 
42  @date 04 - 2014
43  @author Simone Rossi <simone.rossi@epfl.ch>
44 
45  @contributor
46  @mantainer Simone Rossi <simone.rossi@epfl.ch>
47  */
48 
49 // Tell the compiler to ignore specific kind of warnings:
50 #pragma GCC diagnostic ignored "-Wunused-variable"
51 #pragma GCC diagnostic ignored "-Wunused-parameter"
52 
53 #include <Epetra_ConfigDefs.h>
54 #ifdef EPETRA_MPI
55 #include <mpi.h>
56 #include <Epetra_MpiComm.h>
57 #else
58 #include <Epetra_SerialComm.h>
59 #endif
60 
61 //Tell the compiler to restore the warning previously silented
62 #pragma GCC diagnostic warning "-Wunused-variable"
63 #pragma GCC diagnostic warning "-Wunused-parameter"
64 
65 //We will use the ETAMonodomainSolver
66 #include <lifev/electrophysiology/solver/ElectroETAMonodomainSolver.hpp>
67 
68 //We will use the Aliev Panfilov model for simplicity
69 #include <lifev/electrophysiology/solver/IonicModels/IonicMinimalModel.hpp>
70 
71 //Include LifeV
72 #include <lifev/core/LifeV.hpp>
73 
74 //Include utilities for importing the fiber field
75 #include <lifev/electrophysiology/util/HeartUtility.hpp>
76 
77 //this is useful to save the out in a separate folder
78 #include <sys/stat.h>
79 
80 using namespace LifeV;
81 
82 //Norm of the solution in order to check if the test failed
83 #define solutionNorm 48.66815714672445381
84 
85 // Test pacing
86 Int main ( Int argc, char** argv )
87 {
88 
89  //! Initializing Epetra communicator
90  MPI_Init (&argc, &argv);
91  std::shared_ptr<Epetra_Comm> Comm ( new Epetra_MpiComm (MPI_COMM_WORLD) );
92  if ( Comm->MyPID() == 0 )
93  {
94  std::cout << "% using MPI" << std::endl;
95  }
96 
97  //*********************************************//
98  // creating output folder
99  //*********************************************//
100  GetPot commandLine ( argc, argv );
101  std::string problemFolder = commandLine.follow ( "Output", 2, "-o", "--output" );
102  // Create the problem folder
103  if ( problemFolder.compare ("./") )
104  {
105  problemFolder += "/";
106 
107  if ( Comm->MyPID() == 0 )
108  {
109  mkdir ( problemFolder.c_str(), 0777 );
110  }
111  }
112 
113  //********************************************//
114  // Some typedefs //
115  //********************************************//
116 
117  typedef RegionMesh<LinearTetra> mesh_Type;
118 
119  typedef IonicMinimalModel ionicModel_Type;
120 
121  typedef ElectroETAMonodomainSolver< mesh_Type, ionicModel_Type > monodomainSolver_Type;
122 
123  typedef std::shared_ptr< monodomainSolver_Type > monodomainSolverPtr_Type;
124 
125  typedef VectorEpetra vector_Type;
126 
127  typedef std::shared_ptr<vector_Type> vectorPtr_Type;
128 
129  //********************************************//
130  // Import parameters from an xml list. Use //
131  // Teuchos to create a list from a given file //
132  // in the execution directory. //
133  //********************************************//
134 
135  if ( Comm->MyPID() == 0 )
136  {
137  std::cout << "Importing parameters list...";
138  }
139  Teuchos::ParameterList monodomainList = * ( Teuchos::getParametersFromXmlFile ( "MonodomainSolverParamList.xml" ) );
140  if ( Comm->MyPID() == 0 )
141  {
142  std::cout << " Done!" << std::endl;
143  }
144 
145  //********************************************//
146  // Creates a new model object representing the//
147  // model from Aliev and Panfilov 1996. The //
148  // model input are the parameters. Pass the //
149  // parameter list in the constructor //
150  //********************************************//
151  if ( Comm->MyPID() == 0 )
152  {
153  std::cout << "Building Constructor for Minimal Model with parameters ... ";
154  }
155  std::shared_ptr<ionicModel_Type> model ( new ionicModel_Type() );
156  if ( Comm->MyPID() == 0 )
157  {
158  std::cout << " Done!" << std::endl;
159  }
160 
161 
162  //********************************************//
163  // In the parameter list we need to specify //
164  // the mesh name and the mesh path. //
165  //********************************************//
166 
167  std::string meshName = monodomainList.get ("mesh_name", "idealized.mesh");
168  std::string meshPath = monodomainList.get ("mesh_path", "./");
169 
170  //********************************************//
171  // We need the GetPot datafile for to setup //
172  // the preconditioner. //
173  //********************************************//
174 
175  GetPot dataFile (argc, argv);
176 
177  //********************************************//
178  // We create the monodomain solver //
179  //********************************************//
180  if ( Comm->MyPID() == 0 )
181  {
182  std::cout << "Building Monodomain Solvers... ";
183  }
184 
185  monodomainSolverPtr_Type monodomain ( new monodomainSolver_Type ( meshName, meshPath, dataFile, model ) );
186  if ( Comm->MyPID() == 0 )
187  {
188  std::cout << " Splitting solver done... ";
189  }
190 
191  //********************************************//
192  // Initialize the solution //
193  //********************************************//
194  monodomain -> setInitialConditions();
195  ElectrophysiologyUtility::setValueOnBoundary ( * (monodomain -> potentialPtr() ), monodomain -> fullMeshPtr(), 1.0, 5 );
196 
197 
198  //********************************************//
199  // Setting up the monodomain solver parameters//
200  //********************************************//
201  monodomain -> setParameters ( monodomainList );
202 
203  //********************************************//
204  // fiber direction //
205  //********************************************//
206  if ( Comm->MyPID() == 0 )
207  {
208  std::cout << "\nSetting fibers: " ;
209  }
210  // This is used only to initialize the pointer in the solver
211  // could be replaced with a method "initialize fibers"
212  // where we just create the pointer to a vectorial vector.
213  // The method generates a default constant fiber direction (0,0,1).
214  // At least, in case of misuse, the fibers will not be zero
215  // and the signal may propagate.
216  monodomain -> setupFibers();
217  std::string fiberFile (monodomainList.get ("solid_fiber_file", "") );
218  std::string fiberField (monodomainList.get ("solid_fiber_field", "") );
219  ElectrophysiologyUtility::importVectorField (monodomain -> fiberPtr(), fiberFile, fiberField, monodomain -> localMeshPtr() );
220 
221  if ( Comm->MyPID() == 0 )
222  {
223  std::cout << "Done! \n" ;
224  }
225 
226  //********************************************//
227  // Saving Fiber direction to file //
228  //********************************************//
229  monodomain -> exportFiberDirection (problemFolder);
230 
231  //********************************************//
232  // Create the global matrix: mass + stiffness //
233  //********************************************//
234  if ( Comm->MyPID() == 0 )
235  {
236  std::cout << "\nSetup operators: " ;
237  }
238  monodomain -> setupLumpedMassMatrix();
239  monodomain -> setupStiffnessMatrix();
240  monodomain -> setupGlobalMatrix();
241  if ( Comm->MyPID() == 0 )
242  {
243  std::cout << "Done! \n" ;
244  }
245 
246  //********************************************//
247  // Creating exporters to save the solution //
248  //********************************************//
249  ExporterHDF5< RegionMesh <LinearTetra> > exporter;
250  monodomain -> setupExporter ( exporter, monodomainList.get ("OutputFile", "Solution"), problemFolder );
251  monodomain -> exportSolution ( exporter, 0);
252 
253  //********************************************//
254  // Solving the system //
255  //********************************************//
256  if ( Comm->MyPID() == 0 )
257  {
258  std::cout << "\nstart solving: " ;
259  }
260 
261  Real dt = monodomain -> timeStep();
262  //Uncomment for proper use
263  Real TF = monodomainList.get ("endTime", 48.0);
264  Int iter = monodomainList.get ("saveStep", 1.0) / dt;
265 
266  //********************************************//
267  // Loop over time solving with L-ICI //
268  //********************************************//
269  int loop = 0;
270  for (Real t = monodomain -> initialTime(); t < TF;)
271  {
272  //********************************************//
273  // Set the applied current from the pacing //
274  // protocol //
275  //********************************************//
276  loop++;
277  t += dt;
278 
279  //********************************************//
280  // Solve the monodomain equations. //
281  //********************************************//
282 
283  monodomain -> solveOneStepGatingVariablesFE();
284  monodomain -> solveOneSVIStep();
285 
286  //********************************************//
287  // Exporting the solution. //
288  //********************************************//
289  if (loop % iter == 0 )
290  {
291  if ( Comm->MyPID() == 0 )
292  {
293  std::cout << "\ntime = " << t;
294  }
295  exporter.postProcess (t);
296  }
297  }
298 
299  //********************************************//
300  // Close the exporter //
301  //********************************************//
302 
303  exporter.closeFile();
304 
305 
306  //********************************************//
307  // Check if the test failed //
308  //********************************************//
309  Real newSolutionNorm = monodomain -> potentialPtr() -> norm2();
310 
311  monodomain.reset();
312  MPI_Barrier (MPI_COMM_WORLD);
313  MPI_Finalize();
314 
315 
316  Real err = std::abs (newSolutionNorm - solutionNorm) / std::abs (solutionNorm);
317  if ( err > 1e-8 )
318  {
319  std::cout << std::setprecision (20) << "\nTest Failed: " << err << "\n" << "\nSolution Norm: " << newSolutionNorm << "\n";
320  return EXIT_FAILURE; // Norm of solution did not match
321  }
322  else
323  {
324  return EXIT_SUCCESS;
325  }
326 }
327 
328 #undef solutionNorm
VectorEpetra - The Epetra Vector format Wrapper.
GetPot(const int argc_, char **argv_, const char *FieldSeparator=0x0)
Definition: GetPot.hpp:507
int32_type Int
Generic integer data.
Definition: LifeV.hpp:188
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