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();
63 assert(fine_elements.size()==mTotalQuadPoints);
64 assert(mpMeshPair!=NULL);
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)
98 mQuadPointToDataAtQuadPointMap[quad_pt_global_index] = data_at_quad_point;
104 mMapIterator = mQuadPointToDataAtQuadPointMap.begin();
107 mConstantFibreSheetDirections = zero_matrix<double>(DIM,DIM);
108 for (
unsigned i=0; i<DIM; i++)
110 mConstantFibreSheetDirections(i,i) = 1.0;
113 mpVariableFibreSheetDirections = NULL;
116 for (std::map<unsigned,DataAtQuadraturePoint>::iterator iter = this->mQuadPointToDataAtQuadPointMap.begin();
117 iter != this->mQuadPointToDataAtQuadPointMap.end();
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.");
209 unsigned elementIndex,
210 unsigned currentQuadPointGlobalIndex,
211 c_matrix<double,DIM,DIM>& rT,
215 for (
unsigned i=0; i<DIM; i++)
217 mCurrentElementFibreDirection(i) = this->mChangeOfBasisMatrix(i,0);
221 double I4_fibre = inner_prod(mCurrentElementFibreDirection, prod(rC, mCurrentElementFibreDirection));
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;
228 GetActiveTensionAndTensionDerivs(lambda_fibre, currentQuadPointGlobalIndex, addToDTdE,
229 active_tension, d_act_tension_dlam, d_act_tension_d_dlamdt);
233 rT += (active_tension*detF/I4_fibre)*outer_prod(mCurrentElementFibreDirection,mCurrentElementFibreDirection);
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;
245 if (IsImplicitSolver())
247 double dt = mNextTime-mCurrentTime;
249 dTdE_coeff1 += (d_act_tension_dlam + d_act_tension_d_dlamdt/dt)*detF/(lambda_fibre*I4_fibre);
252 bool apply_cross_fibre_tension = (this->mrElectroMechanicsProblemDefinition.GetApplyCrossFibreTension()) && (DIM > 1);
253 if (apply_cross_fibre_tension)
255 double sheet_cross_fraction = mrElectroMechanicsProblemDefinition.GetSheetTensionFraction();
257 for (
unsigned i=0; i<DIM; i++)
259 mCurrentElementSheetDirection(i) = this->mChangeOfBasisMatrix(i,1);
262 double I4_sheet = inner_prod(mCurrentElementSheetDirection, prod(rC, mCurrentElementSheetDirection));
265 dTdE_coeff_s1 = -2*sheet_cross_fraction*detF*active_tension/(I4_sheet*I4_sheet);
267 if (IsImplicitSolver())
269 double dt = mNextTime-mCurrentTime;
270 dTdE_coeff_s3 = sheet_cross_fraction*(d_act_tension_dlam + d_act_tension_d_dlamdt/dt)*detF/(lambda_fibre*I4_sheet);
273 rT += sheet_cross_fraction*(active_tension*detF/I4_sheet)*outer_prod(mCurrentElementSheetDirection,mCurrentElementSheetDirection);
275 dTdE_coeff_s2 = active_tension*sheet_cross_fraction*detF/I4_sheet;
279 double sheet_normal_cross_fraction = mrElectroMechanicsProblemDefinition.GetSheetNormalTensionFraction();
280 for (
unsigned i=0; i<DIM; i++)
282 mCurrentElementSheetNormalDirection(i) = this->mChangeOfBasisMatrix(i,2);
285 double I4_sheet_normal = inner_prod(mCurrentElementSheetNormalDirection, prod(rC, mCurrentElementSheetNormalDirection));
287 dTdE_coeff_n1 =-2*sheet_normal_cross_fraction*detF*active_tension/(I4_sheet_normal*I4_sheet_normal);
289 rT += sheet_normal_cross_fraction*(active_tension*detF/I4_sheet_normal)*outer_prod(mCurrentElementSheetNormalDirection,mCurrentElementSheetNormalDirection);
291 dTdE_coeff_n2 = active_tension*sheet_normal_cross_fraction*detF/I4_sheet_normal;
292 if (IsImplicitSolver())
294 double dt = mNextTime-mCurrentTime;
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++)
313 rDTdE(M,N,P,Q) += dTdE_coeff1 * mCurrentElementFibreDirection(M)
314 * mCurrentElementFibreDirection(N)
315 * mCurrentElementFibreDirection(P)
316 * mCurrentElementFibreDirection(Q)
318 + dTdE_coeff2 * mCurrentElementFibreDirection(M)
319 * mCurrentElementFibreDirection(N)
321 if (apply_cross_fibre_tension)
323 rDTdE(M,N,P,Q) += dTdE_coeff_s1 * mCurrentElementSheetDirection(M)
324 * mCurrentElementSheetDirection(N)
325 * mCurrentElementSheetDirection(P)
326 * mCurrentElementSheetDirection(Q)
328 + dTdE_coeff_s2 * mCurrentElementSheetDirection(M)
329 * mCurrentElementSheetDirection(N)
332 + dTdE_coeff_s3 * mCurrentElementSheetDirection(M)
333 * mCurrentElementSheetDirection(N)
334 * mCurrentElementFibreDirection(P)
335 * mCurrentElementFibreDirection(Q);
338 rDTdE(M,N,P,Q) += dTdE_coeff_n1 * mCurrentElementSheetNormalDirection(M)
339 * mCurrentElementSheetNormalDirection(N)
340 * mCurrentElementSheetNormalDirection(P)
341 * mCurrentElementSheetNormalDirection(Q)
343 + dTdE_coeff_n2 * mCurrentElementSheetNormalDirection(M)
344 * mCurrentElementSheetNormalDirection(N)
347 + dTdE_coeff_n3 * mCurrentElementSheetNormalDirection(M)
348 * mCurrentElementSheetNormalDirection(N)
349 * mCurrentElementFibreDirection(P)
350 * mCurrentElementFibreDirection(Q);
419 std::vector<c_matrix<double,DIM,DIM> >& rDeformationGradients,
420 std::vector<double>& rStretches)
422 assert(rStretches.size()==this->mrQuadMesh.GetNumElements());
425 assert(!mpVariableFibreSheetDirections || !mFibreSheetDirectionsDefinedByQuadraturePoint);
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++)
442 SetupChangeOfBasisMatrix(elem_index, 0);
443 for (
unsigned i=0; i<DIM; i++)
445 mCurrentElementFibreDirection(i) = this->mChangeOfBasisMatrix(i,0);
449 for (
unsigned II=0; II<NUM_VERTICES_PER_ELEMENT; II++)
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);
466 for (
unsigned node_index=0; node_index<NUM_VERTICES_PER_ELEMENT; node_index++)
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;
480 c_vector<double,DIM> deformed_fibre = prod(F, mCurrentElementFibreDirection);
481 rStretches[elem_index] = norm_2(deformed_fibre);