BEM++  2.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
numerical_kernel_trial_integrator_imp.hpp
1 // Copyright (C) 2011-2012 by the BEM++ Authors
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 // THE SOFTWARE.
20 
21 #include "numerical_kernel_trial_integrator.hpp" // To keep IDEs happy
22 
23 #include "_2d_array.hpp"
24 #include "_3d_array.hpp"
25 #include "_4d_array.hpp"
26 
27 #include "shapeset.hpp"
28 #include "basis_data.hpp"
29 #include "conjugate.hpp"
30 #include "collection_of_shapeset_transformations.hpp"
31 #include "geometrical_data.hpp"
32 #include "collection_of_kernels.hpp"
33 #include "opencl_handler.hpp"
34 #include "raw_grid_geometry.hpp"
35 #include "kernel_trial_integral.hpp"
36 #include "types.hpp"
37 
38 #include <cassert>
39 #include <memory>
40 
41 namespace Fiber
42 {
43 
44 template <typename BasisFunctionType, typename KernelType,
45  typename ResultType, typename GeometryFactory>
46 NumericalKernelTrialIntegrator<
47 BasisFunctionType, KernelType, ResultType, GeometryFactory>::
48 NumericalKernelTrialIntegrator(
49  const arma::Mat<CoordinateType>& localQuadPoints,
50  const std::vector<CoordinateType> quadWeights,
51  const arma::Mat<CoordinateType>& points,
52  const GeometryFactory& geometryFactory,
53  const RawGridGeometry<CoordinateType>& rawGeometry,
54  const CollectionOfKernels<KernelType>& kernels,
55  const CollectionOfShapesetTransformations<CoordinateType>& trialTransformations,
56  const KernelTrialIntegral<BasisFunctionType, KernelType, ResultType>& integral) :
57  m_localQuadPoints(localQuadPoints),
58  m_quadWeights(quadWeights),
59  m_points(points),
60  m_geometryFactory(geometryFactory),
61  m_rawGeometry(rawGeometry),
62  m_kernels(kernels),
63  m_trialTransformations(trialTransformations),
64  m_integral(integral)
65 {
66  if (localQuadPoints.n_cols != quadWeights.size())
67  throw std::invalid_argument("NumericalKernelTrialIntegrator::"
68  "NumericalKernelTrialIntegrator(): "
69  "numbers of test points and weights "
70  "do not match");
71 }
72 
73 template <typename BasisFunctionType, typename KernelType,
74  typename ResultType, typename GeometryFactory>
75 void NumericalKernelTrialIntegrator<
76 BasisFunctionType, KernelType, ResultType, GeometryFactory>::
77 integrate(const std::vector<int>& pointIndices,
78  int trialElementIndex,
79  const Shapeset<BasisFunctionType>& trialShapeset,
80  LocalDofIndex localTrialDofIndex,
81  const std::vector<arma::Mat<ResultType>*>& result) const
82 {
83  const int quadPointCount = m_localQuadPoints.n_cols;
84  const int pointCount = pointIndices.size();
85  const int componentCount = m_integral.resultDimension();
86  const int trialDofCount = localTrialDofIndex == ALL_DOFS ? trialShapeset.size() : 1;
87 
88  if (result.size() != pointCount)
89  throw std::invalid_argument(
90  "NumericalKernelTrialIntegrator::integrate(): "
91  "arrays 'result' and 'pointCount' must have the same number "
92  "of elements");
93  if (pointCount == 0 || quadPointCount == 0)
94  return;
95  // TODO: in the (pathological) case that quadPointCount == 0 but
96  // geometryCount != 0, set elements of result to 0.
97 
98  BasisData<BasisFunctionType> trialBasisData;
99  GeometricalData<CoordinateType> pointGeomData, trialGeomData;
100 
101  size_t trialBasisDeps = 0;
102  size_t pointGeomDeps = 0, trialGeomDeps = 0;
103 
104  m_trialTransformations.addDependencies(trialBasisDeps, trialGeomDeps);
105  m_kernels.addGeometricalDependencies(pointGeomDeps, trialGeomDeps);
106  m_integral.addGeometricalDependencies(trialGeomDeps);
107 
108  typedef typename GeometryFactory::Geometry Geometry;
109  std::auto_ptr<Geometry> trialGeometry = m_geometryFactory.make();
110 
111  CollectionOf3dArrays<BasisFunctionType> trialValues;
112  CollectionOf4dArrays<KernelType> kernelValues;
113 
114  for (size_t i = 0; i < result.size(); ++i) {
115  assert(result[i]);
116  result[i]->set_size(componentCount, trialDofCount);
117  }
118 
119  m_rawGeometry.setupGeometry(trialElementIndex, *trialGeometry);
120  trialShapeset.evaluate(trialBasisDeps, m_localQuadPoints,
121  localTrialDofIndex, trialBasisData);
122  trialGeometry->getData(trialGeomDeps, m_localQuadPoints, trialGeomData);
123  m_trialTransformations.evaluate(trialBasisData, trialGeomData, trialValues);
124 
125  // Iterate over the points
126  for (int i = 0; i < pointCount; ++i) {
127  pointGeomData.globals = m_points.col(pointIndices[i]);
128  m_kernels.evaluateOnGrid(pointGeomData, trialGeomData, kernelValues);
129  _3dArray<ResultType> result3dView(componentCount, trialDofCount, 1,
130  result[i]->memptr(), true /* strict */);
131  m_integral.evaluateWithPureWeights(
132  trialGeomData, kernelValues, trialValues,
133  m_quadWeights,
134  result3dView);
135  }
136 }
137 
138 template <typename BasisFunctionType, typename KernelType,
139  typename ResultType, typename GeometryFactory>
140 void NumericalKernelTrialIntegrator<
141 BasisFunctionType, KernelType, ResultType, GeometryFactory>::
142 integrate(int pointIndex,
143  int componentIndex,
144  const std::vector<int>& trialElementIndices,
145  const Shapeset<BasisFunctionType>& trialShapeset,
146  const std::vector<arma::Mat<ResultType>*>& result) const
147 {
148  const int quadPointCount = m_localQuadPoints.n_cols;
149  const int trialElementCount = trialElementIndices.size();
150  const int componentCount =
151  componentIndex == ALL_COMPONENTS ? m_integral.resultDimension() : 1;
152  const int trialDofCount = trialShapeset.size();
153 
154  if (result.size() != trialElementCount)
155  throw std::invalid_argument(
156  "NumericalKernelTrialIntegrator::integrate(): "
157  "arrays 'result' and 'pointCount' must have the same number "
158  "of elements");
159  if (trialElementCount == 0 || quadPointCount == 0)
160  return;
161  // TODO: in the (pathological) case that quadPointCount == 0 but
162  // geometryCount != 0, set elements of result to 0.
163 
164  BasisData<BasisFunctionType> trialBasisData;
165  GeometricalData<CoordinateType> pointGeomData, trialGeomData;
166 
167  size_t trialBasisDeps = 0;
168  size_t pointGeomDeps = 0, trialGeomDeps = 0;
169 
170  m_trialTransformations.addDependencies(trialBasisDeps, trialGeomDeps);
171  m_kernels.addGeometricalDependencies(pointGeomDeps, trialGeomDeps);
172  m_integral.addGeometricalDependencies(trialGeomDeps);
173 
174  typedef typename GeometryFactory::Geometry Geometry;
175  std::auto_ptr<Geometry> trialGeometry = m_geometryFactory.make();
176 
177  CollectionOf3dArrays<BasisFunctionType> trialValues;
178  CollectionOf4dArrays<KernelType> kernelValues;
179 
180  for (size_t i = 0; i < result.size(); ++i) {
181  assert(result[i]);
182  result[i]->set_size(componentCount, trialDofCount);
183  }
184  _3dArray<ResultType> result3d(componentCount, trialDofCount, 1);
185 
186  pointGeomData.globals = m_points.col(pointIndex);
187 
188  // Iterate over the trial elements
189  for (int i = 0; i < trialElementCount; ++i) {
190  m_rawGeometry.setupGeometry(trialElementIndices[i], *trialGeometry);
191  trialShapeset.evaluate(trialBasisDeps, m_localQuadPoints,
192  ALL_DOFS, trialBasisData);
193  trialGeometry->getData(trialGeomDeps, m_localQuadPoints, trialGeomData);
194  m_trialTransformations.evaluate(trialBasisData, trialGeomData,
195  trialValues);
196  m_kernels.evaluateOnGrid(pointGeomData, trialGeomData, kernelValues);
197  // Currently we evaluate all the components of the integral.
198  // Later we may consider optimizing and evaluating only one
199  // if componentIndex != ALL_COMPONENTS.
200  m_integral.evaluateWithPureWeights(
201  trialGeomData, kernelValues, trialValues,
202  m_quadWeights,
203  result3d);
204  if (componentIndex == ALL_COMPONENTS)
205  for (size_t dof = 0; dof < trialDofCount; ++dof)
206  for (size_t component = 0; component < componentCount; ++component)
207  (*result[i])(component, dof) = result3d(component, dof, 0);
208  else
209  for (size_t dof = 0; dof < trialDofCount; ++dof)
210  (*result[i])(0, dof) = result3d(componentIndex, dof, 0);
211  }
212 }
213 
214 template <typename BasisFunctionType, typename KernelType,
215  typename ResultType, typename GeometryFactory>
216 void NumericalKernelTrialIntegrator<
217 BasisFunctionType, KernelType, ResultType, GeometryFactory>::
218 integrate(const std::vector<PointElementIndexPair>& pointElementIndexPairs,
219  const Shapeset<BasisFunctionType>& trialShapeset,
220  const std::vector<arma::Mat<ResultType>*>& result) const
221 {
222  const int quadPointCount = m_localQuadPoints.n_cols;
223  const int pairCount = pointElementIndexPairs.size();
224  const int componentCount = m_integral.resultDimension();
225  const int trialDofCount = trialShapeset.size();
226 
227  if (result.size() != pairCount)
228  throw std::invalid_argument(
229  "NumericalKernelTrialIntegrator::integrate(): "
230  "arrays 'result' and 'pointCount' must have the same number "
231  "of elements");
232  if (pairCount == 0 || quadPointCount == 0)
233  return;
234  // TODO: in the (pathological) case that quadPointCount == 0 but
235  // geometryCount != 0, set elements of result to 0.
236 
237  BasisData<BasisFunctionType> trialBasisData;
238  GeometricalData<CoordinateType> pointGeomData, trialGeomData;
239 
240  size_t trialBasisDeps = 0;
241  size_t pointGeomDeps = 0, trialGeomDeps = 0;
242 
243  m_trialTransformations.addDependencies(trialBasisDeps, trialGeomDeps);
244  m_kernels.addGeometricalDependencies(pointGeomDeps, trialGeomDeps);
245  m_integral.addGeometricalDependencies(trialGeomDeps);
246 
247  typedef typename GeometryFactory::Geometry Geometry;
248  std::auto_ptr<Geometry> trialGeometry = m_geometryFactory.make();
249 
250  CollectionOf3dArrays<BasisFunctionType> trialValues;
251  CollectionOf4dArrays<KernelType> kernelValues;
252 
253  for (size_t i = 0; i < result.size(); ++i) {
254  assert(result[i]);
255  result[i]->set_size(componentCount, trialDofCount);
256  }
257 
258  // Iterate over the (point, trial element) pairs
259  for (int i = 0; i < pairCount; ++i) {
260  const int activePointIndex = pointElementIndexPairs[i].first;
261  const int activeTrialElementIndex = pointElementIndexPairs[i].second;
262 
263  pointGeomData.globals = m_points.col(activePointIndex);
264  m_rawGeometry.setupGeometry(activeTrialElementIndex, *trialGeometry);
265  trialShapeset.evaluate(trialBasisDeps, m_localQuadPoints,
266  ALL_DOFS, trialBasisData);
267  trialGeometry->getData(trialGeomDeps, m_localQuadPoints, trialGeomData);
268  m_trialTransformations.evaluate(trialBasisData, trialGeomData, trialValues);
269  m_kernels.evaluateOnGrid(pointGeomData, trialGeomData, kernelValues);
270  _3dArray<ResultType> result3dView(componentCount, trialDofCount, 1,
271  result[i]->memptr(), true /* strict */);
272  m_integral.evaluateWithPureWeights(
273  trialGeomData, kernelValues, trialValues,
274  m_quadWeights,
275  result3dView);
276  }
277 }
278 
279 } // namespace Fiber
virtual void addGeometricalDependencies(size_t &testGeomDeps, size_t &trialGeomDeps) const =0
Retrieve types of geometrical data on which the kernels depend.
virtual void evaluateOnGrid(const GeometricalData< CoordinateType > &testGeomData, const GeometricalData< CoordinateType > &trialGeomData, CollectionOf4dArrays< ValueType > &result) const =0
Evaluate the kernels on a tensor grid of test and trial points.