AbstractStaticAssembler.hpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2009
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
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 // Implementation
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 // With the new signature of GetInverseJacobianForElement, inverse and jacobian are returned at the same time
00326 //        // Initialise element contributions to zero
00327 //        if ( assembleMatrix || this->ProblemIsNonlinear() ) // don't need to construct grad_phi or grad_u in that case
00328 //        {
00329 //            this->mpMesh->GetInverseJacobianForElement(rElement.GetIndex(), inverse_jacobian);
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     // allocate memory for the basis functions values and derivative values
00345     c_vector<double, ELEMENT_DIM+1> phi;
00346     c_matrix<double, SPACE_DIM, ELEMENT_DIM+1> grad_phi;
00347 
00348     // loop over Gauss points
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         // Location of the gauss point in the original element will be stored in x
00361         // Where applicable, u will be set to the value of the current solution at x
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         // allow the concrete version of the assembler to interpolate any
00368         // desired quantities
00369         static_cast<typename AssemblerTraits<CONCRETE>::INTERPOLATE_CLS *>(this)->ResetInterpolatedQuantities();
00370 
00372         // interpolation
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                 // interpolate x
00382                 x.rGetLocation() += phi(i)*r_node_loc;
00383             }
00384 
00385             // interpolate u and grad u if a current solution or guess exists
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                     // If we have a current solution (e.g. this is a dynamic problem)
00392                     // get the value in a usable form.rElement
00393 
00394                     // NOTE - currentSolutionOrGuess input is actually now redundant at this point -
00395 
00396                     // NOTE - following assumes that, if say there are two unknowns u and v, they
00397                     // are stored in the current solution vector as
00398                     // [U1 V1 U2 V2 ... U_n V_n]
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() ) // don't need to construct grad_phi or grad_u in that case
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             // allow the concrete version of the assembler to interpolate any
00413             // desired quantities
00414             static_cast<typename AssemblerTraits<CONCRETE>::INTERPOLATE_CLS *>(this)->IncrementInterpolatedQuantities(phi(i), p_node);
00415         }
00416 
00417         //HeartEventHandler::BeginEvent(HeartEventHandler::USER1); //Temporarily using USER1 to instrument the Compute.. terms
00418         double wJ = jacobian_determinant * quad_rule.GetWeight(quad_index);
00419 
00421         // create rAElem and rBElem
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         //HeartEventHandler::EndEvent(HeartEventHandler::USER1); //Temporarily using USER1 to instrument the Compute.. terms
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     // allocate memory for the basis function values
00451     c_vector<double, ELEMENT_DIM>  phi;
00452 
00453     // loop over Gauss points
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         // interpolation
00463 
00464         // Location of the gauss point in the original element will be
00465         // stored in x
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             // allow the concrete version of the assembler to interpolate any
00475             // desired quantities
00476             IncrementInterpolatedQuantities(phi(i), rSurfaceElement.GetNode(i));
00477 
00479         }
00480 
00481         double wJ = jacobian_determinant * quad_rule.GetWeight(quad_index);
00482 
00484         // create rAElem and rBElem
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     // Check we've actually been asked to do something!
00507     assert(assembleVector || assembleMatrix);
00508 
00509     // Check the linear system object has been set up correctly
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     // Replicate the current solution and store so can be used in
00516     // AssembleOnElement
00517     if (currentSolutionOrGuess != NULL)
00518     {
00519         HeartEventHandler::BeginEvent(HeartEventHandler::COMMUNICATION);
00520         this->mCurrentSolutionOrGuessReplicated.ReplicatePetscVector(currentSolutionOrGuess);
00521         HeartEventHandler::EndEvent(HeartEventHandler::COMMUNICATION);
00522     }
00523 
00524     // the AssembleOnElement type methods will determine if a current solution or
00525     // current guess exists by looking at the size of the replicated vector, so
00526     // check the size is zero if there isn't a current solution
00527     assert(    ( currentSolutionOrGuess && mCurrentSolutionOrGuessReplicated.size()>0)
00528             || ( !currentSolutionOrGuess && mCurrentSolutionOrGuessReplicated.size()==0));
00529 
00530     // the concrete class can override this following method if there is
00531     // work to be done before assembly
00532     this->PrepareForAssembleSystem(currentSolutionOrGuess, currentTime);
00533 
00534     // this has to be below PrepareForAssembleSystem as in that
00535     // method the odes are solved in cardiac problems
00536     HeartEventHandler::BeginEvent(assemble_event);
00537 
00538     // Zero the matrix/vector if it is to be assembled
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     // loop over elements
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     // add the integrals associated with Neumann boundary conditions to the linear system
00581     typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::BoundaryElementIterator
00582         surf_iter = this->mpMesh->GetBoundaryElementIteratorBegin();
00583 
00585     // Apply any Neumann boundary conditions
00586     //
00587     // NB. We assume that if an element has a boundary condition on any unknown there is a boundary condition
00588     // on unknown 0. This can be so for any problem by adding zero constant conditions where required
00589     // although this is a bit inefficient. Proper solution involves changing BCC to have a map of arrays
00590     // boundary conditions rather than an array of maps.
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     // Apply Dirichlet boundary conditions
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     // overload this method if the assembler has to do anything else
00624     // required (like setting up a null basis (see BidomainDg0Assembler))
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(); // Calls GetDistributedVectorFactory to set static variables in DistributedVector class - ultimately this can be removed (hopefully!)
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     // Initialise mesh and bcs to null, so we can check they
00671     // have been set before attempting to solve
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_

Generated on Tue Aug 4 16:10:24 2009 for Chaste by  doxygen 1.5.5