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 "AbstractTetrahedralMesh.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 {
00078 typedef boost::mpl::void_ CVT_CLS;
00080 typedef boost::mpl::void_ CMT_CLS;
00082 typedef boost::mpl::void_ INTERPOLATE_CLS;
00083 };
00084
00103 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM, bool NON_HEART, class CONCRETE>
00104 class AbstractStaticAssembler : virtual public AbstractAssembler<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>
00105 {
00106 protected:
00107
00109 AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM> *mpMesh;
00110
00112 GaussianQuadratureRule<ELEMENT_DIM> *mpQuadRule;
00113
00115 GaussianQuadratureRule<ELEMENT_DIM-1> *mpSurfaceQuadRule;
00116
00118 typedef LinearBasisFunction<ELEMENT_DIM> BasisFunction;
00120 typedef LinearBasisFunction<ELEMENT_DIM-1> SurfaceBasisFunction;
00121
00126 ReplicatableVector mCurrentSolutionOrGuessReplicated;
00127
00132 LinearSystem *mpLinearSystem;
00133
00153 void ComputeTransformedBasisFunctionDerivatives(const ChastePoint<ELEMENT_DIM>& rPoint,
00154 const c_matrix<double, ELEMENT_DIM, SPACE_DIM>& rInverseJacobian,
00155 c_matrix<double, SPACE_DIM, ELEMENT_DIM+1>& rReturnValue);
00174 virtual void AssembleOnElement(Element<ELEMENT_DIM,SPACE_DIM>& rElement,
00175 c_matrix<double, PROBLEM_DIM*(ELEMENT_DIM+1), PROBLEM_DIM*(ELEMENT_DIM+1) >& rAElem,
00176 c_vector<double, PROBLEM_DIM*(ELEMENT_DIM+1)>& rBElem,
00177 bool assembleVector,
00178 bool assembleMatrix);
00179
00189 virtual void AssembleOnSurfaceElement(const BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>& rSurfaceElement,
00190 c_vector<double, PROBLEM_DIM*ELEMENT_DIM>& rBSurfElem);
00191
00219 virtual void AssembleSystem(bool assembleVector, bool assembleMatrix,
00220 Vec currentSolutionOrGuess=NULL, double currentTime=0.0);
00221
00226 virtual void PrepareForSolve();
00227
00228 public:
00233 LinearSystem** GetLinearSystem();
00234
00235 protected:
00240 ReplicatableVector& rGetCurrentSolutionOrGuess();
00241
00248 virtual double GetCurrentSolutionOrGuessValue(unsigned nodeIndex, unsigned indexOfUnknown);
00249
00250 public:
00251
00257 AbstractStaticAssembler(unsigned numQuadPoints=2);
00258
00268 void SetNumberOfQuadraturePointsPerDimension(unsigned numQuadPoints);
00269
00275 void SetMesh(AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh);
00276
00280 virtual ~AbstractStaticAssembler();
00281
00282 };
00283
00284
00286
00288
00289
00290 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM, bool NON_HEART, class CONCRETE>
00291 void AbstractStaticAssembler<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, NON_HEART, CONCRETE>::ComputeTransformedBasisFunctionDerivatives(
00292 const ChastePoint<ELEMENT_DIM>& rPoint,
00293 const c_matrix<double, ELEMENT_DIM, SPACE_DIM>& rInverseJacobian,
00294 c_matrix<double, SPACE_DIM, ELEMENT_DIM+1>& rReturnValue)
00295 {
00296 assert(ELEMENT_DIM < 4 && ELEMENT_DIM > 0);
00297 static c_matrix<double, ELEMENT_DIM, ELEMENT_DIM+1> grad_phi;
00298
00299 LinearBasisFunction<ELEMENT_DIM>::ComputeBasisFunctionDerivatives(rPoint, grad_phi);
00300 rReturnValue = prod(trans(rInverseJacobian), grad_phi);
00301 }
00302
00303
00304 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM, bool NON_HEART, class CONCRETE>
00305 void AbstractStaticAssembler<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, NON_HEART, CONCRETE>::AssembleOnElement(Element<ELEMENT_DIM,SPACE_DIM>& rElement,
00306 c_matrix<double, PROBLEM_DIM*(ELEMENT_DIM+1), PROBLEM_DIM*(ELEMENT_DIM+1) >& rAElem,
00307 c_vector<double, PROBLEM_DIM*(ELEMENT_DIM+1)>& rBElem,
00308 bool assembleVector,
00309 bool assembleMatrix)
00310 {
00311 GaussianQuadratureRule<ELEMENT_DIM>& quad_rule =
00312 *(AbstractStaticAssembler<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM, NON_HEART, CONCRETE>::mpQuadRule);
00313
00319 c_matrix<double, SPACE_DIM, ELEMENT_DIM> jacobian;
00320 c_matrix<double, ELEMENT_DIM, SPACE_DIM> inverse_jacobian;
00321 double jacobian_determinant;
00322
00323 mpMesh->GetInverseJacobianForElement(rElement.GetIndex(), jacobian, jacobian_determinant, inverse_jacobian);
00324
00325
00326
00327
00328
00329
00330
00331
00332 if (assembleMatrix)
00333 {
00334 rAElem.clear();
00335 }
00336
00337 if (assembleVector)
00338 {
00339 rBElem.clear();
00340 }
00341
00342 const unsigned num_nodes = rElement.GetNumNodes();
00343
00344
00345 c_vector<double, ELEMENT_DIM+1> phi;
00346 c_matrix<double, SPACE_DIM, ELEMENT_DIM+1> grad_phi;
00347
00348
00349 for (unsigned quad_index=0; quad_index < quad_rule.GetNumQuadPoints(); quad_index++)
00350 {
00351 const ChastePoint<ELEMENT_DIM>& quad_point = quad_rule.rGetQuadPoint(quad_index);
00352
00353 BasisFunction::ComputeBasisFunctions(quad_point, phi);
00354
00355 if ( assembleMatrix || this->ProblemIsNonlinear() )
00356 {
00357 ComputeTransformedBasisFunctionDerivatives(quad_point, inverse_jacobian, grad_phi);
00358 }
00359
00360
00361
00362 ChastePoint<SPACE_DIM> x(0,0,0);
00363
00364 c_vector<double,PROBLEM_DIM> u = zero_vector<double>(PROBLEM_DIM);
00365 c_matrix<double,PROBLEM_DIM,SPACE_DIM> grad_u = zero_matrix<double>(PROBLEM_DIM,SPACE_DIM);
00366
00367
00368
00369 static_cast<typename AssemblerTraits<CONCRETE>::INTERPOLATE_CLS *>(this)->ResetInterpolatedQuantities();
00370
00372
00374 for (unsigned i=0; i<num_nodes; i++)
00375 {
00376 const Node<SPACE_DIM> *p_node = rElement.GetNode(i);
00377
00378 if (NON_HEART)
00379 {
00380 const c_vector<double, SPACE_DIM>& r_node_loc = p_node->rGetLocation();
00381
00382 x.rGetLocation() += phi(i)*r_node_loc;
00383 }
00384
00385
00386 unsigned node_global_index = rElement.GetNodeGlobalIndex(i);
00387 if (mCurrentSolutionOrGuessReplicated.size()>0)
00388 {
00389 for (unsigned index_of_unknown=0; index_of_unknown<(NON_HEART ? PROBLEM_DIM : 1); index_of_unknown++)
00390 {
00391
00392
00393
00394
00395
00396
00397
00398
00399 double u_at_node=GetCurrentSolutionOrGuessValue(node_global_index, index_of_unknown);
00400 u(index_of_unknown) += phi(i)*u_at_node;
00401
00402 if (this->ProblemIsNonlinear() )
00403 {
00404 for (unsigned j=0; j<SPACE_DIM; j++)
00405 {
00406 grad_u(index_of_unknown,j) += grad_phi(j,i)*u_at_node;
00407 }
00408 }
00409 }
00410 }
00411
00412
00413
00414 static_cast<typename AssemblerTraits<CONCRETE>::INTERPOLATE_CLS *>(this)->IncrementInterpolatedQuantities(phi(i), p_node);
00415 }
00416
00417
00418 double wJ = jacobian_determinant * quad_rule.GetWeight(quad_index);
00419
00421
00423 if (assembleMatrix)
00424 {
00425 noalias(rAElem) += static_cast<typename AssemblerTraits<CONCRETE>::CMT_CLS *>(this)->ComputeMatrixTerm(phi, grad_phi, x, u, grad_u, &rElement) * wJ;
00426 }
00427
00428 if (assembleVector)
00429 {
00430 noalias(rBElem) += static_cast<typename AssemblerTraits<CONCRETE>::CVT_CLS *>(this)->ComputeVectorTerm(phi, grad_phi, x, u, grad_u, &rElement) * wJ;
00431 }
00432
00433 }
00434 }
00435
00436
00437 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM, bool NON_HEART, class CONCRETE>
00438 void AbstractStaticAssembler<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, NON_HEART, CONCRETE>::AssembleOnSurfaceElement(const BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>& rSurfaceElement,
00439 c_vector<double, PROBLEM_DIM*ELEMENT_DIM>& rBSurfElem)
00440 {
00441 GaussianQuadratureRule<ELEMENT_DIM-1>& quad_rule =
00442 *(AbstractStaticAssembler<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM, NON_HEART, CONCRETE>::mpSurfaceQuadRule);
00443
00444 c_vector<double, SPACE_DIM> weighted_direction;
00445 double jacobian_determinant;
00446 mpMesh->GetWeightedDirectionForBoundaryElement(rSurfaceElement.GetIndex(), weighted_direction, jacobian_determinant);
00447
00448 rBSurfElem.clear();
00449
00450
00451 c_vector<double, ELEMENT_DIM> phi;
00452
00453
00454 for (unsigned quad_index=0; quad_index<quad_rule.GetNumQuadPoints(); quad_index++)
00455 {
00456 const ChastePoint<ELEMENT_DIM-1>& quad_point = quad_rule.rGetQuadPoint(quad_index);
00457
00458 SurfaceBasisFunction::ComputeBasisFunctions(quad_point, phi);
00459
00461
00463
00464
00465
00466 ChastePoint<SPACE_DIM> x(0,0,0);
00467
00468 this->ResetInterpolatedQuantities();
00469 for (unsigned i=0; i<rSurfaceElement.GetNumNodes(); i++)
00470 {
00471 const c_vector<double, SPACE_DIM> node_loc = rSurfaceElement.GetNode(i)->rGetLocation();
00472 x.rGetLocation() += phi(i)*node_loc;
00473
00474
00475
00476 IncrementInterpolatedQuantities(phi(i), rSurfaceElement.GetNode(i));
00477
00479 }
00480
00481 double wJ = jacobian_determinant * quad_rule.GetWeight(quad_index);
00482
00484
00487 noalias(rBSurfElem) += ComputeVectorSurfaceTerm(rSurfaceElement, phi, x) * wJ;
00488 }
00489 }
00490
00491
00492 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM, bool NON_HEART, class CONCRETE>
00493 void AbstractStaticAssembler<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, NON_HEART, CONCRETE>::AssembleSystem(bool assembleVector, bool assembleMatrix,
00494 Vec currentSolutionOrGuess, double currentTime)
00495 {
00496 HeartEventHandler::EventType assemble_event;
00497 if (assembleMatrix)
00498 {
00499 assemble_event = HeartEventHandler::ASSEMBLE_SYSTEM;
00500 }
00501 else
00502 {
00503 assemble_event = HeartEventHandler::ASSEMBLE_RHS;
00504 }
00505
00506
00507 assert(assembleVector || assembleMatrix);
00508
00509
00510 assert(mpLinearSystem != NULL);
00511 assert(mpLinearSystem->GetSize() == PROBLEM_DIM * this->mpMesh->GetNumNodes());
00512 assert(!assembleVector || mpLinearSystem->rGetRhsVector() != NULL);
00513 assert(!assembleMatrix || mpLinearSystem->rGetLhsMatrix() != NULL);
00514
00515
00516
00517 if (currentSolutionOrGuess != NULL)
00518 {
00519 HeartEventHandler::BeginEvent(HeartEventHandler::COMMUNICATION);
00520 this->mCurrentSolutionOrGuessReplicated.ReplicatePetscVector(currentSolutionOrGuess);
00521 HeartEventHandler::EndEvent(HeartEventHandler::COMMUNICATION);
00522 }
00523
00524
00525
00526
00527 assert( ( currentSolutionOrGuess && mCurrentSolutionOrGuessReplicated.size()>0)
00528 || ( !currentSolutionOrGuess && mCurrentSolutionOrGuessReplicated.size()==0));
00529
00530
00531
00532 this->PrepareForAssembleSystem(currentSolutionOrGuess, currentTime);
00533
00534
00535
00536 HeartEventHandler::BeginEvent(assemble_event);
00537
00538
00539 if (assembleVector)
00540 {
00541 mpLinearSystem->ZeroRhsVector();
00542 }
00543 if (assembleMatrix)
00544 {
00545 mpLinearSystem->ZeroLhsMatrix();
00546 }
00547
00548 const size_t STENCIL_SIZE=PROBLEM_DIM*(ELEMENT_DIM+1);
00549 c_matrix<double, STENCIL_SIZE, STENCIL_SIZE> a_elem;
00550 c_vector<double, STENCIL_SIZE> b_elem;
00551
00553
00555 for (typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator iter = this->mpMesh->GetElementIteratorBegin();
00556 iter != this->mpMesh->GetElementIteratorEnd();
00557 ++iter)
00558 {
00559 Element<ELEMENT_DIM, SPACE_DIM>& element = *iter;
00560
00561 if (element.GetOwnership() == true)
00562 {
00563 AssembleOnElement(element, a_elem, b_elem, assembleVector, assembleMatrix);
00564
00565 unsigned p_indices[STENCIL_SIZE];
00566 element.GetStiffnessMatrixGlobalIndices(PROBLEM_DIM, p_indices);
00567
00568 if (assembleMatrix)
00569 {
00570 mpLinearSystem->AddLhsMultipleValues(p_indices, a_elem);
00571 }
00572
00573 if (assembleVector)
00574 {
00575 mpLinearSystem->AddRhsMultipleValues(p_indices, b_elem);
00576 }
00577 }
00578 }
00579
00580
00581 typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::BoundaryElementIterator
00582 surf_iter = this->mpMesh->GetBoundaryElementIteratorBegin();
00583
00585
00586
00587
00588
00589
00590
00592 if (assembleVector)
00593 {
00594 HeartEventHandler::EndEvent(assemble_event);
00595 this->ApplyNeummanBoundaryConditions();
00596 HeartEventHandler::BeginEvent(assemble_event);
00597 }
00598
00599 if (assembleVector)
00600 {
00601 mpLinearSystem->AssembleRhsVector();
00602 }
00603
00604 if (assembleMatrix)
00605 {
00606 mpLinearSystem->AssembleIntermediateLhsMatrix();
00607 }
00608
00609
00610 this->ApplyDirichletConditions(currentSolutionOrGuess, assembleMatrix);
00611
00612 this->FinaliseLinearSystem(currentSolutionOrGuess, currentTime, assembleVector, assembleMatrix);
00613
00614 if (assembleVector)
00615 {
00616 mpLinearSystem->AssembleRhsVector();
00617 }
00618 if (assembleMatrix)
00619 {
00620 mpLinearSystem->AssembleFinalLhsMatrix();
00621 }
00622
00623
00624
00625 this->FinaliseAssembleSystem(currentSolutionOrGuess, currentTime);
00626
00627 HeartEventHandler::EndEvent(assemble_event);
00628 }
00629
00630
00631 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM, bool NON_HEART, class CONCRETE>
00632 void AbstractStaticAssembler<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, NON_HEART, CONCRETE>::PrepareForSolve()
00633 {
00634 assert(mpMesh != NULL);
00635 assert(this->mpBoundaryConditions != NULL);
00636
00637 mpMesh->GetDistributedVectorFactory();
00638 assert(mpMesh->GetNumNodes() == mpMesh->GetDistributedVectorFactory()->GetProblemSize());
00639
00640 mpMesh->SetElementOwnerships(mpMesh->GetDistributedVectorFactory()->GetLow(),
00641 mpMesh->GetDistributedVectorFactory()->GetHigh());
00642 }
00643
00644
00645 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM, bool NON_HEART, class CONCRETE>
00646 LinearSystem** AbstractStaticAssembler<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, NON_HEART, CONCRETE>::GetLinearSystem()
00647 {
00648 return &mpLinearSystem;
00649 }
00650
00651
00652 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM, bool NON_HEART, class CONCRETE>
00653 ReplicatableVector& AbstractStaticAssembler<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, NON_HEART, CONCRETE>::rGetCurrentSolutionOrGuess()
00654 {
00655 return mCurrentSolutionOrGuessReplicated;
00656 }
00657
00658
00659 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM, bool NON_HEART, class CONCRETE>
00660 double AbstractStaticAssembler<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, NON_HEART, CONCRETE>::GetCurrentSolutionOrGuessValue(unsigned nodeIndex, unsigned indexOfUnknown)
00661 {
00662 return mCurrentSolutionOrGuessReplicated[ PROBLEM_DIM*nodeIndex + indexOfUnknown];
00663 }
00664
00665
00666 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM, bool NON_HEART, class CONCRETE>
00667 AbstractStaticAssembler<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, NON_HEART, CONCRETE>::AbstractStaticAssembler(unsigned numQuadPoints)
00668 : AbstractAssembler<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>()
00669 {
00670
00671
00672 mpMesh = NULL;
00673
00674 mpQuadRule = NULL;
00675 mpSurfaceQuadRule = NULL;
00676 SetNumberOfQuadraturePointsPerDimension(numQuadPoints);
00677
00678 mpLinearSystem = NULL;
00679 }
00680
00681
00682 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM, bool NON_HEART, class CONCRETE>
00683 void AbstractStaticAssembler<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, NON_HEART, CONCRETE>::SetNumberOfQuadraturePointsPerDimension(unsigned numQuadPoints)
00684 {
00685 delete mpQuadRule;
00686 mpQuadRule = new GaussianQuadratureRule<ELEMENT_DIM>(numQuadPoints);
00687 delete mpSurfaceQuadRule;
00688 mpSurfaceQuadRule = new GaussianQuadratureRule<ELEMENT_DIM-1>(numQuadPoints);
00689 }
00690
00691
00692 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM, bool NON_HEART, class CONCRETE>
00693 void AbstractStaticAssembler<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, NON_HEART, CONCRETE>::SetMesh(AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh)
00694 {
00695 mpMesh = pMesh;
00696 }
00697
00698
00699 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM, bool NON_HEART, class CONCRETE>
00700 AbstractStaticAssembler<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, NON_HEART, CONCRETE>::~AbstractStaticAssembler()
00701 {
00702 delete mpQuadRule;
00703 delete mpSurfaceQuadRule;
00704 delete mpLinearSystem;
00705 }
00706
00707 #endif //_ABSTRACTSTATICASSEMBLER_HPP_