LifeV
HeartBidomainSolver.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 /*!
28  @file
29  @brief Class for solving the Bidomain models in electrophysiology.
30 
31  @date 11-2007
32  @author Lucia Mirabella <lucia.mirabella@mail.polimi.it> and Mauro Perego <mauro.perego@polimi.it>
33 
34  @contributors J.Castelneau (INRIA), Ricardo Ruiz-Baier <ricardo.ruiz@epfl.ch>
35  @mantainer Lucia Mirabella <lucia.mirabella@mail.polimi.it>
36  @last update 11-2010
37  */
38 
39 #ifndef _BIDOMAINSOLVER_H_
40 #define _BIDOMAINSOLVER_H_
41 
42 #include <lifev/core/array/MatrixElemental.hpp>
43 #include <lifev/core/array/VectorElemental.hpp>
44 #include <lifev/core/fem/AssemblyElemental.hpp>
45 #include <lifev/core/fem/Assembly.hpp>
46 #include <lifev/core/fem/BCManage.hpp>
47 #include <lifev/core/algorithm/SolverAztecOO.hpp>
48 #include <lifev/core/array/MapEpetra.hpp>
49 #include <lifev/core/array/MatrixEpetra.hpp>
50 #include <lifev/core/array/VectorEpetra.hpp>
51 #include <lifev/core/fem/SobolevNorms.hpp>
52 #include <lifev/core/fem/GeometricMap.hpp>
53 #include <lifev/heart/solver/HeartBidomainData.hpp>
54 #include <lifev/core/util/LifeChrono.hpp>
55 #include <boost/shared_ptr.hpp>
56 #include <lifev/core/fem/FESpace.hpp>
57 #include <lifev/heart/solver/HeartStiffnessFibers.hpp>
58 #include <lifev/core/fem/TimeAdvanceBDF.hpp>
59 namespace LifeV
60 {
61 //! BidomainSolver - This class implements a bidomain solver.
62 
63 const UInt nbComp = 2;
64 
65 template < typename Mesh,
66  typename SolverType = LifeV::SolverAztecOO >
68 {
69 
70 public:
71  //! @name Type definitions
72  //@{
73 
75 
76  typedef Real ( *Function ) ( const Real&, const Real&, const Real&,
77  const Real&, const ID& );
78  typedef std::function < Real ( const Real&, const Real&, const Real&,
79  const Real&, const ID& ) > source_Type;
80 
81  typedef Mesh mesh_Type;
82 
84  // typedef std::shared_ptr<bchandlerRaw_Type> bchandlerRaw_Type;
85 
86  typedef typename SolverType::matrix_type matrix_Type;
88  typedef typename SolverType::vector_type vector_Type;
89 
90  typedef typename SolverType::prec_raw_type precRaw_Type;
91  typedef typename SolverType::prec_type prec_Type;
92 
93  //@}
94 
95 
96 
97  //! @name Constructors & Destructor
98  //@{
99 
100  //! Constructor
101  /*!
102  * @param dataType
103  * @param potential FE space
104  * @param bcHandler boundary conditions for potential
105  * @param Epetra communicator
106  */
107  HeartBidomainSolver ( const data_type& dataType,
108  FESpace<Mesh, MapEpetra>& pFESpace,
109  FESpace<Mesh, MapEpetra>& uFESpace,
110  BCHandler& bcHandler,
111  std::shared_ptr<Epetra_Comm>& comm );
112 
113  //! Destructor
114  virtual ~HeartBidomainSolver();
115 
116  //@}
117 
118  //! @name Methods
119  //@{
120 
121 
122  //! Updates sources, bc treatment and solve the bidomain system
123  virtual void PDEiterate ( bchandlerRaw_Type& bch );
124 
125  //! Sets up the system solver
126  virtual void setup ( const GetPot& dataFile );
127 
128  //! Builds time independent parts of PDE system
129  virtual void buildSystem();
130 
131  //! Updates time dependent parts of PDE system
132  virtual void updatePDESystem (Real alpha,
133  vector_Type& sourceVec);
134 
135  //! Updates time dependent parts of PDE system
136  virtual void updatePDESystem ( vector_Type& sourceVec );
137 
138  //! Initialize
139  void initialize ( const source_Type&, const source_Type& );
140  void initialize ( const Function&, const Function& );
141  void initialize ( const vector_Type&, const vector_Type& );
142 
143  //! Returns the local solution vector
145  {
147  }
149  {
151  }
153  {
155  }
157  {
159  }
160  const vector_Type& fiberVector() const
161  {
162  return M_fiberVector;
163  }
164 
165  //! Returns the local residual vector
166  const vector_Type& residual() const
167  {
168  return M_residual;
169  }
170 
171  //! Returns u FE space
172  FESpace<Mesh, MapEpetra>& potentialFESpace()
173  {
174  return M_uFESpace;
175  }
176 
177  //! Sets Bidomain BCs
178  void setBC (BCHandler& BCh_u)
179  {
180  M_BCh_electric = &BCh_u;
181  M_setBC = true;
182  }
183 
185  {
186  M_resetPreconditioner = true;
187  }
188 
189  //! Return maps getMap
191  {
192  return *M_localMap.map (Repeated);
193  }
194 
196  {
197  return *M_localMapVec.map (Repeated);
198  }
199 
200  MapEpetra const& getMap() const
201  {
202  return M_localMap;
203  }
204 
205  void recomputeMatrix (bool const recomp)
206  {
208  }
209 
211  {
212  return *M_matrMass;
213  }
214 
216  {
218  }
219 
220  //@}
221 
222 protected:
223 
224  //! Solves PDE system
226  vector_Type& rhsFull );
227 
228  //! Apply BC
229  void applyBoundaryConditions ( matrix_Type& matrix,
230  vector_Type& rhs,
231  bchandlerRaw_Type& BCh);
232 
233  //! compute mean of vector x
235 
236  //! removes a scalar from each entry of vector x
237  void removeValue ( vector_Type& x, Real& value );
238 
239  //! Data
241 
242  //! u FE space
243  FESpace<Mesh, MapEpetra>& M_pFESpace;
244  FESpace<Mesh, MapEpetra>& M_uFESpace;
245 
246  //! MPI communicator
249 
250  //! Bidomain BC
252  bool M_setBC;
253 
254  //! Map
258 
259  //! mass matrix
261 
262  //! Stiff matrix: D*stiff
264 
266 
267  //! Right hand side for the PDE
269 
270  //! Global solution _u
272 
274 
276 
278 
280 
281  //! Local fibers vector
283 
284  //! residual
286 
287  //! Solver
288  SolverType M_linearSolver;
289 
291 
293 
294  //! Boolean that indicates if output is sent to cout
295  bool M_verbose;
296 
297  //! Boolean that indicates if the matrix is updated for the current iteration
298  bool M_updated;
299 
300  //! Boolean that indicates if the precond has to be recomputed
303 
304  //! Integer storing the max number of solver iteration with prec recomputing
306 
307  //! Boolean that indicates if the matrix has to be recomputed
309 
311 private:
312 
313  //! Elementary matrices
318  {
319  return M_uFESpace.dim();
320  }
321 }; // class BidomainSolver
322 
323 
324 
325 //
326 // IMPLEMENTATION
327 //
328 
329 //! Constructors
330 template<typename Mesh, typename SolverType>
331 HeartBidomainSolver<Mesh, SolverType>::
332 HeartBidomainSolver ( const data_type& dataType,
333  FESpace<Mesh, MapEpetra>& pFESpace,
334  FESpace<Mesh, MapEpetra>& uFESpace,
335  BCHandler& BCh_u,
336  std::shared_ptr<Epetra_Comm>& comm ) :
337  M_data ( dataType ),
338  M_pFESpace ( pFESpace ),
339  M_uFESpace ( uFESpace ),
340  M_comm ( comm ),
341  M_me ( M_comm->MyPID() ),
342  M_BCh_electric ( &BCh_u ),
343  M_setBC ( true ),
344  M_localMap ( pFESpace.map() ),
345  M_localMap_u ( uFESpace.map() ),
347  M_matrMass ( ),
348  M_matrStiff ( ),
349  M_matrNoBC ( ),
350  M_rhsNoBC ( M_localMap ),
358  M_linearSolver ( ),
359  M_prec ( ),
360  M_verbose ( M_me == 0),
361  M_updated ( false ),
362  M_reusePrec ( true ),
363  M_resetPreconditioner ( true ),
364  M_maxIterSolver ( -1 ),
365  M_recomputeMatrix ( false ),
367  M_elmatStiff ( M_pFESpace.fe().nbFEDof(), 2, 2 ),
368  M_elmatMass ( M_pFESpace.fe().nbFEDof(), 2, 2 )
369 {
370  if (M_data.hasFibers() )
371  {
372  std::stringstream MyPID;
373  ifstream fibers (M_data.fibersFile().c_str() );
374  char line[1024];
375  UInt numPoints = M_localMap_u.map (Unique)->NumGlobalElements();
376  UInt numGlobalElements = M_localMapVec.map (Unique)->NumGlobalElements();
377  std::vector<Real> fiberGlobalVector (numGlobalElements);
379  {
380  fibers.getline (line, 1024);
381  for ( UInt i = 0; i < numPoints; ++i)
382  for (UInt k = 0; k < 3; ++k)
383  {
384  fibers >> fiberGlobalVector[i + k * numPoints];
385  }
386  }
387  else
388  {
389  for (UInt i = 0 ; i < numGlobalElements; ++i)
390  {
391  fibers >> fiberGlobalVector[i];
392  }
393  }
394  UInt numMyElements = M_localMapVec.map (Repeated)->NumMyElements();
395  for (UInt j = 0; j < numMyElements; ++j)
396  {
397  UInt ig = M_localMapVec.map (Repeated)->MyGlobalElements() [j];
398  M_fiberVector[ig] = fiberGlobalVector[ig];
399  }
400  std::cout << std::endl;
401  fiberGlobalVector.clear();
402  }
403 };
404 
405 template<typename Mesh, typename SolverType>
406 HeartBidomainSolver<Mesh, SolverType>::
408 {
409 }
410 
411 template<typename Mesh, typename SolverType>
412 void HeartBidomainSolver<Mesh, SolverType>::setup ( const GetPot& dataFile )
413 {
414  M_diagonalize = dataFile ( "electric/space_discretization/diagonalize", 1. );
415  M_reusePrec = dataFile ( "electric/prec/reuse", true);
416  M_linearSolver.setCommunicator (M_comm);
417  M_linearSolver.setDataFromGetPot ( dataFile, "electric/solver" );
418  M_maxIterSolver = dataFile ( "electric/solver/max_iter", -1);
419  std::string precType = dataFile ( "electric/prec/prectype", "Ifpack");
420  M_prec.reset ( PRECFactory::instance().createObject ( precType ) );
421  ASSERT (M_prec.get() != 0, "bidomainSolver : Preconditioner not set");
422  M_prec->setDataFromGetPot ( dataFile, "electric/prec" );
423 }
424 
425 template<typename Mesh, typename SolverType>
426 void HeartBidomainSolver<Mesh, SolverType>::buildSystem()
427 {
428  M_matrMass.reset ( new matrix_Type (M_localMap) );
429  M_matrStiff.reset ( new matrix_Type (M_localMap) );
430 
431  if (M_verbose)
432  {
433  std::cout << " f- Computing constant matrices ... ";
434  }
435 
436  Chrono chrono;
437  Chrono chronoDer;
438  Chrono chronoStiff;
439  Chrono chronoMass;
440  Chrono chronoStiffAssemble;
441  Chrono chronoMassAssemble;
442  Chrono chronoZero;
443 
444  M_comm->Barrier();
445  chrono.start();
446 
447  //! Elementary computation and matrix assembling
448  //! Loop on elements
449 
450  for ( UInt iVol = 0; iVol < M_pFESpace.mesh()->numVolumes(); iVol++ )
451  {
452  chronoZero.start();
453  M_elmatStiff.zero();
454  M_elmatMass.zero();
455  chronoZero.stop();
456 
457  chronoStiff.start();
459  {
460  case 0:
461  chronoDer.start();
462  M_pFESpace.fe().updateFirstDeriv ( M_pFESpace.mesh()->volumeList ( iVol ) );
463  chronoDer.stop();
464  if (M_data.hasFibers() )
465  {
466  stiff ( M_data.longitudinalInternalConductivity(),
467  M_data.transversalInternalConductivity(),
468  M_fiberVector,
469  M_elmatStiff,
470  M_pFESpace.fe(),
471  M_pFESpace.dof(), 0, 0);
472  stiff ( M_data.longitudinalExternalConductivity(),
473  M_data.transversalExternalConductivity(),
474  M_fiberVector,
475  M_elmatStiff,
476  M_pFESpace.fe(),
477  M_pFESpace.dof(), 1, 1);
478  }
479  else
480  {
481  stiff ( M_data.internalDiffusivity(), M_elmatStiff, M_pFESpace.fe(), 0, 0 );
482  stiff ( M_data.externalDiffusivity(), M_elmatStiff, M_pFESpace.fe(), 1, 1 );
483  }
484  break;
485  case 1:
486  chronoDer.start();
487  M_pFESpace.fe().updateFirstDerivQuadPt ( M_pFESpace.mesh()->volumeList ( iVol ) );
488  chronoDer.stop();
489  if (M_data.hasFibers() )
490  {
491  stiff ( M_data.M_reducedConductivitySphere, M_data.longitudinalInternalConductivity(),
492  M_data.transversalInternalConductivity(),
493  M_fiberVector, M_elmatStiff, M_pFESpace.fe(), M_pFESpace.dof(), 0, 0, 0);
494  stiff ( M_data.M_reducedConductivitySphere, M_data.longitudinalExternalConductivity(),
495  M_data.transversalExternalConductivity(),
496  M_fiberVector, M_elmatStiff, M_pFESpace.fe(), M_pFESpace.dof(), 1, 1, 1);
497  }
498  else
499  {
500  stiff ( M_data.M_reducedConductivitySphere, M_data.internalDiffusivity(),
501  M_elmatStiff, M_pFESpace.fe(), M_pFESpace.dof(), 0, 0, 0);
502  stiff ( M_data.M_reducedConductivitySphere, M_data.externalDiffusivity(),
503  M_elmatStiff, M_pFESpace.fe(), M_pFESpace.dof(), 1, 1, 1);
504  }
505  break;
506  case 2:
507  chronoDer.start();
508  M_pFESpace.fe().updateFirstDerivQuadPt ( M_pFESpace.mesh()->volumeList ( iVol ) );
509  chronoDer.stop();
510  if (M_data.hasFibers() )
511  {
512  stiff ( M_data.M_reducedConductivityCylinder, M_data.longitudinalInternalConductivity(),
513  M_data.transversalInternalConductivity(), M_fiberVector,
514  M_elmatStiff, M_pFESpace.fe(), M_pFESpace.dof(), 0, 0, 0);
515  stiff ( M_data.M_reducedConductivityCylinder, M_data.longitudinalExternalConductivity(),
516  M_data.transversalExternalConductivity(), M_fiberVector,
517  M_elmatStiff, M_pFESpace.fe(), M_pFESpace.dof(), 1, 1, 1);
518  }
519  else
520  {
521  stiff ( M_data.M_reducedConductivityCylinder, M_data.internalDiffusivity(),
522  M_elmatStiff, M_pFESpace.fe(), M_pFESpace.dof(), 0, 0 , 0);
523  stiff ( M_data.M_reducedConductivityCylinder, M_data.externalDiffusivity(),
524  M_elmatStiff, M_pFESpace.fe(), M_pFESpace.dof(), 1, 1, 1);
525  }
526  break;
527  case 3:
528  chronoDer.start();
529  M_pFESpace.fe().updateFirstDerivQuadPt ( M_pFESpace.mesh()->volumeList ( iVol ) );
530  chronoDer.stop();
531  if (M_data.hasFibers() )
532  {
533  stiff ( M_data.M_reducedConductivityBox, M_data.longitudinalInternalConductivity(),
534  M_data.transversalInternalConductivity(), M_fiberVector, M_elmatStiff,
535  M_pFESpace.fe(), M_pFESpace.dof(), 0, 0, 0);
536  stiff ( M_data.M_reducedConductivityBox, M_data.longitudinalExternalConductivity(),
537  M_data.transversalExternalConductivity(), M_fiberVector, M_elmatStiff,
538  M_pFESpace.fe(), M_pFESpace.dof(), 1, 1, 1);
539  }
540  else
541  {
542  stiff ( M_data.M_reducedConductivityBox, M_data.internalDiffusivity(),
543  M_elmatStiff, M_pFESpace.fe(), M_pFESpace.dof(), 0, 0, 0 );
544  stiff ( M_data.M_reducedConductivityBox, M_data.externalDiffusivity(),
545  M_elmatStiff, M_pFESpace.fe(), M_pFESpace.dof(), 1, 1, 1 );
546  }
547  break;
548  }
549  chronoStiff.stop();
550 
551  chronoMass.start();
552  mass ( 1., M_elmatMass, M_pFESpace.fe(), 0, 0 );
553  mass ( -1., M_elmatMass, M_pFESpace.fe(), 0, 1 );
554  mass ( -1., M_elmatMass, M_pFESpace.fe(), 1, 0 );
555  mass ( 1., M_elmatMass, M_pFESpace.fe(), 1, 1 );
556  chronoMass.stop();
557 
558  chronoStiffAssemble.start();
559  for ( UInt iComp = 0; iComp < nbComp; iComp++ )
560  {
561  assembleMatrix ( *M_matrStiff,
562  M_elmatStiff,
563  M_pFESpace.fe(),
564  M_pFESpace.fe(),
565  M_pFESpace.dof(),
566  M_pFESpace.dof(),
567  iComp, iComp,
568  iComp * potentialFESpaceDimension(), iComp * potentialFESpaceDimension() );
569  }
570  chronoStiffAssemble.stop();
571 
572  chronoMassAssemble.start();
573  for ( UInt iComp = 0; iComp < nbComp; iComp++ )
574  {
575  for ( UInt jComp = 0; jComp < nbComp; jComp++ )
576  {
577  assembleMatrix ( *M_matrMass,
578  M_elmatMass,
579  M_pFESpace.fe(),
580  M_pFESpace.fe(),
581  M_pFESpace.dof(),
582  M_pFESpace.dof(),
583  iComp, jComp,
584  iComp * potentialFESpaceDimension(), jComp * potentialFESpaceDimension() );
585  }
586  }
587  chronoMassAssemble.stop();
588  }
589 
591  M_BDFIntraExtraPotential.coefficientFirstDerivative (0) / M_data.timeStep();
592 
593  M_comm->Barrier();
594  chrono.stop();
595 
596  if (M_verbose)
597  {
598  std::cout << "done in " << chrono.diff() << " s.\n" << std::flush;
599  }
600  if (M_verbose)
601  {
602  std::cout << " f- Finalizing the matrices ... " << std::flush;
603  }
604 
605  chrono.start();
606  M_matrStiff->globalAssemble();
607  M_matrMass->globalAssemble();
608  M_comm->Barrier();
609 
610  M_matrNoBC.reset (new matrix_Type (M_localMap, M_matrStiff->meanNumEntries() ) );
611 
612  //! Computing 1.0/dt * M + K
613  *M_matrNoBC += *M_matrStiff;
614  *M_matrNoBC += *M_matrMass * massCoeff;
615  M_matrNoBC->globalAssemble();
616  chrono.stop();
617  if (M_verbose)
618  {
619  std::cout << "done in " << chrono.diff() << " s." << std::endl;
620  }
621 
622  if (false)
623  std::cout << "partial times: \n"
624  << " Der " << chronoDer.diff_cumul() << " s.\n"
625  << " Zero " << chronoZero.diff_cumul() << " s.\n"
626  << " Stiff " << chronoStiff.diff_cumul() << " s.\n"
627  << " Stiff Assemble " << chronoStiffAssemble.diff_cumul() << " s.\n"
628  << " Mass " << chronoMass.diff_cumul() << " s.\n"
629  << " Mass Assemble " << chronoMassAssemble.diff_cumul() << " s.\n"
630  << std::endl;
631 }
632 template<typename Mesh, typename SolverType>
633 void HeartBidomainSolver<Mesh, SolverType>::
634 initialize ( const source_Type& ui0, const source_Type& ue0 )
635 {
636 
637  vector_Type intracellularPotential (M_uFESpace.map() );
638  vector_Type extracellularPotential (M_uFESpace.map() );
639 
640  M_uFESpace.interpolate (ui0, intracellularPotential, 0.);
641  M_uFESpace.interpolate (ue0, extracellularPotential, 0.);
642  initialize (intracellularPotential, extracellularPotential);
643 }
644 
645 template<typename Mesh, typename SolverType>
646 void HeartBidomainSolver<Mesh, SolverType>::
647 initialize ( const Function& ui0, const Function& ue0 )
648 {
649 
650  vector_Type intracellularPotential (M_uFESpace.map() );
651  vector_Type extracellularPotential (M_uFESpace.map() );
652  M_uFESpace.interpolate (ui0, intracellularPotential, 0.);
653  M_uFESpace.interpolate (ue0, extracellularPotential, 0.);
654  initialize (intracellularPotential, extracellularPotential);
655 }
656 
657 template<typename Mesh, typename SolverType>
658 void HeartBidomainSolver<Mesh, SolverType>::
659 initialize ( const vector_Type& ui0, const vector_Type& ue0 )
660 {
662  M_solutionIntraExtraPotential.add (ue0, M_uFESpace.dof().numTotalDof() );
663 
664  for ( Int i = 0 ; i < M_solutionTransmembranePotential.epetraVector().MyLength() ; i++ )
665  {
666  Int ig = M_solutionTransmembranePotential.blockMap().MyGlobalElements() [i];
671  }
675  M_BDFIntraExtraPotential.showMe();
676 }
677 
678 template<typename Mesh, typename SolverType>
679 void HeartBidomainSolver<Mesh, SolverType>::
680 updatePDESystem (Real alpha, vector_Type& sourceVec)
681 {
682 
683  Chrono chrono;
684  if (M_verbose)
685  std::cout << " f- Updating mass term and right hand side... "
686  << std::flush;
687 
688  chrono.start();
689 
690  M_rhsNoBC = sourceVec;
691  M_rhsNoBC.globalAssemble();
692 
693  chrono.stop();
694 
695  if (M_verbose)
696  {
697  std::cout << "done in " << chrono.diff() << " s.\n" << std::flush;
698  }
699 
700  M_updated = false;
701 
702  if (M_recomputeMatrix)
703  {
705  }
706 
707  if (M_verbose)
708  std::cout << " f- Copying the matrices ... "
709  << std::flush;
710 
711  chrono.start();
712 
713  M_matrNoBC.reset (new matrix_Type (M_localMap, M_matrStiff->meanNumEntries() ) );
714 
715  *M_matrNoBC += *M_matrStiff;
716 
717  *M_matrNoBC += *M_matrMass * alpha;
718 
719  chrono.stop();
720  if (M_verbose) std::cout << "done in " << chrono.diff() << " s.\n"
721  << std::flush;
722 
723  M_updated = true;
724  M_matrNoBC->globalAssemble();
725 }
726 
727 template<typename Mesh, typename SolverType>
728 void HeartBidomainSolver<Mesh, SolverType>::
730 {
731 
732  Chrono chrono;
733 
734  if (M_verbose)
735  std::cout << " f- Updating right hand side... "
736  << std::flush;
737 
738  chrono.start();
739  M_rhsNoBC = sourceVec;
740  M_rhsNoBC.globalAssemble();
741  chrono.stop();
742 
743  if (M_verbose)
744  {
745  std::cout << "done in " << chrono.diff() << " s.\n" << std::flush;
746  }
747 }
748 
749 template<typename Mesh, typename SolverType>
750 void HeartBidomainSolver<Mesh, SolverType>::PDEiterate ( bchandlerRaw_Type& bch )
751 {
752 
753  Chrono chrono;
754  chrono.start();
755 
756  matrixPtr_Type matrFull ( new matrix_Type (*M_matrNoBC) );
757  vector_Type rhsFull = M_rhsNoBC;
758 
759  chrono.stop();
760 
761  if (M_verbose)
762  std::cout << "done in " << chrono.diff() << " s.\n"
763  << std::flush;
764 
765  // boundary conditions update
766  M_comm->Barrier();
767  if (M_verbose) std::cout << " f- Applying boundary conditions ... "
768  << std::flush;
769 
770  chrono.start();
771  applyBoundaryConditions ( *matrFull, rhsFull, bch);
772 
773  chrono.stop();
774 
775  M_comm->Barrier();
776 
777  if (M_verbose)
778  {
779  std::cout << "done in " << chrono.diff() << " s.\n" << std::flush;
780  }
781 
782  //! Solving the system
783  solveSystem ( matrFull, rhsFull );
784 
785  // M_residual = M_rhsNoBC;
786  // M_residual -= *M_matrNoBC*M_solutionIntraExtraPotential;
787 
788 } // iterate()
789 
790 
791 template<typename Mesh, typename SolverType>
792 void HeartBidomainSolver<Mesh, SolverType>::solveSystem ( matrixPtr_Type matrFull,
793  vector_Type& rhsFull )
794 {
795  Chrono chrono;
796 
797  if (M_verbose)
798  {
799  std::cout << " f- Setting up the solver ... ";
800  }
801 
802  chrono.start();
803  M_linearSolver.setMatrix (*matrFull);
804  chrono.stop();
805 
806  if (M_verbose)
807  std::cout << "done in " << chrono.diff() << " s.\n"
808  << std::flush;
809 
811  {
812  chrono.start();
813 
814  if (M_verbose)
815  {
816  std::cout << " f- Computing the precond ... ";
817  }
818  M_prec->buildPreconditioner (matrFull);
819 
820  Real condest = M_prec->Condest();
821 
822  M_linearSolver.setPreconditioner (M_prec);
823 
824  chrono.stop();
825  if (M_verbose)
826  {
827  std::cout << "done in " << chrono.diff() << " s.\n";
828  std::cout << " Estimated condition number = " << condest << "\n" << std::flush;
829  }
830 
831  M_resetPreconditioner = false;
832  }
833  else
834  {
835  if (M_verbose)
836  {
837  std::cout << " f- Reusing precond ... \n" << std::flush;
838  }
839  }
840 
841  chrono.start();
842 
843  if (M_verbose)
844  {
845  std::cout << " f- Solving system ... ";
846  }
847 
848  Int numIter = M_linearSolver.solve (M_solutionIntraExtraPotential, rhsFull);
849 
850  chrono.stop();
851 
852  if (M_verbose)
853  {
854  std::cout << "\ndone in " << chrono.diff()
855  << " s. ( " << numIter << " iterations. ) \n"
856  << std::flush;
857  }
858 
859  if (numIter > M_maxIterSolver)
860  {
861  M_resetPreconditioner = true;
862  }
863 
864  for ( Int i = 0 ; i < M_solutionTransmembranePotential.epetraVector().MyLength() ; i++ )
865  {
866  UInt ig = M_solutionTransmembranePotential.blockMap().MyGlobalElements() [i];
868  }
869  Real meanExtraPotential = computeMean (M_solutionExtraPotential);
871 
872  for ( Int i = 0 ; i < M_solutionTransmembranePotential.epetraVector().MyLength() ; i++ )
873  {
874  UInt ig = M_solutionTransmembranePotential.blockMap().MyGlobalElements() [i];
877  }
878 
881 
882  for ( Int i = 0 ; i < M_solutionTransmembranePotential.epetraVector().MyLength() ; i++ )
883  {
884  UInt ig = M_solutionTransmembranePotential.blockMap().MyGlobalElements() [i];
886  }
887 }
888 
889 template<typename Mesh, typename SolverType>
890 void HeartBidomainSolver<Mesh, SolverType>::applyBoundaryConditions (matrix_Type& matrix,
891  vector_Type& rhs,
892  bchandlerRaw_Type& BCh )
893 {
894  // BC manage for the PDE
895  if ( !BCh.bdUpdateDone() )
896  {
897  BCh.bdUpdate ( *M_pFESpace.mesh(), M_pFESpace.feBd(), M_pFESpace.dof() );
898  }
899 
900  vector_Type rhsFull (M_rhsNoBC, Repeated, Zero);
901 
902  // rhsFull.Import(M_rhsNoBC, Zero); // ignoring non-local entries, Otherwise they are summed up lately
903 
904  bcManage ( matrix, rhs, *M_pFESpace.mesh(), M_pFESpace.dof(), BCh, M_pFESpace.feBd(), 1.,
905  M_data.time() );
906  rhs = rhsFull;
907 
909  {
910  matrix.diagonalize ( 1 * potentialFESpaceDimension(),
912  rhs,
913  0.);
914  }
915 
916 } // applyBoundaryCondition
917 
918 template<typename Mesh, typename SolverType>
920 {
921  Real meanExtraPotential (0.);
922  x.epetraVector().MeanValue (&meanExtraPotential);
923  return meanExtraPotential;
924 } // computeMean()
925 
926 template<typename Mesh, typename SolverType>
927 void HeartBidomainSolver<Mesh, SolverType>::removeValue ( vector_Type& x, Real& value )
928 {
929  for ( Int i = 0 ; i < x.epetraVector().MyLength() ; i++ )
930  {
931  Int ig = x.blockMap().MyGlobalElements() [i];
932  x[ig] -= value;
933  }
934 
935 } // removeMean()
936 
937 } // namespace LifeV
938 
939 
940 #endif //_BIDOMAINSOLVER_H_
void initialize(const Function &, const Function &)
bool M_verbose
Boolean that indicates if output is sent to cout.
void initialize(const source_Type &, const source_Type &)
Initialize.
double operator()(const char *VarName, const double &Default) const
Definition: GetPot.hpp:2033
SolverType::vector_type vector_Type
bool M_updated
Boolean that indicates if the matrix is updated for the current iteration.
void removeValue(vector_Type &x, Real &value)
removes a scalar from each entry of vector x
void setBC(BCHandler &BCh_u)
Sets Bidomain BCs.
MatrixElemental M_elmatStiff
Elementary matrices.
const bool & hasFibers() const
const vector_Type & residual() const
Returns the local residual vector.
Int M_maxIterSolver
Integer storing the max number of solver iteration with prec recomputing.
virtual void setup(const GetPot &dataFile)
Sets up the system solver.
BCHandler - class for handling boundary conditions.
Definition: BCHandler.hpp:100
const Real & membraneCapacitance() const
Cm.
FESpace< Mesh, MapEpetra > & M_pFESpace
u FE space
const vector_Type & solutionExtraPotential() const
int32_type Int
Generic integer data.
Definition: LifeV.hpp:188
bool M_recomputeMatrix
Boolean that indicates if the matrix has to be recomputed.
std::function< Real(const Real &, const Real &, const Real &, const Real &, const ID &) > source_Type
bool hasOnlyEssential() const
Determine whether all the stored boundary conditions have EssentialXXX type.
Definition: BCHandler.cpp:394
vector_Type M_solutionTransmembranePotentialExtrapolated
FESpace< Mesh, MapEpetra > & potentialFESpace()
Returns u FE space.
matrixPtr_Type M_matrMass
mass matrix
TimeAdvanceBDF< vector_Type > M_BDFIntraExtraPotential
virtual void buildSystem()
Builds time independent parts of PDE system.
Epetra_Import const & importer()
Getter for the Epetra_Import.
Definition: MapEpetra.cpp:394
const Real & volumeSurfaceRatio() const
Chi.
#define ASSERT(X, A)
Definition: LifeAssert.hpp:90
uint32_type ID
IDs.
Definition: LifeV.hpp:194
HeartBidomainSolver(const data_type &dataType, FESpace< Mesh, MapEpetra > &pFESpace, FESpace< Mesh, MapEpetra > &uFESpace, BCHandler &bcHandler, std::shared_ptr< Epetra_Comm > &comm)
Constructor.
const data_type & M_data
Data.
virtual void PDEiterate(bchandlerRaw_Type &bch)
Updates sources, bc treatment and solve the bidomain system.
const std::shared_ptr< Epetra_Comm > M_comm
MPI communicator.
vector_Type M_solutionIntraExtraPotential
Global solution _u.
const vector_Type & solutionIntraExtraPotential() const
class TimeAdvanceBDF - Backward differencing formula time discretization for the first and the second...
void solveSystem(matrixPtr_Type matrFull, vector_Type &rhsFull)
Solves PDE system.
virtual void updatePDESystem(vector_Type &sourceVec)
Updates time dependent parts of PDE system.
const bool & fibersFormat() const
format vct
double Real
Generic real data.
Definition: LifeV.hpp:175
bool M_reusePrec
Boolean that indicates if the precond has to be recomputed.
int operator()(const char *VarName, int Default) const
Definition: GetPot.hpp:2021
SolverType::prec_raw_type precRaw_Type
matrixPtr_Type M_matrStiff
Stiff matrix: D*stiff.
virtual ~HeartBidomainSolver()
Destructor.
virtual void updatePDESystem(Real alpha, vector_Type &sourceVec)
Updates time dependent parts of PDE system.
const std::string operator()(const char *VarName, const char *Default) const
Definition: GetPot.hpp:2045
vector_Type M_rhsNoBC
Right hand side for the PDE.
vector_Type M_solutionIntraExtraPotentialExtrapolated
SolverType::matrix_type matrix_Type
BCHandler * M_BCh_electric
Bidomain BC.
bool operator()(const char *VarName, bool Default) const
Definition: GetPot.hpp:2008
FESpace< Mesh, MapEpetra > & M_uFESpace
void initialize(const vector_Type &, const vector_Type &)
vector_Type M_fiberVector
Local fibers vector.
const vector_Type & fiberVector() const
const UInt nbComp
BidomainSolver - This class implements a bidomain solver.
std::shared_ptr< matrix_Type > matrixPtr_Type
Real computeMean(vector_Type &x)
compute mean of vector x
SolverType::prec_type prec_Type
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191
const vector_Type & solutionTransmembranePotentialExtrapolated() const
const Int & heartDiffusionFactor() const
const vector_Type & solutionTransmembranePotential() const
Returns the local solution vector.
void applyBoundaryConditions(matrix_Type &matrix, vector_Type &rhs, bchandlerRaw_Type &BCh)
Apply BC.