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 #ifndef _ABSTRACTSTATICASSEMBLER_HPP_
00029 #define _ABSTRACTSTATICASSEMBLER_HPP_
00030
00031 #include "AbstractAssembler.hpp"
00032 #include "LinearBasisFunction.hpp"
00033 #include "GaussianQuadratureRule.hpp"
00034 #include "AbstractMesh.hpp"
00035 #include "BoundaryConditionsContainer.hpp"
00036 #include "LinearSystem.hpp"
00037 #include "GaussianQuadratureRule.hpp"
00038 #include "ReplicatableVector.hpp"
00039 #include "DistributedVector.hpp"
00040 #include "PetscTools.hpp"
00041 #include "HeartEventHandler.hpp"
00042 #include <iostream>
00043
00044 #include <boost/mpl/void.hpp>
00045
00062 template<class T>
00063 struct AssemblerTraits
00064 {
00066 typedef T CVT_CLS;
00068 typedef T CMT_CLS;
00070 typedef AbstractAssembler<T::E_DIM, T::S_DIM, T::P_DIM> INTERPOLATE_CLS;
00071 };
00072
00074 template<>
00075 struct AssemblerTraits<boost::mpl::void_>
00076 {
00077 typedef boost::mpl::void_ CVT_CLS;
00078 typedef boost::mpl::void_ CMT_CLS;
00079 typedef boost::mpl::void_ INTERPOLATE_CLS;
00080 };
00081
00100 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM, bool NON_HEART, class CONCRETE>
00101 class AbstractStaticAssembler : virtual public AbstractAssembler<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>
00102 {
00103 protected:
00105 AbstractMesh<ELEMENT_DIM, SPACE_DIM>* mpMesh;
00106
00108 GaussianQuadratureRule<ELEMENT_DIM> *mpQuadRule;
00110 GaussianQuadratureRule<ELEMENT_DIM-1> *mpSurfaceQuadRule;
00111
00112
00114 typedef LinearBasisFunction<ELEMENT_DIM> BasisFunction;
00116 typedef LinearBasisFunction<ELEMENT_DIM-1> SurfaceBasisFunction;
00117
00122 ReplicatableVector mCurrentSolutionOrGuessReplicated;
00123
00128 LinearSystem *mpLinearSystem;
00129
00130
00152 virtual void AssembleOnElement( Element<ELEMENT_DIM,SPACE_DIM> &rElement,
00153 c_matrix<double, PROBLEM_DIM*(ELEMENT_DIM+1), PROBLEM_DIM*(ELEMENT_DIM+1) > &rAElem,
00154 c_vector<double, PROBLEM_DIM*(ELEMENT_DIM+1)> &rBElem,
00155 bool assembleVector,
00156 bool assembleMatrix)
00157 {
00158 GaussianQuadratureRule<ELEMENT_DIM> &quad_rule =
00159 *(AbstractStaticAssembler<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM, NON_HEART, CONCRETE>::mpQuadRule);
00160
00166 c_matrix<double, SPACE_DIM, SPACE_DIM> jacobian;
00167 c_matrix<double, SPACE_DIM, SPACE_DIM> inverse_jacobian;
00168 double jacobian_determinant;
00169
00170 mpMesh->GetInverseJacobianForElement(rElement.GetIndex(), jacobian, jacobian_determinant, inverse_jacobian);
00171
00172
00173
00174
00175
00176
00177
00178
00179 if (assembleMatrix)
00180 {
00181 rAElem.clear();
00182 }
00183
00184 if (assembleVector)
00185 {
00186 rBElem.clear();
00187 }
00188
00189 const unsigned num_nodes = rElement.GetNumNodes();
00190
00191
00192 c_vector<double, ELEMENT_DIM+1> phi;
00193 c_matrix<double, ELEMENT_DIM, ELEMENT_DIM+1> grad_phi;
00194
00195
00196 for (unsigned quad_index=0; quad_index < quad_rule.GetNumQuadPoints(); quad_index++)
00197 {
00198 const ChastePoint<ELEMENT_DIM>& quad_point = quad_rule.rGetQuadPoint(quad_index);
00199
00200 BasisFunction::ComputeBasisFunctions(quad_point, phi);
00201
00202 if ( assembleMatrix || this->ProblemIsNonlinear() )
00203 {
00204 BasisFunction::ComputeTransformedBasisFunctionDerivatives(quad_point, inverse_jacobian, grad_phi);
00205 }
00206
00207
00208
00209 ChastePoint<SPACE_DIM> x(0,0,0);
00210
00211 c_vector<double,PROBLEM_DIM> u = zero_vector<double>(PROBLEM_DIM);
00212 c_matrix<double,PROBLEM_DIM,SPACE_DIM> grad_u = zero_matrix<double>(PROBLEM_DIM,SPACE_DIM);
00213
00214
00215
00216 static_cast<typename AssemblerTraits<CONCRETE>::INTERPOLATE_CLS *>(this)->ResetInterpolatedQuantities();
00217
00218
00220
00222 for (unsigned i=0; i<num_nodes; i++)
00223 {
00224 const Node<SPACE_DIM> *p_node = rElement.GetNode(i);
00225
00226 if (NON_HEART)
00227 {
00228 const c_vector<double, SPACE_DIM>& r_node_loc = p_node->rGetLocation();
00229
00230 x.rGetLocation() += phi(i)*r_node_loc;
00231 }
00232
00233
00234 unsigned node_global_index = rElement.GetNodeGlobalIndex(i);
00235 if (mCurrentSolutionOrGuessReplicated.size()>0)
00236 {
00237 for (unsigned index_of_unknown=0; index_of_unknown<(NON_HEART ? PROBLEM_DIM : 1); index_of_unknown++)
00238 {
00239
00240
00241
00242
00243
00244
00245
00246
00247 double u_at_node=GetCurrentSolutionOrGuessValue(node_global_index, index_of_unknown);
00248 u(index_of_unknown) += phi(i)*u_at_node;
00249
00250 if (this->ProblemIsNonlinear() )
00251 {
00252 for (unsigned j=0; j<SPACE_DIM; j++)
00253 {
00254 grad_u(index_of_unknown,j) += grad_phi(j,i)*u_at_node;
00255 }
00256 }
00257 }
00258 }
00259
00260
00261
00262 static_cast<typename AssemblerTraits<CONCRETE>::INTERPOLATE_CLS *>(this)->IncrementInterpolatedQuantities(phi(i), p_node);
00263 }
00264
00265
00266 double wJ = jacobian_determinant * quad_rule.GetWeight(quad_index);
00267
00269
00271 if (assembleMatrix)
00272 {
00273 noalias(rAElem) += static_cast<typename AssemblerTraits<CONCRETE>::CMT_CLS *>(this)->ComputeMatrixTerm(phi, grad_phi, x, u, grad_u, &rElement) * wJ;
00274 }
00275
00276 if (assembleVector)
00277 {
00278 noalias(rBElem) += static_cast<typename AssemblerTraits<CONCRETE>::CVT_CLS *>(this)->ComputeVectorTerm(phi, grad_phi, x, u, grad_u, &rElement) * wJ;
00279 }
00280
00281 }
00282 }
00283
00284
00285
00295 virtual void AssembleOnSurfaceElement(const BoundaryElement<ELEMENT_DIM-1,SPACE_DIM> &rSurfaceElement,
00296 c_vector<double, PROBLEM_DIM*ELEMENT_DIM> &rBSurfElem)
00297 {
00298 GaussianQuadratureRule<ELEMENT_DIM-1> &quad_rule =
00299 *(AbstractStaticAssembler<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM, NON_HEART, CONCRETE>::mpSurfaceQuadRule);
00300
00301 c_vector<double, SPACE_DIM> weighted_direction;
00302 double jacobian_determinant;
00303 mpMesh->GetWeightedDirectionForBoundaryElement(rSurfaceElement.GetIndex(), weighted_direction, jacobian_determinant);
00304
00305 rBSurfElem.clear();
00306
00307
00308 c_vector<double, ELEMENT_DIM> phi;
00309
00310
00311 for (unsigned quad_index=0; quad_index<quad_rule.GetNumQuadPoints(); quad_index++)
00312 {
00313 const ChastePoint<ELEMENT_DIM-1>& quad_point = quad_rule.rGetQuadPoint(quad_index);
00314
00315 SurfaceBasisFunction::ComputeBasisFunctions(quad_point, phi);
00316
00317
00319
00321
00322
00323
00324 ChastePoint<SPACE_DIM> x(0,0,0);
00325
00326 this->ResetInterpolatedQuantities();
00327 for (unsigned i=0; i<rSurfaceElement.GetNumNodes(); i++)
00328 {
00329 const c_vector<double, SPACE_DIM> node_loc = rSurfaceElement.GetNode(i)->rGetLocation();
00330 x.rGetLocation() += phi(i)*node_loc;
00331
00332
00333
00334 IncrementInterpolatedQuantities(phi(i), rSurfaceElement.GetNode(i));
00335
00337 }
00338
00339 double wJ = jacobian_determinant * quad_rule.GetWeight(quad_index);
00340
00342
00345 noalias(rBSurfElem) += ComputeVectorSurfaceTerm(rSurfaceElement, phi, x) * wJ;
00346 }
00347 }
00348
00349
00350
00378 virtual void AssembleSystem(bool assembleVector, bool assembleMatrix,
00379 Vec currentSolutionOrGuess=NULL, double currentTime=0.0)
00380 {
00381 HeartEventHandler::EventType assemble_event;
00382 if(assembleMatrix)
00383 {
00384 assemble_event = HeartEventHandler::ASSEMBLE_SYSTEM;
00385 }
00386 else
00387 {
00388 assemble_event = HeartEventHandler::ASSEMBLE_RHS;
00389 }
00390
00391
00392 assert(assembleVector || assembleMatrix);
00393
00394
00395 assert(mpLinearSystem != NULL);
00396 assert(mpLinearSystem->GetSize() == PROBLEM_DIM * this->mpMesh->GetNumNodes());
00397 assert(!assembleVector || mpLinearSystem->rGetRhsVector() != NULL);
00398 assert(!assembleMatrix || mpLinearSystem->rGetLhsMatrix() != NULL);
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408 if (currentSolutionOrGuess != NULL)
00409 {
00410 HeartEventHandler::BeginEvent(HeartEventHandler::COMMUNICATION);
00411 this->mCurrentSolutionOrGuessReplicated.ReplicatePetscVector(currentSolutionOrGuess);
00412 HeartEventHandler::EndEvent(HeartEventHandler::COMMUNICATION);
00413 }
00414
00415
00416
00417
00418
00419 assert( ( currentSolutionOrGuess && mCurrentSolutionOrGuessReplicated.size()>0)
00420 || ( !currentSolutionOrGuess && mCurrentSolutionOrGuessReplicated.size()==0));
00421
00422
00423
00424
00425 this->PrepareForAssembleSystem(currentSolutionOrGuess, currentTime);
00426
00427
00428
00429 HeartEventHandler::BeginEvent(assemble_event);
00430
00431
00432 if (assembleVector)
00433 {
00434 mpLinearSystem->ZeroRhsVector();
00435 }
00436 if (assembleMatrix)
00437 {
00438 mpLinearSystem->ZeroLhsMatrix();
00439 }
00440
00441
00442 typename AbstractMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator
00443 iter = this->mpMesh->GetElementIteratorBegin();
00444
00445 const size_t STENCIL_SIZE=PROBLEM_DIM*(ELEMENT_DIM+1);
00446 c_matrix<double, STENCIL_SIZE, STENCIL_SIZE> a_elem;
00447 c_vector<double, STENCIL_SIZE> b_elem;
00448
00449
00451
00453 while (iter != this->mpMesh->GetElementIteratorEnd())
00454 {
00455 Element<ELEMENT_DIM, SPACE_DIM>& element = **iter;
00456
00457 if (element.GetOwnership() == true)
00458 {
00459 AssembleOnElement(element, a_elem, b_elem, assembleVector, assembleMatrix);
00460
00461 unsigned p_indices[STENCIL_SIZE];
00462 element.GetStiffnessMatrixGlobalIndices(PROBLEM_DIM, p_indices);
00463
00464 if (assembleMatrix)
00465 {
00466 mpLinearSystem->AddLhsMultipleValues(p_indices, a_elem);
00467 }
00468
00469 if (assembleVector)
00470 {
00471 mpLinearSystem->AddRhsMultipleValues(p_indices, b_elem);
00472 }
00473 }
00474
00475 iter++;
00476 }
00477
00478
00479 typename AbstractMesh<ELEMENT_DIM, SPACE_DIM>::BoundaryElementIterator
00480 surf_iter = this->mpMesh->GetBoundaryElementIteratorBegin();
00481
00482
00484
00485
00486
00487
00488
00489
00491 if (assembleVector)
00492 {
00493 this->ApplyNeummanBoundaryConditions();
00494 }
00495
00496 if (assembleVector)
00497 {
00498 mpLinearSystem->AssembleRhsVector();
00499 }
00500
00501 if (assembleMatrix)
00502 {
00503 mpLinearSystem->AssembleIntermediateLhsMatrix();
00504 }
00505
00506
00507 this->ApplyDirichletConditions(currentSolutionOrGuess, assembleMatrix);
00508
00509 this->FinaliseLinearSystem(currentSolutionOrGuess, currentTime, assembleVector, assembleMatrix);
00510
00511 if (assembleVector)
00512 {
00513 mpLinearSystem->AssembleRhsVector();
00514 }
00515 if (assembleMatrix)
00516 {
00517 mpLinearSystem->AssembleFinalLhsMatrix();
00518 }
00519
00520
00521
00522 this->FinaliseAssembleSystem(currentSolutionOrGuess, currentTime);
00523
00524 HeartEventHandler::EndEvent(assemble_event);
00525 }
00526
00527
00528
00533 virtual void PrepareForSolve()
00534 {
00535 assert(mpMesh != NULL);
00536
00537
00538
00539
00540 assert(this->mpBoundaryConditions != NULL);
00541
00542 std::vector<unsigned>& r_nodes_per_processor = mpMesh->rGetNodesPerProcessor();
00543
00544
00545 if((r_nodes_per_processor.size() != 0) && (r_nodes_per_processor.size() != PetscTools::NumProcs()) )
00546 {
00547 EXCEPTION("Number of processors defined in mesh class not equal to number of processors used");
00548 }
00549
00550 if(r_nodes_per_processor.size() != 0)
00551 {
00552 unsigned num_local_nodes = r_nodes_per_processor[ PetscTools::GetMyRank() ];
00553 DistributedVector::SetProblemSizePerProcessor(this->mpMesh->GetNumNodes(), num_local_nodes);
00554 }
00555 else
00556 {
00557 DistributedVector::SetProblemSize(this->mpMesh->GetNumNodes());
00558 }
00559
00560 this->mpMesh->SetElementOwnerships(DistributedVector::Begin().Global,
00561 DistributedVector::End().Global);
00562 }
00563
00564
00565
00570 LinearSystem** GetLinearSystem()
00571 {
00572 return &mpLinearSystem;
00573 }
00574
00579 ReplicatableVector& rGetCurrentSolutionOrGuess()
00580 {
00581 return mCurrentSolutionOrGuessReplicated;
00582 }
00583
00587 virtual double GetCurrentSolutionOrGuessValue(unsigned nodeIndex, unsigned indexOfUnknown)
00588 {
00589 return mCurrentSolutionOrGuessReplicated[ PROBLEM_DIM*nodeIndex + indexOfUnknown];
00590 }
00591
00592 public:
00598 AbstractStaticAssembler(unsigned numQuadPoints = 2)
00599 : AbstractAssembler<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>()
00600 {
00601
00602
00603 mpMesh = NULL;
00604
00605 mpQuadRule = NULL;
00606 mpSurfaceQuadRule = NULL;
00607 SetNumberOfQuadraturePointsPerDimension(numQuadPoints);
00608
00609 mpLinearSystem = NULL;
00610 }
00611
00621 void SetNumberOfQuadraturePointsPerDimension(unsigned numQuadPoints)
00622 {
00623 delete mpQuadRule;
00624 mpQuadRule = new GaussianQuadratureRule<ELEMENT_DIM>(numQuadPoints);
00625 delete mpSurfaceQuadRule;
00626 mpSurfaceQuadRule = new GaussianQuadratureRule<ELEMENT_DIM-1>(numQuadPoints);
00627 }
00628
00629
00633 void SetMesh(AbstractMesh<ELEMENT_DIM,SPACE_DIM>* pMesh)
00634 {
00635 mpMesh = pMesh;
00636 }
00637
00638
00642 virtual ~AbstractStaticAssembler()
00643 {
00644 delete mpQuadRule;
00645 delete mpSurfaceQuadRule;
00646 delete mpLinearSystem;
00647 }
00648 };
00649
00650 #endif //_ABSTRACTSTATICASSEMBLER_HPP_