21 #include "../common/common.hpp"
23 #include "bempp/common/config_opencl.hpp"
25 #include "separable_numerical_test_kernel_trial_integrator.hpp"
27 #include "_2d_array.hpp"
28 #include "_3d_array.hpp"
29 #include "_4d_array.hpp"
31 #include "shapeset.hpp"
32 #include "basis_data.hpp"
33 #include "conjugate.hpp"
34 #include "collection_of_shapeset_transformations.hpp"
35 #include "geometrical_data.hpp"
36 #include "collection_of_kernels.hpp"
37 #include "opencl_handler.hpp"
38 #include "raw_grid_geometry.hpp"
39 #include "test_kernel_trial_integral.hpp"
41 #include "CL/separable_numerical_double_integrator.cl.str"
43 #include "../common/auto_timer.hpp"
51 template <
typename BasisFunctionType,
typename KernelType,
52 typename ResultType,
typename GeometryFactory>
53 SeparableNumericalTestKernelTrialIntegrator<
54 BasisFunctionType, KernelType, ResultType, GeometryFactory>::
55 SeparableNumericalTestKernelTrialIntegrator(
56 const arma::Mat<CoordinateType>& localTestQuadPoints,
57 const arma::Mat<CoordinateType>& localTrialQuadPoints,
58 const std::vector<CoordinateType>& testQuadWeights,
59 const std::vector<CoordinateType>& trialQuadWeights,
60 const GeometryFactory& testGeometryFactory,
61 const GeometryFactory& trialGeometryFactory,
62 const RawGridGeometry<CoordinateType>& testRawGeometry,
63 const RawGridGeometry<CoordinateType>& trialRawGeometry,
64 const CollectionOfShapesetTransformations<CoordinateType>& testTransformations,
65 const CollectionOfKernels<KernelType>& kernels,
66 const CollectionOfShapesetTransformations<CoordinateType>& trialTransformations,
67 const TestKernelTrialIntegral<BasisFunctionType, KernelType, ResultType>& integral,
68 const OpenClHandler& openClHandler,
69 bool cacheGeometricalData) :
70 m_localTestQuadPoints(localTestQuadPoints),
71 m_localTrialQuadPoints(localTrialQuadPoints),
72 m_testQuadWeights(testQuadWeights),
73 m_trialQuadWeights(trialQuadWeights),
74 m_testGeometryFactory(testGeometryFactory),
75 m_trialGeometryFactory(trialGeometryFactory),
76 m_testRawGeometry(testRawGeometry),
77 m_trialRawGeometry(trialRawGeometry),
78 m_testTransformations(testTransformations),
80 m_trialTransformations(trialTransformations),
82 m_openClHandler(openClHandler),
83 m_cacheGeometricalData(cacheGeometricalData)
85 if (localTestQuadPoints.n_cols != testQuadWeights.size())
86 throw std::invalid_argument(
"SeparableNumericalTestKernelTrialIntegrator::"
87 "SeparableNumericalTestKernelTrialIntegrator(): "
88 "numbers of test points and weights do not match");
89 if (localTrialQuadPoints.n_cols != trialQuadWeights.size())
90 throw std::invalid_argument(
"SeparableNumericalTestKernelTrialIntegrator::"
91 "SeparableNumericalTestKernelTrialIntegrator(): "
92 "numbers of trial points and weights do not match");
95 if (openClHandler.UseOpenCl()) {
97 clTestQuadPoints = openClHandler.pushMatrix<CoordinateType> (localTestQuadPoints);
98 clTrialQuadPoints = openClHandler.pushMatrix<CoordinateType> (localTrialQuadPoints);
99 clTestQuadWeights = openClHandler.pushVector<CoordinateType> (testQuadWeights);
100 clTrialQuadWeights = openClHandler.pushVector<CoordinateType> (trialQuadWeights);
104 if (cacheGeometricalData)
105 precalculateGeometricalData();
108 template <
typename BasisFunctionType,
typename KernelType,
109 typename ResultType,
typename GeometryFactory>
110 SeparableNumericalTestKernelTrialIntegrator<
111 BasisFunctionType, KernelType, ResultType, GeometryFactory>::
112 ~SeparableNumericalTestKernelTrialIntegrator()
115 if (m_openClHandler.UseOpenCl()) {
116 delete clTestQuadPoints;
117 delete clTrialQuadPoints;
118 delete clTestQuadWeights;
119 delete clTrialQuadWeights;
124 template <
typename BasisFunctionType,
typename KernelType,
125 typename ResultType,
typename GeometryFactory>
126 void SeparableNumericalTestKernelTrialIntegrator<
127 BasisFunctionType, KernelType, ResultType, GeometryFactory>::
128 precalculateGeometricalData()
130 size_t testBasisDeps = 0, trialBasisDeps = 0;
131 size_t testGeomDeps = 0, trialGeomDeps = 0;
133 m_testTransformations.addDependencies(testBasisDeps, testGeomDeps);
134 m_trialTransformations.addDependencies(trialBasisDeps, trialGeomDeps);
136 m_integral.addGeometricalDependencies(testGeomDeps, trialGeomDeps);
138 precalculateGeometricalDataOnSingleGrid(
139 m_localTestQuadPoints, m_testGeometryFactory,
140 m_testRawGeometry, testGeomDeps, m_cachedTestGeomData);
141 precalculateGeometricalDataOnSingleGrid(
142 m_localTrialQuadPoints, m_trialGeometryFactory,
143 m_trialRawGeometry, trialGeomDeps, m_cachedTrialGeomData);
146 template <
typename BasisFunctionType,
typename KernelType,
147 typename ResultType,
typename GeometryFactory>
148 void SeparableNumericalTestKernelTrialIntegrator<
149 BasisFunctionType, KernelType, ResultType, GeometryFactory>::
150 precalculateGeometricalDataOnSingleGrid(
151 const arma::Mat<CoordinateType>& localQuadPoints,
152 const GeometryFactory& geometryFactory,
153 const RawGridGeometry<CoordinateType>& rawGeometry,
155 std::vector<GeometricalData<CoordinateType> >& geomData)
157 geomData.resize(rawGeometry.elementCount());
159 typedef typename GeometryFactory::Geometry Geometry;
160 std::auto_ptr<Geometry> geometry = geometryFactory.make();
161 for (
size_t e = 0; e < rawGeometry.elementCount(); ++e) {
162 rawGeometry.setupGeometry(e, *geometry);
163 geometry->getData(geomDeps, localQuadPoints, geomData[e]);
167 template <
typename BasisFunctionType,
typename KernelType,
168 typename ResultType,
typename GeometryFactory>
169 void SeparableNumericalTestKernelTrialIntegrator<
170 BasisFunctionType, KernelType, ResultType, GeometryFactory>::
172 CallVariant callVariant,
173 const std::vector<int>& elementIndicesA,
175 const Shapeset<BasisFunctionType>& basisA,
176 const Shapeset<BasisFunctionType>& basisB,
177 LocalDofIndex localDofIndexB,
178 const std::vector<arma::Mat<ResultType>*>& result)
const
180 if (m_openClHandler.UseOpenCl())
182 integrateCl (callVariant, elementIndicesA, elementIndexB, basisA, basisB,
183 localDofIndexB, result);
187 integrateCpu (callVariant, elementIndicesA, elementIndexB, basisA, basisB,
188 localDofIndexB, result);
192 template <
typename BasisFunctionType,
typename KernelType,
193 typename ResultType,
typename GeometryFactory>
194 void SeparableNumericalTestKernelTrialIntegrator<
195 BasisFunctionType, KernelType, ResultType, GeometryFactory>::
197 CallVariant callVariant,
198 const std::vector<int>& elementIndicesA,
200 const Shapeset<BasisFunctionType>& basisA,
201 const Shapeset<BasisFunctionType>& basisB,
202 LocalDofIndex localDofIndexB,
203 const std::vector<arma::Mat<ResultType>*>& result)
const
205 const int testPointCount = m_localTestQuadPoints.n_cols;
206 const int trialPointCount = m_localTrialQuadPoints.n_cols;
207 const int elementACount = elementIndicesA.size();
209 if (result.size() != elementIndicesA.size())
210 throw std::invalid_argument(
211 "SeparableNumericalTestKernelTrialIntegrator::integrate(): "
212 "arrays 'result' and 'elementIndicesA' must have the same number "
214 if (testPointCount == 0 || trialPointCount == 0 || elementACount == 0)
221 const int dofCountA = basisA.size();
222 const int dofCountB = localDofIndexB == ALL_DOFS ? basisB.size() : 1;
223 const int testDofCount = callVariant == TEST_TRIAL ? dofCountA : dofCountB;
224 const int trialDofCount = callVariant == TEST_TRIAL ? dofCountB : dofCountA;
226 BasisData<BasisFunctionType> testBasisData, trialBasisData;
227 GeometricalData<CoordinateType>* testGeomData = &m_testGeomData.local();
228 GeometricalData<CoordinateType>* trialGeomData = &m_trialGeomData.local();
229 const GeometricalData<CoordinateType>* constTestGeomData = testGeomData;
230 const GeometricalData<CoordinateType>* constTrialGeomData = trialGeomData;
232 size_t testBasisDeps = 0, trialBasisDeps = 0;
233 size_t testGeomDeps = 0, trialGeomDeps = 0;
235 m_testTransformations.addDependencies(testBasisDeps, testGeomDeps);
236 m_trialTransformations.addDependencies(trialBasisDeps, trialGeomDeps);
238 m_integral.addGeometricalDependencies(testGeomDeps, trialGeomDeps);
240 typedef typename GeometryFactory::Geometry Geometry;
241 std::auto_ptr<Geometry> geometryA, geometryB;
242 const RawGridGeometry<CoordinateType> *rawGeometryA = 0, *rawGeometryB = 0;
243 if (!m_cacheGeometricalData) {
244 if (callVariant == TEST_TRIAL)
246 geometryA = m_testGeometryFactory.make();
247 geometryB = m_trialGeometryFactory.make();
248 rawGeometryA = &m_testRawGeometry;
249 rawGeometryB = &m_trialRawGeometry;
253 geometryA = m_trialGeometryFactory.make();
254 geometryB = m_testGeometryFactory.make();
255 rawGeometryA = &m_trialRawGeometry;
256 rawGeometryB = &m_testRawGeometry;
260 CollectionOf3dArrays<BasisFunctionType> testValues, trialValues;
261 CollectionOf4dArrays<KernelType> kernelValues;
263 for (
size_t i = 0; i < result.size(); ++i) {
265 result[i]->set_size(testDofCount, trialDofCount);
268 if (!m_cacheGeometricalData)
269 rawGeometryB->setupGeometry(elementIndexB, *geometryB);
270 if (callVariant == TEST_TRIAL)
272 basisA.evaluate(testBasisDeps, m_localTestQuadPoints, ALL_DOFS, testBasisData);
273 basisB.evaluate(trialBasisDeps, m_localTrialQuadPoints, localDofIndexB, trialBasisData);
274 if (m_cacheGeometricalData)
275 constTrialGeomData = &m_cachedTrialGeomData[elementIndexB];
277 geometryB->getData(trialGeomDeps, m_localTrialQuadPoints, *trialGeomData);
278 m_trialTransformations.evaluate(trialBasisData, *constTrialGeomData, trialValues);
282 basisA.evaluate(trialBasisDeps, m_localTrialQuadPoints, ALL_DOFS, trialBasisData);
283 basisB.evaluate(testBasisDeps, m_localTestQuadPoints, localDofIndexB, testBasisData);
284 if (m_cacheGeometricalData)
285 constTestGeomData = &m_cachedTestGeomData[elementIndexB];
287 geometryB->getData(testGeomDeps, m_localTestQuadPoints, *testGeomData);
288 m_testTransformations.evaluate(testBasisData, *constTestGeomData, testValues);
292 for (
int indexA = 0; indexA < elementACount; ++indexA)
294 if (!m_cacheGeometricalData)
295 rawGeometryA->setupGeometry(elementIndicesA[indexA], *geometryA);
296 if (callVariant == TEST_TRIAL)
298 if (m_cacheGeometricalData)
299 constTestGeomData = &m_cachedTestGeomData[elementIndicesA[indexA]];
301 geometryA->getData(testGeomDeps, m_localTestQuadPoints, *testGeomData);
302 m_testTransformations.evaluate(testBasisData, *constTestGeomData, testValues);
306 if (m_cacheGeometricalData)
307 constTrialGeomData = &m_cachedTrialGeomData[elementIndicesA[indexA]];
309 geometryA->getData(trialGeomDeps, m_localTrialQuadPoints, *trialGeomData);
310 m_trialTransformations.evaluate(trialBasisData, *constTrialGeomData, trialValues);
313 m_kernels.
evaluateOnGrid(*constTestGeomData, *constTrialGeomData, kernelValues);
314 m_integral.evaluateWithTensorQuadratureRule(
315 *constTestGeomData, *constTrialGeomData, testValues, trialValues,
316 kernelValues, m_testQuadWeights, m_trialQuadWeights,
321 template <
typename BasisFunctionType,
typename KernelType,
322 typename ResultType,
typename GeometryFactory>
324 SeparableNumericalTestKernelTrialIntegrator<
325 BasisFunctionType, KernelType, ResultType, GeometryFactory>::
327 CallVariant callVariant,
328 const std::vector<int>& elementIndicesA,
330 const Shapeset<BasisFunctionType>& basisA,
331 const Shapeset<BasisFunctionType>& basisB,
332 LocalDofIndex localDofIndexB,
333 const std::vector<arma::Mat<ResultType>*>& result)
const
652 template <
typename BasisFunctionType,
typename KernelType,
653 typename ResultType,
typename GeometryFactory>
655 SeparableNumericalTestKernelTrialIntegrator<
656 BasisFunctionType, KernelType, ResultType, GeometryFactory>::
657 integrate(
const std::vector<ElementIndexPair>& elementIndexPairs,
658 const Shapeset<BasisFunctionType>& testShapeset,
659 const Shapeset<BasisFunctionType>& trialShapeset,
660 const std::vector<arma::Mat<ResultType>*>& result)
const
662 if (m_openClHandler.UseOpenCl())
664 integrateCl (elementIndexPairs, testShapeset, trialShapeset, result);
668 integrateCpu (elementIndexPairs, testShapeset, trialShapeset, result);
672 template <
typename BasisFunctionType,
typename KernelType,
673 typename ResultType,
typename GeometryFactory>
675 SeparableNumericalTestKernelTrialIntegrator<
676 BasisFunctionType, KernelType, ResultType, GeometryFactory>::
678 const std::vector<ElementIndexPair>& elementIndexPairs,
679 const Shapeset<BasisFunctionType>& testShapeset,
680 const Shapeset<BasisFunctionType>& trialShapeset,
681 const std::vector<arma::Mat<ResultType>*>& result)
const
683 const int testPointCount = m_localTestQuadPoints.n_cols;
684 const int trialPointCount = m_localTrialQuadPoints.n_cols;
685 const int geometryPairCount = elementIndexPairs.size();
687 if (result.size() != elementIndexPairs.size())
688 throw std::invalid_argument(
689 "NonseparableNumericalTestKernelTrialIntegrator::integrate(): "
690 "arrays 'result' and 'elementIndicesA' must have the same number "
692 if (testPointCount == 0 || trialPointCount == 0 || geometryPairCount == 0)
699 const int testDofCount = testShapeset.size();
700 const int trialDofCount = trialShapeset.size();
702 BasisData<BasisFunctionType> testBasisData, trialBasisData;
703 GeometricalData<CoordinateType>* testGeomData = &m_testGeomData.local();
704 GeometricalData<CoordinateType>* trialGeomData = &m_trialGeomData.local();
705 const GeometricalData<CoordinateType>* constTestGeomData = testGeomData;
706 const GeometricalData<CoordinateType>* constTrialGeomData = trialGeomData;
708 size_t testBasisDeps = 0, trialBasisDeps = 0;
709 size_t testGeomDeps = 0, trialGeomDeps = 0;
711 m_testTransformations.addDependencies(testBasisDeps, testGeomDeps);
712 m_trialTransformations.addDependencies(trialBasisDeps, trialGeomDeps);
714 m_integral.addGeometricalDependencies(testGeomDeps, trialGeomDeps);
716 typedef typename GeometryFactory::Geometry Geometry;
717 std::auto_ptr<Geometry> testGeometry;
718 std::auto_ptr<Geometry> trialGeometry;
719 if (!m_cacheGeometricalData) {
720 testGeometry = m_testGeometryFactory.make();
721 trialGeometry = m_trialGeometryFactory.make();
724 CollectionOf3dArrays<BasisFunctionType> testValues, trialValues;
725 CollectionOf4dArrays<KernelType> kernelValues;
727 for (
size_t i = 0; i < result.size(); ++i) {
729 result[i]->set_size(testDofCount, trialDofCount);
732 testShapeset.evaluate(testBasisDeps, m_localTestQuadPoints, ALL_DOFS, testBasisData);
733 trialShapeset.evaluate(trialBasisDeps, m_localTrialQuadPoints, ALL_DOFS, trialBasisData);
736 for (
int pairIndex = 0; pairIndex < geometryPairCount; ++pairIndex)
738 if (m_cacheGeometricalData) {
739 constTestGeomData = &m_cachedTestGeomData[elementIndexPairs[pairIndex].first];
740 constTrialGeomData = &m_cachedTrialGeomData[elementIndexPairs[pairIndex].second];
742 m_testRawGeometry.setupGeometry(elementIndexPairs[pairIndex].first, *testGeometry);
743 m_trialRawGeometry.setupGeometry(elementIndexPairs[pairIndex].second, *trialGeometry);
744 testGeometry->getData(testGeomDeps, m_localTestQuadPoints, *testGeomData);
745 trialGeometry->getData(trialGeomDeps, m_localTrialQuadPoints, *trialGeomData);
747 m_testTransformations.evaluate(testBasisData, *constTestGeomData, testValues);
748 m_trialTransformations.evaluate(trialBasisData, *constTrialGeomData, trialValues);
750 m_kernels.
evaluateOnGrid(*constTestGeomData, *constTrialGeomData, kernelValues);
751 m_integral.evaluateWithTensorQuadratureRule(
752 *constTestGeomData, *constTrialGeomData, testValues, trialValues,
753 kernelValues, m_testQuadWeights, m_trialQuadWeights,
759 template <
typename BasisFunctionType,
typename KernelType,
760 typename ResultType,
typename GeometryFactory>
761 void SeparableNumericalTestKernelTrialIntegrator<
762 BasisFunctionType, KernelType, ResultType, GeometryFactory>::
764 const std::vector<ElementIndexPair>& elementIndexPairs,
765 const Shapeset<BasisFunctionType>& testShapeset,
766 const Shapeset<BasisFunctionType>& trialShapeset,
767 const std::vector<arma::Mat<ResultType>*>& result)
const
958 template <
typename BasisFunctionType,
typename KernelType,
959 typename ResultType,
typename GeometryFactory>
960 const std::pair<const char*,int>
961 SeparableNumericalTestKernelTrialIntegrator<
962 BasisFunctionType, KernelType, ResultType, GeometryFactory>::
963 clStrIntegrateRowOrCol ()
const
965 return std::make_pair (separable_numerical_double_integrator_cl,
966 separable_numerical_double_integrator_cl_len);
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.