36 #include "AbstractCardiacMechanicsSolver.hpp" 37 #include "AbstractContractionCellFactory.hpp" 38 #include "FakeBathContractionModel.hpp" 40 template<
class ELASTICITY_SOLVER,
unsigned DIM>
43 std::string outputDirectory)
48 mCurrentTime(DBL_MAX),
50 mOdeTimestep(DBL_MAX),
51 mrElectroMechanicsProblemDefinition(rProblemDefinition)
55 template<
class ELASTICITY_SOLVER,
unsigned DIM>
59 unsigned num_quad_pts_per_element = this->mpQuadratureRule->GetNumQuadPoints();
60 mTotalQuadPoints = this->mrQuadMesh.GetNumElements()*num_quad_pts_per_element;
62 std::vector<ElementAndWeights<DIM> > fine_elements =
mpMeshPair->rGetElementsAndWeights();
69 iter != this->mrQuadMesh.GetElementIteratorEnd();
76 for (
unsigned j=0; j<num_quad_pts_per_element; j++)
78 unsigned quad_pt_global_index = element.
GetIndex()*num_quad_pts_per_element + j;
84 data_at_quad_point.
Stretch = 1.0;
87 if (
mpMeshPair->GetFineMesh().GetElement(fine_elements[quad_pt_global_index].ElementNum)
108 for (
unsigned i=0; i<DIM; i++)
120 if (!
IsImplicitSolver() && (*iter).second.ContractionModel->IsStretchRateDependent())
122 EXCEPTION(
"stretch-rate-dependent contraction model requires an IMPLICIT cardiac mechanics solver.");
125 if (!
IsImplicitSolver() && (*iter).second.ContractionModel->IsStretchDependent())
127 WARN_ONCE_ONLY(
"stretch-dependent contraction model may require an IMPLICIT cardiac mechanics solver.");
133 template<
class ELASTICITY_SOLVER,
unsigned DIM>
136 assert(pMeshPair!=NULL);
139 EXCEPTION(
"When setting a mesh pair into the solver, the coarse mesh of the mesh pair must be the same as the quadratic mesh");
144 template<
class ELASTICITY_SOLVER,
unsigned DIM>
164 template<
class ELASTICITY_SOLVER,
unsigned DIM>
166 std::vector<double>& rVoltages)
174 for (
unsigned i=0; i<rCalciumConcentrations.size(); i++)
177 input_parameters.voltage = rVoltages[i];
183 iter->second.ContractionModel->SetInputParameters(input_parameters);
189 template<
class ELASTICITY_SOLVER,
unsigned DIM>
191 unsigned currentQuadPointGlobalIndex)
199 this->mChangeOfBasisMatrix = (*mpVariableFibreSheetDirections)[elementIndex];
203 this->mChangeOfBasisMatrix = (*mpVariableFibreSheetDirections)[currentQuadPointGlobalIndex];
207 template<
class ELASTICITY_SOLVER,
unsigned DIM>
209 unsigned elementIndex,
210 unsigned currentQuadPointGlobalIndex,
211 c_matrix<double,DIM,DIM>& rT,
215 for (
unsigned i=0; i<DIM; i++)
222 double lambda_fibre = sqrt(I4_fibre);
224 double active_tension = 0;
225 double d_act_tension_dlam = 0.0;
226 double d_act_tension_d_dlamdt = 0.0;
229 active_tension, d_act_tension_dlam, d_act_tension_d_dlamdt);
236 double dTdE_coeff1 = -2*active_tension*detF/(I4_fibre*I4_fibre);
237 double dTdE_coeff2 = active_tension*detF/I4_fibre;
238 double dTdE_coeff_s1 = 0.0;
239 double dTdE_coeff_s2 = 0.0;
240 double dTdE_coeff_s3 = 0.0;
241 double dTdE_coeff_n1 = 0.0;
242 double dTdE_coeff_n2 = 0.0;
243 double dTdE_coeff_n3 = 0.0;
249 dTdE_coeff1 += (d_act_tension_dlam + d_act_tension_d_dlamdt/dt)*detF/(lambda_fibre*I4_fibre);
253 if (apply_cross_fibre_tension)
257 for (
unsigned i=0; i<DIM; i++)
265 dTdE_coeff_s1 = -2*sheet_cross_fraction*detF*active_tension/(I4_sheet*I4_sheet);
270 dTdE_coeff_s3 = sheet_cross_fraction*(d_act_tension_dlam + d_act_tension_d_dlamdt/dt)*detF/(lambda_fibre*I4_sheet);
275 dTdE_coeff_s2 = active_tension*sheet_cross_fraction*detF/I4_sheet;
280 for (
unsigned i=0; i<DIM; i++)
287 dTdE_coeff_n1 =-2*sheet_normal_cross_fraction*detF*active_tension/(I4_sheet_normal*I4_sheet_normal);
291 dTdE_coeff_n2 = active_tension*sheet_normal_cross_fraction*detF/I4_sheet_normal;
295 dTdE_coeff_n3 = sheet_normal_cross_fraction*(d_act_tension_dlam + d_act_tension_d_dlamdt/dt)*detF/(lambda_fibre*I4_sheet_normal);
303 c_matrix<double,DIM,DIM> invC =
Inverse(rC);
305 for (
unsigned M=0; M<DIM; M++)
307 for (
unsigned N=0; N<DIM; N++)
309 for (
unsigned P=0; P<DIM; P++)
311 for (
unsigned Q=0; Q<DIM; Q++)
321 if (apply_cross_fibre_tension)
417 template<
class ELASTICITY_SOLVER,
unsigned DIM>
419 std::vector<c_matrix<double,DIM,DIM> >& rDeformationGradients,
420 std::vector<double>& rStretches)
422 assert(rStretches.size()==this->mrQuadMesh.GetNumElements());
427 static c_matrix<double,DIM,NUM_VERTICES_PER_ELEMENT> element_current_displacements;
428 static c_matrix<double,DIM,NUM_VERTICES_PER_ELEMENT> grad_lin_phi;
429 static c_matrix<double,DIM,DIM> F;
431 static c_matrix<double,DIM,DIM> jacobian;
432 static c_matrix<double,DIM,DIM> inverse_jacobian;
433 double jacobian_determinant;
437 for (
unsigned elem_index=0; elem_index<this->mrQuadMesh.GetNumElements(); elem_index++)
443 for (
unsigned i=0; i<DIM; i++)
451 for (
unsigned JJ=0; JJ<DIM; JJ++)
454 element_current_displacements(JJ,II) = this->mCurrentSolution[this->mProblemDimension*p_elem->
GetNodeGlobalIndex(II) + JJ];
459 this->mrQuadMesh.GetInverseJacobianForElement(elem_index, jacobian, jacobian_determinant, inverse_jacobian);
462 F = identity_matrix<double>(DIM,DIM);
468 for (
unsigned i=0; i<DIM; i++)
470 for (
unsigned M=0; M<DIM; M++)
472 F(i,M) += grad_lin_phi(M,node_index)*element_current_displacements(i,node_index);
477 rDeformationGradients[elem_index] = F;
481 rStretches[elem_index] = norm_2(deformed_fibre);
486 template<
class ELASTICITY_SOLVER,
unsigned DIM>
498 " does not match number of elements in the mesh, " <<
"found " << num_entries <<
499 ", expected " << this->mrQuadMesh.GetNumElements());
505 " does not match number of quadrature points defined, " <<
"found " << num_entries <<
510 for (
unsigned index=0; index<num_entries; index++)
516 template<
class ELASTICITY_SOLVER,
unsigned DIM>
521 c_matrix<double,DIM,DIM> temp = prod(trans(rFibreSheetMatrix),rFibreSheetMatrix);
522 for (
unsigned i=0; i<DIM; i++)
524 for (
unsigned j=0; j<DIM; j++)
526 double val = (i==j ? 1.0 : 0.0);
527 if (fabs(temp(i,j)-val)>1e-4)
529 EXCEPTION(
"The given fibre-sheet matrix, " << rFibreSheetMatrix <<
", is not orthogonal");
ElementIterator GetElementIteratorBegin(bool skipDeletedElements=true)
void ComputeDeformationGradientAndStretchInEachElement(std::vector< c_matrix< double, DIM, DIM > > &rDeformationGradients, std::vector< double > &rStretches)
c_vector< double, DIM > mCurrentElementSheetNormalDirection
boost::numeric::ublas::c_matrix< T, 1, 1 > Inverse(const boost::numeric::ublas::c_matrix< T, 1, 1 > &rM)
virtual bool IsImplicitSolver()=0
std::vector< c_matrix< double, DIM, DIM > > * mpVariableFibreSheetDirections
unsigned GetNodeGlobalIndex(unsigned localIndex) const
unsigned GetNumLinesOfData()
void SetConstantFibreSheetDirections(const c_matrix< double, DIM, DIM > &rFibreSheetMatrix)
std::string GetAbsolutePath() const
AbstractCardiacMechanicsSolver(QuadraticMesh< DIM > &rQuadMesh, ElectroMechanicsProblemDefinition< DIM > &rProblemDefinition, std::string outputDirectory)
virtual unsigned GetNumElements() const
#define EXCEPTION(message)
static HeartRegionType GetValidBathId()
c_vector< double, DIM > mCurrentElementFibreDirection
std::map< unsigned, DataAtQuadraturePoint >::iterator mMapIterator
ElectroMechanicsProblemDefinition< DIM > & mrElectroMechanicsProblemDefinition
const AbstractTetrahedralMesh< DIM, DIM > & GetCoarseMesh() const
T Determinant(const boost::numeric::ublas::c_matrix< T, 1, 1 > &rM)
std::map< unsigned, DataAtQuadraturePoint > mQuadPointToDataAtQuadPointMap
double StretchLastTimeStep
c_matrix< double, DIM, DIM > mConstantFibreSheetDirections
FineCoarseMeshPair< DIM > * mpMeshPair
virtual void GetActiveTensionAndTensionDerivs(double currentFibreStretch, unsigned currentQuadPointGlobalIndex, bool assembleJacobian, double &rActiveTension, double &rDerivActiveTensionWrtLambda, double &rDerivActiveTensionWrtDLambdaDt)=0
static void ComputeTransformedBasisFunctionDerivatives(const ChastePoint< ELEMENT_DIM > &rPoint, const c_matrix< double, ELEMENT_DIM, ELEMENT_DIM > &rInverseJacobian, c_matrix< double, ELEMENT_DIM, ELEMENT_DIM+1 > &rReturnValue)
bool GetOwnership() const
unsigned mTotalQuadPoints
void AddActiveStressAndStressDerivative(c_matrix< double, DIM, DIM > &rC, unsigned elementIndex, unsigned currentQuadPointGlobalIndex, c_matrix< double, DIM, DIM > &rT, FourthOrderTensor< DIM, DIM, DIM, DIM > &rDTdE, bool addToDTdE)
void SetFineCoarseMeshPair(FineCoarseMeshPair< DIM > *pMeshPair)
AbstractContractionModel * ContractionModel
static const unsigned NUM_VERTICES_PER_ELEMENT
void SetCalciumAndVoltage(std::vector< double > &rCalciumConcentrations, std::vector< double > &rVoltages)
unsigned GetIndex() const
void SetVariableFibreSheetDirections(const FileFinder &rOrthoFile, bool definedPerQuadraturePoint)
virtual ~AbstractCardiacMechanicsSolver()
virtual AbstractContractionModel * CreateContractionCellForElement(Element< DIM, DIM > *pElement)=0
void GetFibreSheetAndNormalMatrix(unsigned fibreIndex, c_matrix< double, DIM, DIM > &rFibreMatrix, bool checkOrthogonality=true)
c_vector< double, DIM > mCurrentElementSheetDirection
bool mFibreSheetDirectionsDefinedByQuadraturePoint
void SetupChangeOfBasisMatrix(unsigned elementIndex, unsigned currentQuadPointGlobalIndex)