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 #ifndef ABSTRACTFEVOLUMEINTEGRALASSEMBLER_HPP_
00037 #define ABSTRACTFEVOLUMEINTEGRALASSEMBLER_HPP_
00038
00039 #include "AbstractFeAssemblerCommon.hpp"
00040 #include "GaussianQuadratureRule.hpp"
00041 #include "BoundaryConditionsContainer.hpp"
00042 #include "PetscVecTools.hpp"
00043 #include "PetscMatTools.hpp"
00044
00077 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM, bool CAN_ASSEMBLE_VECTOR, bool CAN_ASSEMBLE_MATRIX, InterpolationLevel INTERPOLATION_LEVEL>
00078 class AbstractFeVolumeIntegralAssembler :
00079 public AbstractFeAssemblerCommon<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM,CAN_ASSEMBLE_VECTOR,CAN_ASSEMBLE_MATRIX,INTERPOLATION_LEVEL>
00080 {
00081 protected:
00083 AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>* mpMesh;
00084
00086 GaussianQuadratureRule<ELEMENT_DIM>* mpQuadRule;
00087
00089 typedef LinearBasisFunction<ELEMENT_DIM> BasisFunction;
00090
00110 void ComputeTransformedBasisFunctionDerivatives(const ChastePoint<ELEMENT_DIM>& rPoint,
00111 const c_matrix<double, ELEMENT_DIM, SPACE_DIM>& rInverseJacobian,
00112 c_matrix<double, SPACE_DIM, ELEMENT_DIM+1>& rReturnValue);
00113
00119 void DoAssemble();
00120
00121 protected:
00122
00142 virtual c_matrix<double,PROBLEM_DIM*(ELEMENT_DIM+1),PROBLEM_DIM*(ELEMENT_DIM+1)> ComputeMatrixTerm(
00143 c_vector<double, ELEMENT_DIM+1>& rPhi,
00144 c_matrix<double, SPACE_DIM, ELEMENT_DIM+1>& rGradPhi,
00145 ChastePoint<SPACE_DIM>& rX,
00146 c_vector<double,PROBLEM_DIM>& rU,
00147 c_matrix<double, PROBLEM_DIM, SPACE_DIM>& rGradU,
00148 Element<ELEMENT_DIM,SPACE_DIM>* pElement)
00149 {
00150
00151
00152 NEVER_REACHED;
00153 return zero_matrix<double>(PROBLEM_DIM*(ELEMENT_DIM+1),PROBLEM_DIM*(ELEMENT_DIM+1));
00154 }
00155
00175 virtual c_vector<double,PROBLEM_DIM*(ELEMENT_DIM+1)> ComputeVectorTerm(
00176 c_vector<double, ELEMENT_DIM+1>& rPhi,
00177 c_matrix<double, SPACE_DIM, ELEMENT_DIM+1>& rGradPhi,
00178 ChastePoint<SPACE_DIM>& rX,
00179 c_vector<double,PROBLEM_DIM>& rU,
00180 c_matrix<double, PROBLEM_DIM, SPACE_DIM>& rGradU,
00181 Element<ELEMENT_DIM,SPACE_DIM>* pElement)
00182 {
00183
00184
00185 NEVER_REACHED;
00186 return zero_vector<double>(PROBLEM_DIM*(ELEMENT_DIM+1));
00187 }
00188
00189
00204 virtual void AssembleOnElement(Element<ELEMENT_DIM,SPACE_DIM>& rElement,
00205 c_matrix<double, PROBLEM_DIM*(ELEMENT_DIM+1), PROBLEM_DIM*(ELEMENT_DIM+1) >& rAElem,
00206 c_vector<double, PROBLEM_DIM*(ELEMENT_DIM+1)>& rBElem);
00207
00215 virtual bool ElementAssemblyCriterion(Element<ELEMENT_DIM,SPACE_DIM>& rElement)
00216 {
00217 return true;
00218 }
00219
00220
00221 public:
00222
00228 AbstractFeVolumeIntegralAssembler(AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh);
00229
00233 virtual ~AbstractFeVolumeIntegralAssembler()
00234 {
00235 delete mpQuadRule;
00236 }
00237 };
00238
00239 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM, bool CAN_ASSEMBLE_VECTOR, bool CAN_ASSEMBLE_MATRIX, InterpolationLevel INTERPOLATION_LEVEL>
00240 AbstractFeVolumeIntegralAssembler<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, CAN_ASSEMBLE_VECTOR, CAN_ASSEMBLE_MATRIX, INTERPOLATION_LEVEL>::AbstractFeVolumeIntegralAssembler(
00241 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh)
00242 : AbstractFeAssemblerCommon<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, CAN_ASSEMBLE_VECTOR, CAN_ASSEMBLE_MATRIX, INTERPOLATION_LEVEL>(),
00243 mpMesh(pMesh)
00244 {
00245 assert(pMesh);
00246
00247
00248
00249 mpQuadRule = new GaussianQuadratureRule<ELEMENT_DIM>(2);
00250 }
00251
00252
00253
00254 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM, bool CAN_ASSEMBLE_VECTOR, bool CAN_ASSEMBLE_MATRIX, InterpolationLevel INTERPOLATION_LEVEL>
00255 void AbstractFeVolumeIntegralAssembler<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, CAN_ASSEMBLE_VECTOR, CAN_ASSEMBLE_MATRIX, INTERPOLATION_LEVEL>::DoAssemble()
00256 {
00257 assert(this->mAssembleMatrix || this->mAssembleVector);
00258
00259 HeartEventHandler::EventType assemble_event;
00260 if (this->mAssembleMatrix)
00261 {
00262 assemble_event = HeartEventHandler::ASSEMBLE_SYSTEM;
00263 }
00264 else
00265 {
00266 assemble_event = HeartEventHandler::ASSEMBLE_RHS;
00267 }
00268
00269 if (this->mAssembleMatrix && this->mMatrixToAssemble==NULL)
00270 {
00271 EXCEPTION("Matrix to be assembled has not been set");
00272 }
00273 if (this->mAssembleVector && this->mVectorToAssemble==NULL)
00274 {
00275 EXCEPTION("Vector to be assembled has not been set");
00276 }
00277
00278 HeartEventHandler::BeginEvent(assemble_event);
00279
00280
00281 if (this->mAssembleVector && this->mZeroVectorBeforeAssembly)
00282 {
00283 PetscVecTools::Zero(this->mVectorToAssemble);
00284 }
00285 if (this->mAssembleMatrix && this->mZeroMatrixBeforeAssembly)
00286 {
00287 PetscMatTools::Zero(this->mMatrixToAssemble);
00288 }
00289
00290 const size_t STENCIL_SIZE=PROBLEM_DIM*(ELEMENT_DIM+1);
00291 c_matrix<double, STENCIL_SIZE, STENCIL_SIZE> a_elem;
00292 c_vector<double, STENCIL_SIZE> b_elem;
00293
00294
00295 for (typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator iter = mpMesh->GetElementIteratorBegin();
00296 iter != mpMesh->GetElementIteratorEnd();
00297 ++iter)
00298 {
00299 Element<ELEMENT_DIM, SPACE_DIM>& r_element = *iter;
00300
00301
00302 if ( r_element.GetOwnership() == true && ElementAssemblyCriterion(r_element)==true )
00303 {
00304 AssembleOnElement(r_element, a_elem, b_elem);
00305
00306 unsigned p_indices[STENCIL_SIZE];
00307 r_element.GetStiffnessMatrixGlobalIndices(PROBLEM_DIM, p_indices);
00308
00309 if (this->mAssembleMatrix)
00310 {
00311 PetscMatTools::AddMultipleValues<STENCIL_SIZE>(this->mMatrixToAssemble, p_indices, a_elem);
00312 }
00313
00314 if (this->mAssembleVector)
00315 {
00316 PetscVecTools::AddMultipleValues<STENCIL_SIZE>(this->mVectorToAssemble, p_indices, b_elem);
00317 }
00318 }
00319 }
00320
00321 HeartEventHandler::EndEvent(assemble_event);
00322 }
00323
00324
00326
00328
00329 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM, bool CAN_ASSEMBLE_VECTOR, bool CAN_ASSEMBLE_MATRIX, InterpolationLevel INTERPOLATION_LEVEL>
00330 void AbstractFeVolumeIntegralAssembler<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, CAN_ASSEMBLE_VECTOR, CAN_ASSEMBLE_MATRIX, INTERPOLATION_LEVEL>::ComputeTransformedBasisFunctionDerivatives(
00331 const ChastePoint<ELEMENT_DIM>& rPoint,
00332 const c_matrix<double, ELEMENT_DIM, SPACE_DIM>& rInverseJacobian,
00333 c_matrix<double, SPACE_DIM, ELEMENT_DIM+1>& rReturnValue)
00334 {
00335 assert(ELEMENT_DIM < 4 && ELEMENT_DIM > 0);
00336 static c_matrix<double, ELEMENT_DIM, ELEMENT_DIM+1> grad_phi;
00337
00338 LinearBasisFunction<ELEMENT_DIM>::ComputeBasisFunctionDerivatives(rPoint, grad_phi);
00339 rReturnValue = prod(trans(rInverseJacobian), grad_phi);
00340 }
00341
00342 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM, bool CAN_ASSEMBLE_VECTOR, bool CAN_ASSEMBLE_MATRIX, InterpolationLevel INTERPOLATION_LEVEL>
00343 void AbstractFeVolumeIntegralAssembler<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, CAN_ASSEMBLE_VECTOR, CAN_ASSEMBLE_MATRIX, INTERPOLATION_LEVEL>::AssembleOnElement(
00344 Element<ELEMENT_DIM,SPACE_DIM>& rElement,
00345 c_matrix<double, PROBLEM_DIM*(ELEMENT_DIM+1), PROBLEM_DIM*(ELEMENT_DIM+1) >& rAElem,
00346 c_vector<double, PROBLEM_DIM*(ELEMENT_DIM+1)>& rBElem)
00347 {
00353 c_matrix<double, SPACE_DIM, ELEMENT_DIM> jacobian;
00354 c_matrix<double, ELEMENT_DIM, SPACE_DIM> inverse_jacobian;
00355 double jacobian_determinant;
00356
00357 mpMesh->GetInverseJacobianForElement(rElement.GetIndex(), jacobian, jacobian_determinant, inverse_jacobian);
00358
00359 if (this->mAssembleMatrix)
00360 {
00361 rAElem.clear();
00362 }
00363
00364 if (this->mAssembleVector)
00365 {
00366 rBElem.clear();
00367 }
00368
00369 const unsigned num_nodes = rElement.GetNumNodes();
00370
00371
00372 c_vector<double, ELEMENT_DIM+1> phi;
00373 c_matrix<double, SPACE_DIM, ELEMENT_DIM+1> grad_phi;
00374
00375
00376 for (unsigned quad_index=0; quad_index < mpQuadRule->GetNumQuadPoints(); quad_index++)
00377 {
00378 const ChastePoint<ELEMENT_DIM>& quad_point = mpQuadRule->rGetQuadPoint(quad_index);
00379
00380 BasisFunction::ComputeBasisFunctions(quad_point, phi);
00381
00382 if ( this->mAssembleMatrix || INTERPOLATION_LEVEL==NONLINEAR )
00383 {
00384 ComputeTransformedBasisFunctionDerivatives(quad_point, inverse_jacobian, grad_phi);
00385 }
00386
00387
00388
00389 ChastePoint<SPACE_DIM> x(0,0,0);
00390
00391 c_vector<double,PROBLEM_DIM> u = zero_vector<double>(PROBLEM_DIM);
00392 c_matrix<double,PROBLEM_DIM,SPACE_DIM> grad_u = zero_matrix<double>(PROBLEM_DIM,SPACE_DIM);
00393
00394
00395 this->ResetInterpolatedQuantities();
00396
00397
00398 for (unsigned i=0; i<num_nodes; i++)
00399 {
00400 const Node<SPACE_DIM>* p_node = rElement.GetNode(i);
00401
00402 if (INTERPOLATION_LEVEL != CARDIAC)
00403 {
00404 const c_vector<double, SPACE_DIM>& r_node_loc = p_node->rGetLocation();
00405
00406 x.rGetLocation() += phi(i)*r_node_loc;
00407 }
00408
00409
00410 unsigned node_global_index = rElement.GetNodeGlobalIndex(i);
00411 if (this->mCurrentSolutionOrGuessReplicated.GetSize() > 0)
00412 {
00413 for (unsigned index_of_unknown=0; index_of_unknown<(INTERPOLATION_LEVEL!=CARDIAC ? PROBLEM_DIM : 1); index_of_unknown++)
00414 {
00415
00416
00417
00418
00419
00420
00421
00422
00423 double u_at_node = this->GetCurrentSolutionOrGuessValue(node_global_index, index_of_unknown);
00424 u(index_of_unknown) += phi(i)*u_at_node;
00425
00426 if (INTERPOLATION_LEVEL==NONLINEAR)
00427 {
00428 for (unsigned j=0; j<SPACE_DIM; j++)
00429 {
00430 grad_u(index_of_unknown,j) += grad_phi(j,i)*u_at_node;
00431 }
00432 }
00433 }
00434 }
00435
00436
00437 this->IncrementInterpolatedQuantities(phi(i), p_node);
00438 if ( this->mAssembleMatrix || INTERPOLATION_LEVEL==NONLINEAR )
00439 {
00440 this->IncrementInterpolatedGradientQuantities(grad_phi, i, p_node);
00441 }
00442 }
00443
00444 double wJ = jacobian_determinant * mpQuadRule->GetWeight(quad_index);
00445
00446
00447 if (this->mAssembleMatrix)
00448 {
00449 noalias(rAElem) += ComputeMatrixTerm(phi, grad_phi, x, u, grad_u, &rElement) * wJ;
00450 }
00451
00452 if (this->mAssembleVector)
00453 {
00454 noalias(rBElem) += ComputeVectorTerm(phi, grad_phi, x, u, grad_u, &rElement) * wJ;
00455 }
00456 }
00457 }
00458
00459
00460 #endif