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
57
58/**
59 * @brief PhysInterp1DScaled help class to calculate the size of the collection
60 * that is given as an input and as an output to the PhysInterp1DScaled
61 * Operator. The size evaluation takes into account that both the input and the
62 * output array belong to the physical space and that the output array can have
63 * either a larger, or a smaller size than the input array
64 */
65class PhysInterp1DScaled_Helper : virtual public Operator
66{
67public:
68 void UpdateFactors(StdRegions::FactorMap factors) override
69 {
70 if (factors == m_factors)
71 {
72 return;
73 }
74 m_factors = factors;
75 // Set scaling factor for the PhysInterp1DScaled function
76 [[maybe_unused]] auto x = factors.find(StdRegions::eFactorConst);
78 x != factors.end(),
79 "Constant factor not defined: " +
80 std::string(
82
84
85 int shape_dimension = m_stdExp->GetShapeDimension();
86 m_outputSize = m_numElmt; // initializing m_outputSize
87 int npt0 = m_stdExp->GetNumPoints(0);
88
89 for (int i = 0; i < shape_dimension; ++i)
90 {
91 int npt = m_stdExp->GetNumPoints(i);
92 m_outputSize *= (npt0 - npt == 1) ? (int)(npt0 * scale - 1)
93 : (int)(npt * scale);
94 }
95 }
96
97protected:
99 {
100 NekDouble scale; // declaration of the scaling factor to be used for the
101 // output size
103 {
105 }
106 else
107 {
108 scale = 1.5;
109 }
110 // expect input to be number of elements by the number of quad points
111 m_inputSize = m_numElmt * m_stdExp->GetTotPoints();
112 // expect input to be number of elements by the number of quad points
113 int shape_dimension = m_stdExp->GetShapeDimension();
114 m_outputSize = m_numElmt; // initializing m_outputSize
115 int npt0 = m_stdExp->GetNumPoints(0);
116 for (int i = 0; i < shape_dimension; ++i)
117 {
118 int npt = m_stdExp->GetNumPoints(i);
119 m_outputSize *= (npt0 - npt == 1) ? (int)(npt0 * scale - 1)
120 : (int)(npt * scale);
121 }
122 }
123
125 m_factors; // map for storing the scaling factor of the operator
126};
127
128/**
129 * @brief PhysInterp1DScaled operator using matrix free implementation.
130 */
131class PhysInterp1DScaled_MatrixFree final : virtual public Operator,
134{
135public:
137
139
140 void operator()(const Array<OneD, const NekDouble> &input,
141 Array<OneD, NekDouble> &output0,
142 [[maybe_unused]] Array<OneD, NekDouble> &output1,
143 [[maybe_unused]] Array<OneD, NekDouble> &output2,
144 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
145 {
146 (*m_oper)(input, output0);
147 }
148
149 void operator()([[maybe_unused]] int dir,
150 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
151 [[maybe_unused]] Array<OneD, NekDouble> &output,
152 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
153 {
155 "PhysInterp1DScaled_MatrixFree: Not valid for this operator.");
156 }
157
158 void UpdateFactors([[maybe_unused]] StdRegions::FactorMap factors) override
159 {
160
161 // Set lambda for this call
162 auto x = factors.find(StdRegions::eFactorConst);
163 ASSERTL1(
164 x != factors.end(),
165 "Constant factor not defined: " +
166 std::string(
168 // Update the factors member inside PhysInterp1DScaled_MatrixFree
169 // class
170 m_factors = factors;
171
172 const auto dim = m_stdExp->GetShapeDimension();
173
174 // Definition of basis vector
175 std::vector<LibUtilities::BasisSharedPtr> basis(dim);
176 for (unsigned int i = 0; i < dim; ++i)
177 {
178 basis[i] = m_stdExp->GetBasis(i);
179 }
180
181 // Update the scaling factor inside MatrixFreeOps using the SetLamda
182 // routine
183 m_oper->SetScalingFactor(x->second);
184 m_oper->SetUpInterp1D(basis, m_factors[StdRegions::eFactorConst]);
186 }
187
188private:
189 std::shared_ptr<MatrixFree::PhysInterp1DScaled> m_oper;
190
192 vector<LocalRegions::ExpansionSharedPtr> pCollExp,
194 : Operator(pCollExp, pGeomData, factors),
195 MatrixFreeBase(pCollExp[0]->GetTotPoints(),
196 pCollExp[0]->GetTotPoints(), pCollExp.size()),
198 {
199 const auto dim = pCollExp[0]->GetShapeDimension();
200
201 // Definition of basis vector
202 std::vector<LibUtilities::BasisSharedPtr> basis(dim);
203 for (unsigned int i = 0; i < dim; ++i)
204 {
205 basis[i] = pCollExp[0]->GetBasis(i);
206 }
207
208 // Get shape type
209 auto shapeType = pCollExp[0]->DetShapeType();
210
211 // Generate operator string and create operator.
212 std::string op_string = "PhysInterp1DScaled";
213 op_string += MatrixFree::GetOpstring(shapeType, false);
214 auto oper = MatrixFree::GetOperatorFactory().CreateInstance(
215 op_string, basis, pCollExp.size());
216
217 m_oper =
218 std::dynamic_pointer_cast<MatrixFree::PhysInterp1DScaled>(oper);
219 ASSERTL0(m_oper, "Failed to cast pointer.");
220
221 NekDouble scale; // declaration of the scaling factor to be used for the
222 // output size
223 if (factors[StdRegions::eFactorConst] != 0)
224 {
225 m_factors = factors;
227 }
228 else
229 {
230 scale = 1.5;
232 }
233 // Update the scaling factor inside MatrixFreeOps using the SetLamda
234 // routine
235 m_oper->SetScalingFactor(scale);
236 m_oper->SetUpInterp1D(basis, scale);
238 }
239};
240
241/// Factory initialisation for the PhysInterp1DScaled_MatrixFree operators
242OperatorKey PhysInterp1DScaled_MatrixFree::m_typeArr[] = {
245 PhysInterp1DScaled_MatrixFree::create,
246 "PhysInterp1DScaled_MatrixFree_Seg"),
248 OperatorKey(eTriangle, ePhysInterp1DScaled, eMatrixFree, false),
249 PhysInterp1DScaled_MatrixFree::create,
250 "PhysInterp1DScaled_MatrixFree_Tri"),
253 PhysInterp1DScaled_MatrixFree::create,
254 "PhysInterp1DScaled_MatrixFree_NodalTri"),
256 OperatorKey(eQuadrilateral, ePhysInterp1DScaled, eMatrixFree, false),
257 PhysInterp1DScaled_MatrixFree::create,
258 "PhysInterp1DScaled_MatrixFree_Quad"),
260 OperatorKey(eTetrahedron, ePhysInterp1DScaled, eMatrixFree, false),
261 PhysInterp1DScaled_MatrixFree::create,
262 "PhysInterp1DScaled_MatrixFree_Tet"),
265 PhysInterp1DScaled_MatrixFree::create,
266 "PhysInterp1DScaled_MatrixFree_NodalTet"),
269 PhysInterp1DScaled_MatrixFree::create,
270 "PhysInterp1DScaled_MatrixFree_Pyr"),
273 PhysInterp1DScaled_MatrixFree::create,
274 "PhysInterp1DScaled_MatrixFree_Prism"),
276 OperatorKey(eNodalPrism, ePhysInterp1DScaled, eMatrixFree, true),
277 PhysInterp1DScaled_MatrixFree::create,
278 "PhysInterp1DScaled_MatrixFree_NodalPrism"),
280 OperatorKey(eHexahedron, ePhysInterp1DScaled, eMatrixFree, false),
281 PhysInterp1DScaled_MatrixFree::create,
282 "PhysInterp1DScaled_NoCollection_Hex"),
283};
284
285/**
286 * @brief PhysInterp1DScaled operator using LocalRegions implementation.
287 */
288class PhysInterp1DScaled_NoCollection final : virtual public Operator,
290{
291public:
293
297
300 [[maybe_unused]] Array<OneD, NekDouble> &output1,
301 [[maybe_unused]] Array<OneD, NekDouble> &output2,
302 [[maybe_unused]] Array<OneD, NekDouble> &wsp) override
303 {
304 int cnt{0};
305 int cnt1{0};
307 int dim{m_expList[0]->GetShapeDimension()}; // same as m_expType
308 switch (dim)
309 {
310 case 1:
311 {
313 // the number of points before and after interpolation are the
314 // same for each element inside a single collection
315 int pt0 = m_expList[0]->GetNumPoints(0);
316 int npt0 = (int)(pt0 * scale);
317 // current points key - use first entry
318 LibUtilities::PointsKey PointsKey0(
319 pt0, m_expList[0]->GetPointsType(0));
320 // get new points key
321 LibUtilities::PointsKey newPointsKey0(
322 npt0, m_expList[0]->GetPointsType(0));
323 // Interpolate points;
324 I0 = LibUtilities::PointsManager()[PointsKey0]->GetI(
325 newPointsKey0);
326
327 for (int i = 0; i < m_numElmt; ++i)
328 {
329
330 Blas::Dgemv('N', npt0, pt0, 1.0, I0->GetPtr().data(), npt0,
331 &input[cnt], 1, 0.0, &output[cnt1], 1);
332 cnt += pt0;
333 cnt1 += npt0;
334 }
335 }
336 break;
337 case 2:
338 {
339 DNekMatSharedPtr I0, I1;
340 // the number of points before and after interpolation are
341 // the same for each element inside a single collection
342 int pt0 = m_expList[0]->GetNumPoints(0);
343 int pt1 = m_expList[0]->GetNumPoints(1);
344 int npt0 = (int)(pt0 * scale);
345 int npt1 = (pt0 - pt1 == 1) ? (int)(pt0 * scale - 1)
346 : (int)(pt1 * scale);
347 // workspace declaration
348 Array<OneD, NekDouble> wsp(npt1 * pt0); // fnp0*tnp1
349
350 // current points key - using first entry
351 LibUtilities::PointsKey PointsKey0(
352 pt0, m_expList[0]->GetPointsType(0));
353 LibUtilities::PointsKey PointsKey1(
354 pt1, m_expList[0]->GetPointsType(1));
355 // get new points key
356 LibUtilities::PointsKey newPointsKey0(
357 npt0, m_expList[0]->GetPointsType(0));
358 LibUtilities::PointsKey newPointsKey1(
359 npt1, m_expList[0]->GetPointsType(1));
360
361 // Interpolate points;
362 I0 = LibUtilities::PointsManager()[PointsKey0]->GetI(
363 newPointsKey0);
364 I1 = LibUtilities::PointsManager()[PointsKey1]->GetI(
365 newPointsKey1);
366
367 for (int i = 0; i < m_numElmt; ++i)
368 {
369 Blas::Dgemm('N', 'T', pt0, npt1, pt1, 1.0, &input[cnt], pt0,
370 I1->GetPtr().data(), npt1, 0.0, wsp.data(),
371 pt0);
372
373 Blas::Dgemm('N', 'N', npt0, npt1, pt0, 1.0,
374 I0->GetPtr().data(), npt0, wsp.data(), pt0, 0.0,
375 &output[cnt1], npt0);
376
377 cnt += pt0 * pt1;
378 cnt1 += npt0 * npt1;
379 }
380 }
381 break;
382 case 3:
383 {
384 DNekMatSharedPtr I0, I1, I2;
385
386 int pt0 = m_expList[0]->GetNumPoints(0);
387 int pt1 = m_expList[0]->GetNumPoints(1);
388 int pt2 = m_expList[0]->GetNumPoints(2);
389 int npt0 = (int)(pt0 * scale);
390 int npt1 = (pt0 - pt1 == 1) ? (int)(pt0 * scale - 1)
391 : (int)(pt1 * scale);
392 int npt2 = (pt0 - pt2 == 1) ? (int)(pt0 * scale - 1)
393 : (int)(pt2 * scale);
394 Array<OneD, NekDouble> wsp1(npt0 * npt1 * pt2);
395 Array<OneD, NekDouble> wsp2(npt0 * pt1 * pt2);
396
397 // current points key
398 LibUtilities::PointsKey PointsKey0(
399 pt0, m_expList[0]->GetPointsType(0));
400 LibUtilities::PointsKey PointsKey1(
401 pt1, m_expList[0]->GetPointsType(1));
402 LibUtilities::PointsKey PointsKey2(
403 pt2, m_expList[0]->GetPointsType(2));
404 // get new points key
405 LibUtilities::PointsKey newPointsKey0(
406 npt0, m_expList[0]->GetPointsType(0));
407 LibUtilities::PointsKey newPointsKey1(
408 npt1, m_expList[0]->GetPointsType(1));
409 LibUtilities::PointsKey newPointsKey2(
410 npt2, m_expList[0]->GetPointsType(2));
411
412 I0 = LibUtilities::PointsManager()[PointsKey0]->GetI(
413 newPointsKey0);
414 I1 = LibUtilities::PointsManager()[PointsKey1]->GetI(
415 newPointsKey1);
416 I2 = LibUtilities::PointsManager()[PointsKey2]->GetI(
417 newPointsKey2);
418
419 for (int i = 0; i < m_numElmt; ++i)
420 {
421 // Interpolate points
422 Blas::Dgemm('N', 'N', npt0, pt1 * pt2, pt0, 1.0,
423 I0->GetPtr().data(), npt0, &input[cnt], pt0,
424 0.0, wsp2.data(), npt0);
425
426 for (int j = 0; j < pt2; j++)
427 {
428 Blas::Dgemm('N', 'T', npt0, npt1, pt1, 1.0,
429 wsp2.data() + j * npt0 * pt1, npt0,
430 I1->GetPtr().data(), npt1, 0.0,
431 wsp1.data() + j * npt0 * npt1, npt0);
432 }
433
434 Blas::Dgemm('N', 'T', npt0 * npt1, npt2, pt2, 1.0,
435 wsp1.data(), npt0 * npt1, I2->GetPtr().data(),
436 npt2, 0.0, &output[cnt1], npt0 * npt1);
437
438 cnt += pt0 * pt1 * pt2;
439 cnt1 += npt0 * npt1 * npt2;
440 }
441 }
442 break;
443 default:
444 {
445 NEKERROR(ErrorUtil::efatal, "This expansion is not set for the "
446 "PhysInterp1DScaled operator.");
447 }
448 break;
449 }
450 }
451 void operator()([[maybe_unused]] int dir,
452 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
453 [[maybe_unused]] Array<OneD, NekDouble> &output,
454 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
455 {
456 ASSERTL0(false, "Not valid for this operator.");
457 }
458
459 void UpdateFactors([[maybe_unused]] StdRegions::FactorMap factors) override
460 {
462 m_factors = factors;
463 }
464
465private:
467 vector<LocalRegions::ExpansionSharedPtr> pCollExp,
469 : Operator(pCollExp, pGeomData, factors), PhysInterp1DScaled_Helper()
470 {
471 m_expList = pCollExp;
472 m_factors = factors;
473 }
474
476 vector<LocalRegions::ExpansionSharedPtr> m_expList;
477};
478
479/// Factory initialisation for the PhysInterp1DScaled_NoCollection operators
480OperatorKey PhysInterp1DScaled_NoCollection::m_typeArr[] = {
483 PhysInterp1DScaled_NoCollection::create,
484 "PhysInterp1DScaled_NoCollection_Seg"),
487 PhysInterp1DScaled_NoCollection::create,
488 "PhysInterp1DScaled_NoCollection_Tri"),
491 PhysInterp1DScaled_NoCollection::create,
492 "PhysInterp1DScaled_NoCollection_NodalTri"),
495 PhysInterp1DScaled_NoCollection::create,
496 "PhysInterp1DScaled_NoCollection_Quad"),
499 PhysInterp1DScaled_NoCollection::create,
500 "PhysInterp1DScaled_NoCollection_Tet"),
503 PhysInterp1DScaled_NoCollection::create,
504 "PhysInterp1DScaled_NoCollection_NodalTet"),
507 PhysInterp1DScaled_NoCollection::create,
508 "PhysInterp1DScaled_NoCollection_Pyr"),
511 PhysInterp1DScaled_NoCollection::create,
512 "PhysInterp1DScaled_NoCollection_Prism"),
515 PhysInterp1DScaled_NoCollection::create,
516 "PhysInterp1DScaled_NoCollection_NodalPrism"),
519 PhysInterp1DScaled_NoCollection::create,
520 "PhysInterp1DScaled_NoCollection_Hex"),
521};
522
523} // 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:230
unsigned int m_numElmt
number of elements that the operator is applied on
Definition Operator.h:232
unsigned int m_outputSize
number of modes or quadrature points that are taken as output from an operator
Definition Operator.h:240
unsigned int m_inputSize
number of modes or quadrature points that are passed as input to an operator
Definition Operator.h:237
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.
std::shared_ptr< MatrixFree::PhysInterp1DScaled > m_oper
PhysInterp1DScaled_MatrixFree(vector< LocalRegions::ExpansionSharedPtr > pCollExp, CoalescedGeomDataSharedPtr pGeomData, StdRegions::FactorMap factors)
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.
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.
PhysInterp1DScaled_NoCollection(vector< LocalRegions::ExpansionSharedPtr > pCollExp, CoalescedGeomDataSharedPtr pGeomData, StdRegions::FactorMap factors)
void operator()(int dir, const Array< OneD, const NekDouble > &input, Array< OneD, NekDouble > &output, Array< OneD, NekDouble > &wsp) final
vector< LocalRegions::ExpansionSharedPtr > m_expList
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:152
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:324
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.