Nektar++
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:
66 {
67 if (factors == m_factors)
68 {
69 return;
70 }
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 for (int i = 0; i < shape_dimension; ++i)
85 {
86 m_outputSize *= (int)(m_stdExp->GetNumPoints(i) * scale);
87 }
88 }
89
90protected:
92 {
93 NekDouble scale; // declaration of the scaling factor to be used for the
94 // output size
96 {
98 }
99 else
100 {
101 scale = 1.5;
102 }
103 // expect input to be number of elements by the number of quad points
104 m_inputSize = m_numElmt * m_stdExp->GetTotPoints();
105 // expect input to be number of elements by the number of quad points
106 int shape_dimension = m_stdExp->GetShapeDimension();
107 m_outputSize = m_numElmt; // initializing m_outputSize
108 for (int i = 0; i < shape_dimension; ++i)
109 {
110 m_outputSize *= (int)(m_stdExp->GetNumPoints(i) * scale);
111 }
112 }
113
115 m_factors; // map for storing the scaling factor of the operator
116};
117
118/**
119 * @brief PhysInterp1DScaled operator using matrix free implementation.
120 */
121class PhysInterp1DScaled_MatrixFree final : virtual public Operator,
124{
125public:
127
129
130 void operator()(const Array<OneD, const NekDouble> &input,
131 Array<OneD, NekDouble> &output0,
132 [[maybe_unused]] Array<OneD, NekDouble> &output1,
133 [[maybe_unused]] Array<OneD, NekDouble> &output2,
134 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
135 {
136 (*m_oper)(input, output0);
137 }
138
139 void operator()([[maybe_unused]] int dir,
140 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
141 [[maybe_unused]] Array<OneD, NekDouble> &output,
142 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
143 {
145 "PhysInterp1DScaled_MatrixFree: Not valid for this operator.");
146 }
147
148 void UpdateFactors([[maybe_unused]] StdRegions::FactorMap factors) override
149 {
150
151 // Set lambda for this call
152 auto x = factors.find(StdRegions::eFactorConst);
153 ASSERTL1(
154 x != factors.end(),
155 "Constant factor not defined: " +
156 std::string(
158 // Update the factors member inside PhysInterp1DScaled_MatrixFree
159 // class
161
162 const auto dim = m_stdExp->GetShapeDimension();
163
164 // Definition of basis vector
165 std::vector<LibUtilities::BasisSharedPtr> basis(dim);
166 for (unsigned int i = 0; i < dim; ++i)
167 {
168 basis[i] = m_stdExp->GetBasis(i);
169 }
170
171 // Update the scaling factor inside MatrixFreeOps using the SetLamda
172 // routine
173 m_oper->SetScalingFactor(x->second);
174 m_oper->SetUpInterp1D(basis, m_factors[StdRegions::eFactorConst]);
176 }
177
178private:
179 std::shared_ptr<MatrixFree::PhysInterp1DScaled> m_oper;
180
182 vector<StdRegions::StdExpansionSharedPtr> pCollExp,
184 : Operator(pCollExp, pGeomData, factors),
185 MatrixFreeBase(pCollExp[0]->GetStdExp()->GetTotPoints(),
186 pCollExp[0]->GetStdExp()->GetTotPoints(),
187 pCollExp.size()),
189 {
190 const auto dim = pCollExp[0]->GetStdExp()->GetShapeDimension();
191
192 // Definition of basis vector
193 std::vector<LibUtilities::BasisSharedPtr> basis(dim);
194 for (unsigned int i = 0; i < dim; ++i)
195 {
196 basis[i] = pCollExp[0]->GetBasis(i);
197 }
198
199 // Get shape type
200 auto shapeType = pCollExp[0]->GetStdExp()->DetShapeType();
201
202 // Generate operator string and create operator.
203 std::string op_string = "PhysInterp1DScaled";
204 op_string += MatrixFree::GetOpstring(shapeType, false);
206 op_string, basis, pCollExp.size());
207
208 m_oper =
209 std::dynamic_pointer_cast<MatrixFree::PhysInterp1DScaled>(oper);
210 ASSERTL0(m_oper, "Failed to cast pointer.");
211
212 NekDouble scale; // declaration of the scaling factor to be used for the
213 // output size
215 {
218 }
219 else
220 {
221 scale = 1.5;
223 }
224 // Update the scaling factor inside MatrixFreeOps using the SetLamda
225 // routine
226 m_oper->SetScalingFactor(scale);
227 m_oper->SetUpInterp1D(basis, scale);
229 }
230};
231
232/// Factory initialisation for the PhysInterp1DScaled_MatrixFree operators
233OperatorKey PhysInterp1DScaled_MatrixFree::m_typeArr[] = {
236 PhysInterp1DScaled_MatrixFree::create,
237 "PhysInterp1DScaled_MatrixFree_Seg"),
240 PhysInterp1DScaled_MatrixFree::create,
241 "PhysInterp1DScaled_MatrixFree_Tri"),
244 PhysInterp1DScaled_MatrixFree::create,
245 "PhysInterp1DScaled_MatrixFree_NodalTri"),
248 PhysInterp1DScaled_MatrixFree::create,
249 "PhysInterp1DScaled_MatrixFree_Quad"),
252 PhysInterp1DScaled_MatrixFree::create,
253 "PhysInterp1DScaled_MatrixFree_Tet"),
256 PhysInterp1DScaled_MatrixFree::create,
257 "PhysInterp1DScaled_MatrixFree_NodalTet"),
260 PhysInterp1DScaled_MatrixFree::create,
261 "PhysInterp1DScaled_MatrixFree_Pyr"),
264 PhysInterp1DScaled_MatrixFree::create,
265 "PhysInterp1DScaled_MatrixFree_Prism"),
268 PhysInterp1DScaled_MatrixFree::create,
269 "PhysInterp1DScaled_MatrixFree_NodalPrism"),
272 PhysInterp1DScaled_MatrixFree::create,
273 "PhysInterp1DScaled_NoCollection_Hex"),
274};
275
276/**
277 * @brief PhysInterp1DScaled operator using LocalRegions implementation.
278 */
279class PhysInterp1DScaled_NoCollection final : virtual public Operator,
281{
282public:
284
286 {
287 }
288
291 [[maybe_unused]] Array<OneD, NekDouble> &output1,
292 [[maybe_unused]] Array<OneD, NekDouble> &output2,
293 [[maybe_unused]] Array<OneD, NekDouble> &wsp) override
294 {
295 int cnt{0};
296 int cnt1{0};
298 int dim{m_expList[0]->GetShapeDimension()}; // same as m_expType
299 switch (dim)
300 {
301 case 1:
302 {
304 // the number of points before and after interpolation are the
305 // same for each element inside a single collection
306 int pt0 = m_expList[0]->GetNumPoints(0);
307 int npt0 = (int)pt0 * scale;
308 // current points key - use first entry
309 LibUtilities::PointsKey PointsKey0(
310 pt0, m_expList[0]->GetPointsType(0));
311 // get new points key
312 LibUtilities::PointsKey newPointsKey0(
313 npt0, m_expList[0]->GetPointsType(0));
314 // Interpolate points;
315 I0 = LibUtilities::PointsManager()[PointsKey0]->GetI(
316 newPointsKey0);
317
318 for (int i = 0; i < m_numElmt; ++i)
319 {
320
321 Blas::Dgemv('N', npt0, pt0, 1.0, I0->GetPtr().get(), npt0,
322 &input[cnt], 1, 0.0, &output[cnt1], 1);
323 cnt += pt0;
324 cnt1 += npt0;
325 }
326 }
327 break;
328 case 2:
329 {
330 DNekMatSharedPtr I0, I1;
331 // the number of points before and after interpolation are
332 // the same for each element inside a single collection
333 int pt0 = m_expList[0]->GetNumPoints(0);
334 int pt1 = m_expList[0]->GetNumPoints(1);
335 int npt0 = (int)pt0 * scale;
336 int npt1 = (int)pt1 * scale;
337 // workspace declaration
338 Array<OneD, NekDouble> wsp(npt1 * pt0); // fnp0*tnp1
339
340 // current points key - using first entry
341 LibUtilities::PointsKey PointsKey0(
342 pt0, m_expList[0]->GetPointsType(0));
343 LibUtilities::PointsKey PointsKey1(
344 pt1, m_expList[0]->GetPointsType(1));
345 // get new points key
346 LibUtilities::PointsKey newPointsKey0(
347 npt0, m_expList[0]->GetPointsType(0));
348 LibUtilities::PointsKey newPointsKey1(
349 npt1, m_expList[0]->GetPointsType(1));
350
351 // Interpolate points;
352 I0 = LibUtilities::PointsManager()[PointsKey0]->GetI(
353 newPointsKey0);
354 I1 = LibUtilities::PointsManager()[PointsKey1]->GetI(
355 newPointsKey1);
356
357 for (int i = 0; i < m_numElmt; ++i)
358 {
359 Blas::Dgemm('N', 'T', pt0, npt1, pt1, 1.0, &input[cnt], pt0,
360 I1->GetPtr().get(), npt1, 0.0, wsp.get(), pt0);
361
362 Blas::Dgemm('N', 'N', npt0, npt1, pt0, 1.0,
363 I0->GetPtr().get(), npt0, wsp.get(), pt0, 0.0,
364 &output[cnt1], npt0);
365
366 cnt += pt0 * pt1;
367 cnt1 += npt0 * npt1;
368 }
369 }
370 break;
371 case 3:
372 {
373 DNekMatSharedPtr I0, I1, I2;
374
375 int pt0 = m_expList[0]->GetNumPoints(0);
376 int pt1 = m_expList[0]->GetNumPoints(1);
377 int pt2 = m_expList[0]->GetNumPoints(2);
378 int npt0 = (int)pt0 * scale;
379 int npt1 = (int)pt1 * scale;
380 int npt2 = (int)pt2 * scale;
381 Array<OneD, NekDouble> wsp1(npt0 * npt1 * pt2);
382 Array<OneD, NekDouble> wsp2(npt0 * pt1 * pt2);
383
384 // current points key
385 LibUtilities::PointsKey PointsKey0(
386 pt0, m_expList[0]->GetPointsType(0));
387 LibUtilities::PointsKey PointsKey1(
388 pt1, m_expList[0]->GetPointsType(1));
389 LibUtilities::PointsKey PointsKey2(
390 pt2, m_expList[0]->GetPointsType(2));
391 // get new points key
392 LibUtilities::PointsKey newPointsKey0(
393 npt0, m_expList[0]->GetPointsType(0));
394 LibUtilities::PointsKey newPointsKey1(
395 npt1, m_expList[0]->GetPointsType(1));
396 LibUtilities::PointsKey newPointsKey2(
397 npt2, m_expList[0]->GetPointsType(2));
398
399 I0 = LibUtilities::PointsManager()[PointsKey0]->GetI(
400 newPointsKey0);
401 I1 = LibUtilities::PointsManager()[PointsKey1]->GetI(
402 newPointsKey1);
403 I2 = LibUtilities::PointsManager()[PointsKey2]->GetI(
404 newPointsKey2);
405
406 for (int i = 0; i < m_numElmt; ++i)
407 {
408 // Interpolate points
409 Blas::Dgemm('N', 'N', npt0, pt1 * pt2, pt0, 1.0,
410 I0->GetPtr().get(), npt0, &input[cnt], pt0, 0.0,
411 wsp2.get(), npt0);
412
413 for (int j = 0; j < pt2; j++)
414 {
415 Blas::Dgemm('N', 'T', npt0, npt1, pt1, 1.0,
416 wsp2.get() + j * npt0 * pt1, npt0,
417 I1->GetPtr().get(), npt1, 0.0,
418 wsp1.get() + j * npt0 * npt1, npt0);
419 }
420
421 Blas::Dgemm('N', 'T', npt0 * npt1, npt2, pt2, 1.0,
422 wsp1.get(), npt0 * npt1, I2->GetPtr().get(),
423 npt2, 0.0, &output[cnt1], npt0 * npt1);
424
425 cnt += pt0 * pt1 * pt2;
426 cnt1 += npt0 * npt1 * npt2;
427 }
428 }
429 break;
430 default:
431 {
432 NEKERROR(ErrorUtil::efatal, "This expansion is not set for the "
433 "PhysInterp1DScaled operator.");
434 }
435 break;
436 }
437 }
438 void operator()([[maybe_unused]] int dir,
439 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
440 [[maybe_unused]] Array<OneD, NekDouble> &output,
441 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
442 {
443 ASSERTL0(false, "Not valid for this operator.");
444 }
445
446 void UpdateFactors([[maybe_unused]] StdRegions::FactorMap factors) override
447 {
450 }
451
452private:
454 vector<StdRegions::StdExpansionSharedPtr> pCollExp,
456 : Operator(pCollExp, pGeomData, factors), PhysInterp1DScaled_Helper()
457 {
458 m_expList = pCollExp;
460 }
461
463 vector<StdRegions::StdExpansionSharedPtr> m_expList;
464};
465
466/// Factory initialisation for the PhysInterp1DScaled_NoCollection operators
467OperatorKey PhysInterp1DScaled_NoCollection::m_typeArr[] = {
470 PhysInterp1DScaled_NoCollection::create,
471 "PhysInterp1DScaled_NoCollection_Seg"),
474 PhysInterp1DScaled_NoCollection::create,
475 "PhysInterp1DScaled_NoCollection_Tri"),
478 PhysInterp1DScaled_NoCollection::create,
479 "PhysInterp1DScaled_NoCollection_NodalTri"),
482 PhysInterp1DScaled_NoCollection::create,
483 "PhysInterp1DScaled_NoCollection_Quad"),
486 PhysInterp1DScaled_NoCollection::create,
487 "PhysInterp1DScaled_NoCollection_Tet"),
490 PhysInterp1DScaled_NoCollection::create,
491 "PhysInterp1DScaled_NoCollection_NodalTet"),
494 PhysInterp1DScaled_NoCollection::create,
495 "PhysInterp1DScaled_NoCollection_Pyr"),
498 PhysInterp1DScaled_NoCollection::create,
499 "PhysInterp1DScaled_NoCollection_Prism"),
502 PhysInterp1DScaled_NoCollection::create,
503 "PhysInterp1DScaled_NoCollection_NodalPrism"),
506 PhysInterp1DScaled_NoCollection::create,
507 "PhysInterp1DScaled_NoCollection_Hex"),
508};
509
510} // namespace Nektar::Collections
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:208
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
Definition: ErrorUtil.hpp:202
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
Definition: ErrorUtil.hpp:242
#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.
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
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[]
Definition: StdRegions.hpp:413
ConstFactorMap FactorMap
Definition: StdRegions.hpp:434
StdRegions::ConstFactorMap factors
std::shared_ptr< DNekMat > DNekMatSharedPtr
Definition: NekTypeDefs.hpp:75
double NekDouble
STL namespace.