21 #include "default_evaluator_for_integral_operators.hpp"
23 #include "../common/common.hpp"
25 #include "basis_data.hpp"
26 #include "collection_of_basis_transformations.hpp"
27 #include "geometrical_data.hpp"
28 #include "collection_of_kernels.hpp"
29 #include "collection_of_2d_arrays.hpp"
30 #include "collection_of_3d_arrays.hpp"
31 #include "collection_of_4d_arrays.hpp"
32 #include "kernel_trial_integral.hpp"
34 #include "opencl_handler.hpp"
35 #include "raw_grid_geometry.hpp"
36 #include "serial_blas_region.hpp"
37 #include "shapeset.hpp"
39 #include <tbb/parallel_for.h>
40 #include <tbb/task_scheduler_init.h>
48 template <
typename BasisFunctionType,
typename KernelType,
typename ResultType>
49 class EvaluationLoopBody
52 typedef typename ScalarTraits<ResultType>::RealType CoordinateType;
56 const arma::Mat<CoordinateType>& points,
57 const GeometricalData<CoordinateType>& trialGeomData,
58 const CollectionOf2dArrays<ResultType>& trialTransfValues,
59 const std::vector<CoordinateType>& weights,
60 const CollectionOfKernels<KernelType>& kernels,
61 const KernelTrialIntegral<BasisFunctionType, KernelType, ResultType>& integral,
62 arma::Mat<ResultType>& result) :
63 m_chunkSize(chunkSize),
64 m_points(points), m_trialGeomData(trialGeomData),
65 m_trialTransfValues(trialTransfValues), m_weights(weights),
66 m_kernels(kernels), m_integral(integral), m_result(result),
67 m_pointCount(result.n_cols), m_outputComponentCount(result.n_rows)
71 void operator() (
const tbb::blocked_range<size_t>& r)
const {
72 CollectionOf4dArrays<KernelType> kernelValues;
73 GeometricalData<CoordinateType> evalPointGeomData;
74 for (
size_t i = r.begin(); i < r.end(); ++i)
76 size_t start = m_chunkSize * i;
77 size_t end = std::min(start + m_chunkSize, m_pointCount);
78 evalPointGeomData.globals = m_points.cols(start, end - 1 );
79 m_kernels.
evaluateOnGrid(evalPointGeomData, m_trialGeomData, kernelValues);
81 _2dArray<ResultType> resultChunk(m_outputComponentCount, end - start,
82 m_result.colptr(start));
83 m_integral.evaluate(m_trialGeomData,
93 const arma::Mat<CoordinateType>& m_points;
94 const GeometricalData<CoordinateType>& m_trialGeomData;
95 const CollectionOf2dArrays<ResultType>& m_trialTransfValues;
96 const std::vector<CoordinateType>& m_weights;
97 const CollectionOfKernels<KernelType>& m_kernels;
98 const KernelTrialIntegral<BasisFunctionType, KernelType, ResultType>& m_integral;
99 arma::Mat<ResultType>& m_result;
101 size_t m_outputComponentCount;
106 template <
typename BasisFunctionType,
typename KernelType,
107 typename ResultType,
typename GeometryFactory>
108 DefaultEvaluatorForIntegralOperators<BasisFunctionType, KernelType,
109 ResultType, GeometryFactory>::DefaultEvaluatorForIntegralOperators(
110 const shared_ptr<const GeometryFactory>& geometryFactory,
111 const shared_ptr<
const RawGridGeometry<CoordinateType> >& rawGeometry,
112 const shared_ptr<
const std::vector<
const Shapeset<BasisFunctionType>*> >& trialShapesets,
113 const shared_ptr<
const CollectionOfKernels<KernelType> >& kernels,
114 const shared_ptr<
const CollectionOfShapesetTransformations<CoordinateType> >& trialTransformations,
115 const shared_ptr<
const KernelTrialIntegral<BasisFunctionType, KernelType, ResultType> >& integral,
116 const shared_ptr<
const std::vector<std::vector<ResultType> > >& argumentLocalCoefficients,
117 const shared_ptr<const OpenClHandler >& openClHandler,
118 const ParallelizationOptions& parallelizationOptions,
119 const shared_ptr<
const QuadratureDescriptorSelectorForPotentialOperators<
120 BasisFunctionType> >& quadDescSelector,
121 const shared_ptr<
const SingleQuadratureRuleFamily<
122 CoordinateType> >& quadRuleFamily) :
123 m_geometryFactory(geometryFactory), m_rawGeometry(rawGeometry),
124 m_trialShapesets(trialShapesets), m_kernels(kernels),
125 m_trialTransformations(trialTransformations), m_integral(integral),
126 m_argumentLocalCoefficients(argumentLocalCoefficients),
127 m_openClHandler(openClHandler),
128 m_parallelizationOptions(parallelizationOptions),
129 m_quadDescSelector(quadDescSelector),
130 m_quadRuleFamily(quadRuleFamily)
132 const size_t elementCount = rawGeometry->elementCount();
133 if (!rawGeometry->auxData().is_empty() &&
134 rawGeometry->auxData().n_cols != elementCount)
135 throw std::invalid_argument(
136 "DefaultEvaluatorForIntegralOperators::"
137 "DefaultEvaluatorForIntegralOperators(): "
138 "number of columns of auxData must match that of "
139 "elementCornerIndices");
140 if (trialShapesets->size() != elementCount)
141 throw std::invalid_argument(
142 "DefaultEvaluatorForIntegralOperators::"
143 "DefaultEvaluatorForIntegralOperators(): "
144 "size of testShapesetss must match the number of columns of "
145 "elementCornerIndices");
152 template <
typename BasisFunctionType,
typename KernelType,
153 typename ResultType,
typename GeometryFactory>
154 void DefaultEvaluatorForIntegralOperators<BasisFunctionType, KernelType,
155 ResultType, GeometryFactory>::evaluate(
157 const arma::Mat<CoordinateType>& points, arma::Mat<ResultType>& result)
const
159 const size_t pointCount = points.n_cols;
160 const int outputComponentCount = m_integral->resultDimension();
162 result.set_size(outputComponentCount, pointCount);
165 const GeometricalData<CoordinateType>& trialGeomData =
166 (region == EvaluatorForIntegralOperators<ResultType>::NEAR_FIELD) ?
167 m_nearFieldTrialGeomData :
168 m_farFieldTrialGeomData;
169 const CollectionOf2dArrays<ResultType>& trialTransfValues =
170 (region == EvaluatorForIntegralOperators<ResultType>::NEAR_FIELD) ?
171 m_nearFieldTrialTransfValues :
172 m_farFieldTrialTransfValues;
173 const std::vector<CoordinateType>& weights =
174 (region == EvaluatorForIntegralOperators<ResultType>::NEAR_FIELD) ?
183 const size_t kernelValuesSizePerEvalPoint =
184 trialGeomData.globals.n_cols *
sizeof(KernelType);
185 const size_t chunkSize =
186 std::max(
size_t(1), 10 * 1024 * 1024 / kernelValuesSizePerEvalPoint);
187 const size_t chunkCount = (pointCount + chunkSize - 1) / chunkSize;
189 int maxThreadCount = 1;
190 if (!m_parallelizationOptions.isOpenClEnabled()) {
191 if (m_parallelizationOptions.maxThreadCount() ==
192 ParallelizationOptions::AUTO)
193 maxThreadCount = tbb::task_scheduler_init::automatic;
195 maxThreadCount = m_parallelizationOptions.maxThreadCount();
197 tbb::task_scheduler_init scheduler(maxThreadCount);
198 typedef EvaluationLoopBody<
199 BasisFunctionType, KernelType, ResultType> Body;
202 tbb::parallel_for(tbb::blocked_range<size_t>(0, chunkCount),
204 points, trialGeomData, trialTransfValues, weights,
205 *m_kernels, *m_integral, result));
226 template <
typename BasisFunctionType,
typename KernelType,
227 typename ResultType,
typename GeometryFactory>
228 void DefaultEvaluatorForIntegralOperators<BasisFunctionType, KernelType,
229 ResultType, GeometryFactory>::cacheTrialData()
231 size_t testGeomDeps = 0, trialGeomDeps = 0;
233 if (testGeomDeps != 0 && testGeomDeps != GLOBALS)
234 throw std::runtime_error(
235 "DefaultEvaluatorForIntegralOperators::cacheTrialData(): "
236 "potentials cannot contain kernels that depend on other test data "
237 "than global coordinates");
239 calcTrialData(EvaluatorForIntegralOperators<ResultType>::FAR_FIELD,
240 trialGeomDeps, m_farFieldTrialGeomData,
241 m_farFieldTrialTransfValues, m_farFieldWeights);
243 calcTrialData(EvaluatorForIntegralOperators<ResultType>::FAR_FIELD,
244 trialGeomDeps, m_nearFieldTrialGeomData,
245 m_nearFieldTrialTransfValues, m_nearFieldWeights);
248 template <
typename BasisFunctionType,
typename KernelType,
249 typename ResultType,
typename GeometryFactory>
250 void DefaultEvaluatorForIntegralOperators<BasisFunctionType, KernelType,
251 ResultType, GeometryFactory>::calcTrialData(
253 int kernelTrialGeomDeps,
254 GeometricalData<CoordinateType>& trialGeomData,
255 CollectionOf2dArrays<ResultType>& trialTransfValues,
256 std::vector<CoordinateType>& weights)
const
258 if (region != EvaluatorForIntegralOperators<ResultType>::FAR_FIELD)
259 throw std::invalid_argument(
260 "DefaultEvaluatorForIntegralOperators::calcTrialData(): "
261 "currently region must be set to FAR_FIELD");
263 const int elementCount = m_rawGeometry->elementCount();
264 const int worldDim = m_rawGeometry->worldDimension();
265 const int gridDim = m_rawGeometry->gridDimension();
266 const int transformationCount = m_trialTransformations->transformationCount();
269 size_t basisDeps = 0;
272 size_t trialGeomDeps = kernelTrialGeomDeps;
273 m_trialTransformations->addDependencies(basisDeps, trialGeomDeps);
274 trialGeomDeps |= INTEGRATION_ELEMENTS;
277 typedef typename GeometryFactory::Geometry Geometry;
278 std::auto_ptr<Geometry> geometry(m_geometryFactory->make());
282 typedef std::set<const Shapeset<BasisFunctionType>*> ShapesetSet;
283 ShapesetSet uniqueTrialShapesets(m_trialShapesets->begin(), m_trialShapesets->end());
286 std::vector<GeometricalData<CoordinateType> > geomDataPerElement(elementCount);
287 std::vector<CollectionOf2dArrays<ResultType> >
288 trialTransfValuesPerElement(elementCount);
289 std::vector<std::vector<CoordinateType> > weightsPerElement(elementCount);
291 int quadPointCount = 0;
293 for (
typename ShapesetSet::const_iterator it = uniqueTrialShapesets.begin();
294 it != uniqueTrialShapesets.end(); ++it)
296 const Shapeset<BasisFunctionType>& activeShapeset = *(*it);
299 int elementCornerCount = 0;
300 for (
int e = 0; e < elementCount; ++e)
301 if ((*m_trialShapesets)[e] == &activeShapeset)
306 const arma::Mat<int>& elementCornerIndices =
307 m_rawGeometry->elementCornerIndices();
308 for (
size_t i = 0; i < elementCornerIndices.n_rows; ++i)
309 if (elementCornerIndices(i, e) >= 0)
310 elementCornerCount = i + 1;
318 SingleQuadratureDescriptor desc =
319 m_quadDescSelector->farFieldQuadratureDescriptor(
320 activeShapeset, elementCornerCount);
321 arma::Mat<CoordinateType> localQuadPoints;
322 std::vector<CoordinateType> quadWeights;
323 m_quadRuleFamily->fillQuadraturePointsAndWeights(
324 desc, localQuadPoints, quadWeights);
327 BasisData<BasisFunctionType> basisData;
328 activeShapeset.evaluate(basisDeps, localQuadPoints, ALL_DOFS, basisData);
330 BasisData<ResultType> argumentData;
331 if (basisDeps & VALUES)
332 argumentData.values.set_size(basisData.values.extent(0),
334 basisData.values.extent(2));
335 if (basisDeps & DERIVATIVES)
336 argumentData.derivatives.set_size(basisData.derivatives.extent(0),
337 basisData.derivatives.extent(1),
339 basisData.derivatives.extent(3));
342 CollectionOf3dArrays<ResultType> trialValues;
343 for (
int e = 0; e < elementCount; ++e)
345 if ((*m_trialShapesets)[e] != &activeShapeset)
349 const std::vector<ResultType>& localCoefficients =
350 (*m_argumentLocalCoefficients)[e];
354 if (basisDeps & VALUES)
356 std::fill(argumentData.values.begin(),
357 argumentData.values.end(), 0.);
358 assert(localCoefficients.size() == basisData.values.extent(1));
359 for (
size_t point = 0; point < basisData.values.extent(2); ++point)
360 for (
size_t dim = 0; dim < basisData.values.extent(0); ++dim)
361 for (
size_t fun = 0; fun < basisData.values.extent(1); ++fun)
362 argumentData.values(dim, 0, point) +=
363 basisData.values(dim, fun, point) *
364 localCoefficients[fun];
366 if (basisDeps & DERIVATIVES)
368 std::fill(argumentData.derivatives.begin(),
369 argumentData.derivatives.end(), 0.);
370 assert(localCoefficients.size() == basisData.derivatives.extent(2));
371 for (
size_t point = 0; point < basisData.derivatives.extent(3); ++point)
372 for (
size_t dim = 0; dim < basisData.derivatives.extent(1); ++dim)
373 for (
size_t comp = 0; comp < basisData.derivatives.extent(0); ++comp)
374 for (
size_t fun = 0; fun < basisData.derivatives.extent(2); ++fun)
375 argumentData.derivatives(comp, dim, 0, point) +=
376 basisData.derivatives(comp, dim, fun, point) *
377 localCoefficients[fun];
381 m_rawGeometry->setupGeometry(e, *geometry);
382 geometry->getData(trialGeomDeps, localQuadPoints,
383 geomDataPerElement[e]);
385 m_trialTransformations->evaluate(argumentData, geomDataPerElement[e],
403 const size_t localQuadPointCount = quadWeights.size();
405 trialTransfValuesPerElement[e].set_size(transformationCount);
406 for (
int transf = 0; transf < transformationCount; ++transf)
408 const size_t dimCount = trialValues[transf].extent(0);
409 assert(trialValues[transf].extent(2) == localQuadPointCount);
410 trialTransfValuesPerElement[e][transf].set_size(
411 dimCount, localQuadPointCount);
412 for (
size_t point = 0; point < localQuadPointCount; ++point)
413 for (
size_t dim = 0; dim < dimCount; ++dim)
414 trialTransfValuesPerElement[e][transf](dim, point) =
415 trialValues[transf](dim, 0, point);
418 weightsPerElement[e].resize(localQuadPointCount);
419 for (
size_t point = 0; point < localQuadPointCount; ++point)
420 weightsPerElement[e][point] = quadWeights[point] *
421 geomDataPerElement[e].integrationElements(point);
423 quadPointCount += quadWeights.size();
434 if (kernelTrialGeomDeps & GLOBALS)
435 trialGeomData.globals.set_size(worldDim, quadPointCount);
436 if (kernelTrialGeomDeps & INTEGRATION_ELEMENTS)
437 trialGeomData.integrationElements.set_size(quadPointCount);
438 if (kernelTrialGeomDeps & NORMALS)
439 trialGeomData.normals.set_size(worldDim, quadPointCount);
440 if (kernelTrialGeomDeps & JACOBIANS_TRANSPOSED)
441 trialGeomData.jacobiansTransposed.set_size(gridDim, worldDim, quadPointCount);
442 if (kernelTrialGeomDeps & JACOBIAN_INVERSES_TRANSPOSED)
443 trialGeomData.jacobianInversesTransposed.set_size(worldDim, gridDim, quadPointCount);
448 trialTransfValues.set_size(transformationCount);
449 for (
int transf = 0; transf < transformationCount; ++transf)
450 trialTransfValues[transf].set_size(
451 m_trialTransformations->resultDimension(transf), quadPointCount);
452 weights.resize(quadPointCount);
454 for (
int e = 0, startCol = 0;
456 startCol += trialTransfValuesPerElement[e][0].extent(1), ++e)
458 int endCol = startCol + trialTransfValuesPerElement[e][0].extent(1) - 1;
459 if (kernelTrialGeomDeps & GLOBALS)
460 trialGeomData.globals.cols(startCol, endCol) =
461 geomDataPerElement[e].globals;
462 if (kernelTrialGeomDeps & INTEGRATION_ELEMENTS)
463 trialGeomData.integrationElements.cols(startCol, endCol) =
464 geomDataPerElement[e].integrationElements;
465 if (kernelTrialGeomDeps & NORMALS)
466 trialGeomData.normals.cols(startCol, endCol) =
467 geomDataPerElement[e].normals;
468 if (kernelTrialGeomDeps & JACOBIANS_TRANSPOSED) {
470 trialGeomData.jacobiansTransposed.extent(0);
472 trialGeomData.jacobiansTransposed.extent(1);
473 for (
int col = startCol; col <= endCol; ++col)
474 for (
int c = 0; c < n; ++c)
475 for (
int r = 0; r < n; ++r)
476 trialGeomData.jacobiansTransposed(r, c, col) =
477 geomDataPerElement[e].jacobiansTransposed(
478 r, c, col - startCol);
480 if (kernelTrialGeomDeps & JACOBIAN_INVERSES_TRANSPOSED) {
482 trialGeomData.jacobianInversesTransposed.extent(0);
484 trialGeomData.jacobianInversesTransposed.extent(1);
485 for (
int col = startCol; col <= endCol; ++col)
486 for (
int c = 0; c < n; ++c)
487 for (
int r = 0; r < n; ++r)
488 trialGeomData.jacobianInversesTransposed(r, c, col) =
489 geomDataPerElement[e].jacobianInversesTransposed(
490 r, c, col - startCol);
492 for (
int transf = 0; transf < transformationCount; ++transf)
493 for (
size_t point = 0; point < trialTransfValuesPerElement[e][transf].extent(1); ++point)
494 for (
size_t dim = 0; dim < trialTransfValuesPerElement[e][transf].extent(0); ++dim)
495 trialTransfValues[transf](dim, startCol + point) =
496 trialTransfValuesPerElement[e][transf](dim, point);
497 for (
size_t point = 0; point < trialTransfValuesPerElement[e][0].extent(1); ++point)
498 weights[startCol + point] = weightsPerElement[e][point];
virtual void addGeometricalDependencies(size_t &testGeomDeps, size_t &trialGeomDeps) const =0
Retrieve types of geometrical data on which the kernels depend.
Management of the number of threads used by BLAS and LAPACK.
Definition: serial_blas_region.hpp:30
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.