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 #ifndef ABSTRACTCONTINUUMMECHANICSASSEMBLER_HPP_
00030 #define ABSTRACTCONTINUUMMECHANICSASSEMBLER_HPP_
00031
00032 #include "AbstractFeAssemblerInterface.hpp"
00033 #include "QuadraticMesh.hpp"
00034 #include "LinearBasisFunction.hpp"
00035 #include "QuadraticBasisFunction.hpp"
00036 #include "ReplicatableVector.hpp"
00037 #include "DistributedVector.hpp"
00038 #include "PetscTools.hpp"
00039 #include "PetscVecTools.hpp"
00040 #include "PetscMatTools.hpp"
00041 #include "GaussianQuadratureRule.hpp"
00042
00043
00062 template<unsigned DIM, bool CAN_ASSEMBLE_VECTOR, bool CAN_ASSEMBLE_MATRIX>
00063 class AbstractContinuumMechanicsAssembler : public AbstractFeAssemblerInterface<CAN_ASSEMBLE_VECTOR,CAN_ASSEMBLE_MATRIX>
00064 {
00068 static const bool BLOCK_SYMMETRIC_MATRIX = true;
00069
00071 static const unsigned NUM_VERTICES_PER_ELEMENT = DIM+1;
00072
00074 static const unsigned NUM_NODES_PER_ELEMENT = (DIM+1)*(DIM+2)/2;
00075
00077 static const unsigned SPATIAL_BLOCK_SIZE_ELEMENTAL = DIM*NUM_NODES_PER_ELEMENT;
00079 static const unsigned PRESSURE_BLOCK_SIZE_ELEMENTAL = NUM_VERTICES_PER_ELEMENT;
00080
00082 static const unsigned STENCIL_SIZE = DIM*NUM_NODES_PER_ELEMENT + NUM_VERTICES_PER_ELEMENT;
00083
00084 protected:
00086 QuadraticMesh<DIM>* mpMesh;
00087
00089 GaussianQuadratureRule<DIM>* mpQuadRule;
00090
00097 void DoAssemble();
00098
00099
00118 virtual c_matrix<double,SPATIAL_BLOCK_SIZE_ELEMENTAL,SPATIAL_BLOCK_SIZE_ELEMENTAL> ComputeSpatialSpatialMatrixTerm(
00119 c_vector<double, NUM_NODES_PER_ELEMENT>& rQuadPhi,
00120 c_matrix<double, DIM, NUM_NODES_PER_ELEMENT>& rGradQuadPhi,
00121 c_vector<double,DIM>& rX,
00122 Element<DIM,DIM>* pElement)
00123 {
00124 return zero_matrix<double>(SPATIAL_BLOCK_SIZE_ELEMENTAL,SPATIAL_BLOCK_SIZE_ELEMENTAL);
00125 }
00126
00148 virtual c_matrix<double,SPATIAL_BLOCK_SIZE_ELEMENTAL,PRESSURE_BLOCK_SIZE_ELEMENTAL> ComputeSpatialPressureMatrixTerm(
00149 c_vector<double, NUM_NODES_PER_ELEMENT>& rQuadPhi,
00150 c_matrix<double, DIM, NUM_NODES_PER_ELEMENT>& rGradQuadPhi,
00151 c_vector<double, NUM_VERTICES_PER_ELEMENT>& rLinearPhi,
00152 c_matrix<double, DIM, NUM_VERTICES_PER_ELEMENT>& rGradLinearPhi,
00153 c_vector<double,DIM>& rX,
00154 Element<DIM,DIM>* pElement)
00155 {
00156 return zero_matrix<double>(SPATIAL_BLOCK_SIZE_ELEMENTAL,PRESSURE_BLOCK_SIZE_ELEMENTAL);
00157 }
00158
00159
00178 virtual c_matrix<double,PRESSURE_BLOCK_SIZE_ELEMENTAL,PRESSURE_BLOCK_SIZE_ELEMENTAL> ComputePressurePressureMatrixTerm(
00179 c_vector<double, NUM_VERTICES_PER_ELEMENT>& rLinearPhi,
00180 c_matrix<double, DIM, NUM_VERTICES_PER_ELEMENT>& rGradLinearPhi,
00181 c_vector<double,DIM>& rX,
00182 Element<DIM,DIM>* pElement)
00183 {
00184 return zero_matrix<double>(PRESSURE_BLOCK_SIZE_ELEMENTAL,PRESSURE_BLOCK_SIZE_ELEMENTAL);
00185 }
00186
00187
00209 virtual c_vector<double,SPATIAL_BLOCK_SIZE_ELEMENTAL> ComputeSpatialVectorTerm(
00210 c_vector<double, NUM_NODES_PER_ELEMENT>& rQuadPhi,
00211 c_matrix<double, DIM, NUM_NODES_PER_ELEMENT>& rGradQuadPhi,
00212 c_vector<double,DIM>& rX,
00213 Element<DIM,DIM>* pElement)
00214 {
00215 return zero_vector<double>(SPATIAL_BLOCK_SIZE_ELEMENTAL);
00216 }
00217
00218
00240 virtual c_vector<double,PRESSURE_BLOCK_SIZE_ELEMENTAL> ComputePressureVectorTerm(
00241 c_vector<double, NUM_VERTICES_PER_ELEMENT>& rLinearPhi,
00242 c_matrix<double, DIM, NUM_VERTICES_PER_ELEMENT>& rGradLinearPhi,
00243 c_vector<double,DIM>& rX,
00244 Element<DIM,DIM>* pElement)
00245 {
00246 return zero_vector<double>(PRESSURE_BLOCK_SIZE_ELEMENTAL);
00247 }
00248
00249
00250
00262 void AssembleOnElement(Element<DIM, DIM>& rElement,
00263 c_matrix<double, STENCIL_SIZE, STENCIL_SIZE >& rAElem,
00264 c_vector<double, STENCIL_SIZE>& rBElem);
00265
00266 public:
00270 AbstractContinuumMechanicsAssembler(QuadraticMesh<DIM>* pMesh, unsigned numQuadPoints = 3)
00271 : AbstractFeAssemblerInterface<CAN_ASSEMBLE_VECTOR,CAN_ASSEMBLE_MATRIX>(),
00272 mpMesh(pMesh)
00273 {
00274 assert(pMesh);
00275 mpQuadRule = new GaussianQuadratureRule<DIM>(numQuadPoints);
00276 }
00277
00278
00279
00280
00281
00285 virtual ~AbstractContinuumMechanicsAssembler()
00286 {
00287 delete mpQuadRule;
00288 }
00289 };
00290
00291
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309 template<unsigned DIM, bool CAN_ASSEMBLE_VECTOR, bool CAN_ASSEMBLE_MATRIX>
00310 void AbstractContinuumMechanicsAssembler<DIM,CAN_ASSEMBLE_VECTOR,CAN_ASSEMBLE_MATRIX>::DoAssemble()
00311 {
00312 assert(this->mAssembleMatrix || this->mAssembleVector);
00313 if (this->mAssembleMatrix)
00314 {
00315 if(this->mMatrixToAssemble==NULL)
00316 {
00317 EXCEPTION("Matrix to be assembled has not been set");
00318 }
00319 if( PetscMatTools::GetSize(this->mMatrixToAssemble) != DIM*mpMesh->GetNumNodes()+mpMesh->GetNumVertices() )
00320 {
00321 EXCEPTION("Matrix provided to be assembled has size " << PetscMatTools::GetSize(this->mMatrixToAssemble) << ", not expected size of " << DIM*mpMesh->GetNumNodes()+mpMesh->GetNumVertices() << " (dim*num_nodes+num_vertices)");
00322 }
00323 }
00324
00325 if (this->mAssembleVector)
00326 {
00327 if(this->mVectorToAssemble==NULL)
00328 {
00329 EXCEPTION("Vector to be assembled has not been set");
00330 }
00331 if( PetscVecTools::GetSize(this->mVectorToAssemble) != DIM*mpMesh->GetNumNodes()+mpMesh->GetNumVertices() )
00332 {
00333 EXCEPTION("Vector provided to be assembled has size " << PetscVecTools::GetSize(this->mVectorToAssemble) << ", not expected size of " << DIM*mpMesh->GetNumNodes()+mpMesh->GetNumVertices() << " (dim*num_nodes+num_vertices)");
00334 }
00335 }
00336
00337
00338 if (this->mAssembleVector && this->mZeroVectorBeforeAssembly)
00339 {
00340 PetscVecTools::Zero(this->mVectorToAssemble);
00341 }
00342 if (this->mAssembleMatrix && this->mZeroMatrixBeforeAssembly)
00343 {
00344 PetscMatTools::Zero(this->mMatrixToAssemble);
00345 }
00346
00347
00348
00349
00350 c_matrix<double, STENCIL_SIZE, STENCIL_SIZE> a_elem = zero_matrix<double>(STENCIL_SIZE,STENCIL_SIZE);
00351 c_vector<double, STENCIL_SIZE> b_elem = zero_vector<double>(STENCIL_SIZE);
00352
00353
00354
00355 for (typename AbstractTetrahedralMesh<DIM, DIM>::ElementIterator iter = mpMesh->GetElementIteratorBegin();
00356 iter != mpMesh->GetElementIteratorEnd();
00357 ++iter)
00358 {
00359 Element<DIM, DIM>& r_element = *iter;
00360
00361
00362 if ( r_element.GetOwnership() == true )
00363 {
00364 AssembleOnElement(r_element, a_elem, b_elem);
00365
00366 unsigned p_indices[STENCIL_SIZE];
00367 for (unsigned i=0; i<NUM_NODES_PER_ELEMENT; i++)
00368 {
00369 for (unsigned j=0; j<DIM; j++)
00370 {
00371 p_indices[DIM*i+j] = DIM*r_element.GetNodeGlobalIndex(i) + j;
00372 }
00373 }
00374
00375 for (unsigned i=0; i<NUM_VERTICES_PER_ELEMENT; i++)
00376 {
00377 p_indices[DIM*NUM_NODES_PER_ELEMENT + i] = DIM*mpMesh->GetNumNodes() + r_element.GetNodeGlobalIndex(i);
00378 }
00379
00380 if (this->mMatrixToAssemble)
00381 {
00382 PetscMatTools::AddMultipleValues<STENCIL_SIZE>(this->mMatrixToAssemble, p_indices, a_elem);
00383 }
00384
00385
00386
00387 if (this->mAssembleVector)
00388 {
00389 PetscVecTools::AddMultipleValues<STENCIL_SIZE>(this->mVectorToAssemble, p_indices, b_elem);
00390 }
00391 }
00392 }
00393 }
00394
00395 template<unsigned DIM, bool CAN_ASSEMBLE_VECTOR, bool CAN_ASSEMBLE_MATRIX>
00396 void AbstractContinuumMechanicsAssembler<DIM,CAN_ASSEMBLE_VECTOR,CAN_ASSEMBLE_MATRIX>::AssembleOnElement(Element<DIM, DIM>& rElement,
00397 c_matrix<double, STENCIL_SIZE, STENCIL_SIZE >& rAElem,
00398 c_vector<double, STENCIL_SIZE>& rBElem)
00399 {
00400 static c_matrix<double,DIM,DIM> jacobian;
00401 static c_matrix<double,DIM,DIM> inverse_jacobian;
00402 double jacobian_determinant;
00403
00404 mpMesh->GetInverseJacobianForElement(rElement.GetIndex(), jacobian, jacobian_determinant, inverse_jacobian);
00405
00406 if (this->mAssembleMatrix)
00407 {
00408 rAElem.clear();
00409 }
00410
00411 if (this->mAssembleVector)
00412 {
00413 rBElem.clear();
00414 }
00415
00416
00417
00418 static c_vector<double, NUM_VERTICES_PER_ELEMENT> linear_phi;
00419 static c_vector<double, NUM_NODES_PER_ELEMENT> quad_phi;
00420 static c_matrix<double, DIM, NUM_NODES_PER_ELEMENT> grad_quad_phi;
00421 static c_matrix<double, DIM, NUM_VERTICES_PER_ELEMENT> grad_linear_phi;
00422
00423 c_vector<double,DIM> body_force;
00424
00425
00426 for (unsigned quadrature_index=0; quadrature_index < mpQuadRule->GetNumQuadPoints(); quadrature_index++)
00427 {
00428 double wJ = jacobian_determinant * mpQuadRule->GetWeight(quadrature_index);
00429 const ChastePoint<DIM>& quadrature_point = mpQuadRule->rGetQuadPoint(quadrature_index);
00430
00431
00432 LinearBasisFunction<DIM>::ComputeBasisFunctions(quadrature_point, linear_phi);
00433 QuadraticBasisFunction<DIM>::ComputeBasisFunctions(quadrature_point, quad_phi);
00434 QuadraticBasisFunction<DIM>::ComputeTransformedBasisFunctionDerivatives(quadrature_point, inverse_jacobian, grad_quad_phi);
00435 LinearBasisFunction<DIM>::ComputeTransformedBasisFunctionDerivatives(quadrature_point, inverse_jacobian, grad_linear_phi);
00436
00437
00438 c_vector<double,DIM> X = zero_vector<double>(DIM);
00439 for (unsigned vertex_index=0; vertex_index<NUM_VERTICES_PER_ELEMENT; vertex_index++)
00440 {
00441 for(unsigned j=0; j<DIM; j++)
00442 {
00443 X(j) += linear_phi(vertex_index)*rElement.GetNode(vertex_index)->rGetLocation()(j);
00444 }
00445 }
00446
00447 if(this->mAssembleVector)
00448 {
00449 c_vector<double,SPATIAL_BLOCK_SIZE_ELEMENTAL> b_spatial
00450 = ComputeSpatialVectorTerm(quad_phi, grad_quad_phi, X, &rElement);
00451 c_vector<double,PRESSURE_BLOCK_SIZE_ELEMENTAL> b_pressure = ComputePressureVectorTerm(linear_phi, grad_linear_phi, X, &rElement);
00452
00453 for (unsigned i=0; i<SPATIAL_BLOCK_SIZE_ELEMENTAL; i++)
00454 {
00455 rBElem(i) += b_spatial(i)*wJ;
00456 }
00457
00458
00459 for (unsigned i=0; i<PRESSURE_BLOCK_SIZE_ELEMENTAL; i++)
00460 {
00461 rBElem(SPATIAL_BLOCK_SIZE_ELEMENTAL + i) += b_pressure(i)*wJ;
00462 }
00463 }
00464
00465
00466 if(this->mAssembleMatrix)
00467 {
00468 c_matrix<double,SPATIAL_BLOCK_SIZE_ELEMENTAL,SPATIAL_BLOCK_SIZE_ELEMENTAL> a_spatial_spatial
00469 = ComputeSpatialSpatialMatrixTerm(quad_phi, grad_quad_phi, X, &rElement);
00470
00471 c_matrix<double,SPATIAL_BLOCK_SIZE_ELEMENTAL,PRESSURE_BLOCK_SIZE_ELEMENTAL> a_spatial_pressure
00472 = ComputeSpatialPressureMatrixTerm(quad_phi, grad_quad_phi, linear_phi, grad_linear_phi, X, &rElement);
00473
00474 c_matrix<double,PRESSURE_BLOCK_SIZE_ELEMENTAL,SPATIAL_BLOCK_SIZE_ELEMENTAL> a_pressure_spatial;
00475 if(!BLOCK_SYMMETRIC_MATRIX)
00476 {
00477 NEVER_REACHED;
00478
00479 }
00480
00481 c_matrix<double,PRESSURE_BLOCK_SIZE_ELEMENTAL,PRESSURE_BLOCK_SIZE_ELEMENTAL> a_pressure_pressure
00482 = ComputePressurePressureMatrixTerm(linear_phi, grad_linear_phi, X, &rElement);
00483
00484 for (unsigned i=0; i<SPATIAL_BLOCK_SIZE_ELEMENTAL; i++)
00485 {
00486 for(unsigned j=0; j<SPATIAL_BLOCK_SIZE_ELEMENTAL; j++)
00487 {
00488 rAElem(i,j) += a_spatial_spatial(i,j)*wJ;
00489 }
00490
00491 for(unsigned j=0; j<PRESSURE_BLOCK_SIZE_ELEMENTAL; j++)
00492 {
00493 rAElem(i, SPATIAL_BLOCK_SIZE_ELEMENTAL + j) += a_spatial_pressure(i,j)*wJ;
00494 }
00495 }
00496
00497 for(unsigned i=0; i<PRESSURE_BLOCK_SIZE_ELEMENTAL; i++)
00498 {
00499 if(BLOCK_SYMMETRIC_MATRIX)
00500 {
00501 for(unsigned j=0; j<SPATIAL_BLOCK_SIZE_ELEMENTAL; j++)
00502 {
00503 rAElem(SPATIAL_BLOCK_SIZE_ELEMENTAL + i, j) += a_spatial_pressure(j,i)*wJ;
00504 }
00505 }
00506 else
00507 {
00508 NEVER_REACHED;
00509 }
00510
00511 for(unsigned j=0; j<PRESSURE_BLOCK_SIZE_ELEMENTAL; j++)
00512 {
00513 rAElem(SPATIAL_BLOCK_SIZE_ELEMENTAL + i, SPATIAL_BLOCK_SIZE_ELEMENTAL + j) += a_pressure_pressure(i,j)*wJ;
00514 }
00515 }
00516 }
00517 }
00518 }
00519
00520
00521 #endif // ABSTRACTCONTINUUMMECHANICSASSEMBLER_HPP_