Chaste  Release::2017.1
AbstractFeSurfaceIntegralAssembler.hpp
1 /*
2 
3 Copyright (c) 2005-2017, University of Oxford.
4 All rights reserved.
5 
6 University of Oxford means the Chancellor, Masters and Scholars of the
7 University of Oxford, having an administrative office at Wellington
8 Square, Oxford OX1 2JD, UK.
9 
10 This file is part of Chaste.
11 
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions are met:
14  * Redistributions of source code must retain the above copyright notice,
15  this list of conditions and the following disclaimer.
16  * Redistributions in binary form must reproduce the above copyright notice,
17  this list of conditions and the following disclaimer in the documentation
18  and/or other materials provided with the distribution.
19  * Neither the name of the University of Oxford nor the names of its
20  contributors may be used to endorse or promote products derived from this
21  software without specific prior written permission.
22 
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 
34 */
35 
36 #ifndef ABSTRACTFESURFACENTEGRALASSEMBLER_HPP_
37 #define ABSTRACTFESURFACENTEGRALASSEMBLER_HPP_
38 
39 #include "AbstractFeAssemblerCommon.hpp"
40 #include "GaussianQuadratureRule.hpp"
41 #include "BoundaryConditionsContainer.hpp"
42 #include "PetscVecTools.hpp"
43 #include "PetscMatTools.hpp"
44 
45 
60 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
61 class AbstractFeSurfaceIntegralAssembler : public AbstractFeAssemblerCommon<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM,true,false,NORMAL>
62 {
63 protected:
66 
69 
72 
74  typedef LinearBasisFunction<ELEMENT_DIM-1> SurfaceBasisFunction;
75 
89  // LCOV_EXCL_START
90  virtual c_vector<double, PROBLEM_DIM*ELEMENT_DIM> ComputeVectorSurfaceTerm(
91  const BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>& rSurfaceElement,
92  c_vector<double, ELEMENT_DIM>& rPhi,
94  {
95  // If this line is reached this means this method probably hasn't been over-ridden correctly in
96  // the concrete class
98  return zero_vector<double>(ELEMENT_DIM*PROBLEM_DIM);
99  }
100  // LCOV_EXCL_STOP
101 
111  virtual void AssembleOnSurfaceElement(const BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>& rSurfaceElement,
112  c_vector<double, PROBLEM_DIM*ELEMENT_DIM>& rBSurfElem);
113 
114 
118  void DoAssemble();
119 
120 
121 public:
130 
135 
141  {
142  assert(pBoundaryConditions);
143  this->mpBoundaryConditions = pBoundaryConditions;
144  }
145 };
146 
147 
148 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
152  : AbstractFeAssemblerCommon<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM,true,false,NORMAL>(),
153  mpMesh(pMesh),
154  mpBoundaryConditions(pBoundaryConditions)
155 {
156  assert(pMesh);
157  assert(pBoundaryConditions);
158  // Default to 2nd order quadrature. Our default basis functions are piecewise linear
159  // which means that we are integrating functions which in the worst case (mass matrix)
160  // are quadratic.
161  mpSurfaceQuadRule = new GaussianQuadratureRule<ELEMENT_DIM-1>(2);
162 }
163 
164 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
166 {
167  delete mpSurfaceQuadRule;
168 }
169 
170 
171 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
173 {
174  assert(this->mAssembleVector);
175 
176  HeartEventHandler::BeginEvent(HeartEventHandler::NEUMANN_BCS);
177 
178  // Loop over surface elements with non-zero Neumann boundary conditions
179  if (mpBoundaryConditions->AnyNonZeroNeumannConditions())
180  {
182  neumann_iterator = mpBoundaryConditions->BeginNeumann();
183 
184  c_vector<double, PROBLEM_DIM*ELEMENT_DIM> b_surf_elem;
185 
186  // Iterate over defined conditions
187  while (neumann_iterator != mpBoundaryConditions->EndNeumann())
188  {
189  const BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>& r_surf_element = *(neumann_iterator->first);
190  AssembleOnSurfaceElement(r_surf_element, b_surf_elem);
191 
192  const size_t STENCIL_SIZE=PROBLEM_DIM*ELEMENT_DIM; // problem_dim*num_nodes_on_surface_element
193  unsigned p_indices[STENCIL_SIZE];
194  r_surf_element.GetStiffnessMatrixGlobalIndices(PROBLEM_DIM, p_indices);
195  PetscVecTools::AddMultipleValues<STENCIL_SIZE>(this->mVectorToAssemble, p_indices, b_surf_elem);
196  ++neumann_iterator;
197  }
198  }
199 
200  HeartEventHandler::EndEvent(HeartEventHandler::NEUMANN_BCS);
201 }
202 
203 
204 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
206  const BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>& rSurfaceElement,
207  c_vector<double, PROBLEM_DIM*ELEMENT_DIM>& rBSurfElem)
208 {
209  c_vector<double, SPACE_DIM> weighted_direction;
210  double jacobian_determinant;
211  mpMesh->GetWeightedDirectionForBoundaryElement(rSurfaceElement.GetIndex(), weighted_direction, jacobian_determinant);
212 
213  rBSurfElem.clear();
214 
215  // Allocate memory for the basis function values
216  c_vector<double, ELEMENT_DIM> phi;
217 
218  // Loop over Gauss points
219  for (unsigned quad_index=0; quad_index<mpSurfaceQuadRule->GetNumQuadPoints(); quad_index++)
220  {
221  const ChastePoint<ELEMENT_DIM-1>& quad_point = mpSurfaceQuadRule->rGetQuadPoint(quad_index);
222 
224 
226  // Interpolation: X only
228 
229  // The location of the Gauss point in the original element will be stored in x
230  ChastePoint<SPACE_DIM> x(0,0,0);
231 
233  for (unsigned i=0; i<rSurfaceElement.GetNumNodes(); i++)
234  {
235  const c_vector<double, SPACE_DIM> node_loc = rSurfaceElement.GetNode(i)->rGetLocation();
236  x.rGetLocation() += phi(i)*node_loc;
237 
238  // Allow the concrete version of the assembler to interpolate any desired quantities
239  this->IncrementInterpolatedQuantities(phi(i), rSurfaceElement.GetNode(i));
240  }
241 
242 
244  // Create elemental contribution
246 
247  double wJ = jacobian_determinant * mpSurfaceQuadRule->GetWeight(quad_index);
249  noalias(rBSurfElem) += ComputeVectorSurfaceTerm(rSurfaceElement, phi, x) * wJ;
250  }
251 }
252 
253 #endif // ABSTRACTFESURFACENTEGRALASSEMBLER_HPP_
virtual void AssembleOnSurfaceElement(const BoundaryElement< ELEMENT_DIM-1, SPACE_DIM > &rSurfaceElement, c_vector< double, PROBLEM_DIM *ELEMENT_DIM > &rBSurfElem)
c_vector< double, DIM > & rGetLocation()
Definition: ChastePoint.cpp:76
AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM > * mpMesh
std::map< const BoundaryElement< ELEMENT_DIM-1, SPACE_DIM > *, const AbstractBoundaryCondition< SPACE_DIM > * >::const_iterator NeumannMapIterator
#define NEVER_REACHED
Definition: Exception.hpp:206
unsigned GetNumQuadPoints() const
Node< SPACE_DIM > * GetNode(unsigned localIndex) const
BoundaryConditionsContainer< ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM > * mpBoundaryConditions
GaussianQuadratureRule< ELEMENT_DIM-1 > * mpSurfaceQuadRule
LinearBasisFunction< ELEMENT_DIM-1 > SurfaceBasisFunction
unsigned GetNumNodes() const
void GetStiffnessMatrixGlobalIndices(unsigned problemDim, unsigned *pIndices) const
AbstractFeSurfaceIntegralAssembler(AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM > *pMesh, BoundaryConditionsContainer< ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM > *pBoundaryConditions)
static void ComputeBasisFunctions(const ChastePoint< ELEMENT_DIM > &rPoint, c_vector< double, ELEMENT_DIM+1 > &rReturnValue)
virtual void IncrementInterpolatedQuantities(double phiI, const Node< SPACE_DIM > *pNode)
void ResetBoundaryConditionsContainer(BoundaryConditionsContainer< ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM > *pBoundaryConditions)
unsigned GetIndex() const
double GetWeight(unsigned index) const
const ChastePoint< ELEMENT_DIM > & rGetQuadPoint(unsigned index) const
virtual c_vector< double, PROBLEM_DIM *ELEMENT_DIM > ComputeVectorSurfaceTerm(const BoundaryElement< ELEMENT_DIM-1, SPACE_DIM > &rSurfaceElement, c_vector< double, ELEMENT_DIM > &rPhi, ChastePoint< SPACE_DIM > &rX)