00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include "NonlinearElasticityAssembler.hpp"
00042 #include "LinearBasisFunction.hpp"
00043 #include "QuadraticBasisFunction.hpp"
00044
00045
00046 template<size_t DIM>
00047 void NonlinearElasticityAssembler<DIM>::AssembleSystem(bool assembleResidual,
00048 bool assembleJacobian)
00049 {
00050
00051 assert(assembleResidual || assembleJacobian);
00052 assert(this->mCurrentSolution.size()==this->mNumDofs);
00053
00054
00055 if (assembleResidual)
00056 {
00057 this->mpLinearSystem->ZeroRhsVector();
00058 }
00059 if (assembleJacobian)
00060 {
00061 this->mpLinearSystem->ZeroLhsMatrix();
00062 this->mpPreconditionMatrixLinearSystem->ZeroLhsMatrix();
00063 }
00064
00065 c_matrix<double, STENCIL_SIZE, STENCIL_SIZE> a_elem;
00066
00067
00068 c_matrix<double, STENCIL_SIZE, STENCIL_SIZE> a_elem_precond;
00069 c_vector<double, STENCIL_SIZE> b_elem;
00070
00072
00074 for (typename AbstractTetrahedralMesh<DIM, DIM>::ElementIterator iter = mpQuadMesh->GetElementIteratorBegin();
00075 iter != mpQuadMesh->GetElementIteratorEnd();
00076 ++iter)
00077 {
00078 #ifdef MECH_VERY_VERBOSE
00079 if (assembleJacobian)
00080 {
00081 std::cout << "\r[" << PetscTools::GetMyRank() << "]: Element " << (*iter).GetIndex() << " of " << this->mpQuadMesh->GetNumElements() << std::flush;
00082 }
00083 #endif
00084
00085 Element<DIM, DIM>& element = *iter;
00086
00087 if (element.GetOwnership() == true)
00088 {
00089 AssembleOnElement(element, a_elem, a_elem_precond, b_elem, assembleResidual, assembleJacobian);
00090
00091 unsigned p_indices[STENCIL_SIZE];
00092 for (unsigned i=0; i<NUM_NODES_PER_ELEMENT; i++)
00093 {
00094 for (unsigned j=0; j<DIM; j++)
00095 {
00096 p_indices[DIM*i+j] = DIM*element.GetNodeGlobalIndex(i) + j;
00097 }
00098 }
00099
00100 for (unsigned i=0; i<NUM_VERTICES_PER_ELEMENT; i++)
00101 {
00102 p_indices[DIM*NUM_NODES_PER_ELEMENT + i] = DIM*mpQuadMesh->GetNumNodes() + element.GetNodeGlobalIndex(i);
00103 }
00104
00105 if (assembleJacobian)
00106 {
00107 this->mpLinearSystem->AddLhsMultipleValues(p_indices, a_elem);
00108 this->mpPreconditionMatrixLinearSystem->AddLhsMultipleValues(p_indices, a_elem_precond);
00109 }
00110
00111 if (assembleResidual)
00112 {
00113 this->mpLinearSystem->AddRhsMultipleValues(p_indices, b_elem);
00114 }
00115 }
00116 }
00117
00119
00120
00122 c_vector<double, BOUNDARY_STENCIL_SIZE> b_boundary_elem;
00123 c_matrix<double, BOUNDARY_STENCIL_SIZE, BOUNDARY_STENCIL_SIZE> a_boundary_elem;
00124 if (mBoundaryElements.size()>0)
00125 {
00126 for (unsigned i=0; i<mBoundaryElements.size(); i++)
00127 {
00128 BoundaryElement<DIM-1,DIM>& r_boundary_element = *(mBoundaryElements[i]);
00129 AssembleOnBoundaryElement(r_boundary_element, a_boundary_elem, b_boundary_elem, this->mSurfaceTractions[i], assembleResidual, assembleJacobian);
00130
00131 unsigned p_indices[BOUNDARY_STENCIL_SIZE];
00132 for (unsigned i=0; i<NUM_NODES_PER_BOUNDARY_ELEMENT; i++)
00133 {
00134 for (unsigned j=0; j<DIM; j++)
00135 {
00136 p_indices[DIM*i+j] = DIM*r_boundary_element.GetNodeGlobalIndex(i) + j;
00137 }
00138 }
00139
00140 for (unsigned i=0; i<DIM ; i++)
00141 {
00142 p_indices[DIM*NUM_NODES_PER_BOUNDARY_ELEMENT + i] = DIM*mpQuadMesh->GetNumNodes() + r_boundary_element.GetNodeGlobalIndex(i);
00143 }
00144
00145 if (assembleJacobian)
00146 {
00147 this->mpLinearSystem->AddLhsMultipleValues(p_indices, a_boundary_elem);
00148 this->mpPreconditionMatrixLinearSystem->AddLhsMultipleValues(p_indices, a_boundary_elem);
00149 }
00150
00151 if (assembleResidual)
00152 {
00153 this->mpLinearSystem->AddRhsMultipleValues(p_indices, b_boundary_elem);
00154 }
00155
00156
00157 if (DIM==2)
00158 {
00159 assert(8==BOUNDARY_STENCIL_SIZE);
00160 assert(b_boundary_elem(6)==0);
00161 assert(b_boundary_elem(7)==0);
00162 }
00163 }
00164 }
00165
00166 if (assembleResidual)
00167 {
00168 this->mpLinearSystem->AssembleRhsVector();
00169 }
00170 if (assembleJacobian)
00171 {
00172 this->mpLinearSystem->AssembleIntermediateLhsMatrix();
00173 this->mpPreconditionMatrixLinearSystem->AssembleIntermediateLhsMatrix();
00174 }
00175
00176
00177 this->ApplyBoundaryConditions(assembleJacobian);
00178
00179 if (assembleResidual)
00180 {
00181 this->mpLinearSystem->AssembleRhsVector();
00182 }
00183 if (assembleJacobian)
00184 {
00185 this->mpLinearSystem->AssembleFinalLhsMatrix();
00186 this->mpPreconditionMatrixLinearSystem->AssembleFinalLhsMatrix();
00187 }
00188 }
00189
00190 template<size_t DIM>
00191 void NonlinearElasticityAssembler<DIM>::AssembleOnElement(
00192 Element<DIM, DIM>& rElement,
00193 c_matrix<double, STENCIL_SIZE, STENCIL_SIZE >& rAElem,
00194 c_matrix<double, STENCIL_SIZE, STENCIL_SIZE >& rAElemPrecond,
00195 c_vector<double, STENCIL_SIZE>& rBElem,
00196 bool assembleResidual,
00197 bool assembleJacobian)
00198 {
00199 c_matrix<double, DIM, DIM> jacobian, inverse_jacobian;
00200 double jacobian_determinant;
00201
00202 mpQuadMesh->GetInverseJacobianForElement(rElement.GetIndex(), jacobian, jacobian_determinant, inverse_jacobian);
00203
00204 if (assembleJacobian)
00205 {
00206 rAElem.clear();
00207 rAElemPrecond.clear();
00208 }
00209
00210 if (assembleResidual)
00211 {
00212 rBElem.clear();
00213 }
00214
00216
00218 static c_matrix<double,DIM,NUM_NODES_PER_ELEMENT> element_current_displacements;
00219 static c_vector<double,NUM_VERTICES_PER_ELEMENT> element_current_pressures;
00220 for (unsigned II=0; II<NUM_NODES_PER_ELEMENT; II++)
00221 {
00222 for (unsigned JJ=0; JJ<DIM; JJ++)
00223 {
00224 element_current_displacements(JJ,II) = this->mCurrentSolution[DIM*rElement.GetNodeGlobalIndex(II) + JJ];
00225 }
00226 }
00227
00229
00231 for (unsigned II=0; II<NUM_VERTICES_PER_ELEMENT; II++)
00232 {
00233 element_current_pressures(II) = this->mCurrentSolution[DIM*mpQuadMesh->GetNumNodes() + rElement.GetNodeGlobalIndex(II)];
00234 }
00235
00236
00237 c_vector<double, NUM_VERTICES_PER_ELEMENT> linear_phi;
00238 c_vector<double, NUM_NODES_PER_ELEMENT> quad_phi;
00239 c_matrix<double, DIM, NUM_NODES_PER_ELEMENT> grad_quad_phi;
00240
00241
00242 AbstractIncompressibleMaterialLaw<DIM>* p_material_law;
00243 if (this->mMaterialLaws.size()==1)
00244 {
00245
00246 p_material_law = this->mMaterialLaws[0];
00247 }
00248 else
00249 {
00250
00251 #define COVERAGE_IGNORE // not going to have tests in cts for everything
00252 p_material_law = this->mMaterialLaws[rElement.GetIndex()];
00253 #undef COVERAGE_IGNORE
00254 }
00255
00256
00262 for (unsigned quadrature_index=0; quadrature_index < this->mpQuadratureRule->GetNumQuadPoints(); quadrature_index++)
00263 {
00264 double wJ = jacobian_determinant * this->mpQuadratureRule->GetWeight(quadrature_index);
00265
00266 const ChastePoint<DIM>& quadrature_point = this->mpQuadratureRule->rGetQuadPoint(quadrature_index);
00267
00269
00271 LinearBasisFunction<DIM>::ComputeBasisFunctions(quadrature_point, linear_phi);
00272 QuadraticBasisFunction<DIM>::ComputeBasisFunctions(quadrature_point, quad_phi);
00273 QuadraticBasisFunction<DIM>::ComputeTransformedBasisFunctionDerivatives(quadrature_point, inverse_jacobian, grad_quad_phi);
00274
00275
00277
00279 c_vector<double,DIM> body_force;
00280
00281 if (this->mUsingBodyForceFunction)
00282 {
00283 c_vector<double,DIM> X = zero_vector<double>(DIM);
00284
00285 for (unsigned node_index=0; node_index<NUM_VERTICES_PER_ELEMENT; node_index++)
00286 {
00287 X += linear_phi(node_index)*mpQuadMesh->GetNode( rElement.GetNodeGlobalIndex(node_index) )->rGetLocation();
00288 }
00289 body_force = (*(this->mpBodyForceFunction))(X);
00290 }
00291 else
00292 {
00293 body_force = this->mBodyForce;
00294 }
00295
00297
00299 static c_matrix<double,DIM,DIM> grad_u;
00300 grad_u = zero_matrix<double>(DIM,DIM);
00301
00302 for (unsigned node_index=0; node_index<NUM_NODES_PER_ELEMENT; node_index++)
00303 {
00304 for (unsigned i=0; i<DIM; i++)
00305 {
00306 for (unsigned M=0; M<DIM; M++)
00307 {
00308 grad_u(i,M) += grad_quad_phi(M,node_index)*element_current_displacements(i,node_index);
00309 }
00310 }
00311 }
00312
00313 double pressure = 0;
00314 for (unsigned vertex_index=0; vertex_index<NUM_VERTICES_PER_ELEMENT; vertex_index++)
00315 {
00316 pressure += linear_phi(vertex_index)*element_current_pressures(vertex_index);
00317 }
00318
00319
00321
00323 static c_matrix<double,DIM,DIM> F;
00324 static c_matrix<double,DIM,DIM> C;
00325 static c_matrix<double,DIM,DIM> inv_C;
00326 static c_matrix<double,DIM,DIM> inv_F;
00327 static c_matrix<double,DIM,DIM> T;
00328
00329 for (unsigned i=0; i<DIM; i++)
00330 {
00331 for (unsigned M=0; M<DIM; M++)
00332 {
00333 F(i,M) = (i==M?1:0) + grad_u(i,M);
00334 }
00335 }
00336
00337 C = prod(trans(F),F);
00338 inv_C = Inverse(C);
00339 inv_F = Inverse(F);
00340
00341 double detF = Determinant(F);
00342
00343 p_material_law->ComputeStressAndStressDerivative(C,inv_C,pressure,T,this->dTdE,assembleJacobian);
00344
00345 static FourthOrderTensor<DIM> dTdE_F;
00346 static FourthOrderTensor<DIM> dTdE_FF1;
00347 static FourthOrderTensor<DIM> dTdE_FF2;
00348
00349 dTdE_F.SetAsProduct(this->dTdE, F, 1);
00350 dTdE_FF1.SetAsProduct(dTdE_F, F, 3);
00351 dTdE_FF2.SetAsProduct(dTdE_F, F, 2);
00352
00353
00355
00357 if (assembleResidual)
00358 {
00359 for (unsigned index=0; index<NUM_NODES_PER_ELEMENT*DIM; index++)
00360 {
00361 unsigned spatial_dim = index%DIM;
00362 unsigned node_index = (index-spatial_dim)/DIM;
00363
00364 assert(node_index < NUM_NODES_PER_ELEMENT);
00365
00366 rBElem(index) += - this->mDensity
00367 * body_force(spatial_dim)
00368 * quad_phi(node_index)
00369 * wJ;
00370
00371 for (unsigned M=0; M<DIM; M++)
00372 {
00373 for (unsigned N=0; N<DIM; N++)
00374 {
00375 rBElem(index) += T(M,N)
00376 * F(spatial_dim,M)
00377 * grad_quad_phi(N,node_index)
00378 * wJ;
00379 }
00380 }
00381 }
00382
00383 for (unsigned vertex_index=0; vertex_index<NUM_VERTICES_PER_ELEMENT; vertex_index++)
00384 {
00385 rBElem( NUM_NODES_PER_ELEMENT*DIM + vertex_index ) += linear_phi(vertex_index)
00386 * (detF - 1)
00387 * wJ;
00388 }
00389 }
00390
00392
00394 if (assembleJacobian)
00395 {
00396 for (unsigned index1=0; index1<NUM_NODES_PER_ELEMENT*DIM; index1++)
00397 {
00398 unsigned spatial_dim1 = index1%DIM;
00399 unsigned node_index1 = (index1-spatial_dim1)/DIM;
00400
00401
00402 for (unsigned index2=0; index2<NUM_NODES_PER_ELEMENT*DIM; index2++)
00403 {
00404 unsigned spatial_dim2 = index2%DIM;
00405 unsigned node_index2 = (index2-spatial_dim2)/DIM;
00406
00407 for (unsigned M=0; M<DIM; M++)
00408 {
00409 for (unsigned N=0; N<DIM; N++)
00410 {
00411 rAElem(index1,index2) += T(M,N)
00412 * grad_quad_phi(M,node_index1)
00413 * grad_quad_phi(N,node_index2)
00414 * (spatial_dim1==spatial_dim2?1:0)
00415 * wJ;
00416 }
00417 }
00418
00419 for (unsigned M=0; M<DIM; M++)
00420 {
00421 for (unsigned P=0; P<DIM; P++)
00422 {
00423 rAElem(index1,index2) += 0.5
00424 * dTdE_FF1(M,spatial_dim1,P,spatial_dim2)
00425 * grad_quad_phi(P,node_index2)
00426 * grad_quad_phi(M,node_index1)
00427 * wJ;
00428 }
00429
00430 for (unsigned Q=0; Q<DIM; Q++)
00431 {
00432 rAElem(index1,index2) += 0.5
00433 * dTdE_FF2(M,spatial_dim1,spatial_dim2,Q)
00434 * grad_quad_phi(Q,node_index2)
00435 * grad_quad_phi(M,node_index1)
00436 * wJ;
00437 }
00438 }
00439 }
00440
00441 for (unsigned vertex_index=0; vertex_index<NUM_VERTICES_PER_ELEMENT; vertex_index++)
00442 {
00443 unsigned index2 = NUM_NODES_PER_ELEMENT*DIM + vertex_index;
00444
00445 for (unsigned M=0; M<DIM; M++)
00446 {
00447 rAElem(index1,index2) += - inv_F(M,spatial_dim1)
00448 * grad_quad_phi(M,node_index1)
00449 * linear_phi(vertex_index)
00450 * wJ;
00451 }
00452 }
00453 }
00454
00455 for (unsigned vertex_index=0; vertex_index<NUM_VERTICES_PER_ELEMENT; vertex_index++)
00456 {
00457 unsigned index1 = NUM_NODES_PER_ELEMENT*DIM + vertex_index;
00458
00459 for (unsigned index2=0; index2<NUM_NODES_PER_ELEMENT*DIM; index2++)
00460 {
00461 unsigned spatial_dim2 = index2%DIM;
00462 unsigned node_index2 = (index2-spatial_dim2)/DIM;
00463
00464 for (unsigned M=0; M<DIM; M++)
00465 {
00466
00467 rAElem(index1,index2) += detF
00468 * inv_F(M,spatial_dim2)
00469 * grad_quad_phi(M,node_index2)
00470 * linear_phi(vertex_index)
00471 * wJ;
00472 }
00473 }
00474
00476
00477
00478
00479
00481 for (unsigned vertex_index2=0; vertex_index2<NUM_VERTICES_PER_ELEMENT; vertex_index2++)
00482 {
00483 unsigned index2 = NUM_NODES_PER_ELEMENT*DIM + vertex_index2;
00484 rAElemPrecond(index1,index2) += linear_phi(vertex_index)
00485 * linear_phi(vertex_index2)
00486 * wJ;
00487 }
00488 }
00489 }
00490 }
00491
00492 if (assembleJacobian)
00493 {
00494
00495
00496
00497
00498
00499
00500
00501
00502 rAElemPrecond = rAElemPrecond + rAElem;
00503 for(unsigned i=NUM_NODES_PER_ELEMENT*DIM; i<STENCIL_SIZE; i++)
00504 {
00505 for(unsigned j=0; j<NUM_NODES_PER_ELEMENT*DIM; j++)
00506 {
00507 rAElemPrecond(i,j) = 0.0;
00508 }
00509 }
00510 }
00511 }
00512
00513 template<size_t DIM>
00514 void NonlinearElasticityAssembler<DIM>::AssembleOnBoundaryElement(
00515 BoundaryElement<DIM-1,DIM>& rBoundaryElement,
00516 c_matrix<double,BOUNDARY_STENCIL_SIZE,BOUNDARY_STENCIL_SIZE>& rAelem,
00517 c_vector<double,BOUNDARY_STENCIL_SIZE>& rBelem,
00518 c_vector<double,DIM>& rTraction,
00519 bool assembleResidual,
00520 bool assembleJacobian)
00521 {
00522 rAelem.clear();
00523 rBelem.clear();
00524
00525 if (assembleJacobian && !assembleResidual)
00526 {
00527
00528 return;
00529 }
00530
00531 c_vector<double, DIM> weighted_direction;
00532 double jacobian_determinant;
00533 mpQuadMesh->GetWeightedDirectionForBoundaryElement(rBoundaryElement.GetIndex(), weighted_direction, jacobian_determinant);
00534
00535 c_vector<double,NUM_NODES_PER_BOUNDARY_ELEMENT> phi;
00536
00537 for (unsigned quad_index=0; quad_index<this->mpBoundaryQuadratureRule->GetNumQuadPoints(); quad_index++)
00538 {
00539 double wJ = jacobian_determinant * this->mpBoundaryQuadratureRule->GetWeight(quad_index);
00540
00541 const ChastePoint<DIM-1>& quad_point = this->mpBoundaryQuadratureRule->rGetQuadPoint(quad_index);
00542
00543 QuadraticBasisFunction<DIM-1>::ComputeBasisFunctions(quad_point, phi);
00544
00545
00546
00547 c_vector<double,DIM> traction = zero_vector<double>(DIM);
00548 if (this->mUsingTractionBoundaryConditionFunction)
00549 {
00550 c_vector<double,DIM> X = zero_vector<double>(DIM);
00551 for (unsigned node_index=0; node_index<NUM_NODES_PER_BOUNDARY_ELEMENT; node_index++)
00552 {
00553 X += phi(node_index)*mpQuadMesh->GetNode( rBoundaryElement.GetNodeGlobalIndex(node_index) )->rGetLocation();
00554 }
00555 traction = (*(this->mpTractionBoundaryConditionFunction))(X);
00556 }
00557 else
00558 {
00559 traction = rTraction;
00560 }
00561
00562
00563 for (unsigned index=0; index<NUM_NODES_PER_BOUNDARY_ELEMENT*DIM; index++)
00564 {
00565 unsigned spatial_dim = index%DIM;
00566 unsigned node_index = (index-spatial_dim)/DIM;
00567
00568 assert(node_index < NUM_NODES_PER_BOUNDARY_ELEMENT);
00569
00570 rBelem(index) -= traction(spatial_dim)
00571 * phi(node_index)
00572 * wJ;
00573 }
00574 }
00575 }
00576
00577 template<size_t DIM>
00578 void NonlinearElasticityAssembler<DIM>::FormInitialGuess()
00579 {
00580 this->mCurrentSolution.resize(this->mNumDofs, 0.0);
00581
00582 for (unsigned i=0; i<mpQuadMesh->GetNumElements(); i++)
00583 {
00584 double zero_strain_pressure;
00585 if (this->mMaterialLaws.size()==1)
00586 {
00587
00588 zero_strain_pressure = this->mMaterialLaws[0]->GetZeroStrainPressure();
00589 }
00590 else
00591 {
00592
00593 zero_strain_pressure = this->mMaterialLaws[i]->GetZeroStrainPressure();
00594 }
00595
00596
00597 for (unsigned j=0; j<NUM_VERTICES_PER_ELEMENT; j++)
00598 {
00599 unsigned index = mpQuadMesh->GetElement(i)->GetNodeGlobalIndex(j);
00600 this->mCurrentSolution[ DIM*mpQuadMesh->GetNumNodes() + index ] = zero_strain_pressure;
00601 }
00602 }
00603 }
00604
00605 template<size_t DIM>
00606 void NonlinearElasticityAssembler<DIM>::Initialise(std::vector<c_vector<double,DIM> >* pFixedNodeLocations)
00607 {
00608 assert(mpQuadMesh);
00609
00610 AllocateMatrixMemory();
00611
00612 for (unsigned i=0; i<this->mFixedNodes.size(); i++)
00613 {
00614 assert(this->mFixedNodes[i] < mpQuadMesh->GetNumNodes());
00615 }
00616
00617 this->mpQuadratureRule = new GaussianQuadratureRule<DIM>(3);
00618 this->mpBoundaryQuadratureRule = new GaussianQuadratureRule<DIM-1>(3);
00619
00620 FormInitialGuess();
00621
00622
00623
00624 if (pFixedNodeLocations == NULL)
00625 {
00626 this->mFixedNodeDisplacements.clear();
00627 for (unsigned i=0; i<this->mFixedNodes.size(); i++)
00628 {
00629 this->mFixedNodeDisplacements.push_back(zero_vector<double>(DIM));
00630 }
00631 }
00632 else
00633 {
00634 assert(pFixedNodeLocations->size()==this->mFixedNodes.size());
00635 for (unsigned i=0; i<this->mFixedNodes.size(); i++)
00636 {
00637 unsigned index = this->mFixedNodes[i];
00638 c_vector<double,DIM> displacement = (*pFixedNodeLocations)[i]-mpQuadMesh->GetNode(index)->rGetLocation();
00639 this->mFixedNodeDisplacements.push_back(displacement);
00640 }
00641 }
00642 assert(this->mFixedNodeDisplacements.size()==this->mFixedNodes.size());
00643 }
00644
00645 template<size_t DIM>
00646 void NonlinearElasticityAssembler<DIM>::AllocateMatrixMemory()
00647 {
00648
00650
00651
00652
00653 this->mpLinearSystem = new LinearSystem(this->mNumDofs, (MatType)MATAIJ);
00654 this->mpPreconditionMatrixLinearSystem = new LinearSystem(this->mNumDofs, (MatType)MATAIJ);
00655
00656
00657
00658 if(DIM==2)
00659 {
00660
00661 unsigned num_non_zeros = 75;
00662
00663 if(PetscTools::GetNumProcs()==1)
00664 {
00665 MatSeqAIJSetPreallocation(this->mpLinearSystem->rGetLhsMatrix(), num_non_zeros, PETSC_NULL);
00666 MatSeqAIJSetPreallocation(this->mpPreconditionMatrixLinearSystem->rGetLhsMatrix(), num_non_zeros, PETSC_NULL);
00667 }
00668 else
00669 {
00670 MatMPIAIJSetPreallocation(this->mpLinearSystem->rGetLhsMatrix(), num_non_zeros, PETSC_NULL, num_non_zeros, PETSC_NULL);
00671 MatMPIAIJSetPreallocation(this->mpPreconditionMatrixLinearSystem->rGetLhsMatrix(), num_non_zeros, PETSC_NULL, num_non_zeros, PETSC_NULL);
00672 }
00673 }
00674 else
00675 {
00676 assert(DIM==3);
00677
00678
00679
00680
00681 int* num_non_zeros_each_row = new int[this->mNumDofs];
00682 for(unsigned i=0; i<this->mNumDofs; i++)
00683 {
00684 num_non_zeros_each_row[i] = 0;
00685 }
00686
00687 for(unsigned i=0; i<mpQuadMesh->GetNumNodes(); i++)
00688 {
00689
00690
00691
00692 unsigned num_non_zeros_upper_bound = 4 + 30*mpQuadMesh->GetNode(i)->GetNumContainingElements();
00693
00694 num_non_zeros_each_row[DIM*i + 0] = num_non_zeros_upper_bound;
00695 num_non_zeros_each_row[DIM*i + 1] = num_non_zeros_upper_bound;
00696 num_non_zeros_each_row[DIM*i + 2] = num_non_zeros_upper_bound;
00697
00698 if(i<mpQuadMesh->GetNumVertices())
00699 {
00700 num_non_zeros_each_row[DIM*mpQuadMesh->GetNumNodes() + i] = num_non_zeros_upper_bound;
00701 }
00702 }
00703
00704 if(PetscTools::GetNumProcs()==1)
00705 {
00706 MatSeqAIJSetPreallocation(this->mpLinearSystem->rGetLhsMatrix(), PETSC_NULL, num_non_zeros_each_row);
00707 MatSeqAIJSetPreallocation(this->mpPreconditionMatrixLinearSystem->rGetLhsMatrix(), PETSC_NULL, num_non_zeros_each_row);
00708 }
00709 else
00710 {
00711 PetscInt lo, hi;
00712 this->mpLinearSystem->GetOwnershipRange(lo, hi);
00713 int* num_non_zeros_each_row_this_proc = new int[hi-lo];
00714 for(unsigned i=0; i<unsigned(hi-lo); i++)
00715 {
00716 num_non_zeros_each_row_this_proc[i] = num_non_zeros_each_row[lo+i];
00717 }
00718
00719 MatMPIAIJSetPreallocation(this->mpLinearSystem->rGetLhsMatrix(), PETSC_NULL, num_non_zeros_each_row_this_proc, PETSC_NULL, num_non_zeros_each_row_this_proc);
00720 MatMPIAIJSetPreallocation(this->mpPreconditionMatrixLinearSystem->rGetLhsMatrix(), PETSC_NULL, num_non_zeros_each_row_this_proc, PETSC_NULL, num_non_zeros_each_row_this_proc);
00721 }
00722
00723
00724
00725
00726
00727
00728
00729
00730 delete [] num_non_zeros_each_row;
00731 }
00732 }
00733
00734
00735
00736 template<size_t DIM>
00737 NonlinearElasticityAssembler<DIM>::NonlinearElasticityAssembler(
00738 QuadraticMesh<DIM>* pQuadMesh,
00739 AbstractIncompressibleMaterialLaw<DIM>* pMaterialLaw,
00740 c_vector<double,DIM> bodyForce,
00741 double density,
00742 std::string outputDirectory,
00743 std::vector<unsigned>& fixedNodes,
00744 std::vector<c_vector<double,DIM> >* pFixedNodeLocations)
00745 : AbstractNonlinearElasticityAssembler<DIM>(DIM*pQuadMesh->GetNumNodes()+pQuadMesh->GetNumVertices(),
00746 pMaterialLaw, bodyForce, density,
00747 outputDirectory, fixedNodes),
00748 mpQuadMesh(pQuadMesh)
00749 {
00750 Initialise(pFixedNodeLocations);
00751 }
00752
00753
00754 template<size_t DIM>
00755 NonlinearElasticityAssembler<DIM>::NonlinearElasticityAssembler(
00756 QuadraticMesh<DIM>* pQuadMesh,
00757 std::vector<AbstractIncompressibleMaterialLaw<DIM>*>& rMaterialLaws,
00758 c_vector<double,DIM> bodyForce,
00759 double density,
00760 std::string outputDirectory,
00761 std::vector<unsigned>& fixedNodes,
00762 std::vector<c_vector<double,DIM> >* pFixedNodeLocations)
00763 : AbstractNonlinearElasticityAssembler<DIM>(DIM*pQuadMesh->GetNumNodes()+pQuadMesh->GetNumVertices(),
00764 rMaterialLaws, bodyForce, density,
00765 outputDirectory, fixedNodes),
00766 mpQuadMesh(pQuadMesh)
00767 {
00768 assert(rMaterialLaws.size()==pQuadMesh->GetNumElements());
00769 Initialise(pFixedNodeLocations);
00770 }
00771
00772
00773 template<size_t DIM>
00774 NonlinearElasticityAssembler<DIM>::~NonlinearElasticityAssembler()
00775 {
00776 delete mpQuadratureRule;
00777 delete mpBoundaryQuadratureRule;
00778 }
00779
00780 template<size_t DIM>
00781 void NonlinearElasticityAssembler<DIM>::SetSurfaceTractionBoundaryConditions(
00782 std::vector<BoundaryElement<DIM-1,DIM>*>& rBoundaryElements,
00783 std::vector<c_vector<double,DIM> >& rSurfaceTractions)
00784 {
00785 assert(rBoundaryElements.size()==rSurfaceTractions.size());
00786 mBoundaryElements = rBoundaryElements;
00787 this->mSurfaceTractions = rSurfaceTractions;
00788 }
00789
00790 template<size_t DIM>
00791 void NonlinearElasticityAssembler<DIM>::SetFunctionalTractionBoundaryCondition(
00792 std::vector<BoundaryElement<DIM-1,DIM>*> rBoundaryElements,
00793 c_vector<double,DIM> (*pFunction)(c_vector<double,DIM>&))
00794 {
00795 mBoundaryElements = rBoundaryElements;
00796 this->mUsingTractionBoundaryConditionFunction = true;
00797 this->mpTractionBoundaryConditionFunction = pFunction;
00798 }
00799
00800 template<size_t DIM>
00801 std::vector<double>& NonlinearElasticityAssembler<DIM>::rGetPressures()
00802 {
00803 this->mPressures.clear();
00804 this->mPressures.resize(mpQuadMesh->GetNumVertices());
00805
00806 for (unsigned i=0; i<mpQuadMesh->GetNumVertices(); i++)
00807 {
00808 this->mPressures[i] = this->mCurrentSolution[DIM*mpQuadMesh->GetNumNodes() + i];
00809 }
00810 return this->mPressures;
00811 }
00812
00813 template<size_t DIM>
00814 std::vector<c_vector<double,DIM> >& NonlinearElasticityAssembler<DIM>::rGetDeformedPosition()
00815 {
00816 this->mDeformedPosition.resize(mpQuadMesh->GetNumNodes(), zero_vector<double>(DIM));
00817 for (unsigned i=0; i<mpQuadMesh->GetNumNodes(); i++)
00818 {
00819 for (unsigned j=0; j<DIM; j++)
00820 {
00821 this->mDeformedPosition[i](j) = mpQuadMesh->GetNode(i)->rGetLocation()[j] + this->mCurrentSolution[DIM*i+j];
00822 }
00823 }
00824 return this->mDeformedPosition;
00825 }
00826
00827
00829
00831
00832
00833 template class NonlinearElasticityAssembler<2>;
00834 template class NonlinearElasticityAssembler<3>;