LifeV
ElectroETABidomainSolver.hpp
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  @file
28  @brief Class for solving the Bidomain equations in electrophysiology.
29 
30  @date 09-10-2013
31  @author Toni Lassila <toni.lassila@epfl.ch>
32  @author Matthias Lange <m.lange@sheffield.ac.uk>
33 
34  @last update 10-10-2013
35 
36  This class provides interfaces to solve the bidomain equations
37  ( reaction diffusion equation ) using the ETA framework.
38  The solution can be performed using three different methods:
39  -operator splitting method (at this point available only with forward Euler
40  for the reaction step and backward Euler for the diffusion step. );
41  -Ionic Currents Interpolation (at this point only forward Euler);
42  -State Variable interpolation (at this point only forward Euler).
43  */
44 
45 #ifndef _ELECTROETABIDOMAINSOLVER_H_
46 #define _ELECTROETABIDOMAINSOLVER_H_
47 
48 #ifdef EPETRA_MPI
49 #include <mpi.h>
50 #include <Epetra_MpiComm.h>
51 #else
52 #include <Epetra_SerialComm.h>
53 #endif
54 
55 #include <string>
56 #include <lifev/core/fem/BCManage.hpp>
57 #include <lifev/core/filter/ExporterEnsight.hpp>
58 #ifdef HAVE_HDF5
59 #include <lifev/core/filter/ExporterHDF5.hpp>
60 #endif
61 #include <lifev/core/filter/ExporterEmpty.hpp>
62 
63 #include <Epetra_LocalMap.h>
64 
65 #include <lifev/core/array/MatrixElemental.hpp>
66 #include <lifev/core/array/MatrixSmall.hpp>
67 
68 #include <lifev/core/algorithm/SolverAztecOO.hpp>
69 #include <lifev/core/array/MapEpetra.hpp>
70 #include <lifev/core/array/MatrixEpetra.hpp>
71 #include <lifev/core/array/MatrixEpetraStructured.hpp>
72 #include <lifev/core/array/VectorEpetra.hpp>
73 #include <lifev/core/array/VectorEpetraStructured.hpp>
74 #include <lifev/core/array/MatrixEpetraStructuredUtility.hpp>
75 #include <lifev/core/fem/SobolevNorms.hpp>
76 #include <lifev/core/fem/GeometricMap.hpp>
77 #include <lifev/electrophysiology/solver/IonicModels/ElectroIonicModel.hpp>
78 
79 #include <lifev/core/util/LifeChrono.hpp>
80 #include <lifev/core/fem/FESpace.hpp>
81 #include <lifev/electrophysiology/util/HeartUtility.hpp>
82 
83 #include <Teuchos_RCP.hpp>
84 #include <Teuchos_ParameterList.hpp>
85 #include "Teuchos_XMLParameterListHelpers.hpp"
86 
87 #include <lifev/eta/fem/ETFESpace.hpp>
88 #include <lifev/eta/expression/Integrate.hpp>
89 #include <lifev/core/mesh/MeshLoadingUtility.hpp>
90 
91 #include <lifev/core/algorithm/LinearSolver.hpp>
92 #include <lifev/core/algorithm/Preconditioner.hpp>
93 #include <lifev/core/algorithm/PreconditionerML.hpp>
94 #include <lifev/core/algorithm/PreconditionerIfpack.hpp>
95 
96 #include <boost/typeof/typeof.hpp>
97 
98 #include <lifev/core/fem/GradientRecovery.hpp>
99 
100 namespace LifeV
101 {
102 
103 //! BidomainSolver - Class featuring the usual solver for bidomain equations
104 
105 template<typename Mesh, typename IonicModel>
107 {
108 
109  //!Bidomain Solver
110  /*!
111  The Bidomain equation reads
112 
113 
114  */
115 
116 public:
117 
118  //! @name Type definitions
119  //@{
120 
121  typedef Mesh mesh_Type;
123 
126 
127  typedef VectorEpetraStructured blockVector_Type;
129 
131 
132 
133 
136 
137  typedef MatrixEpetraStructured<Real> blockMatrix_Type;
139 
142 
145 
148 
151 
152  typedef LinearSolver linearSolver_Type;
154 
155 
156  typedef Exporter<mesh_Type> IOFile_Type;
158  typedef ExporterData<mesh_Type> IOData_Type;
160 #ifdef HAVE_HDF5
162 #endif
163 
164  typedef LifeV::Preconditioner basePrec_Type;
166  typedef LifeV::PreconditionerML prec_Type;
168 
169  typedef IonicModel ionicModel_Type;
172 
174 
175  typedef std::function <
176  Real (const Real& t, const Real& x, const Real& y, const Real& z,
177  const ID& i) > function_Type;
178 
179  typedef MatrixSmall<3, 3> matrixSmall_Type;
180 
181  //@}
182 
183  //! @name Constructors & Destructor
184  //@{
185 
186  //!Empty Constructor
187  /*!
188  */
190 
191  //! Constructor
192  /*!
193  * @param Teuchos::ParameterList parameter list
194  * @param GetPot datafile (for preconditioner)
195  * @param std::shared_ptr<IonicModel> chosen ionic model pointer
196  */
197 
198  ElectroETABidomainSolver (list_Type list, GetPot& dataFile,
199  ionicModelPtr_Type model);
200 
201  //! Constructor
202  /*!
203  * @param GetPot datafile (for preconditioner)
204  * @param std::shared_ptr<IonicModel> chosen ionic model pointer
205  * @param std::shared_ptr<Mesh> Pointer to the partitioned mesh
206  */
208  meshPtr_Type meshPtr);
209  //! Constructor
210  /*!
211  * @param Teuchos::ParameterList parameter list
212  * @param GetPot datafile (for preconditioner)
213  * @param std::shared_ptr<IonicModel> chosen ionic model pointer
214  * @param std::shared_ptr<Epetra_Comm> Epetra communicator
215  */
216 
217  ElectroETABidomainSolver (list_Type list, GetPot& dataFile,
218  ionicModelPtr_Type model, commPtr_Type comm);
219 
220  //! Constructor
221  /*!
222  * @param Teuchos::ParameterList parameter list
223  * @param GetPot datafile (for preconditioner)
224  * @param std::shared_ptr<IonicModel> chosen ionic model pointer
225  * @param std::shared_ptr<Mesh> Pointer to the partitioned mesh
226  */
227 
228  ElectroETABidomainSolver (list_Type list, GetPot& dataFile,
229  ionicModelPtr_Type model, meshPtr_Type meshPtr);
230 
231  //! Constructor
232  /*!
233  * @param string file name of the mesh
234  * @param string path to the mesh
235  * @param GetPot datafile (for preconditioner)
236  * @param std::shared_ptr<IonicModel> chosen ionic model pointer
237  */
238 
239  ElectroETABidomainSolver (std::string meshName, std::string meshPath,
240  GetPot& dataFile, ionicModelPtr_Type model);
241 
242 
243 
244  //! Constructor
245  /*!
246  * @param string file name of the mesh
247  * @param string path to the mesh
248  * @param GetPot datafile (for preconditioner)
249  * @param std::shared_ptr<IonicModel> chosen ionic model pointer
250  * @param std::shared_ptr<Epetra_Comm> Epetra communicator
251  */
252  ElectroETABidomainSolver (std::string meshName, std::string meshPath,
253  GetPot& dataFile, ionicModelPtr_Type model, commPtr_Type comm);
254 
255 
256 
257  //! Copy Constructor
258  /*!
259  * @param ElectroETABidomainSolver object
260  */
262 
263  //!Operator=()
264  /*!
265  * @param ElectroETABidomainSolver object
266  */
267  ElectroETABidomainSolver<Mesh, IonicModel>& operator= (
268  const ElectroETABidomainSolver& solver);
269 
270 
271  //! Destructor
273  {
274  }
275 
276  //@}
277 
278  //! @name Get Methods
279  //@{
280 
281  //! get the surface to volume ratio
282  /*!
283  * Not used in the code ( implicit definition inside the diffusion tensor)
284  */
285  inline const Real& surfaceVolumeRatio() const
286  {
287  return M_surfaceVolumeRatio;
288  }
289 
290  //! get the initial time (by default 0)
291  inline const Real& initialTime() const
292  {
293  return M_initialTime;
294  }
295  //! get the final time
296  inline const Real& timeStep() const
297  {
298  return M_timeStep;
299  }
300  //! get the time step
301  inline const Real& endTime() const
302  {
303  return M_endTime;
304  }
305  //! get the diagonal intra cellular diffusion tensor
306  inline const VectorSmall<3>& diffusionTensorIntra() const
307  {
308  return M_diffusionTensorIntra;
309  }
310  //! get the diagonal extra cellular diffusion tensor
311  inline const VectorSmall<3>& diffusionTensorExtra() const
312  {
313  return M_diffusionTensorExtra;
314  }
315  //! get the order of the elements
316  inline const std::string elementsOrder() const
317  {
318  return M_elementsOrder;
319  }
320  //! get the pointer to the ionic model
321  inline const ionicModelPtr_Type ionicModelPtr() const
322  {
323  return M_ionicModelPtr;
324  }
325  //! get the pointer to the Epetra communicator
326  inline const commPtr_Type commPtr() const
327  {
328  return M_commPtr;
329  }
330  //! get the pointer to the partitioned mesh
331  inline const meshPtr_Type localMeshPtr() const
332  {
333  return M_localMeshPtr;
334  }
335  //! get the pointer to the partitioned mesh
336  inline const meshPtr_Type fullMeshPtr() const
337  {
338  return M_fullMeshPtr;
339  }
340  //! get the pointer to the ETA finite element space
341  inline const ETFESpacePtr_Type ETFESpacePtr() const
342  {
343  return M_ETFESpacePtr;
344  }
345  //! get the pointer to the usual finite element space
346  inline const feSpacePtr_Type feSpacePtr() const
347  {
348  return M_feSpacePtr;
349  }
350  //! get the pointer to the mass matrix
351  inline const blockMatrixPtr_Type massMatrixPtr() const
352  {
353  return M_massMatrixPtr;
354  }
355  //! get the pointer to the stiffness matrix
357  {
358  return M_stiffnessMatrixPtr;
359  }
360 
361  //! get the pointer to the global matrix
362  /*!
363  * \f[
364  * A = \frac{M}{\Delta t} + K(\mathbf{f})
365  * \f]
366  */
368  {
369  return M_globalMatrixPtr;
370  }
371  //! get the pointer to the right hand side
372  inline const blockVectorPtr_Type rhsPtr() const
373  {
374  return M_rhsPtr;
375  }
376  //! get the pointer to the unique version of the right hand side
377  inline const blockVectorPtr_Type rhsPtrUnique() const
378  {
379  return M_rhsPtrUnique;
380  }
381  //! get the pointer to the transmembrane potential
382  inline const vectorPtr_Type potentialTransPtr() const
383  {
384  return M_potentialTransPtr;
385  }
386  //! get the pointer to the potential
388  {
389  return M_potentialGlobalPtr;
390  }
391  //! get the pointer to the extra cellular potential
392  inline const vectorPtr_Type potentialExtraPtr() const
393  {
394  return M_potentialExtraPtr;
395  }
396 
397  //! get the pointer to the fiber vector
398  inline const vectorPtr_Type fiberPtr() const
399  {
400  return M_fiberPtr;
401  }
402  //! get the pointer to the applied intra cellular current vector
404  {
405  return M_ionicModelPtr->appliedCurrentPtr();
406  }
407 
408  //! get the pointer to the linear solver
410  {
411  return M_linearSolverPtr;
412  }
413  //! get the pointer to the vector of pointers containing the transmembrane potential (at 0) and the gating variables
414  inline const vectorOfPtr_Type& globalSolution() const
415  {
416  return M_globalSolution;
417  }
418  //! get the pointer to the vector of pointers containing the rhs for transmembrane potential (at 0) and the gating variables
419  inline const vectorOfPtr_Type& globalRhs() const
420  {
421  return M_globalRhs;
422  }
423  //! get the pointer to the transmembrane potential
425  {
426  return M_displacementPtr;
427  }
428 
430  {
432  }
433 
434  inline bool lumpedMassMatrix() const
435  {
436  return M_lumpedMassMatrix;
437  }
438  //@}
439 
440  //! @name Set Methods
441  //@{
442 
443 
444  //! set the surface to volume ratio
445  /*!
446  @param Real surface to volume ratio
447  */
448  inline void setSurfaceVolumeRatio (const Real& p)
449  {
450  this->M_surfaceVolumeRatio = p;
451  }
452 
453  //! set the starting time
454  /*!
455  @param Real initial time
456  */
457  inline void setInitialTime (const Real& p)
458  {
459  this->M_initialTime = p;
460  }
461  //! set the ending time
462  /*!
463  @param Real ending time
464  */
465  inline void setTimeStep (const Real& p)
466  {
467  this->M_timeStep = p;
468  }
469  //! set the time step
470  /*!
471  @param Real time step
472  */
473  inline void setEndTime (const Real& p)
474  {
475  this->M_endTime = p;
476  }
477  //! set the intra cellular diagonal diffusion tensor
478  /*!
479  @param VectorSmall<3> diagonal intra cellular diffusion tensor
480  */
481  inline void setDiffusionTensorIntra (const VectorSmall<3>& p)
482  {
483  this->M_diffusionTensorIntra = p;
484  }
485  //! set the extra cellular diagonal diffusion tensor
486  /*!
487  @param VectorSmall<3> diagonal extra cellular diffusion tensor
488  */
489  inline void setDiffusionTensorExtra (const VectorSmall<3>& p)
490  {
491  this->M_diffusionTensorExtra = p;
492  }
493 
494  //! set the pointer to the ionic model
495  /*!
496  @param std::shared_ptr<IonicModel> pointer to the ionic model
497  */
498  inline void setIonicModelPtr (const ionicModelPtr_Type p)
499  {
500  this->M_ionicModelPtr = p;
501  }
502  //! set the pointer to the Epetra communicator
503  /*!
504  @param std::shared_ptr<Epetra_Comm> pointer to the Epetra communicator
505  */
506 
507  inline void setCommPtr (const commPtr_Type p)
508  {
509  this->M_commPtr = p;
510  }
511  //! set the pointer to the partitioned mesh
512  /*!
513  @param std::shared_ptr<Mesh> pointer to the partitioned mesh
514  */
515  inline void setLocalMeshPtr (const meshPtr_Type p)
516  {
517  this->M_localMeshPtr = p;
518  }
519  //! set the pointer to the partitioned mesh
520  /*!
521  @param std::shared_ptr<Mesh> pointer to the partitioned mesh
522  */
523  inline void setFullMeshPtr (const meshPtr_Type p)
524  {
525  this->M_fullMeshPtr = p;
526  }
527  //! set the pointer to the ETA fe space
528  /*!
529  @param std::shared_ptr<ETFESpace<Mesh,MapEpetra,3,1>> pointer to the ETA fe space
530  */
531  inline void setETFESpacePtr (const ETFESpacePtr_Type p)
532  {
533  this->M_ETFESpacePtr = p;
534  }
535  //! set the pointer to the usual fe space
536  /*!
537  @param std::shared_ptr<IFESpace<Mesh,MapEpetra>> pointer to the usual fe space
538  */
539  inline void setFeSpacePtr (const feSpacePtr_Type p)
540  {
541  this->M_feSpacePtr = p;
542  }
543 
544  //! set the pointer to the mass matrix
545  /*!
546  @param std::shared_ptr<MatrixEpetra<Real>> pointer to the mass matrix
547  */
548  inline void setMassMatrixPtr (const blockMatrixPtr_Type p)
549  {
550  this->M_massMatrixPtr = p;
551  }
552  //! set the pointer to the stiffness matrix
553  /*!
554  @param std::shared_ptr<MatrixEpetra<Real>> pointer to the stiffness matrix
555  */
557  {
558  this->M_stiffnessMatrixPtr = p;
559  }
560  //! set the pointer to the global matrix
561  /*!
562  @param std::shared_ptr<MatrixEpetra<Real>> pointer to the global matrix
563  */
565  {
566  this->M_globalMatrixPtr = p;
567  }
568  //! set the pointer to the right hand side
569  /*!
570  @param std::shared_ptr<VectorEpetra> pointer to the right hand side
571  */
572  inline void setRhsPtr (const blockVectorPtr_Type p)
573  {
574  this->M_rhsPtr = p;
575  }
576  //! set the pointer to the unique version of the right hand side
577  /*!
578  @param std::shared_ptr<VectorEpetra> pointer to the unique version of the right hand side
579  */
580  inline void setRhsPtrUnique (const blockVectorPtr_Type p)
581  {
582  this->M_rhsPtrUnique = p;
583  }
584 
585  inline void setPotentialExtraPtr (const vectorPtr_Type p)
586  {
587  this->M_potentialExtraPtr = p;
588  this->M_potentialGlobalPtr->replace ( (*p), this->M_potentialGlobalPtr->block (1)->firstIndex);
589  }
590 
591  inline void setPotentialTransPtr (const vectorPtr_Type p)
592  {
593  this->M_potentialTransPtr = p;
594  this->M_potentialGlobalPtr->replace ( (*p), this->M_potentialGlobalPtr->block (0)->firstIndex() );
595  }
596 
597 
598  //! set the pointer to the intra cell applied current vector
599  /*!
600  @param std::shared_ptr<VectorEpetra> pointer to the intra cellular applied current vector
601  */
603  {
604  M_ionicModelPtr->setAppliedCurrentPtr (p);
605  }
606 
607  //! set the pointer to the linear solver
608  /*!
609  @param std::shared_ptr<LinearSolver> pointer to the linear solver
610  */
612  {
613  this->M_linearSolverPtr = p;
614  }
615  //! set the vector of pointers containing the transmembrane potential (at 0) and the gating variables
616  /*!
617  @param std::vector<std::shared_ptr<VectorEpetra>> vector of pointers containing the transmembrane potential (at 0) and the gating variables
618  */
619  inline void setGlobalSolution (const vectorOfPtr_Type& p)
620  {
621  this->M_globalSolution = p;
622  }
623  //! set the vector of pointers containing the rhs for the transmembrane potential (at 0) and the gating variables
624  /*!
625  @param std::vector<std::shared_ptr<VectorEpetra>> vector of pointers containing the rhs for the transmembrane potential (at 0) and the gating variables
626  */
627  inline void setGlobalRhs (const vectorOfPtr_Type& p)
628  {
629  this->M_globalRhs = p;
630  }
631  //! set the pointer to the fiber direction vector
632  /*!
633  @param std::shared_ptr<VectorEpetra> pointer to the fiber direction vector
634  */
635  inline void setFiberPtr (const vectorPtr_Type p)
636  {
637  this->M_fiberPtr = p;
638  }
639  //! set the pointer to displacement of the tissue
640  inline void setDisplacementPtr (const vectorPtr_Type p)
641  {
642  this->M_displacementPtr = p;
643  }
644 
645  //@}
646 
647  //! @name Copy Methods
648  //@{
649  inline void setIonicModel (const ionicModel_Type& p)
650  {
651  (* (M_ionicModelPtr) ) = p;
652  }
653  inline void setComm (const comm_Type& p)
654  {
655  (* (M_commPtr) ) = p;
656  }
657  inline void setLocalMesh (const mesh_Type& p)
658  {
659  (* (M_localMeshPtr) ) = p;
660  }
661  inline void setFullMesh (const mesh_Type& p)
662  {
663  (* (M_fullMeshPtr) ) = p;
664  }
665  inline void setETFESpace (const ETFESpace_Type& p)
666  {
667  (* (M_ETFESpacePtr) ) = p;
668  }
669  inline void setFeSpace (const feSpace_Type& p)
670  {
671  (* (M_feSpacePtr) ) = p;
672  }
673  inline void setMassMatrix (const matrix_Type& p)
674  {
675  (* (M_massMatrixPtr) ) = p;
676  }
677  inline void setStiffnessMatrix (const matrix_Type& p)
678  {
679  (* (M_stiffnessMatrixPtr) ) = p;
680  }
681  inline void setGlobalMatrix (const matrix_Type& p)
682  {
683  (* (M_globalMatrixPtr) ) = p;
684  }
685  inline void setRhs (const vector_Type& p)
686  {
687  (* (M_rhsPtr) ) = p;
688  }
689  inline void setRhsUnique (const vector_Type& p)
690  {
691  (* (M_rhsPtrUnique) ) = p;
692  }
693  inline void setPotentialTrans (const vector_Type& p)
694  {
695  (* (M_potentialTransPtr) ) = p;
696  this->M_potentialGlobalPtr->replace (p, this->M_potentialGlobalPtr->block (0)->firstIndex() );
697  }
698  inline void setPotentialExtra (const blockVector_Type& p)
699  {
700  (* (M_potentialExtraPtr) ) = p;
701  this->M_potentialGlobalPtr->replace (p, this->M_potentialGlobalPtr->block (1)->firstIndex() );
702  }
703  inline void setFiber (const vector_Type& p)
704  {
705  (* (M_fiberPtr) ) = p;
706  }
707  inline void setDisplacement (const vector_Type& p)
708  {
709  (* (M_displacementPtr) ) = p;
710  }
711  inline void setAppliedCurrentIntra (const vector_Type& p)
712  {
713  M_ionicModelPtr->setAppliedCurrent (p);
714  }
715  inline void setLinearSolver (const linearSolver_Type& p)
716  {
717  (* (M_linearSolverPtr) ) = p;
718  }
719  inline void copyGlobalSolution (const vectorOfPtr_Type& p)
720  {
721  for (int j = 0; j < M_ionicModelPtr->Size(); j++)
722  {
723  (* (M_globalSolution.at (j) ) ) = (* (p.at (j) ) );
724  }
725  }
726 
727  inline void setVariablePtr (const vectorPtr_Type p, int j)
728  {
729  M_globalSolution.at (j) = p;
730  }
731 
732  inline void copyGlobalRhs (const vectorOfPtr_Type& p)
733  {
734  for (int j = 0; j < M_ionicModelPtr->Size(); j++)
735  {
736  (* (M_globalRhs.at (j) ) ) = (* (p.at (j) ) );
737  }
738  }
739 
740  inline void setLumpedMassMatrix (bool p) const
741  {
742  M_lumpedMassMatrix = p;
743  }
744 
745 
746  //@}
747 
748  //! @name Methods
749  //@{
750 
751  void setup (GetPot& dataFile, short int ionicSize);
752 
753  void setup (std::string meshName, std::string meshPath, GetPot& dataFile,
754  short int ionicSize);
755 
756  //! create mass matrix
757  void setupMassMatrix(); //! create mass matrix
758  void setupMassMatrix (vector_Type& disp);
759  //! create mass matrix
760  void setupLumpedMassMatrix();
761  void setupLumpedMassMatrix (vector_Type& disp);
762  //! create stiffness matrix
763  void setupStiffnessMatrix();
764  //! create stiffness matrix in a moving domain
766  //! create stiffness matrix given a diagonal diffusion tensor
767  void setupStiffnessMatrix (VectorSmall<3> diffusionIntra, VectorSmall<3> diffusionExtra);
768  //! create stiffness matrix given the fiber direction and a diagonal diffusion tensor
769  //void setupStiffnessMatrix (VectorEpetra& fiber, VectorSmall<3> diffusion);
770  //! setup the total matrix
771  /*!
772  * \f[
773  * A = \frac{M}{\Delta t} + K(\mathbf{f})
774  * \f]
775  */
776  void setupGlobalMatrix();
777  //! setup the linear solver
778  /*!
779  * A file named BidomainSolverParamList.xml must be in the execution folder
780  * with the parameters to set the linear solver
781  */
782  void setupLinearSolver (GetPot dataFile);
783  //! setup the linear solver
784  void setupLinearSolver (GetPot dataFile, list_Type list);
785  //! Initialize the potentials to zero
786  void inline initializePotential()
787  {
788  (*M_potentialTransPtr) *= 0;
789  (*M_potentialExtraPtr) *= 0;
790  (*M_potentialGlobalPtr) *= 0;
791  }
792  //! Initialize the potential to the value k
794  {
795  (* (M_globalSolution.at (0) ) ) = k;
796  this->M_potentialGlobalPtr->replace ( (* (M_globalSolution.at (0) ) ), this->M_potentialGlobalPtr->block (0)->firstIndex);
797 
798  }
800  {
801  (*M_potentialExtraPtr) = k;
802  this->M_potentialGlobalPtr->replace ( (*M_potentialExtraPtr), this->M_potentialGlobalPtr->block (1)->firstIndex);
803 
804  }
805 
806  //! Initialize the applied current to zero
808  {
809  (* (M_ionicModelPtr->appliedCurrentPtr() ) ) *= 0;
810  //(*M_IappExtraPtr)*=0;
811  }
812  //! Initialize the intra cellular applied current to the value k
814  {
815  (* (M_ionicModelPtr->appliedCurrentPtr() ) ) = k;
816  }
817  //! creates a vector of pointers to store the solution
818  /*!
819  * The first pointer points to the vector of the transmembrane potential,
820  * while the others point to the gating variables
821  */
822  void setupGlobalSolution (short int ionicSize);
823  //! creates a vector of pointers to store the rhs
824  /*!
825  * The first pointer points to the rhs of the transmembrane potential,
826  * while the others point to the rhs of the gating variables
827  */
828  void setupGlobalRhs (short int ionicSize);
829  //! Set parameters from an xml file
830  void setParameters (list_Type list);
831  //! partition the mesh
832  void inline partitionMesh (std::string meshName, std::string meshPath)
833  {
834  MeshUtility::loadMesh (M_localMeshPtr, M_fullMeshPtr, meshName,
835  meshPath);
836  }
837  //! given a boost function initialize the transmembrane potential
838  void inline setPotentialFromFunctionTrans (function_Type& f, Real time = 0.0)
839  {
840  M_feSpacePtr->interpolate (
841  static_cast<FESpace<RegionMesh<LinearTetra>, MapEpetra>::function_Type> (f),
842  * (M_globalSolution.at (0) ), time);
843  }
844  //! given a boost function initialize the extra cellular potential
845  void inline setPotentialFromFunctionExtra (function_Type& f, Real time = 0.0)
846  {
847  M_feSpacePtr->interpolate (
848  static_cast<FESpace<RegionMesh<LinearTetra>, MapEpetra>::function_Type> (f),
849  *M_potentialExtraPtr, time);
850  }
851  //! given a boost function initialize the applied intra cellular current
853  Real time = 0.0)
854  {
855  M_ionicModelPtr->setAppliedCurrentFromFunction (f, M_feSpacePtr, time);
856  }
857  //! Solves one reaction step using the forward Euler scheme
858  /*!
859  * \f[
860  * \mathbf{V}^* = \mathbf{V}^n + \Delta t I_{ion}(\mathbf{V}^n).
861  * \f]
862  */
863  void solveOneReactionStepFE (int subiterations = 1);
864  void solveOneReactionStepFE (matrix_Type& mass, int subiterations = 1);
865  void solveOneReactionStepRL (int subiterations = 1);
866 
867  //! Update the rhs
868  /*!
869  * \f[
870  * rhs \leftarrow C_m \frac{M}{\Delta t} \mathbf{V}^n
871  * \f]
872  */
873  void inline updateRhs()
874  {
875  blockVectorPtr_Type tmp ( new blockVector_Type ( *M_rhsPtrUnique ) );
876  M_massMatrixPtr -> multiply (false, (*M_potentialGlobalPtr) * (M_ionicModelPtr -> membraneCapacitance() / (M_timeStep) ), *tmp );
877  (*M_rhsPtrUnique) += (*tmp);
878  }
879 
880  //! Solves one diffusion step using the BDF2 scheme
881  /*!
882  * \f[
883  * ( \frac{3}{\Delta t}M + A ) V^{n+1} = \frac{1}{\Delta t}M(4 V^n -V^{n-1})
884  * \f]
885  */
886  void solveOneDiffusionStepBDF2 (vectorPtr_Type previousPotentialGlobalPtr);
887 
888  //! Solves one diffusion step using the backward Euler scheme
889  /*!
890  * \f[
891  * A\mathbf{V}^{n+1} = \left( C_m \frac{M}{\Delta t} + K(\mathbf{f}) \right)\mathbf{V}^{n+1} =\frac{M}{\Delta t} \mathbf{V}^*.
892  * \f]
893  */
895 
896  //!Solve one full step with operator splitting
897  /*!
898  * \f[
899  * \mathbf{V}^* = \mathbf{V}^n + \Delta t I_{ion}(\mathbf{V}^n).
900  * \f]
901  * \f[
902  * A\mathbf{V}^{n+1} = \left( \frac{M}{\Delta t} + K(\mathbf{f}) \right)\mathbf{V}^{n+1} =\frac{M}{\Delta t} \mathbf{V}^*.
903  * \f]
904  */
905  void solveOneSplittingStep();
906  //!Solve the system with operator splitting from M_initialTime to the M_endTime with time step M_timeStep
907  void solveSplitting();
908  //!Solve one full step with operator splitting and export the solution
909  /*!
910  * \f[
911  * \mathbf{V}^* = \mathbf{V}^n + \Delta t I_{ion}(\mathbf{V}^n).
912  * \f]
913  * \f[
914  * A\mathbf{V}^{n+1} = \left( \frac{M}{\Delta t} + K(\mathbf{f}) \right)\mathbf{V}^{n+1} =\frac{M}{\Delta t} \mathbf{V}^*.
915  * \f]
916  */
917  void solveOneSplittingStep (IOFile_Type& exporter, Real t);
918  //!Solve the system with operator splitting from M_initialTime to the M_endTime with time step M_timeStep and export the solution
919  void solveSplitting (IOFile_Type& exporter);
920  //!Solve the system with operator splitting from M_initialTime to the M_endTime with time step M_timeStep and export the solution every dt
921  void solveSplitting (IOFile_Type& exporter, Real dt);
922  //! add to a given exporter the pointer to the potential
923  void setupPotentialExporter (IOFile_Type& exporter);
924  //! add to a given exporter the pointer to the potential saved with name fileName
925  void setupPotentialExporter (IOFile_Type& exporter, std::string fileName);
926  //! add to a given exporter the pointer to the potential and to the gating variables saved with name fileName
927  void setupExporter (IOFile_Type& exporter, std::string fileName = "output",
928  std::string folder = "./");
929 
930  //! Generates a default fiber direction (0,1,0)
931  void setupFibers();
932  //! Generates the fiber direction given the three component of the vector (F_x,F_y,F_z)
933  void setupFibers (VectorSmall<3> fibers);
934  //! Imports the fiber direction from a hdf5 file
935  inline void setupFibers (std::string fibersFile)
936  {
937  ElectrophysiologyUtility::importFibers (M_fiberPtr, fibersFile, M_localMeshPtr);
938  }
939  //! Imports the fiber direction from a vtk file ( format = 0), or text file
940  //
941  inline void setupFibers (std::string fibersFile, std::string directory,
942  int format = 0)
943  {
944  ElectrophysiologyUtility::importFibersFromTextFile (M_fiberPtr, fibersFile,
945  directory, format);
946  }
947  //! Solves the gating variables with forward Euler
950  //! Compute the rhs using state variable interpolation
951  void computeRhsSVI();
952  //! Compute the rhs using ionic current interpolation
953  void computeRhsICI();
954  void computeRhsICI (matrix_Type& mass);
955  //!Solve one full step with ionic current interpolation
956  /*!
957  * \f[
958  * A\mathbf{V}^{n+1} = \left( \frac{M}{\Delta t} + K(\mathbf{f}) \right)\mathbf{V}^{n+1} =\frac{M}{\Delta t} \mathbf{V}^n+M\mathbf{I},
959  * \f]
960  * where $\mathbf{I}$ is the vector of the ionic currents $I_j = I_{ion}(V_j^n)$
961  */
962  void solveOneICIStep();
963  void solveOneICIStep (matrix_Type& mass);
964  //!Solve one full step with ionic current interpolation
965  /*!
966  * \f[
967  * A\mathbf{V}^{n+1} = \left( \frac{M}{\Delta t} + K(\mathbf{f}) \right)\mathbf{V}^{n+1} =\frac{M}{\Delta t} \mathbf{V}^n+\mathbf{I}_{ion}(\mathbf{V}^n).
968  * \f]
969  */
970  void solveOneSVIStep();
971  //! solve system using ICI from M_initialTime to the M_endTime with time step M_timeStep
972  void solveICI();
973  //! solve system using SVI from M_initialTime to the M_endTime with time step M_timeStep
974  void solveSVI();
975  //!Solve one full step with ionic current interpolation and export the solution
976  /*!
977  * \f[
978  * A\mathbf{V}^{n+1} = \left( \frac{M}{\Delta t} + K(\mathbf{f}) \right)\mathbf{V}^{n+1} =\frac{M}{\Delta t} \mathbf{V}^n+M\mathbf{I},
979  * \f]
980  * where $\mathbf{I}$ is the vector of the ionic currents $I_j = I_{ion}(V_j^n)$
981  */
982  void solveOneICIStep (IOFile_Type& exporter, Real t);
983  //!Solve one full step with ionic current interpolation and export the solution
984  /*!
985  * \f[
986  * A\mathbf{V}^{n+1} = \left( \frac{M}{\Delta t} + K(\mathbf{f}) \right)\mathbf{V}^{n+1} =\frac{M}{\Delta t} \mathbf{V}^n+\mathbf{I}_{ion}(\mathbf{V}^n).
987  * \f]
988  */
989  void solveOneSVIStep (IOFile_Type& exporter, Real t);
990 
991  //! solve system using ICI from M_initialTime to the M_endTime with time step M_timeStep and export the solution
992  void solveICI (IOFile_Type& exporter);
993  //! solve system using SVI from M_initialTime to the M_endTime with time step M_timeStep and export the solution
994  void solveSVI (IOFile_Type& exporter);
995  //!Solve the system using ICI from M_initialTime to the M_endTime with time step M_timeStep and export the solution every dt
996  void solveICI (IOFile_Type& exporter, Real dt);
997  //!Solve the using SVI from M_initialTime to the M_endTime with time step M_timeStep and export the solution every dt
998  void solveSVI (IOFile_Type& exporter, Real dt);
999  //! Generates a file where the fiber direction is saved
1000  void exportFiberDirection (std::string postDir = "./");
1001  //! save the fiber direction into the given exporter
1002  void exportFiberDirection (IOFile_Type& exporter);
1003  //! Save the solution in the exporter
1004  void inline exportSolution (IOFile_Type& exporter, Real t)
1005  {
1006  exporter.postProcess (t);
1007  }
1008  //! Import solution
1009  void importSolution (GetPot& dataFile, std::string prefix,
1010  std::string postDir, Real time);
1011 
1012  void inline setInitialConditions()
1013  {
1014  M_ionicModelPtr->initialize (M_globalSolution);
1015  }
1016 
1017  //! save the fiber direction into the given exporter
1018  void registerActivationTime (vector_Type& activationTimeVector, Real time,
1019  Real threshold = 0.0);
1020 
1021  //@}
1022 
1023 private:
1024 
1025  void setParameters();
1026  void init();
1027  void init (commPtr_Type comm);
1028  void init (meshPtr_Type meshPtr);
1029  void init (ionicModelPtr_Type model);
1030  void init (commPtr_Type comm, ionicModelPtr_Type model);
1031  void init (meshPtr_Type meshPtr, ionicModelPtr_Type model);
1032 
1034 
1036 
1042 
1046 
1050 
1053 
1059 
1061 
1064 
1066 
1068 
1070 
1071  //Create the identity for F
1073 
1075 
1077 
1078 protected:
1079  void importFibers (vectorPtr_Type M_fiberPtr, std::string fibersFile, meshPtr_Type M_localMeshPtr);
1080 };
1081 
1082 
1083 
1084 // class BidomainSolver
1085 
1086 //
1087 // IMPLEMENTATION
1088 //
1089 // ===================================================
1090 //! Constructors
1091 // ===================================================
1092 template<typename Mesh, typename IonicModel>
1094 {
1095  setParameters();
1096  init();
1097 }
1098 
1099 template<typename Mesh, typename IonicModel>
1101  list_Type list, GetPot& dataFile, ionicModelPtr_Type model)
1102 {
1103  init (model);
1104  setParameters (list);
1105  setup (list.get ("meshName", "lid16.mesh"), list.get ("meshPath", "./"),
1106  dataFile, M_ionicModelPtr->Size() );
1107 }
1108 
1109 template<typename Mesh, typename IonicModel>
1111  list_Type list, GetPot& dataFile, ionicModelPtr_Type model,
1112  commPtr_Type comm)
1113 {
1114  setParameters (list);
1115  init (comm);
1116  setup (list.get ("meshName", "lid16.mesh"), list.get ("meshPath", "./"),
1117  dataFile, M_ionicModelPtr->Size() );
1118 }
1119 
1120 template<typename Mesh, typename IonicModel>
1122  list_Type list, GetPot& dataFile, ionicModelPtr_Type model,
1123  meshPtr_Type meshPtr)
1124 {
1125  setParameters (list);
1126  init (meshPtr);
1127  setup (dataFile, M_ionicModelPtr->Size() );
1128 }
1129 
1130 template<typename Mesh, typename IonicModel>
1132  std::string meshName, std::string meshPath, GetPot& dataFile,
1133  ionicModelPtr_Type model)
1134 {
1135  setParameters();
1136  init (model);
1137  setup (meshName, meshPath, dataFile, M_ionicModelPtr->Size() );
1138 }
1139 
1140 template<typename Mesh, typename IonicModel>
1142  std::string meshName, std::string meshPath, GetPot& dataFile,
1143  ionicModelPtr_Type model, commPtr_Type comm) :
1144  M_ionicModelPtr (model)
1145 {
1146  setParameters();
1147  init (comm);
1148  setup (meshName, meshPath, dataFile, M_ionicModelPtr->Size() );
1149 }
1150 
1151 template<typename Mesh, typename IonicModel>
1153  GetPot& dataFile, ionicModelPtr_Type model, meshPtr_Type meshPtr) :
1154  M_ionicModelPtr (model)
1155 {
1156  setParameters();
1157  init (meshPtr);
1158  setup (dataFile, M_ionicModelPtr->Size() );
1159 }
1160 
1161 template<typename Mesh, typename IonicModel>
1163  const ElectroETABidomainSolver& solver) :
1164  M_surfaceVolumeRatio (solver.M_surfaceVolumeRatio), M_ionicModelPtr (
1165  solver.M_ionicModelPtr), M_commPtr (solver.M_commPtr), M_localMeshPtr (
1166  solver.M_localMeshPtr), M_fullMeshPtr (solver.M_fullMeshPtr), M_ETFESpacePtr (
1167  solver.M_ETFESpacePtr), M_feSpacePtr (solver.M_feSpacePtr), M_massMatrixPtr (
1171  solver.M_initialTime), M_endTime (solver.M_endTime), M_timeStep (
1172  solver.M_timeStep), M_diffusionTensorIntra (solver.M_diffusionTensorIntra),
1173  M_diffusionTensorExtra (solver.M_diffusionTensorExtra), M_rhsPtr (
1179  new vector_Type (* (solver.M_fiberPtr) )
1180  ) ,
1181  M_lumpedMassMatrix (false)
1182 {
1183  if (M_commPtr -> MyPID() == 0)
1184  {
1185  std::cout << "\n WARNING!!! ETA Bidomain Solver: you are using the copy constructor! This method is outdated.";
1186  std::cout << "\n WARNING!!! ETA Bidomain Solver: Don't count on it, at this moment. Feel free to update yourself...";
1187  }
1188 
1189  setupGlobalSolution (M_ionicModelPtr->Size() );
1190  copyGlobalSolution (solver.M_globalSolution);
1191  setupGlobalRhs (M_ionicModelPtr->Size() );
1192  copyGlobalRhs (solver.M_globalRhs);
1193 }
1194 
1195 template<typename Mesh, typename IonicModel>
1196 ElectroETABidomainSolver<Mesh, IonicModel>& ElectroETABidomainSolver < Mesh,
1197  IonicModel >::operator= (const ElectroETABidomainSolver& solver)
1198 {
1199  if (M_commPtr -> MyPID() == 0)
1200  {
1201  std::cout << "\n WARNING!!! ETA Bidomain Solver: you are using the assignment operator! This method is outdated.";
1202  std::cout << "\n WARNING!!! ETA Bidomain Solver: Don't count on it, at this moment. Feel free to update yourself...";
1203  }
1204  M_surfaceVolumeRatio = solver.M_surfaceVolumeRatio;
1205  setIonicModel ( (*solver.M_ionicModelPtr) );
1206  M_commPtr = solver.M_commPtr;
1207  M_localMeshPtr = solver.M_localMeshPtr;
1208  M_fullMeshPtr = solver.M_fullMeshPtr;
1209  setETFESpace (* (solver.M_ETFESpacePtr) );
1210  setFeSpace (* (solver.M_feSpacePtr) );
1211  setMassMatrix (* (solver.M_massMatrixPtr) );
1212  setStiffnessMatrix (* (solver.M_stiffnessMatrixPtr) );
1213  setGlobalMatrix (* (solver.M_globalMatrixPtr) );
1214  M_initialTime = solver.M_initialTime;
1215  M_endTime = solver.M_endTime;
1216  M_timeStep = solver.M_timeStep;
1217  M_diffusionTensorIntra = solver.M_diffusionTensorIntra;
1218  M_diffusionTensorExtra = solver.M_diffusionTensorExtra;
1219  setRhs (* (solver.M_rhsPtr) );
1220  setRhsUnique (* (solver.M_rhsPtrUnique) );
1221  setPotential (* (solver.M_potentialPtr) );
1222 
1223  setLinearSolver (* (solver.M_linearSolverPtr) );
1224  copyGlobalSolution (solver.M_globalSolution);
1225  copyGlobalRhs (solver.M_globalRhs);
1226  M_elementsOrder = solver.M_elementsOrder;
1227  setFiber (* (solver.M_fiberPtr) );
1228 
1229  return *this;
1230 }
1231 
1232 
1233 /********* SETUP METHODS */ //////
1234 template<typename Mesh, typename IonicModel>
1235 void ElectroETABidomainSolver<Mesh, IonicModel>::setupFibers()
1236 {
1237 
1238  std::shared_ptr<FESpace<mesh_Type, MapEpetra> > Space3D (
1239  new FESpace<mesh_Type, MapEpetra> (M_localMeshPtr, M_elementsOrder,
1240  3, M_commPtr) );
1241 
1242  M_fiberPtr.reset (new vector_Type (Space3D->map() ) );
1243 
1244  int d1 = (*M_fiberPtr).epetraVector().MyLength() / 3;
1245  (*M_fiberPtr) *= 0;
1246  int j (0);
1247  for (int k (0); k < d1; k++)
1248  {
1249  j = (*M_fiberPtr).blockMap().GID (k + d1);
1250  (*M_fiberPtr) [j] = 1.0;
1251  }
1252 }
1253 
1254 template<typename Mesh, typename IonicModel>
1255 void ElectroETABidomainSolver<Mesh, IonicModel>::setupFibers (
1256  VectorSmall<3> fibers)
1257 {
1258  std::shared_ptr<FESpace<mesh_Type, MapEpetra> > Space3D (
1259  new FESpace<mesh_Type, MapEpetra> (M_localMeshPtr, M_elementsOrder,
1260  3, M_commPtr) );
1261 
1262  M_fiberPtr.reset (new vector_Type (Space3D->map() ) );
1263 
1264  ElectrophysiologyUtility::setupFibers (*M_fiberPtr, fibers);
1265 }
1266 
1267 template<typename Mesh, typename IonicModel>
1269  std::string postDir)
1270 {
1271  std::shared_ptr<FESpace<mesh_Type, MapEpetra> > Space3D (
1272  new FESpace<mesh_Type, MapEpetra> (M_localMeshPtr, M_elementsOrder,
1273  3, M_commPtr) );
1274 
1275  ExporterHDF5 < mesh_Type > exp;
1276  exp.setMeshProcId (M_localMeshPtr, M_commPtr->MyPID() );
1277  exp.setPostDir (postDir);
1278  exp.setPrefix ("FiberDirection");
1279  exp.addVariable (ExporterData<mesh_Type>::VectorField, "fibers", Space3D,
1280  M_fiberPtr, UInt (0) );
1281  exp.postProcess (0);
1282  exp.closeFile();
1283 }
1284 
1285 template<typename Mesh, typename IonicModel>
1287  IOFile_Type& exporter)
1288 {
1289  std::shared_ptr<FESpace<mesh_Type, MapEpetra> > Space3D (
1290  new FESpace<mesh_Type, MapEpetra> (M_localMeshPtr, M_elementsOrder,
1291  3, M_commPtr) );
1292 
1293  exporter.addVariable (ExporterData<mesh_Type>::VectorField, "fibers",
1294  Space3D, M_fiberPtr, UInt (0) );
1295  exporter.postProcess (0);
1296 }
1297 
1298 template<typename Mesh, typename IonicModel>
1299 void ElectroETABidomainSolver<Mesh, IonicModel>::importSolution (
1300  GetPot& dataFile, std::string prefix, std::string postDir, Real time)
1301 {
1302  const std::string exporterType = dataFile ("exporter/type", "ensight");
1303 
1304  IOFilePtr_Type importer (new hdf5IOFile_Type() );
1305  importer->setDataFromGetPot (dataFile);
1306  importer->setPrefix (prefix);
1307  importer->setPostDir (postDir);
1308 
1309  importer->setMeshProcId (M_feSpacePtr->mesh(),
1310  M_feSpacePtr->map().comm().MyPID() );
1311 
1312  int i;
1313  for (i = 0; i < M_ionicModelPtr->Size(); i++)
1314  importer->addVariable (IOData_Type::ScalarField,
1315  "Variable" + number2string (i), M_feSpacePtr,
1316  M_globalSolution.at (i), static_cast<UInt> (0) );
1317  importer->addVariable (IOData_Type::ScalarField, "Variable" + number2string (i), M_feSpacePtr, M_potentialExtraPtr, static_cast<UInt> (0) );
1318  importer->importFromTime (time);
1319  importer->closeFile();
1320 
1321 }
1322 
1323 
1324 template<typename Mesh, typename IonicModel>
1325 void ElectroETABidomainSolver<Mesh, IonicModel>::setup (GetPot& dataFile,
1326  short int ionicSize)
1327 {
1328 
1329 
1330 
1331  M_feSpacePtr.reset (
1332  new feSpace_Type (M_localMeshPtr, M_elementsOrder, 1, M_commPtr) );
1333  M_ETFESpacePtr.reset (
1334  new ETFESpace_Type (M_localMeshPtr, & (M_feSpacePtr -> refFE() ) , M_commPtr) );
1335  M_displacementETFESpacePtr.reset (
1336  new ETFESpaceVectorial_Type (M_localMeshPtr, & (M_feSpacePtr -> refFE() ), M_commPtr) );
1337 
1338  M_massMatrixPtr.reset (new blockMatrix_Type (M_ETFESpacePtr->map() | M_ETFESpacePtr->map() ) );
1339  M_stiffnessMatrixPtr.reset (new blockMatrix_Type (M_ETFESpacePtr->map() | M_ETFESpacePtr->map() ) );
1340  M_globalMatrixPtr.reset (new blockMatrix_Type (M_ETFESpacePtr->map() | M_ETFESpacePtr->map() ) );
1341 
1342  M_rhsPtr.reset (new blockVector_Type (M_ETFESpacePtr->map() | M_ETFESpacePtr->map(), Repeated) );
1343  M_rhsPtrUnique.reset (new blockVector_Type (M_ETFESpacePtr->map() | M_ETFESpacePtr->map(), Unique) );
1344  M_potentialGlobalPtr.reset (new blockVector_Type (M_ETFESpacePtr->map() | M_ETFESpacePtr->map() ) );
1345  M_potentialTransPtr.reset (new vector_Type (M_ETFESpacePtr->map() ) );
1346  M_potentialExtraPtr.reset (new vector_Type (M_ETFESpacePtr->map() ) );
1347 
1348 
1349  //***********************//
1350  // Setup Linear Solver //
1351  //***********************//
1352  setupLinearSolver (dataFile);
1353 
1354  //**************************//
1355  // Setup Initial condition //
1356  //**************************//
1358  vector_Type Iapp (M_feSpacePtr->map() );
1359  Iapp *= 0.0;
1360  M_ionicModelPtr->setAppliedCurrent (Iapp);
1361 
1362  setupGlobalSolution (ionicSize);
1363  setupGlobalRhs (ionicSize);
1364 }
1365 
1366 template<typename Mesh, typename IonicModel>
1367 void ElectroETABidomainSolver<Mesh, IonicModel>::setup (std::string meshName,
1368  std::string meshPath, GetPot& dataFile, short int ionicSize)
1369 {
1370  //partitioning the mesh
1371  partitionMesh (meshName, meshPath);
1372  setup (dataFile, ionicSize);
1373 }
1374 
1375 
1376 template<typename Mesh, typename IonicModel>
1378 {
1379 
1380 
1381  if (M_lumpedMassMatrix)
1382  {
1383  // if (M_displacementPtr)
1384  // setupLumpedMassMatrix(*M_displacementPtr);
1385  // else
1386  setupLumpedMassMatrix();
1387  }
1388  else
1389  {
1390  if (M_displacementPtr)
1391  {
1392  setupMassMatrix (*M_displacementPtr);
1393  }
1394  else
1395  {
1396  *M_massMatrixPtr *= 0.0;
1397  if (M_localMeshPtr->comm()->MyPID() == 0)
1398  {
1399  std::cout << "\nETA Bidomain Solver: Setting up mass matrix";
1400  }
1401 
1402  {
1403  using namespace ExpressionAssembly;
1404  integrate (elements (M_localMeshPtr), M_feSpacePtr->qr(),
1405  M_ETFESpacePtr, M_ETFESpacePtr, phi_i * phi_j)
1406  >> M_massMatrixPtr->block (0, 0);
1407  }
1408 
1409  M_massMatrixPtr->globalAssemble();
1410  }
1411  }
1412 }
1413 
1414 
1415 template<typename Mesh, typename IonicModel>
1417  vector_Type& disp)
1418 {
1419  if (M_commPtr->MyPID() == 0)
1420  {
1421  std::cout << "\nETA Bidomain Solver: Setting up mass matrix with coupling with mechanics ";
1422  }
1423 
1424  *M_massMatrixPtr *= 0.0;
1425  ETFESpaceVectorialPtr_Type spaceVectorial ( new ETFESpaceVectorial_Type ( M_localMeshPtr, & (M_feSpacePtr -> refFE() ), M_commPtr ) );
1426 
1427  {
1428  using namespace ExpressionAssembly;
1429  BOOST_AUTO_TPL (I, value (M_identity) );
1430  BOOST_AUTO_TPL (Grad_u, grad (spaceVectorial, disp) );
1431  BOOST_AUTO_TPL (F, (Grad_u + I) );
1432  BOOST_AUTO_TPL (J, det (F) );
1433  integrate (elements (M_localMeshPtr), M_feSpacePtr->qr(), M_ETFESpacePtr,
1434  M_ETFESpacePtr, J * phi_i * phi_j)
1435  >> M_massMatrixPtr->block (0, 0);
1436  }
1437 
1438  M_massMatrixPtr->globalAssemble();
1439 }
1440 
1441 
1442 template<typename Mesh, typename IonicModel>
1444 {
1445 
1446  M_lumpedMassMatrix = true;
1447  if (M_displacementPtr)
1448  {
1449  setupLumpedMassMatrix (*M_displacementPtr);
1450  }
1451  else
1452  {
1453  *M_massMatrixPtr *= 0.0;
1454  if (M_localMeshPtr->comm()->MyPID() == 0)
1455  {
1456  std::cout << "\nETA Bidomain Solver: Setting up lumped mass matrix";
1457  }
1458  {
1459  using namespace ExpressionAssembly;
1460 
1461  integrate (elements (M_localMeshPtr), quadRuleTetra4ptNodal,
1462  M_ETFESpacePtr, M_ETFESpacePtr, phi_i * phi_j)
1463  >> M_massMatrixPtr->block (0, 0);
1464 
1465  }
1466  M_massMatrixPtr->globalAssemble();
1467 
1468  }
1469 }
1470 
1471 
1472 
1473 template<typename Mesh, typename IonicModel>
1475  vector_Type& disp)
1476 {
1477  /*
1478  *M_massMatrixPtr *= 0.0;
1479  std::shared_ptr<FESpace<mesh_Type, MapEpetra> > vectorialSpace(
1480  new FESpace<mesh_Type, MapEpetra>(M_localMeshPtr, M_elementsOrder,
1481  3, M_commPtr));
1482 
1483  vectorPtr_Type dUdx(new vector_Type(M_displacementPtr->map()));
1484  vectorPtr_Type dUdy(new vector_Type(M_displacementPtr->map()));
1485  vectorPtr_Type dUdz(new vector_Type(M_displacementPtr->map()));
1486 
1487  *dUdx = GradientRecovery::ZZGradient(vectorialSpace, *M_displacementPtr, 0);
1488  *dUdy = GradientRecovery::ZZGradient(vectorialSpace, *M_displacementPtr, 1);
1489  *dUdz = GradientRecovery::ZZGradient(vectorialSpace, *M_displacementPtr, 2);
1490 
1491  vectorPtr_Type J(new vector_Type(M_potentialPtr->map()));
1492  int n = J->epetraVector().MyLength();
1493  int i(0);
1494  int j(0);
1495  int k(0);
1496  for (int p(0); p < n; p++) {
1497  i = dUdx->blockMap().GID(p);
1498  j = dUdx->blockMap().GID(p + n);
1499  k = dUdx->blockMap().GID(p + 2 * n);
1500 
1501  Real F11 = 1.0 + (*dUdx)[i];
1502  Real F12 = (*dUdy)[i];
1503  Real F13 = (*dUdz)[i];
1504  Real F21 = (*dUdx)[j];
1505  Real F22 = 1.0 + (*dUdy)[j];
1506  Real F23 = (*dUdz)[j];
1507  Real F31 = (*dUdx)[k];
1508  Real F32 = (*dUdy)[k];
1509  Real F33 = 1.0 + (*dUdz)[k];
1510 
1511  (*J)[i] = F11 * ( F22 * F33 - F32 * F23 )
1512  - F12 * ( F21 * F33 - F31 * F23 )
1513  + F13 * ( F21 * F32 - F31 * F22 );
1514  }
1515 
1516  if (M_localMeshPtr->comm()->MyPID() == 0) {
1517  std::cout << "\nETA Bidomain Solver: Setting up lumped mass matrix coupling with mechanics";
1518  }
1519  //CHECK IT !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11
1520  /* {
1521  using namespace ExpressionAssembly;
1522 
1523  integrate(elements(M_localMeshPtr), quadRuleTetra4ptNodal,
1524  M_ETFESpacePtr, M_ETFESpacePtr,
1525  value(M_ETFESpacePtr, *J) * phi_i * phi_j) >> M_massMatrixPtr;
1526 
1527  }*/
1528 
1529  //Create one Mass Matrix, because it is the same in all the blocks up to an sign
1530  /* std::shared_ptr<blockMatrix_Type> ETcomponentMassMatrix
1531  (new blockMatrix_Type ( M_ETFESpacePtr->map() ) );
1532  *ETcomponentMassMatrix *= 0.0;
1533 
1534  {
1535  using namespace ExpressionAssembly;
1536 
1537  integrate ( elements (M_ETFESpacePtr->mesh() ),
1538  quadRuleTetra4ptNodal,
1539  ETFESpacePtr,
1540  ETFESpacePtr,
1541  value(M_ETFESpacePtr, *J) * phi_i * phi_j
1542  )
1543  >> ETcomponentMassMatrix->block (0, 0);
1544  }
1545  ETcomponentMassMatrix->globalAssemble();
1546 
1547 
1548  // ---------------------------------------------------------------
1549  // We copy the blocks
1550  // ---------------------------------------------------------------
1551  //result matrix
1552  // M -M
1553  // -M M
1554  MatrixEpetraStructuredUtility::copyBlock (*ETcomponentMassMatrix->block (0, 0), *M_massMatrixPtr->block (0, 0) );
1555  MatrixEpetraStructuredUtility::copyBlock (*ETcomponentMassMatrix->block (0, 0), *M_massMatrixPtr->block (1, 1) );
1556  *ETsystemMatrixIII *= -1.0;
1557  MatrixEpetraStructuredUtility::copyBlock (*ETcomponentMassMatrix->block (0, 0), *M_massMatrixPtr->block (0, 1) );
1558  MatrixEpetraStructuredUtility::copyBlock (*ETcomponentMassMatrix->block (0, 0), *M_massMatrixPtr->block (1, 0) );
1559 
1560 
1561  M_massMatrixPtr->globalAssemble();
1562  */
1563 }
1564 
1565 template<typename Mesh, typename IonicModel>
1567 {
1568 
1569  if (M_displacementPtr)
1570  {
1571  setupStiffnessMatrix (M_displacementPtr);
1572  }
1573  else
1574  {
1575  setupStiffnessMatrix (M_diffusionTensorIntra, M_diffusionTensorExtra);
1576  }
1577 
1578 
1579 }
1580 
1581 
1582 
1583 template<typename Mesh, typename IonicModel>
1585  VectorSmall<3> diffusionIntra, VectorSmall<3> diffusionExtra)
1586 {
1587 
1588  if (M_localMeshPtr->comm()->MyPID() == 0)
1589  {
1590  std::cout
1591  << "\nETA Bidomain Solver: Setting up stiffness matrix (only fiber field)";
1592  }
1593 
1594  *M_stiffnessMatrixPtr *= 0.0;
1595  Real sigmal = diffusionIntra[0];
1596  Real sigmat = diffusionIntra[1];
1597 
1598  ETFESpaceVectorialPtr_Type spaceVectorial (
1599  new ETFESpaceVectorial_Type (M_localMeshPtr, & (M_feSpacePtr -> refFE() ), M_commPtr) );
1600  blockMatrixPtr_Type ETcomponentStiffnessMatrix
1601  (new blockMatrix_Type ( M_ETFESpacePtr->map() ) );
1602  *ETcomponentStiffnessMatrix *= 0.0;
1603 
1604  //Intracellular conduction
1605  {
1606  using namespace ExpressionAssembly;
1607 
1608  BOOST_AUTO_TPL (I, value (M_identity) );
1609  BOOST_AUTO_TPL (f0, value (spaceVectorial, *M_fiberPtr) );
1610  BOOST_AUTO_TPL (D,
1611  value (sigmat) * I
1612  + (value (sigmal) - value (sigmat) )
1613  * outerProduct (f0, f0) );
1614 
1615  integrate (elements (M_localMeshPtr), M_feSpacePtr->qr(), M_ETFESpacePtr,
1616  M_ETFESpacePtr,
1617  dot ( D * grad (phi_i), grad (phi_j) ) )
1618  >> ETcomponentStiffnessMatrix->block (0, 0);
1619 
1620  }
1621  ETcomponentStiffnessMatrix->globalAssemble();
1622 
1623  MatrixEpetraStructuredUtility::copyBlock (*ETcomponentStiffnessMatrix->block (0, 0), *M_stiffnessMatrixPtr->block (0, 1) );
1624  MatrixEpetraStructuredUtility::copyBlock (*ETcomponentStiffnessMatrix->block (0, 0), *M_stiffnessMatrixPtr->block (1, 0) );
1625  MatrixEpetraStructuredUtility::copyBlock (*ETcomponentStiffnessMatrix->block (0, 0), *M_stiffnessMatrixPtr->block (0, 0) );
1626 
1627  // Extracellular conduction
1628  sigmal += diffusionExtra[0];
1629  sigmat += diffusionExtra[1];
1630 
1631  {
1632  using namespace ExpressionAssembly;
1633 
1634  BOOST_AUTO_TPL (I, value (M_identity) );
1635  BOOST_AUTO_TPL (f0, value (spaceVectorial, *M_fiberPtr) );
1636  BOOST_AUTO_TPL (D,
1637  (value (sigmat) * I
1638  + (value (sigmal) - value (sigmat) )
1639  * outerProduct (f0, f0) ) );
1640 
1641  integrate (elements (M_localMeshPtr), M_feSpacePtr->qr(), M_ETFESpacePtr,
1642  M_ETFESpacePtr,
1643  dot ( D * grad (phi_i), grad (phi_j) ) )
1644  >> M_stiffnessMatrixPtr->block (1, 1);
1645 
1646  }
1647  M_stiffnessMatrixPtr->globalAssemble();
1648 }
1649 
1650 
1651 
1652 
1653 
1654 template<typename Mesh, typename IonicModel>
1656  vectorPtr_Type disp)
1657 {
1658  /*
1659  //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11
1660  //At least the ExtraCellular is wrong. It whould be minus.
1661  if (M_localMeshPtr->comm()->MyPID() == 0) {
1662  std::cout
1663  << "\nETA Bidomain Solver: Setting up stiffness matrix coupling with mechanics";
1664  }
1665 
1666  *M_stiffnessMatrixPtr *= 0.0;
1667 
1668  //Intra Cellular
1669  Real sigmal = M_diffusionTensorIntra[0];
1670  Real sigmat = M_diffusionTensorIntra[1];
1671 
1672  ETFESpaceVectorialPtr_Type spaceVectorial(
1673  new ETFESpaceVectorial_Type(M_localMeshPtr, &(M_feSpacePtr -> refFE()), M_commPtr));
1674 
1675  {
1676  using namespace ExpressionAssembly;
1677 
1678  BOOST_AUTO_TPL(I, value(M_identity));
1679  BOOST_AUTO_TPL(Grad_u, grad(spaceVectorial, *disp));
1680  BOOST_AUTO_TPL(F, (Grad_u + I));
1681  BOOST_AUTO_TPL(FmT, minusT(F));
1682  BOOST_AUTO_TPL(Fm1, transpose(FmT));
1683  BOOST_AUTO_TPL(J, det(F));
1684  BOOST_AUTO_TPL(Jm23, pow(J, -2. / 3));
1685  BOOST_AUTO_TPL(f0, value(spaceVectorial, *M_fiberPtr));
1686  BOOST_AUTO_TPL(D,
1687  value(sigmat) * I
1688  + (value(sigmal) - value(sigmat))
1689  * outerProduct(f0, f0));
1690 
1691  integrate(elements(M_localMeshPtr), M_feSpacePtr->qr(), M_ETFESpacePtr,
1692  M_ETFESpacePtr,
1693  dot(J * Fm1 * D * FmT * grad(phi_i), grad(phi_j)))
1694  >> M_stiffnessMatrixPtr->block (0, 0);
1695 
1696  }
1697  //Extra cellular
1698  sigmal = M_diffusionTensorExtra[0];
1699  sigmat = M_diffusionTensorExtra[1];
1700  {
1701  using namespace ExpressionAssembly;
1702 
1703  BOOST_AUTO_TPL(I, value(M_identity));
1704  BOOST_AUTO_TPL(Grad_u, grad(spaceVectorial, *disp));
1705  BOOST_AUTO_TPL(F, (Grad_u + I));
1706  BOOST_AUTO_TPL(FmT, minusT(F));
1707  BOOST_AUTO_TPL(Fm1, transpose(FmT));
1708  BOOST_AUTO_TPL(J, det(F));
1709  BOOST_AUTO_TPL(Jm23, pow(J, -2. / 3));
1710  BOOST_AUTO_TPL(f0, value(spaceVectorial, *M_fiberPtr));
1711  BOOST_AUTO_TPL(D,
1712  value(sigmat) * I
1713  + (value(sigmal) - value(sigmat))
1714  * outerProduct(f0, f0));
1715 
1716  integrate(elements(M_localMeshPtr), M_feSpacePtr->qr(), M_ETFESpacePtr,
1717  M_ETFESpacePtr,
1718  dot(J * Fm1 * D * FmT * grad(phi_i), grad(phi_j)))
1719  >> M_stiffnessMatrixPtr->block (0, 0);
1720 
1721  }
1722 
1723  M_stiffnessMatrixPtr->globalAssemble();
1724  */
1725 }
1726 
1727 
1728 template<typename Mesh, typename IonicModel>
1730 {
1731  (*M_globalMatrixPtr) *= 0;
1732  (*M_globalMatrixPtr) = (*M_stiffnessMatrixPtr);
1733  (*M_globalMatrixPtr) *= 1.0 / M_surfaceVolumeRatio;
1734 
1735  // This line should be right, as long as the membraneCpacitance is intra and extra cellular the same
1736  (*M_globalMatrixPtr) += ( (*M_massMatrixPtr) * ( M_ionicModelPtr -> membraneCapacitance() / M_timeStep) );
1737 }
1738 
1739 template<typename Mesh, typename IonicModel>
1741  GetPot dataFile)
1742 {
1743 
1744  prec_Type* precRawPtr;
1745  basePrecPtr_Type precPtr;
1746  precRawPtr = new prec_Type;
1747  precRawPtr->setDataFromGetPot (dataFile, "prec");
1748  precPtr.reset (precRawPtr);
1749  Teuchos::RCP < Teuchos::ParameterList > solverParamList = Teuchos::rcp (
1750  new Teuchos::ParameterList);
1751 
1752  std::string xmlpath = dataFile ("electrophysiology/bidomain_xml_path",
1753  "./");
1754  std::string xmlfile = dataFile ("electrophysiology/bidomain_xml_file",
1755  "BidomainSolverParamList.xml");
1756 
1757  solverParamList = Teuchos::getParametersFromXmlFile (xmlpath + xmlfile);
1758 
1759  M_linearSolverPtr->setCommunicator (M_commPtr);
1760  M_linearSolverPtr->setParameters (*solverParamList);
1761  M_linearSolverPtr->setPreconditioner (precPtr);
1762  M_linearSolverPtr->setOperator (M_globalMatrixPtr);
1763 }
1764 
1765 template<typename Mesh, typename IonicModel>
1766 void ElectroETABidomainSolver<Mesh, IonicModel>::setupLinearSolver (
1767  GetPot dataFile, list_Type list)
1768 {
1769 
1770  prec_Type* precRawPtr;
1771  basePrecPtr_Type precPtr;
1772  precRawPtr = new prec_Type;
1773  precRawPtr->setDataFromGetPot (dataFile, "prec");
1774  precPtr.reset (precRawPtr);
1775 
1776  M_linearSolverPtr->setCommunicator (M_commPtr);
1777  M_linearSolverPtr->setParameters (list);
1778  M_linearSolverPtr->setPreconditioner (precPtr);
1779  M_linearSolverPtr->setOperator (M_globalMatrixPtr);
1780 }
1781 
1782 template<typename Mesh, typename IonicModel>
1783 void ElectroETABidomainSolver<Mesh, IonicModel>::setupGlobalSolution (
1784  short int ionicSize)
1785 {
1786  //This is the solution vector for the IonicModel
1787  M_globalSolution.push_back (M_potentialTransPtr);
1788  //M_globalSolution.push_back(M_potentialExtraPtr);
1789  for (int k = 1; k < ionicSize; ++k)
1790  {
1791  M_globalSolution.push_back (
1792  * (new vectorPtr_Type (new VectorEpetra (M_ETFESpacePtr->map() ) ) ) );
1793  }
1794 }
1795 
1796 template<typename Mesh, typename IonicModel>
1797 void ElectroETABidomainSolver<Mesh, IonicModel>::setupGlobalRhs (
1798  short int ionicSize)
1799 {
1800  M_globalRhs.push_back (M_ionicModelPtr->appliedCurrentPtr() );
1801  for (int k = 1; k < ionicSize; ++k)
1802  {
1803  M_globalRhs.push_back (
1804  * (new vectorPtr_Type (new VectorEpetra (M_ETFESpacePtr->map() ) ) ) );
1805  }
1806 }
1807 
1808 /****************Solver ********************************************/
1809 
1810 template<typename Mesh, typename IonicModel>
1811 void ElectroETABidomainSolver<Mesh, IonicModel>::solveOneReactionStepFE (
1812  int subiterations)
1813 {
1814  M_ionicModelPtr->superIonicModel::computeRhs (M_globalSolution, M_globalRhs);
1815  for (int i = 0; i < M_ionicModelPtr->Size(); i++)
1816  {
1817  if (i == 0)
1818  * (M_globalSolution.at (i) ) = * (M_globalSolution.at (i) )
1819  + ( (M_timeStep) / subiterations / M_ionicModelPtr -> membraneCapacitance() ) * (* (M_globalRhs.at (i) ) );
1820  else
1821  * (M_globalSolution.at (i) ) = * (M_globalSolution.at (i) )
1822  + ( (M_timeStep) / subiterations) * (* (M_globalRhs.at (i) ) );
1823  }
1824  //copying th transmembrane potential back
1825  M_potentialGlobalPtr->subset ( (*M_globalSolution.at (0) ), (M_globalSolution.at (0)->map() ), (UInt) 0, (UInt) 0);
1826 }
1827 
1828 
1829 template<typename Mesh, typename IonicModel>
1830 void ElectroETABidomainSolver<Mesh, IonicModel>::solveOneReactionStepRL (
1831  int subiterations)
1832 {
1833  M_ionicModelPtr->superIonicModel::computeRhs (M_globalSolution, M_globalRhs);
1834 
1835  * (M_globalSolution.at (0) ) = * (M_globalSolution.at (0) )
1836  + ( (M_timeStep) / subiterations / M_ionicModelPtr -> membraneCapacitance() ) * (* (M_globalRhs.at (0) ) );
1837 
1838  M_ionicModelPtr->superIonicModel::computeGatingVariablesWithRushLarsen (
1839  M_globalSolution, M_timeStep / subiterations);
1840  int offset = M_ionicModelPtr->numberOfGatingVariables() + 1;
1841  for (int i = offset; i < M_ionicModelPtr->Size(); i++)
1842  {
1843  * (M_globalSolution.at (i) ) = * (M_globalSolution.at (i) )
1844  + ( (M_timeStep) / subiterations) * (* (M_globalRhs.at (i) ) );
1845  }
1846  M_potentialGlobalPtr->subset ( (*M_globalRhs.at (0) ), (M_globalRhs.at (0)->map() ), (UInt) 0, (UInt) 0);
1847 }
1848 
1849 template<typename Mesh, typename IonicModel>
1850 void ElectroETABidomainSolver<Mesh, IonicModel>::solveOneDiffusionStepBE()
1851 {
1852  if (M_displacementPtr)
1853  {
1854  M_linearSolverPtr->setOperator (M_globalMatrixPtr);
1855  }
1856  M_linearSolverPtr->setRightHandSide (M_rhsPtrUnique);
1857  M_linearSolverPtr->solve (M_potentialGlobalPtr);
1858 
1859  M_potentialTransPtr->subset ( (const VectorEpetra&) (*M_potentialGlobalPtr->block (0)->vectorPtr() ), M_potentialTransPtr->map(), M_potentialGlobalPtr->block (0)->firstIndex(), static_cast<UInt> (0) );
1860  M_potentialExtraPtr->subset ( (const VectorEpetra&) (*M_potentialGlobalPtr->block (1)->vectorPtr() ), M_potentialExtraPtr->map(), M_potentialGlobalPtr->block (1)->firstIndex(), static_cast<UInt> (0) );
1861 }
1862 
1863 template<typename Mesh, typename IonicModel>
1864 void ElectroETABidomainSolver<Mesh, IonicModel>::solveOneSplittingStep()
1865 {
1866  solveOneReactionStepFE();
1867  (*M_rhsPtrUnique) *= 0.0;
1868  updateRhs();
1869  solveOneDiffusionStepBE();
1870 }
1871 
1872 
1873 
1874 /************** EXPORTER */ //////////////
1875 template<typename Mesh, typename IonicModel>
1876 void ElectroETABidomainSolver<Mesh, IonicModel>::setupPotentialExporter (
1877  IOFile_Type& exporter)
1878 {
1879  exporter.setMeshProcId (M_localMeshPtr, M_commPtr->MyPID() );
1880  exporter.setPrefix ("Potential");
1881  exporter.addVariable (ExporterData<mesh_Type>::ScalarField, "PotentialTransmembrane",
1882  M_feSpacePtr, M_globalSolution.at (0), UInt (0) );
1883  exporter.addVariable (ExporterData<mesh_Type>::ScalarField, "PotentialExtracellular",
1884  M_feSpacePtr, M_potentialExtraPtr, UInt (0) );
1885 
1886 }
1887 
1888 template<typename Mesh, typename IonicModel>
1889 void ElectroETABidomainSolver<Mesh, IonicModel>::setupPotentialExporter (
1890  IOFile_Type& exporter, std::string fileName)
1891 {
1892  exporter.setMeshProcId (M_localMeshPtr, M_commPtr->MyPID() );
1893  exporter.setPrefix (fileName);
1894  exporter.exportPID (M_localMeshPtr, M_commPtr);
1895  exporter.addVariable (ExporterData<mesh_Type>::ScalarField, "PotentialTransmembrane",
1896  M_feSpacePtr, M_globalSolution.at (0), UInt (0) );
1897  exporter.addVariable (ExporterData<mesh_Type>::ScalarField, "PotentialExtracellular",
1898  M_feSpacePtr, M_potentialExtraPtr, UInt (0) );
1899 }
1900 
1901 template<typename Mesh, typename IonicModel>
1902 void ElectroETABidomainSolver<Mesh, IonicModel>::setupExporter (
1903  IOFile_Type& exporter, std::string fileName, std::string folder)
1904 {
1905  exporter.setMeshProcId (M_localMeshPtr, M_commPtr->MyPID() );
1906  exporter.setPrefix (fileName);
1907  exporter.exportPID (M_localMeshPtr, M_commPtr);
1908  exporter.setPostDir (folder);
1909  std::string variableName;
1910  for (int i = 0; i < M_ionicModelPtr->Size(); i++)
1911  {
1912  variableName = "Variable" + std::to_string<std::string> (i);
1913  exporter.addVariable (ExporterData<mesh_Type>::ScalarField, variableName,
1914  M_feSpacePtr, M_globalSolution.at (i), UInt (0) );
1915  }
1916  exporter.addVariable (ExporterData<mesh_Type>::ScalarField, "PotentialExtracellular",
1917  M_feSpacePtr, M_potentialExtraPtr, UInt (0) );
1918 }
1919 
1920 /******** INITIALIZITION FOR CONSTRUCTOR ****/ //////
1921 template<typename Mesh, typename IonicModel>
1922 void ElectroETABidomainSolver<Mesh, IonicModel>::init()
1923 {
1924  M_linearSolverPtr.reset (new LinearSolver() );
1925  M_globalSolution = * (new vectorOfPtr_Type() );
1926  M_globalRhs = * (new vectorOfPtr_Type() );
1927  M_identity (0, 0) = 1.0;
1928  M_identity (0, 1) = 0.0;
1929  M_identity (0, 2) = 0.0;
1930  M_identity (1, 0) = 0.0;
1931  M_identity (1, 1) = 1.0;
1932  M_identity (1, 2) = 0.0;
1933  M_identity (2, 0) = 0.0;
1934  M_identity (2, 1) = 0.0;
1935  M_identity (2, 2) = 1.0;
1936 }
1937 
1938 template<typename Mesh, typename IonicModel>
1939 void ElectroETABidomainSolver<Mesh, IonicModel>::init (
1940  ionicModelPtr_Type model)
1941 {
1942  init();
1943  M_commPtr.reset (new Epetra_MpiComm (MPI_COMM_WORLD) );
1944  M_localMeshPtr.reset (new mesh_Type (M_commPtr) );
1945  M_fullMeshPtr.reset (new mesh_Type (M_commPtr) );
1946  M_ionicModelPtr = model;
1947 
1948 }
1949 
1950 template<typename Mesh, typename IonicModel>
1951 void ElectroETABidomainSolver<Mesh, IonicModel>::init (commPtr_Type comm)
1952 {
1953  init();
1954  M_commPtr = comm;
1955  M_localMeshPtr.reset (new mesh_Type (M_commPtr) );
1956  M_fullMeshPtr.reset (new mesh_Type (M_commPtr) );
1957 }
1958 
1959 template<typename Mesh, typename IonicModel>
1960 void ElectroETABidomainSolver<Mesh, IonicModel>::init (meshPtr_Type meshPtr)
1961 {
1962  init();
1963  //TODO change the meshPtr to pass the fullMeshPtr
1964  M_localMeshPtr = meshPtr;
1965  M_fullMeshPtr.reset (new mesh_Type (M_commPtr) );
1966  M_commPtr = meshPtr->comm();
1967 }
1968 
1969 template<typename Mesh, typename IonicModel>
1970 void ElectroETABidomainSolver<Mesh, IonicModel>::init (commPtr_Type comm,
1971  ionicModelPtr_Type model)
1972 {
1973  init (comm);
1974  M_ionicModelPtr = model;
1975 }
1976 
1977 template<typename Mesh, typename IonicModel>
1978 void ElectroETABidomainSolver<Mesh, IonicModel>::init (meshPtr_Type meshPtr,
1979  ionicModelPtr_Type model)
1980 {
1981  init (meshPtr);
1982  M_ionicModelPtr = model;
1983 }
1984 
1985 /********* parameter initialization */ ////////
1986 template<typename Mesh, typename IonicModel>
1987 void ElectroETABidomainSolver<Mesh, IonicModel>::setParameters()
1988 {
1989 
1990  // Suggested values from Niederer et al. 2011
1991 
1992  M_surfaceVolumeRatio = 1400.0;
1993 
1994  M_diffusionTensorIntra[0] = 1.7;
1995  M_diffusionTensorIntra[1] = 0.19;
1996  M_diffusionTensorIntra[2] = 0.19;
1997 
1998  M_diffusionTensorExtra[0] = 6.2;
1999  M_diffusionTensorExtra[1] = 2.4;
2000  M_diffusionTensorExtra[2] = 2.4;
2001 
2002  M_initialTime = 0.0;
2003  M_endTime = 50.0;
2004  M_timeStep = 0.01;
2005  M_elementsOrder = "P1";
2006  M_lumpedMassMatrix = false;
2007 
2008 }
2009 
2010 template<typename Mesh, typename IonicModel>
2011 void ElectroETABidomainSolver<Mesh, IonicModel>::setParameters (
2012  list_Type list)
2013 {
2014 
2015  // Suggested values from Niederer et al. 2011
2016 
2017  M_surfaceVolumeRatio = list.get ("surfaceVolumeRatio", 1400.0);
2018 
2019  M_diffusionTensorIntra[0] = list.get ("longitudinalDiffusionIntra", 1.7);
2020  M_diffusionTensorIntra[1] = list.get ("transversalDiffusionIntra", 0.19);
2021  M_diffusionTensorIntra[2] = M_diffusionTensorIntra[1];
2022 
2023  M_diffusionTensorExtra[0] = list.get ("longitudinalDiffusionExtra", 6.2);
2024  M_diffusionTensorExtra[1] = list.get ("transversalDiffusionExtra", 2.4);
2025  M_diffusionTensorExtra[2] = M_diffusionTensorExtra[1];
2026 
2027  M_initialTime = list.get ("initialTime", 0.0);
2028  M_endTime = list.get ("endTime", 50.0);
2029  M_timeStep = list.get ("timeStep", 0.01);
2030  M_elementsOrder = list.get ("elementsOrder", "P1");
2031  M_lumpedMassMatrix = list.get ("LumpedMass", false);
2032 
2033 }
2034 
2035 } // namespace LifeV
2036 
2037 #endif //_BIDOMAINSOLVER_H_
VectorEpetra - The Epetra Vector format Wrapper.
void setup(GetPot &dataFile, short int ionicSize)
void setPotentialTransPtr(const vectorPtr_Type p)
void exportFiberDirection(IOFile_Type &exporter)
save the fiber direction into the given exporter
void copyGlobalRhs(const vectorOfPtr_Type &p)
void solveOneSVIStep(IOFile_Type &exporter, Real t)
Solve one full step with ionic current interpolation and export the solution.
void setIonicModel(const ionicModel_Type &p)
void setCommPtr(const commPtr_Type p)
set the pointer to the Epetra communicator
void setSurfaceVolumeRatio(const Real &p)
set the surface to volume ratio
void setupStiffnessMatrix(VectorSmall< 3 > diffusionIntra, VectorSmall< 3 > diffusionExtra)
create stiffness matrix given a diagonal diffusion tensor
vectorPtr_Type displacementPtr() const
get the pointer to the transmembrane potential
std::shared_ptr< mesh_Type > meshPtr_Type
ElectroETABidomainSolver(list_Type list, GetPot &dataFile, ionicModelPtr_Type model, meshPtr_Type meshPtr)
Constructor.
void solveOneICIStep()
Solve one full step with ionic current interpolation.
void exportFiberDirection(std::string postDir="./")
Generates a file where the fiber direction is saved.
void setETFESpace(const ETFESpace_Type &p)
void solveOneDiffusionStepBE()
Solves one diffusion step using the backward Euler scheme.
ETFESpaceVectorialPtr_Type M_displacementETFESpacePtr
std::shared_ptr< ETFESpaceVectorial_Type > ETFESpaceVectorialPtr_Type
void setPotentialExtra(const blockVector_Type &p)
ExporterEnsight data exporter.
void setAppliedCurrentIntraPtr(const vectorPtr_Type p)
set the pointer to the intra cell applied current vector
const linearSolverPtr_Type linearSolverPtr() const
get the pointer to the linear solver
MatrixEpetraStructured< Real > blockMatrix_Type
FESpace - Short description here please!
Definition: FESpace.hpp:78
const vectorOfPtr_Type & globalSolution() const
get the pointer to the vector of pointers containing the transmembrane potential (at 0) and the gatin...
void setLocalMeshPtr(const meshPtr_Type p)
set the pointer to the partitioned mesh
void setupFibers(std::string fibersFile, std::string directory, int format=0)
Imports the fiber direction from a vtk file ( format = 0), or text file.
void solveSplitting(IOFile_Type &exporter, Real dt)
Solve the system with operator splitting from M_initialTime to the M_endTime with time step M_timeSte...
void setRhsPtr(const blockVectorPtr_Type p)
set the pointer to the right hand side
void setupStiffnessMatrix(vectorPtr_Type disp)
create stiffness matrix in a moving domain
void importFromHDF5(std::string const &fileName, std::string const &matrixName="matrix")
Read a matrix from a HDF5 (.h5) file.
std::shared_ptr< comm_Type > commPtr_Type
void solveOneReactionStepFE(int subiterations=1)
Solves one reaction step using the forward Euler scheme.
void setDiffusionTensorIntra(const VectorSmall< 3 > &p)
set the intra cellular diagonal diffusion tensor
void solveOneReactionStepRL(int subiterations=1)
const vectorOfPtr_Type & globalRhs() const
get the pointer to the vector of pointers containing the rhs for transmembrane potential (at 0) and t...
void initializePotentialTrans(Real k)
Initialize the potential to the value k.
virtual std::vector< std::vector< Real > > getJac(const std::vector< Real > &v, Real h=1.0e-8)
This methods computes the Jacobian numerically.
void solveICI()
solve system using ICI from M_initialTime to the M_endTime with time step M_timeStep ...
void solveOneSplittingStep()
Solve one full step with operator splitting.
void setLinearSolverPtr(const linearSolverPtr_Type p)
set the pointer to the linear solver
std::shared_ptr< matrix_Type > matrixPtr_Type
ElectroETABidomainSolver(std::string meshName, std::string meshPath, GetPot &dataFile, ionicModelPtr_Type model)
Constructor.
std::function< Real(const Real &t, const Real &x, const Real &y, const Real &z, const ID &i) > function_Type
void setDisplacement(const vector_Type &p)
const commPtr_Type commPtr() const
get the pointer to the Epetra communicator
void solveOneSVIStep()
Solve one full step with ionic current interpolation.
void setAppliedCurrentIntra(const vector_Type &p)
void setupPotentialExporter(IOFile_Type &exporter, std::string fileName)
add to a given exporter the pointer to the potential saved with name fileName
const meshPtr_Type fullMeshPtr() const
get the pointer to the partitioned mesh
void setup(std::string meshName, std::string meshPath, GetPot &dataFile, short int ionicSize)
void solveSplitting(IOFile_Type &exporter)
Solve the system with operator splitting from M_initialTime to the M_endTime with time step M_timeSte...
void computeRhsICI()
Compute the rhs using ionic current interpolation.
void computeRhsICI(matrix_Type &mass)
const Real & timeStep() const
get the final time
std::shared_ptr< IOFile_Type > IOFilePtr_Type
const VectorSmall< 3 > & diffusionTensorIntra() const
get the diagonal intra cellular diffusion tensor
void setVariablePtr(const vectorPtr_Type p, int j)
void setMassMatrixPtr(const blockMatrixPtr_Type p)
set the pointer to the mass matrix
void setupLinearSolver(GetPot dataFile)
setup the linear solver
blockVectorPtr_Type potentialGlobalPtr()
get the pointer to the potential
void init(meshPtr_Type meshPtr, ionicModelPtr_Type model)
std::shared_ptr< basePrec_Type > basePrecPtr_Type
const vectorPtr_Type potentialTransPtr() const
get the pointer to the transmembrane potential
ElectroETABidomainSolver(GetPot &dataFile, ionicModelPtr_Type model, meshPtr_Type meshPtr)
Constructor.
const Real & endTime() const
get the time step
void setStiffnessMatrix(const matrix_Type &p)
void setPotentialExtraPtr(const vectorPtr_Type p)
void registerActivationTime(vector_Type &activationTimeVector, Real time, Real threshold=0.0)
save the fiber direction into the given exporter
Epetra_Import const & importer()
Getter for the Epetra_Import.
Definition: MapEpetra.cpp:394
void solveICI(IOFile_Type &exporter)
solve system using ICI from M_initialTime to the M_endTime with time step M_timeStep and export the s...
void setupGlobalMatrix()
create stiffness matrix given the fiber direction and a diagonal diffusion tensor ...
Real & operator[](UInt const &i)
Operator [].
void setDisplacementPtr(const vectorPtr_Type p)
set the pointer to displacement of the tissue
void copyGlobalSolution(const vectorOfPtr_Type &p)
void setupFibers(std::string fibersFile)
Imports the fiber direction from a hdf5 file.
void setupPotentialExporter(IOFile_Type &exporter)
add to a given exporter the pointer to the potential
ElectroETABidomainSolver(const ElectroETABidomainSolver &solver)
Copy Constructor.
void setTimeStep(const Real &p)
set the ending time
void setupLumpedMassMatrix()
create mass matrix
const vectorPtr_Type potentialExtraPtr() const
get the pointer to the extra cellular potential
void setupMassMatrix(vector_Type &disp)
create mass matrix
void initializeAppliedCurrentIntra(Real k)
Initialize the intra cellular applied current to the value k.
void setInitialTime(const Real &p)
set the starting time
const feSpacePtr_Type feSpacePtr() const
get the pointer to the usual finite element space
void solveOneICIStep(IOFile_Type &exporter, Real t)
Solve one full step with ionic current interpolation and export the solution.
const blockMatrixPtr_Type stiffnessMatrixPtr() const
get the pointer to the stiffness matrix
void setupFibers()
Generates a default fiber direction (0,1,0)
std::shared_ptr< VectorEpetra > vectorPtr_Type
void importFibers(vectorPtr_Type M_fiberPtr, std::string fibersFile, meshPtr_Type M_localMeshPtr)
void setFiberPtr(const vectorPtr_Type p)
set the pointer to the fiber direction vector
const blockMatrixPtr_Type globalMatrixPtr() const
get the pointer to the global matrix
const ETFESpacePtr_Type ETFESpacePtr() const
get the pointer to the ETA finite element space
void setAppliedCurrentFromFunctionIntra(function_Type &f, Real time=0.0)
given a boost function initialize the applied intra cellular current
const Real & initialTime() const
get the initial time (by default 0)
void setIonicModelPtr(const ionicModelPtr_Type p)
set the pointer to the ionic model
void setParameters(list_Type list)
Set parameters from an xml file.
std::shared_ptr< blockMatrix_Type > blockMatrixPtr_Type
void setMassMatrix(const matrix_Type &p)
void setFeSpace(const feSpace_Type &p)
double Real
Generic real data.
Definition: LifeV.hpp:175
void setupFibers(VectorSmall< 3 > fibers)
Generates the fiber direction given the three component of the vector (F_x,F_y,F_z) ...
void importSolution(GetPot &dataFile, std::string prefix, std::string postDir, Real time)
Import solution.
void solveOneICIStep(matrix_Type &mass)
void setupStiffnessMatrix()
create stiffness matrix
void setETFESpacePtr(const ETFESpacePtr_Type p)
set the pointer to the ETA fe space
ETFESpace< mesh_Type, MapEpetra, 3, 1 > ETFESpace_Type
void setDiffusionTensorExtra(const VectorSmall< 3 > &p)
set the extra cellular diagonal diffusion tensor
const VectorSmall< 3 > & diffusionTensorExtra() const
get the diagonal extra cellular diffusion tensor
void setupExporter(IOFile_Type &exporter, std::string fileName="output", std::string folder="./")
add to a given exporter the pointer to the potential and to the gating variables saved with name file...
void setPotentialFromFunctionTrans(function_Type &f, Real time=0.0)
given a boost function initialize the transmembrane potential
ETFESpace< mesh_Type, MapEpetra, 3, 3 > ETFESpaceVectorial_Type
const blockVectorPtr_Type rhsPtrUnique() const
get the pointer to the unique version of the right hand side
const meshPtr_Type localMeshPtr() const
get the pointer to the partitioned mesh
void setGlobalMatrixPtr(const blockMatrixPtr_Type p)
set the pointer to the global matrix
ElectroETABidomainSolver(std::string meshName, std::string meshPath, GetPot &dataFile, ionicModelPtr_Type model, commPtr_Type comm)
Constructor.
void solveSplitting()
Solve the system with operator splitting from M_initialTime to the M_endTime with time step M_timeSte...
std::shared_ptr< blockVector_Type > blockVectorPtr_Type
const blockMatrixPtr_Type massMatrixPtr() const
get the pointer to the mass matrix
const vectorPtr_Type appliedCurrentIntraPtr()
get the pointer to the applied intra cellular current vector
void setFullMeshPtr(const meshPtr_Type p)
set the pointer to the partitioned mesh
std::shared_ptr< feSpace_Type > feSpacePtr_Type
const ionicModelPtr_Type ionicModelPtr() const
get the pointer to the ionic model
void partitionMesh(std::string meshName, std::string meshPath)
partition the mesh
ElectroETABidomainSolver< Mesh, IonicModel > & operator=(const ElectroETABidomainSolver &solver)
Operator=()
VectorEpetra & operator*=(const data_type &scalar)
Multiplication operator.
ElectroETABidomainSolver(list_Type list, GetPot &dataFile, ionicModelPtr_Type model)
Constructor.
void setFeSpacePtr(const feSpacePtr_Type p)
set the pointer to the usual fe space
void solveICI(IOFile_Type &exporter, Real dt)
Solve the system using ICI from M_initialTime to the M_endTime with time step M_timeStep and export t...
const Real & surfaceVolumeRatio() const
get the surface to volume ratio
void setPotentialTrans(const vector_Type &p)
void setStiffnessMatrixPtr(const blockMatrixPtr_Type p)
set the pointer to the stiffness matrix
void init(ionicModelPtr_Type model)
void setGlobalRhs(const vectorOfPtr_Type &p)
set the vector of pointers containing the rhs for the transmembrane potential (at 0) and the gating v...
std::shared_ptr< LinearSolver > linearSolverPtr_Type
void setupGlobalRhs(short int ionicSize)
creates a vector of pointers to store the rhs
void exportSolution(IOFile_Type &exporter, Real t)
Save the solution in the exporter.
void computeRhsSVI()
Compute the rhs using state variable interpolation.
void initializeAppliedCurrentIntra()
Initialize the applied current to zero.
ExporterEnsight< mesh_Type > ensightIOFile_Type
void solveOneReactionStepFE(matrix_Type &mass, int subiterations=1)
void setGlobalSolution(const vectorOfPtr_Type &p)
set the vector of pointers containing the transmembrane potential (at 0) and the gating variables ...
void solveOneDiffusionStepBDF2(vectorPtr_Type previousPotentialGlobalPtr)
Solves one diffusion step using the BDF2 scheme.
void solveOneStepGatingVariablesFE()
Solves the gating variables with forward Euler.
void setRhsPtrUnique(const blockVectorPtr_Type p)
set the pointer to the unique version of the right hand side
class ETFESpace A light, templated version of the FESpace
Definition: ETFESpace.hpp:93
ETFESpaceVectorialPtr_Type displacementETFESpacePtr() const
std::shared_ptr< ionicModel_Type > ionicModelPtr_Type
const blockVectorPtr_Type rhsPtr() const
get the pointer to the right hand side
void solveOneSplittingStep(IOFile_Type &exporter, Real t)
Solve one full step with operator splitting and export the solution.
void setEndTime(const Real &p)
set the time step
void setGlobalMatrix(const matrix_Type &p)
const std::string elementsOrder() const
get the order of the elements
void initializePotential()
Initialize the potentials to zero.
const vectorPtr_Type fiberPtr() const
get the pointer to the fiber vector
void setupGlobalSolution(short int ionicSize)
creates a vector of pointers to store the solution
void setLinearSolver(const linearSolver_Type &p)
void solveSVI(IOFile_Type &exporter)
solve system using SVI from M_initialTime to the M_endTime with time step M_timeStep and export the s...
void setPotentialFromFunctionExtra(function_Type &f, Real time=0.0)
given a boost function initialize the extra cellular potential
std::shared_ptr< prec_Type > precPtr_Type
void setupLinearSolver(GetPot dataFile, list_Type list)
setup the linear solver
std::shared_ptr< ETFESpace< mesh_Type, MapEpetra, 3, 1 > > ETFESpacePtr_Type
void solveSVI(IOFile_Type &exporter, Real dt)
Solve the using SVI from M_initialTime to the M_endTime with time step M_timeStep and export the solu...
FESpace< mesh_Type, MapEpetra > feSpace_Type
void solveSVI()
solve system using SVI from M_initialTime to the M_endTime with time step M_timeStep ...
std::vector< vectorPtr_Type > vectorOfPtr_Type