53 bool assembleJacobian)
56 assert(assembleResidual || assembleJacobian);
57 assert(this->mCurrentSolution.size()==this->mNumDofs);
71 c_matrix<double, STENCIL_SIZE, STENCIL_SIZE> a_elem;
74 c_matrix<double, STENCIL_SIZE, STENCIL_SIZE> a_elem_precond;
75 c_vector<double, STENCIL_SIZE> b_elem;
79 iter != this->mrQuadMesh.GetElementIteratorEnd();
86 std::cout <<
"\r[" <<
PetscTools::GetMyRank() <<
"]: Element " << (*iter).GetIndex() <<
" of " << this->mrQuadMesh.GetNumElements() << std::flush;
94 AssembleOnElement(element, a_elem, a_elem_precond, b_elem, assembleResidual, assembleJacobian);
113 unsigned p_indices[STENCIL_SIZE];
114 for (
unsigned i=0; i<NUM_NODES_PER_ELEMENT; i++)
116 for (
unsigned j=0; j<DIM; j++)
123 for (
unsigned i=0; i<NUM_VERTICES_PER_ELEMENT; i++)
129 p_indices[DIM*NUM_NODES_PER_ELEMENT + i] = (DIM+1)*vertex_index + DIM;
132 if (assembleJacobian)
134 PetscMatTools::AddMultipleValues<STENCIL_SIZE>(this->mrJacobianMatrix, p_indices, a_elem);
135 PetscMatTools::AddMultipleValues<STENCIL_SIZE>(this->mPreconditionMatrix, p_indices, a_elem_precond);
138 if (assembleResidual)
140 PetscVecTools::AddMultipleValues<STENCIL_SIZE>(this->mResidualVector, p_indices, b_elem);
146 c_vector<double, BOUNDARY_STENCIL_SIZE> b_boundary_elem;
147 c_matrix<double, BOUNDARY_STENCIL_SIZE, BOUNDARY_STENCIL_SIZE> a_boundary_elem;
149 if (this->mrProblemDefinition.GetTractionBoundaryConditionType() != NO_TRACTIONS)
151 for (
unsigned bc_index=0; bc_index<this->mrProblemDefinition.rGetTractionBoundaryElements().size(); bc_index++)
153 BoundaryElement<DIM-1,DIM>& r_boundary_element = *(this->mrProblemDefinition.rGetTractionBoundaryElements()[bc_index]);
161 this->AssembleOnBoundaryElement(r_boundary_element, a_boundary_elem, b_boundary_elem, assembleResidual, assembleJacobian, bc_index);
163 unsigned p_indices[BOUNDARY_STENCIL_SIZE];
164 for (
unsigned i=0; i<NUM_NODES_PER_BOUNDARY_ELEMENT; i++)
166 for (
unsigned j=0; j<DIM; j++)
169 p_indices[DIM*i+j] = (DIM+1)*r_boundary_element.GetNodeGlobalIndex(i) + j;
173 if (assembleJacobian)
175 PetscMatTools::AddMultipleValues<BOUNDARY_STENCIL_SIZE>(this->mrJacobianMatrix, p_indices, a_boundary_elem);
176 PetscMatTools::AddMultipleValues<BOUNDARY_STENCIL_SIZE>(this->mPreconditionMatrix, p_indices, a_boundary_elem);
179 if (assembleResidual)
181 PetscVecTools::AddMultipleValues<BOUNDARY_STENCIL_SIZE>(this->mResidualVector, p_indices, b_boundary_elem);
187 if (assembleResidual)
191 if (assembleJacobian)
197 if (assembleJacobian)
199 this->AddIdentityBlockForDummyPressureVariables(NONLINEAR_PROBLEM_APPLY_TO_EVERYTHING);
201 else if (assembleResidual)
203 this->AddIdentityBlockForDummyPressureVariables(NONLINEAR_PROBLEM_APPLY_TO_RESIDUAL_ONLY);
206 this->FinishAssembleSystem(assembleResidual, assembleJacobian);
212 c_matrix<double, STENCIL_SIZE, STENCIL_SIZE >& rAElem,
213 c_matrix<double, STENCIL_SIZE, STENCIL_SIZE >& rAElemPrecond,
214 c_vector<double, STENCIL_SIZE>& rBElem,
215 bool assembleResidual,
216 bool assembleJacobian)
218 static c_matrix<double,DIM,DIM> jacobian;
219 static c_matrix<double,DIM,DIM> inverse_jacobian;
220 double jacobian_determinant;
222 this->mrQuadMesh.GetInverseJacobianForElement(rElement.
GetIndex(), jacobian, jacobian_determinant, inverse_jacobian);
224 if (assembleJacobian)
227 rAElemPrecond.clear();
230 if (assembleResidual)
236 static c_matrix<double,DIM,NUM_NODES_PER_ELEMENT> element_current_displacements;
237 static c_vector<double,NUM_VERTICES_PER_ELEMENT> element_current_pressures;
238 for (
unsigned II=0; II<NUM_NODES_PER_ELEMENT; II++)
240 for (
unsigned JJ=0; JJ<DIM; JJ++)
243 element_current_displacements(JJ,II) = this->mCurrentSolution[(DIM+1)*rElement.
GetNodeGlobalIndex(II) + JJ];
248 for (
unsigned II=0; II<NUM_VERTICES_PER_ELEMENT; II++)
255 element_current_pressures(II) = this->mCurrentSolution[(DIM+1)*vertex_index + DIM];
259 static c_vector<double, NUM_VERTICES_PER_ELEMENT> linear_phi;
260 static c_vector<double, NUM_NODES_PER_ELEMENT> quad_phi;
261 static c_matrix<double, DIM, NUM_NODES_PER_ELEMENT> grad_quad_phi;
262 static c_matrix<double, NUM_NODES_PER_ELEMENT, DIM> trans_grad_quad_phi;
267 static c_matrix<double,DIM,DIM> grad_u;
269 static c_matrix<double,DIM,DIM> F;
270 static c_matrix<double,DIM,DIM> C;
271 static c_matrix<double,DIM,DIM> inv_C;
272 static c_matrix<double,DIM,DIM> inv_F;
273 static c_matrix<double,DIM,DIM> T;
275 static c_matrix<double,DIM,DIM> F_T;
276 static c_matrix<double,DIM,NUM_NODES_PER_ELEMENT> F_T_grad_quad_phi;
278 c_vector<double,DIM> body_force;
286 static c_matrix<double, DIM, NUM_NODES_PER_ELEMENT> temp_matrix;
287 static c_matrix<double,NUM_NODES_PER_ELEMENT,DIM> grad_quad_phi_times_invF;
290 if (this->mSetComputeAverageStressPerElement)
292 this->mAverageStressesPerElement[rElement.
GetIndex()] = zero_vector<double>(DIM*(DIM+1)/2);
296 for (
unsigned quadrature_index=0; quadrature_index < this->mpQuadratureRule->GetNumQuadPoints(); quadrature_index++)
299 unsigned current_quad_point_global_index = rElement.
GetIndex()*this->mpQuadratureRule->GetNumQuadPoints()
302 double wJ = jacobian_determinant * this->mpQuadratureRule->GetWeight(quadrature_index);
304 const ChastePoint<DIM>& quadrature_point = this->mpQuadratureRule->rGetQuadPoint(quadrature_index);
310 trans_grad_quad_phi = trans(grad_quad_phi);
313 if (assembleResidual)
315 switch (this->mrProblemDefinition.GetBodyForceType())
317 case FUNCTIONAL_BODY_FORCE:
319 c_vector<double,DIM> X = zero_vector<double>(DIM);
321 for (
unsigned node_index=0; node_index<NUM_VERTICES_PER_ELEMENT; node_index++)
323 X += linear_phi(node_index)*this->mrQuadMesh.GetNode( rElement.
GetNodeGlobalIndex(node_index) )->rGetLocation();
325 body_force = this->mrProblemDefinition.EvaluateBodyForceFunction(X, this->mCurrentTime);
328 case CONSTANT_BODY_FORCE:
330 body_force = this->mrProblemDefinition.GetConstantBodyForce();
339 grad_u = zero_matrix<double>(DIM,DIM);
341 for (
unsigned node_index=0; node_index<NUM_NODES_PER_ELEMENT; node_index++)
343 for (
unsigned i=0; i<DIM; i++)
345 for (
unsigned M=0; M<DIM; M++)
347 grad_u(i,M) += grad_quad_phi(M,node_index)*element_current_displacements(i,node_index);
353 for (
unsigned vertex_index=0; vertex_index<NUM_VERTICES_PER_ELEMENT; vertex_index++)
355 pressure += linear_phi(vertex_index)*element_current_pressures(vertex_index);
359 for (
unsigned i=0; i<DIM; i++)
361 for (
unsigned M=0; M<DIM; M++)
363 F(i,M) = (i==M?1:0) + grad_u(i,M);
367 C = prod(trans(F),F);
374 this->SetupChangeOfBasisMatrix(rElement.
GetIndex(), current_quad_point_global_index);
378 if (this->mIncludeActiveTension)
382 this->AddActiveStressAndStressDerivative(C, rElement.
GetIndex(), current_quad_point_global_index,
383 T, dTdE, assembleJacobian);
386 if (this->mSetComputeAverageStressPerElement)
388 this->AddStressToAverageStressPerElement(T,rElement.
GetIndex());
392 if (assembleResidual)
395 F_T_grad_quad_phi = prod(F_T, grad_quad_phi);
397 for (
unsigned index=0; index<NUM_NODES_PER_ELEMENT*DIM; index++)
399 unsigned spatial_dim = index%DIM;
400 unsigned node_index = (index-spatial_dim)/DIM;
402 rBElem(index) += - this->mrProblemDefinition.GetDensity()
403 * body_force(spatial_dim)
404 * quad_phi(node_index)
408 rBElem(index) += F_T_grad_quad_phi(spatial_dim,node_index)
412 for (
unsigned vertex_index=0; vertex_index<NUM_VERTICES_PER_ELEMENT; vertex_index++)
414 rBElem( NUM_NODES_PER_ELEMENT*DIM + vertex_index ) += linear_phi(vertex_index)
421 if (assembleJacobian)
424 grad_quad_phi_times_invF = prod(trans_grad_quad_phi, inv_F);
439 for (
unsigned M=0; M<DIM; M++)
441 for (
unsigned N=0; N<DIM; N++)
443 for (
unsigned P=0; P<DIM; P++)
445 for (
unsigned Q=0; Q<DIM; Q++)
448 dSdF(M,N,P,Q) = 0.5*(dTdE(M,N,P,Q) + dTdE(M,N,Q,P));
455 dTdE.template SetAsContractionOnSecondDimension<DIM>(F, dSdF);
458 dSdF.template SetAsContractionOnFourthDimension<DIM>(F, dTdE);
461 for (
unsigned M=0; M<DIM; M++)
463 for (
unsigned N=0; N<DIM; N++)
465 for (
unsigned i=0; i<DIM; i++)
467 dSdF(M,i,N,i) += T(M,N);
484 temp_tensor.template SetAsContractionOnFirstDimension<DIM>( trans_grad_quad_phi, dSdF );
485 dSdF_quad_quad.template SetAsContractionOnThirdDimension<DIM>( trans_grad_quad_phi, temp_tensor );
487 for (
unsigned index1=0; index1<NUM_NODES_PER_ELEMENT*DIM; index1++)
489 unsigned spatial_dim1 = index1%DIM;
490 unsigned node_index1 = (index1-spatial_dim1)/DIM;
493 for (
unsigned index2=0; index2<NUM_NODES_PER_ELEMENT*DIM; index2++)
495 unsigned spatial_dim2 = index2%DIM;
496 unsigned node_index2 = (index2-spatial_dim2)/DIM;
499 rAElem(index1,index2) += dSdF_quad_quad(node_index1,spatial_dim1,node_index2,spatial_dim2)
503 for (
unsigned vertex_index=0; vertex_index<NUM_VERTICES_PER_ELEMENT; vertex_index++)
505 unsigned index2 = NUM_NODES_PER_ELEMENT*DIM + vertex_index;
508 rAElem(index1,index2) += - grad_quad_phi_times_invF(node_index1,spatial_dim1)
509 * linear_phi(vertex_index)
514 for (
unsigned vertex_index=0; vertex_index<NUM_VERTICES_PER_ELEMENT; vertex_index++)
516 unsigned index1 = NUM_NODES_PER_ELEMENT*DIM + vertex_index;
518 for (
unsigned index2=0; index2<NUM_NODES_PER_ELEMENT*DIM; index2++)
520 unsigned spatial_dim2 = index2%DIM;
521 unsigned node_index2 = (index2-spatial_dim2)/DIM;
524 rAElem(index1,index2) += detF
525 * grad_quad_phi_times_invF(node_index2,spatial_dim2)
526 * linear_phi(vertex_index)
536 for (
unsigned vertex_index2=0; vertex_index2<NUM_VERTICES_PER_ELEMENT; vertex_index2++)
538 unsigned index2 = NUM_NODES_PER_ELEMENT*DIM + vertex_index2;
539 rAElemPrecond(index1,index2) += linear_phi(vertex_index)
540 * linear_phi(vertex_index2)
547 if (assembleJacobian)
549 if (this->mPetscDirectSolve)
555 rAElemPrecond = rAElemPrecond + rAElem;
566 rAElemPrecond = rAElemPrecond + rAElem;
568 for (
unsigned i=NUM_NODES_PER_ELEMENT*DIM; i<STENCIL_SIZE; i++)
570 for (
unsigned j=0; j<NUM_NODES_PER_ELEMENT*DIM; j++)
572 rAElemPrecond(i,j) = 0.0;
578 if (this->mSetComputeAverageStressPerElement)
580 for (
unsigned i=0; i<DIM*(DIM+1)/2; i++)
582 this->mAverageStressesPerElement[rElement.
GetIndex()](i) /= this->mpQuadratureRule->GetNumQuadPoints();