Nektar++
ExpList3DHomogeneous1D.cpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: ExpList3DHomogeneous1D.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: An ExpList which is homogeneous in 1 direction and so
32// uses much of the functionality from a ExpList and its daughters
33//
34///////////////////////////////////////////////////////////////////////////////
35
38
39using namespace std;
40
41namespace Nektar
42{
43namespace MultiRegions
44{
45// Forward declaration for typedefs
47{
48}
49
52 const LibUtilities::BasisKey &HomoBasis, const NekDouble lhom,
53 const bool useFFT, const bool dealiasing)
54 : ExpListHomogeneous1D(e3DH1D, pSession, HomoBasis, lhom, useFFT,
55 dealiasing)
56{
57}
58
59// Constructor for ExpList3DHomogeneous1D to act as a Explist field
62 const LibUtilities::BasisKey &HomoBasis, const NekDouble lhom,
63 const bool useFFT, const bool dealiasing,
64 const SpatialDomains::MeshGraphSharedPtr &graph2D, const std::string &var,
66 : ExpListHomogeneous1D(e3DH1D, pSession, HomoBasis, lhom, useFFT,
67 dealiasing)
68{
69 GenExpList3DHomogeneous1D(graph2D->GetExpansionInfo(var), ImpType);
71 m_graph = graph2D;
72}
73
74// Constructor for ExpList3DHomogeneous1D to act as a Explist field
77 const LibUtilities::BasisKey &HomoBasis, const NekDouble lhom,
78 const bool useFFT, const bool dealiasing,
79 const SpatialDomains::ExpansionInfoMap &expansions,
81 : ExpListHomogeneous1D(e3DH1D, pSession, HomoBasis, lhom, useFFT,
82 dealiasing)
83{
84 GenExpList3DHomogeneous1D(expansions, ImpType);
85}
86
88 const SpatialDomains::ExpansionInfoMap &expansions,
90{
91 int n, j, nel;
92 bool False = false;
93 ExpListSharedPtr plane_zero;
94
95 // note that nzplanes can be larger than nzmodes
97 m_session, expansions, false, ImpType);
98
100 nel = m_planes[0]->GetExpSize();
101
102 for (j = 0; j < nel; ++j)
103 {
104 (*m_exp).push_back(m_planes[0]->GetExp(j));
105 }
106
107 for (n = 1; n < m_planes.size(); ++n)
108 {
109 m_planes[n] =
111 for (j = 0; j < nel; ++j)
112 {
113 (*m_exp).push_back((*m_exp)[j]);
114 }
115 }
116
117 SetCoeffPhys();
118}
119
120/**
121 * @param In ExpList3DHomogeneous1D object to copy.
122 */
124 bool DeclarePlanesSetCoeffPhys)
126{
127 if (DeclarePlanesSetCoeffPhys)
128 {
129 bool False = false;
130 ExpListSharedPtr zero_plane =
131 std::dynamic_pointer_cast<ExpList>(In.m_planes[0]);
132
133 for (int n = 0; n < m_planes.size(); ++n)
134 {
135 m_planes[n] =
137 }
138
139 SetCoeffPhys();
140 }
141}
142
143/**
144 * @param In ExpList3DHomogeneous1D object to copy.
145 * @param eIDs Id of elements that should be copied.
146 */
148 const ExpList3DHomogeneous1D &In, const std::vector<unsigned int> &eIDs,
149 bool DeclarePlanesSetCoeffPhys,
151 : ExpListHomogeneous1D(In, eIDs, ImpType)
152{
153 if (DeclarePlanesSetCoeffPhys)
154 {
155 bool False = false;
156 std::vector<unsigned int> eIDsPlane;
157 int nel = eIDs.size() / m_planes.size();
158
159 for (int i = 0; i < nel; ++i)
160 {
161 eIDsPlane.push_back(eIDs[i]);
162 }
163
164 ExpListSharedPtr zero_plane_old =
165 std::dynamic_pointer_cast<ExpList>(In.m_planes[0]);
166
168 *(zero_plane_old), eIDsPlane, DeclarePlanesSetCoeffPhys, ImpType);
169
170 for (int n = 0; n < m_planes.size(); ++n)
171 {
172 m_planes[n] =
174 }
175
176 SetCoeffPhys();
177 }
178}
179
180/**
181 * Destructor
182 */
184{
185}
186
188{
189 int i, n, cnt;
190 int ncoeffs_per_plane = m_planes[0]->GetNcoeffs();
191 int npoints_per_plane = m_planes[0]->GetTotPoints();
192
193 int nzplanes = m_planes.size();
194
195 // Set total coefficients and points
196 m_ncoeffs = ncoeffs_per_plane * nzplanes;
197 m_npoints = npoints_per_plane * nzplanes;
198
201
202 int nel = m_planes[0]->GetExpSize();
203 m_coeff_offset = Array<OneD, int>(nel * nzplanes);
204 m_phys_offset = Array<OneD, int>(nel * nzplanes);
205 Array<OneD, NekDouble> tmparray;
206
207 for (cnt = n = 0; n < nzplanes; ++n)
208 {
209 m_planes[n]->SetCoeffsArray(tmparray =
210 m_coeffs + ncoeffs_per_plane * n);
211 m_planes[n]->SetPhysArray(tmparray = m_phys + npoints_per_plane * n);
212
213 for (i = 0; i < nel; ++i)
214 {
215 m_coeff_offset[cnt] =
216 m_planes[n]->GetCoeff_Offset(i) + n * ncoeffs_per_plane;
217 m_phys_offset[cnt++] =
218 m_planes[n]->GetPhys_Offset(i) + n * npoints_per_plane;
219 }
220 }
221}
222
223// @TODO: Could potentially move the extra plane coordinate output here
228{
229 int n;
231 int nzplanes = m_planes.size();
232 int npoints = GetTotPoints(eid);
233
234 (*m_exp)[eid]->GetCoords(xc0, xc1);
235
236 // Fill z-direction
238 Array<OneD, NekDouble> local_pts(m_planes.size());
239
240 for (n = 0; n < m_planes.size(); n++)
241 {
242 local_pts[n] = pts[m_transposition->GetPlaneID(n)];
243 }
244
245 Array<OneD, NekDouble> z(nzplanes);
246
247 Vmath::Smul(nzplanes, m_lhom / 2.0, local_pts, 1, z, 1);
248 Vmath::Sadd(nzplanes, m_lhom / 2.0, z, 1, z, 1);
249
250 for (n = 0; n < nzplanes; ++n)
251 {
252 Vmath::Fill(npoints, z[n], tmp_xc = xc2 + npoints * n, 1);
253 if (n)
254 {
255 Vmath::Vcopy(npoints, xc0, 1, tmp_xc = xc0 + npoints * n, 1);
256 Vmath::Vcopy(npoints, xc1, 1, tmp_xc = xc1 + npoints * n, 1);
257 }
258 }
259}
260
261/**
262 * The operation calls the 2D plane coordinates through the
263 * function ExpList#GetCoords and then evaluated the third
264 * coordinate using the member \a m_lhom
265 *
266 * @param coord_0 After calculation, the \f$x_1\f$ coordinate
267 * will be stored in this array.
268 *
269 * @param coord_1 After calculation, the \f$x_2\f$ coordinate
270 * will be stored in this array.
271 *
272 * @param coord_2 After calculation, the \f$x_3\f$ coordinate
273 * will be stored in this array. This
274 * coordinate is evaluated using the
275 * predefined value \a m_lhom
276 */
280{
281 int n;
283 int nzplanes = m_planes.size();
284 int npoints = m_planes[0]->GetTotPoints();
285
286 m_planes[0]->GetCoords(xc0, xc1);
287
288 // Fill z-direction
290
291 Array<OneD, NekDouble> local_pts(m_planes.size());
292
293 for (n = 0; n < m_planes.size(); n++)
294 {
295 local_pts[n] = pts[m_transposition->GetPlaneID(n)];
296 }
297
298 Array<OneD, NekDouble> z(nzplanes);
299
300 Vmath::Smul(nzplanes, m_lhom / 2.0, local_pts, 1, z, 1);
301 Vmath::Sadd(nzplanes, m_lhom / 2.0, z, 1, z, 1);
302
303 for (n = 0; n < nzplanes; ++n)
304 {
305 Vmath::Fill(npoints, z[n], tmp_xc = xc2 + npoints * n, 1);
306 if (n)
307 {
308 Vmath::Vcopy(npoints, xc0, 1, tmp_xc = xc0 + npoints * n, 1);
309 Vmath::Vcopy(npoints, xc1, 1, tmp_xc = xc1 + npoints * n, 1);
310 }
311 }
312}
313
315 int expansion)
316{
317 ASSERTL0(expansion == -1,
318 "Multi-zone output not supported for homogeneous expansions.");
319
320 const int nPtsPlane = m_planes[0]->GetNpoints();
321 const int nElmt = m_planes[0]->GetExpSize();
322 const int nPlanes = m_planes.size();
323
324 int cnt = 0;
325 int cnt2 = 0;
326 for (int i = 0; i < nElmt; ++i)
327 {
328 const int np0 = (*m_exp)[i]->GetNumPoints(0);
329 const int np1 = (*m_exp)[i]->GetNumPoints(1);
330
331 for (int n = 1; n < nPlanes; ++n)
332 {
333 const int o1 = (n - 1) * nPtsPlane;
334 const int o2 = n * nPtsPlane;
335 for (int j = 1; j < np1; ++j)
336 {
337 for (int k = 1; k < np0; ++k)
338 {
339 outfile << cnt + (j - 1) * np0 + (k - 1) + o1 + 1 << " ";
340 outfile << cnt + (j - 1) * np0 + (k - 1) + o2 + 1 << " ";
341 outfile << cnt + (j - 1) * np0 + k + o2 + 1 << " ";
342 outfile << cnt + (j - 1) * np0 + k + o1 + 1 << " ";
343 outfile << cnt + j * np0 + (k - 1) + o1 + 1 << " ";
344 outfile << cnt + j * np0 + (k - 1) + o2 + 1 << " ";
345 outfile << cnt + j * np0 + k + o2 + 1 << " ";
346 outfile << cnt + j * np0 + k + o1 + 1 << endl;
347 cnt2++;
348 }
349 }
350 }
351
352 cnt += np0 * np1;
353 }
354}
355
357 int expansion, int istrip)
358{
359 // If there is only one plane (e.g. HalfMode), we write a 2D plane.
360 if (m_planes.size() == 1)
361 {
362 m_planes[0]->WriteVtkPieceHeader(outfile, expansion);
363 return;
364 }
365
366 // If we are using Fourier points, output extra plane to fill domain
367 int outputExtraPlane = 0;
368 if (m_homogeneousBasis->GetBasisType() == LibUtilities::eFourier &&
369 m_homogeneousBasis->GetPointsType() ==
371 {
372 outputExtraPlane = 1;
373 }
374
375 int i, j, k;
376 int nq0 = (*m_exp)[expansion]->GetNumPoints(0);
377 int nq1 = (*m_exp)[expansion]->GetNumPoints(1);
378 int nq2 = m_planes.size() + outputExtraPlane;
379 int ntot = nq0 * nq1 * nq2;
380 int ntotminus = (nq0 - 1) * (nq1 - 1) * (nq2 - 1);
381
382 Array<OneD, NekDouble> coords[3];
383 coords[0] = Array<OneD, NekDouble>(ntot);
384 coords[1] = Array<OneD, NekDouble>(ntot);
385 coords[2] = Array<OneD, NekDouble>(ntot);
386 v_GetCoords(expansion, coords[0], coords[1], coords[2]);
387
388 if (outputExtraPlane)
389 {
390 // Copy coords[0] and coords[1] to extra plane
392 Vmath::Vcopy(nq0 * nq1, coords[0], 1,
393 tmp = coords[0] + (nq2 - 1) * nq0 * nq1, 1);
394 Vmath::Vcopy(nq0 * nq1, coords[1], 1,
395 tmp = coords[1] + (nq2 - 1) * nq0 * nq1, 1);
396 // Fill coords[2] for extra plane
397 NekDouble z = coords[2][nq0 * nq1 * m_planes.size() - 1] +
398 (coords[2][nq0 * nq1] - coords[2][0]);
399 Vmath::Fill(nq0 * nq1, z, tmp = coords[2] + (nq2 - 1) * nq0 * nq1, 1);
400 }
401
402 NekDouble DistStrip;
403 m_session->LoadParameter("DistStrip", DistStrip, 0);
404 // Reset the z-coords for homostrips
405 for (int i = 0; i < ntot; i++)
406 {
407 coords[2][i] += istrip * DistStrip;
408 }
409
410 outfile << " <Piece NumberOfPoints=\"" << ntot << "\" NumberOfCells=\""
411 << ntotminus << "\">" << endl;
412 outfile << " <Points>" << endl;
413 outfile << " <DataArray type=\"Float64\" "
414 << "NumberOfComponents=\"3\" format=\"ascii\">" << endl;
415 outfile << " ";
416 for (i = 0; i < ntot; ++i)
417 {
418 for (j = 0; j < 3; ++j)
419 {
420 outfile << coords[j][i] << " ";
421 }
422 outfile << endl;
423 }
424 outfile << endl;
425 outfile << " </DataArray>" << endl;
426 outfile << " </Points>" << endl;
427 outfile << " <Cells>" << endl;
428 outfile << " <DataArray type=\"Int32\" "
429 << "Name=\"connectivity\" format=\"ascii\">" << endl;
430 for (i = 0; i < nq0 - 1; ++i)
431 {
432 for (j = 0; j < nq1 - 1; ++j)
433 {
434 for (k = 0; k < nq2 - 1; ++k)
435 {
436 outfile << k * nq0 * nq1 + j * nq0 + i << " "
437 << k * nq0 * nq1 + j * nq0 + i + 1 << " "
438 << k * nq0 * nq1 + (j + 1) * nq0 + i + 1 << " "
439 << k * nq0 * nq1 + (j + 1) * nq0 + i << " "
440 << (k + 1) * nq0 * nq1 + j * nq0 + i << " "
441 << (k + 1) * nq0 * nq1 + j * nq0 + i + 1 << " "
442 << (k + 1) * nq0 * nq1 + (j + 1) * nq0 + i + 1 << " "
443 << (k + 1) * nq0 * nq1 + (j + 1) * nq0 + i << endl;
444 }
445 }
446 }
447 outfile << endl;
448 outfile << " </DataArray>" << endl;
449 outfile << " <DataArray type=\"Int32\" "
450 << "Name=\"offsets\" format=\"ascii\">" << endl;
451 for (i = 0; i < ntotminus; ++i)
452 {
453 outfile << i * 8 + 8 << " ";
454 }
455 outfile << endl;
456 outfile << " </DataArray>" << endl;
457 outfile << " <DataArray type=\"UInt8\" "
458 << "Name=\"types\" format=\"ascii\">" << endl;
459 for (i = 0; i < ntotminus; ++i)
460 {
461 outfile << "12 ";
462 }
463 outfile << endl;
464 outfile << " </DataArray>" << endl;
465 outfile << " </Cells>" << endl;
466 outfile << " <PointData>" << endl;
467}
468
470 const Array<OneD, const NekDouble> &inarray,
472{
473 int cnt = 0;
474 NekDouble errL2, err = 0.0;
476 Array<OneD, NekDouble> local_w(m_planes.size());
477
478 for (int n = 0; n < m_planes.size(); n++)
479 {
480 local_w[n] = w[m_transposition->GetPlaneID(n)];
481 }
482
483 if (soln == NullNekDouble1DArray)
484 {
485 for (int n = 0; n < m_planes.size(); ++n)
486 {
487 errL2 = m_planes[n]->L2(inarray + cnt);
488 cnt += m_planes[n]->GetTotPoints();
489 err += errL2 * errL2 * local_w[n] * m_lhom * 0.5;
490 }
491 }
492 else
493 {
494 for (int n = 0; n < m_planes.size(); ++n)
495 {
496 errL2 = m_planes[n]->L2(inarray + cnt, soln + cnt);
497 cnt += m_planes[n]->GetTotPoints();
498 err += errL2 * errL2 * local_w[n] * m_lhom * 0.5;
499 }
500 }
501 m_comm->GetColumnComm()->AllReduce(err, LibUtilities::ReduceSum);
502
503 return sqrt(err);
504}
505
507{
508 Array<OneD, NekDouble> energy(m_planes.size() / 2);
509 NekDouble area = 0.0;
510
511 // Calculate total area of elements.
512 for (int n = 0; n < m_planes[0]->GetExpSize(); ++n)
513 {
515 1.0);
516 area += m_planes[0]->GetExp(n)->Integral(inarray);
517 }
518
519 m_comm->GetRowComm()->AllReduce(area, LibUtilities::ReduceSum);
520
521 // Calculate L2 norm of real/imaginary planes.
522 for (int n = 0; n < m_planes.size(); n += 2)
523 {
524 NekDouble err;
525
526 energy[n / 2] = 0;
527
528 for (int i = 0; i < m_planes[n]->GetExpSize(); ++i)
529 {
530 LocalRegions::ExpansionSharedPtr exp = m_planes[n]->GetExp(i);
531 Array<OneD, NekDouble> phys(exp->GetTotPoints());
532 exp->BwdTrans(m_planes[n]->GetCoeffs() +
534 phys);
535 err = exp->L2(phys);
536 energy[n / 2] += err * err;
537
538 exp = m_planes[n + 1]->GetExp(i);
539 exp->BwdTrans(m_planes[n + 1]->GetCoeffs() +
540 m_planes[n + 1]->GetCoeff_Offset(i),
541 phys);
542 err = exp->L2(phys);
543 energy[n / 2] += err * err;
544 }
545
546 m_comm->GetRowComm()->AllReduce(energy[n / 2], LibUtilities::ReduceSum);
547 energy[n / 2] /= 2.0 * area;
548 }
549
550 return energy;
551}
552} // namespace MultiRegions
553} // namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
Describes the specification for a Basis.
Definition: Basis.h:47
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
Abstraction of a two-dimensional multi-elemental expansion which is merely a collection of local expa...
void GenExpList3DHomogeneous1D(const SpatialDomains::ExpansionInfoMap &expansions, const Collections::ImplementationType ImpType)
virtual NekDouble v_L2(const Array< OneD, const NekDouble > &inarray, const Array< OneD, const NekDouble > &soln=NullNekDouble1DArray) override
virtual void v_GetCoords(Array< OneD, NekDouble > &coord_0, Array< OneD, NekDouble > &coord_1, Array< OneD, NekDouble > &coord_2) override
void SetCoeffPhys(void)
Definition of the total number of degrees of freedom and quadrature points. Sets up the storage for m...
virtual Array< OneD, const NekDouble > v_HomogeneousEnergy(void) override
virtual void v_WriteVtkPieceHeader(std::ostream &outfile, int expansion, int istrip) override
virtual void v_WriteTecplotConnectivity(std::ostream &outfile, int expansion) override
Abstraction of a two-dimensional multi-elemental expansion which is merely a collection of local expa...
NekDouble m_lhom
Width of homogeneous direction.
LibUtilities::TranspositionSharedPtr m_transposition
Array< OneD, ExpListSharedPtr > m_planes
LibUtilities::BasisSharedPtr m_homogeneousBasis
Definition of the total number of degrees of freedom and quadrature points. Sets up the storage for m...
Array< OneD, NekDouble > m_coeffs
Concatenation of all local expansion coefficients.
Definition: ExpList.h:1092
const Array< OneD, const NekDouble > & GetCoeffs() const
This function returns (a reference to) the array (implemented as m_coeffs) containing all local expa...
Definition: ExpList.h:1967
int GetCoeff_Offset(int n) const
Get the start offset position for a local contiguous list of coeffs correspoinding to element n.
Definition: ExpList.h:2102
Array< OneD, int > m_coeff_offset
Offset of elemental data into the array m_coeffs.
Definition: ExpList.h:1136
LibUtilities::CommSharedPtr m_comm
Communicator.
Definition: ExpList.h:1065
std::shared_ptr< LocalRegions::ExpansionVector > m_exp
The list of local expansions.
Definition: ExpList.h:1127
int m_ncoeffs
The total number of local degrees of freedom. m_ncoeffs .
Definition: ExpList.h:1072
const std::shared_ptr< LocalRegions::ExpansionVector > GetExp() const
This function returns the vector of elements in the expansion.
Definition: ExpList.h:2094
SpatialDomains::MeshGraphSharedPtr m_graph
Mesh associated with this expansion list.
Definition: ExpList.h:1069
LibUtilities::SessionReaderSharedPtr m_session
Session.
Definition: ExpList.h:1067
Array< OneD, int > m_phys_offset
Offset of elemental data into the array m_phys.
Definition: ExpList.h:1138
ExpansionType m_expType
Exapnsion type.
Definition: ExpList.h:1060
Array< OneD, NekDouble > m_phys
The global expansion evaluated at the quadrature points.
Definition: ExpList.h:1108
int GetTotPoints(void) const
Returns the total number of quadrature points m_npoints .
Definition: ExpList.h:1572
std::shared_ptr< SessionReader > SessionReaderSharedPtr
@ eFourierEvenlySpaced
1D Evenly-spaced points using Fourier Fit
Definition: PointsType.h:76
@ eFourier
Fourier Expansion .
Definition: BasisType.h:57
std::shared_ptr< Expansion > ExpansionSharedPtr
Definition: Expansion.h:68
std::shared_ptr< ExpList > ExpListSharedPtr
Shared pointer to an ExpList object.
std::shared_ptr< MeshGraph > MeshGraphSharedPtr
Definition: MeshGraph.h:176
std::map< int, ExpansionInfoShPtr > ExpansionInfoMap
Definition: MeshGraph.h:143
std::vector< double > w(NPUPPER)
std::vector< double > z(NPUPPER)
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
static Array< OneD, NekDouble > NullNekDouble1DArray
double NekDouble
void Smul(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Scalar multiply y = alpha*x.
Definition: Vmath.cpp:245
void Fill(int n, const T alpha, T *x, const int incx)
Fill a vector with a constant value.
Definition: Vmath.cpp:43
void Sadd(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Add scalar y = alpha + x.
Definition: Vmath.cpp:379
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1191
scalarT< T > sqrt(scalarT< T > in)
Definition: scalar.hpp:294