Nektar++
Loading...
Searching...
No Matches
PhysInterp1DScaled.cpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: PhysInterp1DScaled.cpp
4//
5// For more information, please see: http://www.nektar.info
6//
7// The MIT License
8//
9// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10// Department of Aeronautics, Imperial College London (UK), and Scientific
11// Computing and Imaging Institute, University of Utah (USA).
12//
13// Permission is hereby granted, free of charge, to any person obtaining a
14// copy of this software and associated documentation files (the "Software"),
15// to deal in the Software without restriction, including without limitation
16// the rights to use, copy, modify, merge, publish, distribute, sublicense,
17// and/or sell copies of the Software, and to permit persons to whom the
18// Software is furnished to do so, subject to the following conditions:
19//
20// The above copyright notice and this permission notice shall be included
21// in all copies or substantial portions of the Software.
22//
23// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29// DEALINGS IN THE SOFTWARE.
30//
31// Description: PhysInterp1DScaled operator implementations
32//
33///////////////////////////////////////////////////////////////////////////////
34
40#include <MatrixFreeOps/Operator.hpp>
41
42using namespace std;
43
44namespace Nektar::Collections
45{
46
54
55/**
56 * @brief PhysInterp1DScaled help class to calculate the size of the collection
57 * that is given as an input and as an output to the PhysInterp1DScaled
58 * Operator. The size evaluation takes into account that both the input and the
59 * output array belong to the physical space and that the output array can have
60 * either a larger, or a smaller size than the input array
61 */
62class PhysInterp1DScaled_Helper : virtual public Operator
63{
64public:
65 void UpdateFactors(StdRegions::FactorMap factors) override
66 {
67 if (factors == m_factors)
68 {
69 return;
70 }
71 m_factors = factors;
72 // Set scaling factor for the PhysInterp1DScaled function
73 [[maybe_unused]] auto x = factors.find(StdRegions::eFactorConst);
75 x != factors.end(),
76 "Constant factor not defined: " +
77 std::string(
79
81
82 int shape_dimension = m_stdExp->GetShapeDimension();
83 m_outputSize = m_numElmt; // initializing m_outputSize
84 int npt0 = m_stdExp->GetNumPoints(0);
85
86 for (int i = 0; i < shape_dimension; ++i)
87 {
88 int npt = m_stdExp->GetNumPoints(i);
89 m_outputSize *= (npt0 - npt == 1) ? (int)(npt0 * scale - 1)
90 : (int)(npt * scale);
91 }
92 }
93
94protected:
96 {
97 NekDouble scale; // declaration of the scaling factor to be used for the
98 // output size
100 {
102 }
103 else
104 {
105 scale = 1.5;
106 }
107 // expect input to be number of elements by the number of quad points
108 m_inputSize = m_numElmt * m_stdExp->GetTotPoints();
109 // expect input to be number of elements by the number of quad points
110 int shape_dimension = m_stdExp->GetShapeDimension();
111 m_outputSize = m_numElmt; // initializing m_outputSize
112 int npt0 = m_stdExp->GetNumPoints(0);
113 for (int i = 0; i < shape_dimension; ++i)
114 {
115 int npt = m_stdExp->GetNumPoints(i);
116 m_outputSize *= (npt0 - npt == 1) ? (int)(npt0 * scale - 1)
117 : (int)(npt * scale);
118 }
119 }
120
122 m_factors; // map for storing the scaling factor of the operator
123};
124
125/**
126 * @brief PhysInterp1DScaled operator using matrix free implementation.
127 */
128class PhysInterp1DScaled_MatrixFree final : virtual public Operator,
131{
132public:
134
136
137 void operator()(const Array<OneD, const NekDouble> &input,
138 Array<OneD, NekDouble> &output0,
139 [[maybe_unused]] Array<OneD, NekDouble> &output1,
140 [[maybe_unused]] Array<OneD, NekDouble> &output2,
141 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
142 {
143 (*m_oper)(input, output0);
144 }
145
146 void operator()([[maybe_unused]] int dir,
147 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
148 [[maybe_unused]] Array<OneD, NekDouble> &output,
149 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
150 {
152 "PhysInterp1DScaled_MatrixFree: Not valid for this operator.");
153 }
154
155 void UpdateFactors([[maybe_unused]] StdRegions::FactorMap factors) override
156 {
157
158 // Set lambda for this call
159 auto x = factors.find(StdRegions::eFactorConst);
160 ASSERTL1(
161 x != factors.end(),
162 "Constant factor not defined: " +
163 std::string(
165 // Update the factors member inside PhysInterp1DScaled_MatrixFree
166 // class
167 m_factors = factors;
168
169 const auto dim = m_stdExp->GetShapeDimension();
170
171 // Definition of basis vector
172 std::vector<LibUtilities::BasisSharedPtr> basis(dim);
173 for (unsigned int i = 0; i < dim; ++i)
174 {
175 basis[i] = m_stdExp->GetBasis(i);
176 }
177
178 // Update the scaling factor inside MatrixFreeOps using the SetLamda
179 // routine
180 m_oper->SetScalingFactor(x->second);
181 m_oper->SetUpInterp1D(basis, m_factors[StdRegions::eFactorConst]);
183 }
184
185private:
186 std::shared_ptr<MatrixFree::PhysInterp1DScaled> m_oper;
187
189 vector<StdRegions::StdExpansionSharedPtr> pCollExp,
191 : Operator(pCollExp, pGeomData, factors),
192 MatrixFreeBase(pCollExp[0]->GetStdExp()->GetTotPoints(),
193 pCollExp[0]->GetStdExp()->GetTotPoints(),
194 pCollExp.size()),
196 {
197 const auto dim = pCollExp[0]->GetStdExp()->GetShapeDimension();
198
199 // Definition of basis vector
200 std::vector<LibUtilities::BasisSharedPtr> basis(dim);
201 for (unsigned int i = 0; i < dim; ++i)
202 {
203 basis[i] = pCollExp[0]->GetBasis(i);
204 }
205
206 // Get shape type
207 auto shapeType = pCollExp[0]->GetStdExp()->DetShapeType();
208
209 // Generate operator string and create operator.
210 std::string op_string = "PhysInterp1DScaled";
211 op_string += MatrixFree::GetOpstring(shapeType, false);
212 auto oper = MatrixFree::GetOperatorFactory().CreateInstance(
213 op_string, basis, pCollExp.size());
214
215 m_oper =
216 std::dynamic_pointer_cast<MatrixFree::PhysInterp1DScaled>(oper);
217 ASSERTL0(m_oper, "Failed to cast pointer.");
218
219 NekDouble scale; // declaration of the scaling factor to be used for the
220 // output size
221 if (factors[StdRegions::eFactorConst] != 0)
222 {
223 m_factors = factors;
225 }
226 else
227 {
228 scale = 1.5;
230 }
231 // Update the scaling factor inside MatrixFreeOps using the SetLamda
232 // routine
233 m_oper->SetScalingFactor(scale);
234 m_oper->SetUpInterp1D(basis, scale);
236 }
237};
238
239/// Factory initialisation for the PhysInterp1DScaled_MatrixFree operators
240OperatorKey PhysInterp1DScaled_MatrixFree::m_typeArr[] = {
243 PhysInterp1DScaled_MatrixFree::create,
244 "PhysInterp1DScaled_MatrixFree_Seg"),
246 OperatorKey(eTriangle, ePhysInterp1DScaled, eMatrixFree, false),
247 PhysInterp1DScaled_MatrixFree::create,
248 "PhysInterp1DScaled_MatrixFree_Tri"),
251 PhysInterp1DScaled_MatrixFree::create,
252 "PhysInterp1DScaled_MatrixFree_NodalTri"),
254 OperatorKey(eQuadrilateral, ePhysInterp1DScaled, eMatrixFree, false),
255 PhysInterp1DScaled_MatrixFree::create,
256 "PhysInterp1DScaled_MatrixFree_Quad"),
258 OperatorKey(eTetrahedron, ePhysInterp1DScaled, eMatrixFree, false),
259 PhysInterp1DScaled_MatrixFree::create,
260 "PhysInterp1DScaled_MatrixFree_Tet"),
262 OperatorKey(eTetrahedron, ePhysInterp1DScaled, eMatrixFree, true),
263 PhysInterp1DScaled_MatrixFree::create,
264 "PhysInterp1DScaled_MatrixFree_NodalTet"),
267 PhysInterp1DScaled_MatrixFree::create,
268 "PhysInterp1DScaled_MatrixFree_Pyr"),
271 PhysInterp1DScaled_MatrixFree::create,
272 "PhysInterp1DScaled_MatrixFree_Prism"),
275 PhysInterp1DScaled_MatrixFree::create,
276 "PhysInterp1DScaled_MatrixFree_NodalPrism"),
278 OperatorKey(eHexahedron, ePhysInterp1DScaled, eMatrixFree, false),
279 PhysInterp1DScaled_MatrixFree::create,
280 "PhysInterp1DScaled_NoCollection_Hex"),
281};
282
283/**
284 * @brief PhysInterp1DScaled operator using LocalRegions implementation.
285 */
286class PhysInterp1DScaled_NoCollection final : virtual public Operator,
288{
289public:
291
295
298 [[maybe_unused]] Array<OneD, NekDouble> &output1,
299 [[maybe_unused]] Array<OneD, NekDouble> &output2,
300 [[maybe_unused]] Array<OneD, NekDouble> &wsp) override
301 {
302 int cnt{0};
303 int cnt1{0};
305 int dim{m_expList[0]->GetShapeDimension()}; // same as m_expType
306 switch (dim)
307 {
308 case 1:
309 {
311 // the number of points before and after interpolation are the
312 // same for each element inside a single collection
313 int pt0 = m_expList[0]->GetNumPoints(0);
314 int npt0 = (int)(pt0 * scale);
315 // current points key - use first entry
316 LibUtilities::PointsKey PointsKey0(
317 pt0, m_expList[0]->GetPointsType(0));
318 // get new points key
319 LibUtilities::PointsKey newPointsKey0(
320 npt0, m_expList[0]->GetPointsType(0));
321 // Interpolate points;
322 I0 = LibUtilities::PointsManager()[PointsKey0]->GetI(
323 newPointsKey0);
324
325 for (int i = 0; i < m_numElmt; ++i)
326 {
327
328 Blas::Dgemv('N', npt0, pt0, 1.0, I0->GetPtr().data(), npt0,
329 &input[cnt], 1, 0.0, &output[cnt1], 1);
330 cnt += pt0;
331 cnt1 += npt0;
332 }
333 }
334 break;
335 case 2:
336 {
337 DNekMatSharedPtr I0, I1;
338 // the number of points before and after interpolation are
339 // the same for each element inside a single collection
340 int pt0 = m_expList[0]->GetNumPoints(0);
341 int pt1 = m_expList[0]->GetNumPoints(1);
342 int npt0 = (int)(pt0 * scale);
343 int npt1 = (pt0 - pt1 == 1) ? (int)(pt0 * scale - 1)
344 : (int)(pt1 * scale);
345 // workspace declaration
346 Array<OneD, NekDouble> wsp(npt1 * pt0); // fnp0*tnp1
347
348 // current points key - using first entry
349 LibUtilities::PointsKey PointsKey0(
350 pt0, m_expList[0]->GetPointsType(0));
351 LibUtilities::PointsKey PointsKey1(
352 pt1, m_expList[0]->GetPointsType(1));
353 // get new points key
354 LibUtilities::PointsKey newPointsKey0(
355 npt0, m_expList[0]->GetPointsType(0));
356 LibUtilities::PointsKey newPointsKey1(
357 npt1, m_expList[0]->GetPointsType(1));
358
359 // Interpolate points;
360 I0 = LibUtilities::PointsManager()[PointsKey0]->GetI(
361 newPointsKey0);
362 I1 = LibUtilities::PointsManager()[PointsKey1]->GetI(
363 newPointsKey1);
364
365 for (int i = 0; i < m_numElmt; ++i)
366 {
367 Blas::Dgemm('N', 'T', pt0, npt1, pt1, 1.0, &input[cnt], pt0,
368 I1->GetPtr().data(), npt1, 0.0, wsp.data(),
369 pt0);
370
371 Blas::Dgemm('N', 'N', npt0, npt1, pt0, 1.0,
372 I0->GetPtr().data(), npt0, wsp.data(), pt0, 0.0,
373 &output[cnt1], npt0);
374
375 cnt += pt0 * pt1;
376 cnt1 += npt0 * npt1;
377 }
378 }
379 break;
380 case 3:
381 {
382 DNekMatSharedPtr I0, I1, I2;
383
384 int pt0 = m_expList[0]->GetNumPoints(0);
385 int pt1 = m_expList[0]->GetNumPoints(1);
386 int pt2 = m_expList[0]->GetNumPoints(2);
387 int npt0 = (int)(pt0 * scale);
388 int npt1 = (pt0 - pt1 == 1) ? (int)(pt0 * scale - 1)
389 : (int)(pt1 * scale);
390 int npt2 = (pt0 - pt2 == 1) ? (int)(pt0 * scale - 1)
391 : (int)(pt2 * scale);
392 Array<OneD, NekDouble> wsp1(npt0 * npt1 * pt2);
393 Array<OneD, NekDouble> wsp2(npt0 * pt1 * pt2);
394
395 // current points key
396 LibUtilities::PointsKey PointsKey0(
397 pt0, m_expList[0]->GetPointsType(0));
398 LibUtilities::PointsKey PointsKey1(
399 pt1, m_expList[0]->GetPointsType(1));
400 LibUtilities::PointsKey PointsKey2(
401 pt2, m_expList[0]->GetPointsType(2));
402 // get new points key
403 LibUtilities::PointsKey newPointsKey0(
404 npt0, m_expList[0]->GetPointsType(0));
405 LibUtilities::PointsKey newPointsKey1(
406 npt1, m_expList[0]->GetPointsType(1));
407 LibUtilities::PointsKey newPointsKey2(
408 npt2, m_expList[0]->GetPointsType(2));
409
410 I0 = LibUtilities::PointsManager()[PointsKey0]->GetI(
411 newPointsKey0);
412 I1 = LibUtilities::PointsManager()[PointsKey1]->GetI(
413 newPointsKey1);
414 I2 = LibUtilities::PointsManager()[PointsKey2]->GetI(
415 newPointsKey2);
416
417 for (int i = 0; i < m_numElmt; ++i)
418 {
419 // Interpolate points
420 Blas::Dgemm('N', 'N', npt0, pt1 * pt2, pt0, 1.0,
421 I0->GetPtr().data(), npt0, &input[cnt], pt0,
422 0.0, wsp2.data(), npt0);
423
424 for (int j = 0; j < pt2; j++)
425 {
426 Blas::Dgemm('N', 'T', npt0, npt1, pt1, 1.0,
427 wsp2.data() + j * npt0 * pt1, npt0,
428 I1->GetPtr().data(), npt1, 0.0,
429 wsp1.data() + j * npt0 * npt1, npt0);
430 }
431
432 Blas::Dgemm('N', 'T', npt0 * npt1, npt2, pt2, 1.0,
433 wsp1.data(), npt0 * npt1, I2->GetPtr().data(),
434 npt2, 0.0, &output[cnt1], npt0 * npt1);
435
436 cnt += pt0 * pt1 * pt2;
437 cnt1 += npt0 * npt1 * npt2;
438 }
439 }
440 break;
441 default:
442 {
443 NEKERROR(ErrorUtil::efatal, "This expansion is not set for the "
444 "PhysInterp1DScaled operator.");
445 }
446 break;
447 }
448 }
449 void operator()([[maybe_unused]] int dir,
450 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
451 [[maybe_unused]] Array<OneD, NekDouble> &output,
452 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
453 {
454 ASSERTL0(false, "Not valid for this operator.");
455 }
456
457 void UpdateFactors([[maybe_unused]] StdRegions::FactorMap factors) override
458 {
460 m_factors = factors;
461 }
462
463private:
465 vector<StdRegions::StdExpansionSharedPtr> pCollExp,
467 : Operator(pCollExp, pGeomData, factors), PhysInterp1DScaled_Helper()
468 {
469 m_expList = pCollExp;
470 m_factors = factors;
471 }
472
474 vector<StdRegions::StdExpansionSharedPtr> m_expList;
475};
476
477/// Factory initialisation for the PhysInterp1DScaled_NoCollection operators
478OperatorKey PhysInterp1DScaled_NoCollection::m_typeArr[] = {
481 PhysInterp1DScaled_NoCollection::create,
482 "PhysInterp1DScaled_NoCollection_Seg"),
485 PhysInterp1DScaled_NoCollection::create,
486 "PhysInterp1DScaled_NoCollection_Tri"),
489 PhysInterp1DScaled_NoCollection::create,
490 "PhysInterp1DScaled_NoCollection_NodalTri"),
493 PhysInterp1DScaled_NoCollection::create,
494 "PhysInterp1DScaled_NoCollection_Quad"),
497 PhysInterp1DScaled_NoCollection::create,
498 "PhysInterp1DScaled_NoCollection_Tet"),
501 PhysInterp1DScaled_NoCollection::create,
502 "PhysInterp1DScaled_NoCollection_NodalTet"),
505 PhysInterp1DScaled_NoCollection::create,
506 "PhysInterp1DScaled_NoCollection_Pyr"),
509 PhysInterp1DScaled_NoCollection::create,
510 "PhysInterp1DScaled_NoCollection_Prism"),
513 PhysInterp1DScaled_NoCollection::create,
514 "PhysInterp1DScaled_NoCollection_NodalPrism"),
517 PhysInterp1DScaled_NoCollection::create,
518 "PhysInterp1DScaled_NoCollection_Hex"),
519};
520
521} // namespace Nektar::Collections
#define ASSERTL0(condition, msg)
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
#define OPERATOR_CREATE(cname)
Definition Operator.h:43
unsigned int m_nElmtPad
size after padding
unsigned int m_nOut
actural size of output array
Base class for operators on a collection of elements.
Definition Operator.h:138
StdRegions::StdExpansionSharedPtr m_stdExp
Definition Operator.h:217
unsigned int m_numElmt
number of elements that the operator is applied on
Definition Operator.h:219
unsigned int m_outputSize
number of modes or quadrature points that are taken as output from an operator
Definition Operator.h:227
unsigned int m_inputSize
number of modes or quadrature points that are passed as input to an operator
Definition Operator.h:224
PhysInterp1DScaled help class to calculate the size of the collection that is given as an input and a...
void UpdateFactors(StdRegions::FactorMap factors) override
Update the supplied factor map.
PhysInterp1DScaled operator using matrix free implementation.
PhysInterp1DScaled_MatrixFree(vector< StdRegions::StdExpansionSharedPtr > pCollExp, CoalescedGeomDataSharedPtr pGeomData, StdRegions::FactorMap factors)
std::shared_ptr< MatrixFree::PhysInterp1DScaled > m_oper
void operator()(int dir, const Array< OneD, const NekDouble > &input, Array< OneD, NekDouble > &output, Array< OneD, NekDouble > &wsp) final
void UpdateFactors(StdRegions::FactorMap factors) override
Update the supplied factor map.
PhysInterp1DScaled operator using LocalRegions implementation.
PhysInterp1DScaled_NoCollection(vector< StdRegions::StdExpansionSharedPtr > pCollExp, CoalescedGeomDataSharedPtr pGeomData, StdRegions::FactorMap factors)
void operator()(const Array< OneD, const NekDouble > &input, Array< OneD, NekDouble > &output, Array< OneD, NekDouble > &output1, Array< OneD, NekDouble > &output2, Array< OneD, NekDouble > &wsp) override
Perform operation.
void UpdateFactors(StdRegions::FactorMap factors) override
Update the supplied factor map.
vector< StdRegions::StdExpansionSharedPtr > m_expList
void operator()(int dir, const Array< OneD, const NekDouble > &input, Array< OneD, NekDouble > &output, Array< OneD, NekDouble > &wsp) final
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Defines a specification for a set of points.
Definition Points.h:50
static void Dgemv(const char &trans, const int &m, const int &n, const double &alpha, const double *a, const int &lda, const double *x, const int &incx, const double &beta, double *y, const int &incy)
BLAS level 2: Matrix vector multiply y = alpha A x plus beta y where A[m x n].
Definition Blas.hpp:211
static void Dgemm(const char &transa, const char &transb, const int &m, const int &n, const int &k, const double &alpha, const double *a, const int &lda, const double *b, const int &ldb, const double &beta, double *c, const int &ldc)
BLAS level 3: Matrix-matrix multiply C = A x B where op(A)[m x k], op(B)[k x n], C[m x n] DGEMM perfo...
Definition Blas.hpp:383
std::tuple< LibUtilities::ShapeType, OperatorType, ImplementationType, ExpansionIsNodal > OperatorKey
Key for describing an Operator.
Definition Operator.h:120
std::shared_ptr< CoalescedGeomData > CoalescedGeomDataSharedPtr
OperatorFactory & GetOperatorFactory()
Returns the singleton Operator factory object.
Definition Operator.cpp:44
PointsManagerT & PointsManager(void)
const char *const ConstFactorTypeMap[]
ConstFactorMap FactorMap
std::shared_ptr< DNekMat > DNekMatSharedPtr
STL namespace.