Chaste Release::3.1
|
00001 /* 00002 00003 Copyright (c) 2005-2012, University of Oxford. 00004 All rights reserved. 00005 00006 University of Oxford means the Chancellor, Masters and Scholars of the 00007 University of Oxford, having an administrative office at Wellington 00008 Square, Oxford OX1 2JD, UK. 00009 00010 This file is part of Chaste. 00011 00012 Redistribution and use in source and binary forms, with or without 00013 modification, are permitted provided that the following conditions are met: 00014 * Redistributions of source code must retain the above copyright notice, 00015 this list of conditions and the following disclaimer. 00016 * Redistributions in binary form must reproduce the above copyright notice, 00017 this list of conditions and the following disclaimer in the documentation 00018 and/or other materials provided with the distribution. 00019 * Neither the name of the University of Oxford nor the names of its 00020 contributors may be used to endorse or promote products derived from this 00021 software without specific prior written permission. 00022 00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00024 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00025 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00026 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00033 00034 */ 00035 00036 #ifndef ABSTRACTFESURFACENTEGRALASSEMBLER_HPP_ 00037 #define ABSTRACTFESURFACENTEGRALASSEMBLER_HPP_ 00038 00039 #include "AbstractFeAssemblerCommon.hpp" 00040 #include "GaussianQuadratureRule.hpp" 00041 #include "BoundaryConditionsContainer.hpp" 00042 #include "PetscVecTools.hpp" 00043 #include "PetscMatTools.hpp" 00044 00045 00060 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM> 00061 class AbstractFeSurfaceIntegralAssembler : public AbstractFeAssemblerCommon<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM,true,false,NORMAL> 00062 { 00063 protected: 00065 AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>* mpMesh; 00066 00068 BoundaryConditionsContainer<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>* mpBoundaryConditions; 00069 00071 GaussianQuadratureRule<ELEMENT_DIM-1>* mpSurfaceQuadRule; 00072 00074 typedef LinearBasisFunction<ELEMENT_DIM-1> SurfaceBasisFunction; 00075 00089 virtual c_vector<double, PROBLEM_DIM*ELEMENT_DIM> ComputeVectorSurfaceTerm( 00090 const BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>& rSurfaceElement, 00091 c_vector<double, ELEMENT_DIM>& rPhi, 00092 ChastePoint<SPACE_DIM>& rX) 00093 { 00094 // If this line is reached this means this method probably hasn't been over-ridden correctly in 00095 // the concrete class 00096 NEVER_REACHED; 00097 return zero_vector<double>(ELEMENT_DIM*PROBLEM_DIM); 00098 } 00099 00109 virtual void AssembleOnSurfaceElement(const BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>& rSurfaceElement, 00110 c_vector<double, PROBLEM_DIM*ELEMENT_DIM>& rBSurfElem); 00111 00112 00116 void DoAssemble(); 00117 00118 00119 public: 00127 AbstractFeSurfaceIntegralAssembler(AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh, 00128 BoundaryConditionsContainer<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>* pBoundaryConditions, 00129 unsigned numQuadPoints = 2); 00130 00134 virtual ~AbstractFeSurfaceIntegralAssembler(); 00135 00140 void ResetBoundaryConditionsContainer(BoundaryConditionsContainer<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>* pBoundaryConditions) 00141 { 00142 assert(pBoundaryConditions); 00143 this->mpBoundaryConditions = pBoundaryConditions; 00144 } 00145 }; 00146 00147 00148 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM> 00149 AbstractFeSurfaceIntegralAssembler<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::AbstractFeSurfaceIntegralAssembler( 00150 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh, 00151 BoundaryConditionsContainer<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>* pBoundaryConditions, 00152 unsigned numQuadPoints) 00153 : AbstractFeAssemblerCommon<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM,true,false,NORMAL>(), 00154 mpMesh(pMesh), 00155 mpBoundaryConditions(pBoundaryConditions) 00156 { 00157 assert(pMesh); 00158 assert(pBoundaryConditions); 00159 assert(numQuadPoints > 0); 00160 00161 mpSurfaceQuadRule = new GaussianQuadratureRule<ELEMENT_DIM-1>(numQuadPoints); 00162 } 00163 00164 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM> 00165 AbstractFeSurfaceIntegralAssembler<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::~AbstractFeSurfaceIntegralAssembler() 00166 { 00167 delete mpSurfaceQuadRule; 00168 } 00169 00170 00171 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM> 00172 void AbstractFeSurfaceIntegralAssembler<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::DoAssemble() 00173 { 00174 assert(this->mAssembleVector); 00175 00176 HeartEventHandler::BeginEvent(HeartEventHandler::NEUMANN_BCS); 00177 00178 // Loop over surface elements with non-zero Neumann boundary conditions 00179 if (mpBoundaryConditions->AnyNonZeroNeumannConditions()) 00180 { 00181 typename BoundaryConditionsContainer<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::NeumannMapIterator 00182 neumann_iterator = mpBoundaryConditions->BeginNeumann(); 00183 00184 c_vector<double, PROBLEM_DIM*ELEMENT_DIM> b_surf_elem; 00185 00186 // Iterate over defined conditions 00187 while (neumann_iterator != mpBoundaryConditions->EndNeumann()) 00188 { 00189 const BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>& r_surf_element = *(neumann_iterator->first); 00190 AssembleOnSurfaceElement(r_surf_element, b_surf_elem); 00191 00192 const size_t STENCIL_SIZE=PROBLEM_DIM*ELEMENT_DIM; // problem_dim*num_nodes_on_surface_element 00193 unsigned p_indices[STENCIL_SIZE]; 00194 r_surf_element.GetStiffnessMatrixGlobalIndices(PROBLEM_DIM, p_indices); 00195 PetscVecTools::AddMultipleValues<STENCIL_SIZE>(this->mVectorToAssemble, p_indices, b_surf_elem); 00196 ++neumann_iterator; 00197 } 00198 } 00199 00200 HeartEventHandler::EndEvent(HeartEventHandler::NEUMANN_BCS); 00201 } 00202 00203 00204 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM> 00205 void AbstractFeSurfaceIntegralAssembler<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::AssembleOnSurfaceElement( 00206 const BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>& rSurfaceElement, 00207 c_vector<double, PROBLEM_DIM*ELEMENT_DIM>& rBSurfElem) 00208 { 00209 c_vector<double, SPACE_DIM> weighted_direction; 00210 double jacobian_determinant; 00211 mpMesh->GetWeightedDirectionForBoundaryElement(rSurfaceElement.GetIndex(), weighted_direction, jacobian_determinant); 00212 00213 rBSurfElem.clear(); 00214 00215 // Allocate memory for the basis function values 00216 c_vector<double, ELEMENT_DIM> phi; 00217 00218 // Loop over Gauss points 00219 for (unsigned quad_index=0; quad_index<mpSurfaceQuadRule->GetNumQuadPoints(); quad_index++) 00220 { 00221 const ChastePoint<ELEMENT_DIM-1>& quad_point = mpSurfaceQuadRule->rGetQuadPoint(quad_index); 00222 00223 SurfaceBasisFunction::ComputeBasisFunctions(quad_point, phi); 00224 00226 // Interpolation: X only 00228 00229 // The location of the Gauss point in the original element will be stored in x 00230 ChastePoint<SPACE_DIM> x(0,0,0); 00231 00232 this->ResetInterpolatedQuantities(); 00233 for (unsigned i=0; i<rSurfaceElement.GetNumNodes(); i++) 00234 { 00235 const c_vector<double, SPACE_DIM> node_loc = rSurfaceElement.GetNode(i)->rGetLocation(); 00236 x.rGetLocation() += phi(i)*node_loc; 00237 00238 // Allow the concrete version of the assembler to interpolate any desired quantities 00239 this->IncrementInterpolatedQuantities(phi(i), rSurfaceElement.GetNode(i)); 00240 } 00241 00242 00244 // Create elemental contribution 00246 00247 double wJ = jacobian_determinant * mpSurfaceQuadRule->GetWeight(quad_index); 00249 noalias(rBSurfElem) += ComputeVectorSurfaceTerm(rSurfaceElement, phi, x) * wJ; 00250 } 00251 }; 00252 00253 #endif // ABSTRACTFESURFACENTEGRALASSEMBLER_HPP_