MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
structuredgrid.cpp
Go to the documentation of this file.
1// Copyright (C) 2024 The m-AIA AUTHORS
2//
3// This file is part of m-AIA (https://git.rwth-aachen.de/aia/m-AIA/m-AIA)
4//
5// SPDX-License-Identifier: LGPL-3.0-only
6
7#include "structuredgrid.h"
8#include <numeric>
9#include <vector>
10#include "COMM/mpioverride.h"
11#include "FV/fvstructuredcell.h"
15#include "IO/parallelio.h"
16#include "UTIL/parallelfor.h"
17#include "globals.h"
18#include "globalvariables.h"
19
20using namespace std;
21
27template <MInt nDim>
28StructuredGrid<nDim>::StructuredGrid(const MInt solverId_, const MPI_Comm comm)
29 : m_solverId(solverId_), m_mpiComm(comm) {
30 MPI_Comm_rank(mpiComm(), &m_domainId);
31 MPI_Comm_size(mpiComm(), &m_noDomains);
32
41 m_gridInputFileName = Context::getSolverProperty<MString>("gridInputFileName", m_solverId, AT_);
42 m_noGhostLayers = Context::getSolverProperty<MInt>("noGhostLayers", m_solverId, AT_);
43
44 mAlloc(m_nPoints, nDim, "m_nPoints", -1, AT_);
45 mAlloc(m_nActivePoints, nDim, "m_nActivePoints", -1, AT_);
46 mAlloc(m_nCells, nDim, "m_nCells", -1, AT_);
47 mAlloc(m_nActiveCells, nDim, "m_nActiveCells", -1, AT_);
48 mAlloc(m_nOffsetCells, nDim, "m_nOffsetCells", -1, AT_);
49 mAlloc(m_nOffsetPoints, nDim, "m_nOffsetPoints", -1, AT_);
50 mAlloc(m_nBlockCells, nDim, "m_nBlockCells", -1, AT_);
51
52 mAlloc(m_periodicDisplacements, nDim * nDim, "m_periodicDisplacement", F0, AT_);
53
54 m_totalNoCells = 0;
55 m_noPoints = 1;
56 m_noActiveCells = 1;
57 m_noCells = 1;
58
59 mAlloc(m_singularity, 30, "m_singularity", AT_);
60}
61
62
67template <MInt nDim>
69 if(m_domainId == 0) {
70 cout << "Doing block decomposition..." << endl;
71 }
85 m_readDecompositionFromFile = false;
86 m_readDecompositionFromFile =
87 Context::getSolverProperty<MBool>("readPartitionFromFile", m_solverId, AT_, &m_readDecompositionFromFile);
88
89 ParallelIoHdf5 pio(m_gridInputFileName, maia::parallel_io::PIO_READ, m_mpiComm);
90 // unique grid identifier to associate grid and solution file on restart
91 MInt noBlocksType = pio.getAttributeType("noBlocks", "");
92 if(noBlocksType == 1) {
93 pio.getAttribute<MInt>(&m_noBlocks, "noBlocks", "");
94 } else if(noBlocksType == 0) {
95 MFloat noBlocksFloat = -1.0;
96 pio.getAttribute<MFloat>(&noBlocksFloat, "noBlocks", "");
97 m_noBlocks = (MInt)noBlocksFloat;
98 }
99
100 pio.getAttribute(&m_uID, "UID", "");
101
102 m_partition = make_unique<StructuredDecomposition<nDim>>(m_noBlocks, m_gridInputFileName, m_mpiComm, m_noDomains);
103
104 if(readFromFile) {
105 m_log << "reading repartition from file ....." << endl;
106 MBool success = m_partition->readFromFile();
107 if(!success) {
108 m_log << "..... Reading from partition file FAILED --> new decomposition activated" << endl;
109 m_partition->decompose();
110 }
111 m_log << "..... Reading in successful" << endl;
112 } else {
113 m_partition->decompose();
114 }
115
116 m_totalNoCells = 0;
117 for(MInt i = 0; i < m_noBlocks; i++) {
118 MLong temp = 1;
119 for(MInt dim = 0; dim < nDim; dim++) {
120 temp *= getBlockNoCells(i, dim);
121 }
122 if(temp != 1) m_totalNoCells += temp;
123 }
124 if(m_domainId == 0) {
125 cout << "Doing block decomposition... SUCCESSFUL!" << endl;
126 }
127}
128
133template <MInt nDim>
135 m_blockId = getMyBlockId();
136 for(MInt i = 0; i < nDim; i++) {
137 m_nOffsetCells[i] = getMyOffset(i);
138 if(getMyOffset(i) > 0) {
139 m_nOffsetPoints[i] = getMyOffset(i) + 1;
140 } else {
141 m_nOffsetPoints[i] = 0;
142 }
143 m_nActivePoints[i] = getMyActivePoints(i);
144 m_nPoints[i] = m_nActivePoints[i] + 2 * m_noGhostLayers;
145
146 m_nActiveCells[i] = m_nActivePoints[i] - 1;
147 m_nCells[i] = m_nPoints[i] - 1;
148 m_noPoints *= m_nPoints[i];
149 m_noActiveCells *= m_nActiveCells[i];
150 m_noCells *= m_nCells[i];
151 }
152
153 mAlloc(m_cells->coordinates, nDim, m_noCells, "m_cells->coordinates", AT_);
154 mAlloc(m_coordinates, nDim, m_noPoints, "m_coordinates", -1.01010101, AT_);
155
170 m_movingGrid = false;
171 if(Context::propertyExists("movingGrid", m_solverId)) {
172 m_movingGrid = Context::getSolverProperty<MBool>("movingGrid", m_solverId, AT_, &m_movingGrid);
173 }
174
175 if(m_movingGrid) {
176 mAlloc(m_velocity, nDim, m_noPoints, "m_velocity", F0, AT_);
177 mAlloc(m_acceleration, nDim, m_noPoints, "m_acceleration", F0, AT_);
178 mAlloc(m_oldCoordinates, nDim, m_noPoints, "m_mgOldCoordinates", F0, AT_);
179 mAlloc(m_initCoordinates, nDim, m_noPoints, "m_mgInitCoordinates", F0, AT_);
180 }
181}
182
186template <MInt nDim>
188 mAlloc(m_cells->cornerJac, m_noCells, "m_cells->cornerJac", 123.123, AT_);
189 mAlloc(m_cells->cellJac, m_noCells, "m_cells->cellJac", 123.123, AT_);
190 mAlloc(m_cells->oldCellJac, m_noCells, "m_cells->oldCellJac", 123.123, AT_);
191 IF_CONSTEXPR(nDim == 2) mAlloc(m_cells->surfJac, m_noCells * 2, "m_cells->surfJac", AT_);
192 mAlloc(m_cells->cellMetrics, nDim * nDim, m_noCells, "cellMetrics", 123.123, AT_);
193 mAlloc(m_cells->cornerMetrics, nDim * nDim, m_noCells, "cornerMetrics", 123.123, AT_);
194 mAlloc(m_cells->surfaceMetrics, nDim * nDim, m_noCells, "surfaceMetrics", 123.123, AT_);
195
196 // By now only available in 2D
197 IF_CONSTEXPR(nDim == 2) {
198 if(m_hasSingularity) {
199 MInt no_cells = 0;
200 for(MInt i = 0; i < m_hasSingularity; ++i) {
201 // only correct for bc 6000 not for bc 4000-5000
202 if(m_singularity[i].BC == -6000) {
203 for(MInt j = 0; j < nDim; j++) {
204 const MInt len = m_singularity[i].end[j] - m_singularity[i].start[j];
205 ASSERT(len == 1, "");
206 }
207 no_cells += 1;
208 }
209 }
210
211 const MInt no_metrics = 4;
212
213 mAlloc(m_cells->surfaceMetricsSingularity, no_metrics, no_cells, "surfaceMetrics", 123.123, AT_);
214 }
215 }
216}
217
218
222template <MInt nDim>
224 ParallelIoHdf5 pio(m_gridInputFileName, maia::parallel_io::PIO_READ, m_mpiComm);
225
226 // create the string to contain the datasetname in the file
227 MString sBlockName = "/block";
228 stringstream dummy1;
229 dummy1 << m_blockId << "/";
230 sBlockName += dummy1.str();
231
232 MString varNames[] = {"x", "y", "z"};
233 ParallelIo::size_type offset[3];
234 ParallelIo::size_type size[3];
235 for(MInt i = 0; i < nDim; ++i) {
236 offset[i] = m_nOffsetCells[i];
237 size[i] = m_nActivePoints[i];
238 }
239
240 for(MInt dim = 0; dim < nDim; dim++) {
241 pio.readArray(m_coordinates[dim], sBlockName, varNames[dim], nDim, offset, size);
242 }
243
244 moveCellPoints(); // shifts points and cells in the respective array to account for the ghost cells
245}
246
247
253template <MInt nDim>
255 TRACE();
256 // first every process needs to create the datasets and the structure where the
257 // data will be stored!
258 m_log << "writing the partitionedGrid.hdf5 File" << endl;
259 cout << "writing the partitionedGrid.hdf5 File" << endl;
260 const char* fileName = "partitionedGrid.hdf5";
261 ParallelIoHdf5 pio(fileName, maia::parallel_io::PIO_REPLACE, m_mpiComm);
262 MInt noDomains_ = noDomains();
263 pio.setAttribute(noDomains_, "noBlocks", "");
264 MString gridVarNames[3] = {"x", "y", "z"};
265 for(MInt i = 0; i < noDomains(); i++) {
266 // create datasets for the io library
267 ParallelIo::size_type noPoints[nDim] = {};
268 for(MInt j = 0; j < nDim; j++) {
269 noPoints[j] = getActivePoints(i, j) + 2 * m_noGhostLayers;
270 }
271
272 stringstream path;
273 path << i;
274 MString partitionPathStr = "block";
275 partitionPathStr += path.str();
276 const char* partitionPath = partitionPathStr.c_str();
277 for(MInt dim = 0; dim < nDim; ++dim) {
278 pio.defineArray(maia::parallel_io::PIO_FLOAT, partitionPath, gridVarNames[dim], nDim, noPoints);
279 }
280 }
281
282 // write the values into the array so that we can visualize it
283 ParallelIo::size_type offset[3] = {0, 0, 0};
284 ParallelIo::size_type size[3] = {m_nPoints[0], m_nPoints[1], m_nPoints[2]};
285 stringstream path;
286 path << domainId();
287 MString partitionPathStr = "block";
288 partitionPathStr += path.str();
289 for(MInt dim = 0; dim < nDim; ++dim) {
290 pio.writeArray(&m_coordinates[dim][0], partitionPathStr, gridVarNames[dim], nDim, offset, size);
291 }
292}
293
299template <>
301 constexpr MInt nDim = 2;
302
303 std::array<MInt, nDim> begin{0, 0};
304 std::array<MInt, nDim> end{m_nActivePoints[1], m_nActivePoints[0]};
305
306 // two dimensional case
307 maia::parallelFor<true, nDim>(begin, end, [=](const MInt& i, const MInt& j) {
308 const MInt i_org = end[0] - 1 - i;
309 const MInt j_org = end[1] - 1 - j;
310 const MInt i_new = i_org + m_noGhostLayers;
311 const MInt j_new = j_org + m_noGhostLayers;
312 const MInt pointId_org = i_org + (j_org * m_nActivePoints[1]); // position in Array
313 const MInt pointId_new = i_new + (j_new * m_nPoints[1]); // new position in Array
314 for(MInt dim = 0; dim < nDim; ++dim) {
315 m_coordinates[dim][pointId_new] = m_coordinates[dim][pointId_org]; // copy value to the right place
316 m_coordinates[dim][pointId_org] = -1000.0; // for test purposes only
317 }
318 });
319}
320
326template <>
328 constexpr MInt nDim = 3;
329
330 std::array<MInt, nDim> begin{0, 0};
331 std::array<MInt, nDim> end{m_nActivePoints[2], m_nActivePoints[1], m_nActivePoints[0]};
332
333 // three dimensional case
334 maia::parallelFor<true, nDim>(begin, end, [=](const MInt& i, const MInt& j, const MInt& k) {
335 const MInt i_org = end[0] - 1 - i;
336 const MInt j_org = end[1] - 1 - j;
337 const MInt k_org = end[2] - 1 - k;
338 const MInt i_new = i_org + m_noGhostLayers;
339 const MInt j_new = j_org + m_noGhostLayers;
340 const MInt k_new = k_org + m_noGhostLayers;
341
342 const MInt pointId_org = i_org + (j_org + k_org * m_nActivePoints[1]) * m_nActivePoints[2];
343 const MInt pointId_new = i_new + (j_new + k_new * m_nPoints[1]) * m_nPoints[2];
344
345 for(MInt dim = 0; dim < nDim; ++dim) {
346 m_coordinates[dim][pointId_new] = m_coordinates[dim][pointId_org]; // copy value to the right place
347 m_coordinates[dim][pointId_org] = F0;
348 }
349 });
350}
351
358template <MInt nDim>
359void StructuredGrid<nDim>::writeGrid(MString solutionOutput, MString outputFormat) {
360 stringstream fileName;
361 fileName << solutionOutput << "grid" << globalTimeStep << outputFormat;
362 ParallelIoHdf5 pio(fileName.str(), maia::parallel_io::PIO_REPLACE, m_mpiComm);
363
364 pio.setAttribute(m_noBlocks, "noBlocks", "");
365 MString fileTypeName = "grid";
366 pio.setAttribute(fileTypeName, "filetype", "");
367 MString gridTypeName = "structured";
368 pio.setAttribute(gridTypeName, "gridType", "");
369 pio.setAttribute(m_uID, "UID", "");
370 pio.setAttribute(globalTimeStep, "globalTimeStep", "");
371
372 ParallelIo::size_type allPoints[3]{-1, -1, -1};
373 for(MInt i = 0; i < m_noBlocks; ++i) {
374 for(MInt j = 0; j < nDim; ++j) {
375 allPoints[j] = getBlockNoPoints(i, j);
376 }
377 MString blockPathStr = "block" + std::to_string(i);
378 pio.defineArray(maia::parallel_io::PIO_FLOAT, blockPathStr, "x", nDim, allPoints);
379 pio.defineArray(maia::parallel_io::PIO_FLOAT, blockPathStr, "y", nDim, allPoints);
380 IF_CONSTEXPR(nDim == 3) { pio.defineArray(maia::parallel_io::PIO_FLOAT, blockPathStr, "z", nDim, allPoints); }
381 }
382
383 MString blockPathStr = "block" + std::to_string(m_blockId);
384 ParallelIo::size_type offset[nDim]{};
385 ParallelIo::size_type size[nDim]{};
386 ParallelIo::size_type ghostArray[nDim]{};
387 for(MInt dim = 0; dim < nDim; ++dim) {
388 offset[dim] = m_nOffsetCells[dim];
389 size[dim] = m_nActivePoints[dim];
390 ghostArray[dim] = m_noGhostLayers;
391 }
392
393 pio.writeArray(&m_coordinates[0][0], blockPathStr, "x", nDim, offset, size, ghostArray);
394 pio.writeArray(&m_coordinates[1][0], blockPathStr, "y", nDim, offset, size, ghostArray);
395 IF_CONSTEXPR(nDim == 3) { pio.writeArray(&m_coordinates[2][0], blockPathStr, "z", nDim, offset, size, ghostArray); }
396}
397
398
408template <MInt nDim>
409void StructuredGrid<nDim>::exchangePoints(std::vector<unique_ptr<StructuredComm<nDim>>>& sndComm,
410 std::vector<unique_ptr<StructuredComm<nDim>>>& rcvComm,
411 StructuredCommType commType) {
412 std::vector<MPI_Request> sndRequests;
413 std::vector<MPI_Request> rcvRequests;
414 std::vector<MPI_Status> sndStatus;
415 std::vector<MPI_Status> rcvStatus;
416 sndRequests.reserve(sndComm.size());
417 rcvRequests.reserve(rcvComm.size());
418
419 gatherPoints(sndComm, commType);
420 sendPoints(sndComm, commType, sndRequests);
421 receivePoints(rcvComm, commType, rcvRequests);
422
423 sndStatus.resize(sndRequests.size());
424 MPI_Waitall(sndRequests.size(), &sndRequests[0], &sndStatus[0], AT_);
425
426 rcvStatus.resize(rcvRequests.size());
427 MPI_Waitall(rcvRequests.size(), &rcvRequests[0], &rcvStatus[0], AT_);
428
429 scatterPoints(rcvComm, commType);
430}
431
442template <MInt nDim>
443void StructuredGrid<nDim>::gatherPoints(std::vector<unique_ptr<StructuredComm<nDim>>>& sndComm,
444 StructuredCommType commType) {
445 TRACE();
446 for(auto& snd : sndComm) {
447 if(commType != snd->commType) continue;
448
449
450 MFloat** coordinates = m_coordinates;
451 std::array<MInt, nDim> INC{};
452 for(MInt dim = 0; dim < nDim; ++dim) {
453 INC[dim] = m_nPoints[dim];
454 }
455
456 MInt plusOne = 1;
457 if(snd->commType == SINGULAR || snd->commType == PERIODIC_BC_SINGULAR) {
458 coordinates = m_cells->coordinates;
459 plusOne = 0;
460
461 for(MInt dim = 0; dim < nDim; ++dim) {
462 INC[dim] = m_nCells[dim];
463 }
464 }
465
466 MBool isPeriodic = false;
467 if(snd->commType == PERIODIC_BC || snd->commType == PERIODIC_BC_SINGULAR) {
468 isPeriodic = true;
469 }
470
471 std::array<MInt, nDim> begin{};
472 std::array<MInt, nDim> end{};
473 std::array<MInt, nDim> size{};
474
475 for(MInt dim = 0; dim < nDim; ++dim) {
476 begin[dim] = snd->startInfoPoints[dim];
477 end[dim] = snd->endInfoPoints[dim] + plusOne;
478 size[dim] = end[dim] - begin[dim];
479 }
480 const MInt totalSize = std::accumulate(size.begin(), size.end(), 1, std::multiplies<double>());
481
482 // Aliasing the unique_pointer in snd to a raw point is needed for PSTL on NVHPC
483 const MInt bcId = snd->bcId;
484 auto* pointBuffer = snd->pointBuffer.get();
485 if constexpr(nDim == 3) {
486 for(MInt dim = 0; dim < nDim; dim++) {
487 maia::parallelFor<true, nDim>(begin, end, [=](const MInt& i, const MInt& j, const MInt& k) {
488 const MInt pointId = i + (j + k * INC[1]) * INC[2];
489 const MInt bufferId =
490 totalSize * dim + (i - begin[0]) + ((j - begin[1]) + (k - begin[2]) * size[1]) * size[0];
491
492 if(isPeriodic) {
493 MFloat tmppoint = coordinates[dim][pointId];
494 periodicPointsChange(tmppoint, bcId, dim);
495 pointBuffer[bufferId] = tmppoint;
496 } else {
497 pointBuffer[bufferId] = coordinates[dim][pointId];
498 }
499 });
500 }
501 } else if constexpr(nDim == 2) {
502 for(MInt dim = 0; dim < nDim; dim++) {
503 maia::parallelFor<true, nDim>(begin, end, [=](const MInt& i, const MInt& j) {
504 const MInt pointId = i + j * INC[1];
505 const MInt bufferId = totalSize * dim + (i - begin[0]) + (j - begin[1]) * size[0];
506
507 if(isPeriodic) {
508 MFloat tmppoint = coordinates[dim][pointId];
509 periodicPointsChange(tmppoint, bcId, dim);
510 pointBuffer[bufferId] = tmppoint;
511 } else {
512 pointBuffer[bufferId] = coordinates[dim][pointId];
513 }
514 });
515 }
516 }
517 }
518}
519
530template <MInt nDim>
531inline void StructuredGrid<nDim>::periodicPointsChange(MFloat& pt, const MInt type, const MInt dim) {
532 /*
533 case 4401 4402: first periodic direction
534 case 4403 4404: second periodic direction
535 case 4405 4405: third periodic direction
536 */
537
538 // SND Map BC is reversed, therefore we need
539 // to subtract instead of adding and vice versa compared
540 // to the periodicPointsChange in fvstructuredsolverwindowinfo.cpp
541 switch(type) {
542 case 4401:
543 case 4403:
544 case 4405: {
545 const MInt displacementId = (MFloat)(type - 4400 + 1) / 2.0 - 1;
546 pt = pt - m_periodicDisplacements[dim * nDim + displacementId];
547 break;
548 }
549
550 case 4402:
551 case 4404:
552 case 4406: {
553 const MInt displacementId = (MFloat)(type - 4400 + 1) / 2.0 - 1;
554 pt = pt + m_periodicDisplacements[dim * nDim + displacementId];
555 break;
556 }
557
558 default: {
559#ifndef WAR_NVHPC_PSTL
560 std::cout << "ERROR!!! periodic type is wrong!!! in BC call BC: " << type << endl;
561#endif
562 }
563 }
564}
565
575template <MInt nDim>
576void StructuredGrid<nDim>::sendPoints(std::vector<unique_ptr<StructuredComm<nDim>>>& sndComm,
577 StructuredCommType commType,
578 std::vector<MPI_Request>& sndRequests) {
579 TRACE();
580 for(auto& snd : sndComm) {
581 if(commType != snd->commType) continue;
582 MPI_Request request{};
583 const MInt tag = m_domainId + (snd->tagHelper) * m_noDomains;
584 MInt err = MPI_Isend((void*)&snd->pointBuffer[0],
585 snd->pointBufferSize,
586 MPI_DOUBLE,
587 snd->nghbrId,
588 tag,
589 m_mpiComm,
590 &request,
591 AT_,
592 "snd->pointBuffer");
593 sndRequests.push_back(request);
594 if(err) cout << "rank" << m_domainId << "sending throws errors" << endl;
595 }
596}
597
607template <MInt nDim>
608void StructuredGrid<nDim>::receivePoints(std::vector<unique_ptr<StructuredComm<nDim>>>& rcvComm,
609 StructuredCommType commType,
610 std::vector<MPI_Request>& rcvRequests) {
611 TRACE();
612 for(auto& rcv : rcvComm) {
613 if(commType != rcv->commType) continue;
614 MPI_Request request{};
615 const MInt tag = rcv->nghbrId + (rcv->tagHelper) * m_noDomains;
616 MInt err = MPI_Irecv((void*)&rcv->pointBuffer[0],
617 rcv->pointBufferSize,
618 MPI_DOUBLE,
619 rcv->nghbrId,
620 tag,
621 m_mpiComm,
622 &request,
623 AT_,
624 "rcv->pointBuffer");
625 rcvRequests.push_back(request);
626 if(err) cout << "rank" << m_domainId << " receiving throws errors" << endl;
627 }
628}
629
638template <MInt nDim>
639void StructuredGrid<nDim>::scatterPoints(std::vector<unique_ptr<StructuredComm<nDim>>>& rcvComm,
640 StructuredCommType commType) {
641 TRACE();
642
643 // the ordering of the grid points can be different from
644 // sending instance ==> reorder it and copy it to the
645 // right place
646 for(auto& rcv : rcvComm) {
647 if(commType != rcv->commType) continue;
648
649 MFloat** coordinates = m_coordinates;
650 std::array<MInt, nDim> INC{};
651 MInt plusOne = 1;
652
653 for(MInt dim = 0; dim < nDim; ++dim) {
654 INC[dim] = m_nPoints[dim];
655 }
656
657 if(rcv->commType == SINGULAR || rcv->commType == PERIODIC_BC_SINGULAR) {
658 coordinates = m_cells->coordinates;
659 plusOne = 0;
660 for(MInt dim = 0; dim < nDim; ++dim) {
661 INC[dim] = m_nCells[dim];
662 }
663 }
664
665 std::array<MInt, nDim> begin{};
666 std::array<MInt, nDim> end{};
667 std::array<MInt, nDim> size{};
668
669 for(MInt dim = 0; dim < nDim; ++dim) {
670 begin[dim] = rcv->startInfoPoints[dim];
671 end[dim] = rcv->endInfoPoints[dim] + plusOne;
672 size[dim] = end[dim] - begin[dim];
673 }
674 const MInt totalSize = std::accumulate(size.begin(), size.end(), 1, std::multiplies<double>());
675
676 std::array<MInt, nDim> stepBuffer{};
677 std::array<MInt, nDim> startBuffer{};
678 std::array<MInt, nDim> endBuffer{};
679 std::array<MInt, nDim> sizeBuffer{};
680
681 for(MInt j = 0; j < nDim; j++) {
682 stepBuffer[rcv->orderInfo[j]] = rcv->stepInfo[j];
683 }
684
685 for(MInt j = 0; j < nDim; j++) {
686 endBuffer[j] = size[j] - 1;
687 sizeBuffer[rcv->orderInfo[j]] = size[j];
688 if(stepBuffer[j] < 0) {
689 std::swap(startBuffer[j], endBuffer[j]);
690 }
691 }
692
693 // Aliasing the unique_pointer in rcv to a raw point is needed for PSTL on NVHPC
694 auto* pointBuffer = rcv->pointBuffer.get();
695 auto* orderInfo = rcv->orderInfo.data();
696 auto* startInfoCells = rcv->startInfoCells.data();
697 if constexpr(nDim == 3) {
698 for(MInt dim = 0; dim < nDim; dim++) {
699 maia::parallelFor<true, nDim>(begin, end, [=](const MInt& i, const MInt& j, const MInt& k) {
700 std::array<MInt, nDim> start{};
701 start[orderInfo[0]] = startBuffer[0] + (i - startInfoCells[0]) * stepBuffer[0];
702 start[orderInfo[1]] = startBuffer[1] + (j - startInfoCells[1]) * stepBuffer[1];
703 start[orderInfo[2]] = startBuffer[2] + (k - startInfoCells[2]) * stepBuffer[2];
704
705 const MInt bufferId = dim * totalSize + start[0] + (start[1] + start[2] * sizeBuffer[1]) * sizeBuffer[0];
706 const MInt pointId = i + (j + k * INC[1]) * INC[2];
707
708 coordinates[dim][pointId] = pointBuffer[bufferId];
709 });
710 }
711 } else if constexpr(nDim == 2) {
712 for(MInt dim = 0; dim < nDim; dim++) {
713 maia::parallelFor<true, nDim>(begin, end, [=](const MInt& i, const MInt& j) {
714 std::array<MInt, nDim> start{};
715 start[orderInfo[0]] = startBuffer[0] + (i - startInfoCells[0]) * stepBuffer[0];
716 start[orderInfo[1]] = startBuffer[1] + (j - startInfoCells[1]) * stepBuffer[1];
717
718 const MInt bufferId = dim * totalSize + start[0] + start[1] * sizeBuffer[0];
719 const MInt pointId = i + j * INC[1];
720
721 coordinates[dim][pointId] = pointBuffer[bufferId];
722 });
723 }
724 }
725 }
726}
727
732template <MInt nDim>
734 m_cells = structuredCell;
735}
736
737/*=================================================
738 METRICS/JACOBIAN
739 =================================================*/
740
744template <>
746 constexpr MInt nDim = 2;
747
748 maia::parallelFor<true, nDim>(cellBegin(0), cellEnd(0), [=](const MInt& i, const MInt& j) {
749 const MInt IJ = getPointIdFromCell(i, j);
750 const MInt IP1J = getPointIdFromPoint(IJ, 1, 0);
751 const MInt IJP1 = getPointIdFromPoint(IJ, 0, 1);
752 const MInt IP1JP1 = getPointIdFromPoint(IJ, 1, 1);
753 const MInt cellId = cellIndex(i, j);
754
755 for(MInt dim = 0; dim < nDim; dim++) {
756 // average the coordinates for cell centre data
757 m_cells->coordinates[dim][cellId] =
758 F1B4
759 * (m_coordinates[dim][IJ] + m_coordinates[dim][IP1J] + m_coordinates[dim][IJP1] + m_coordinates[dim][IP1JP1]);
760 }
761 });
762}
763
767template <>
769 constexpr MInt nDim = 3;
770
771 maia::parallelFor<true, nDim>(cellBegin(0), cellEnd(0), [=](const MInt& i, const MInt& j, const MInt& k) {
772 const MInt pointId = i + (j + k * m_nPoints[1]) * m_nPoints[2];
773 const MInt IJK = pointId;
774 const MInt IP1JK = pointId + 1;
775 const MInt IJP1K = pointId + m_nPoints[2];
776 const MInt IP1JP1K = IJP1K + 1;
777 const MInt IJKP1 = pointId + m_nPoints[2] * m_nPoints[1];
778 const MInt IP1JKP1 = IJKP1 + 1;
779 const MInt IJP1KP1 = pointId + m_nPoints[2] + m_nPoints[2] * m_nPoints[1];
780 const MInt IP1JP1KP1 = IJP1KP1 + 1;
781 const MInt cellId = i + (j + k * m_nCells[1]) * m_nCells[2];
782
783 // average the coordinates for cell centre data
784 for(MInt dim = 0; dim < nDim; dim++) {
785 m_cells->coordinates[dim][cellId] =
786 F1B8
787 * (m_coordinates[dim][IJK] + m_coordinates[dim][IP1JK] + m_coordinates[dim][IJP1K]
788 + m_coordinates[dim][IP1JP1K] + m_coordinates[dim][IJKP1] + m_coordinates[dim][IP1JKP1]
789 + m_coordinates[dim][IJP1KP1] + m_coordinates[dim][IP1JP1KP1]);
790 }
791 });
792}
793
797template <MInt nDim>
799 TRACE();
800 computeSurfaceMetrics();
801 computeCornerMetrics();
802 computeCellMetrics();
803 IF_CONSTEXPR(nDim == 2) {
804 if(m_hasSingularity) computeSurfaceMetricsSingularity();
805 }
806}
807
811template <MInt nDim>
813 TRACE();
814 computeCornerJacobian();
815 computeCellJacobian();
816 IF_CONSTEXPR(nDim == 2) computeSurfaceJacobian();
817}
818
822template <>
824 TRACE();
825 // jacobian in the physical space is the inverse of the jacobian in computational space
826 constexpr MInt nDim = 2;
827
828 maia::parallelFor<true, nDim>(
829 cellBegin(m_noGhostLayers - 1), cellEnd(m_noGhostLayers), [=](const MInt& i, const MInt& j) {
830 const MInt cellId = cellIndex(i, j);
831 const MFloat cornerJac =
832 m_cells->cornerMetrics[xsd * 2 + xsd][cellId] * m_cells->cornerMetrics[ysd * 2 + ysd][cellId]
833 - m_cells->cornerMetrics[ysd * 2 + xsd][cellId] * m_cells->cornerMetrics[xsd * 2 + ysd][cellId];
834
835 // since metric terms are with omitted jacobian
836 // there is factor of J^3; multiplied with J^-1 (invJac) we get J^2
837 // --> take square root to get J
838 m_cells->cornerJac[cellId] = cornerJac;
839 });
840}
841
845template <>
847 TRACE();
848 // jacobian in the physical space is the inverse of the jacobian in computational space
849 constexpr MInt nDim = 3;
850 maia::parallelFor<true, nDim>(
851 cellBegin(m_noGhostLayers - 1), cellEnd(m_noGhostLayers), [=](const MInt& i, const MInt& j, const MInt& k) {
852 const MInt cellId = cellIndex(i, j, k);
853
854 const MFloat invJac =
855 m_cells->cornerMetrics[xsd * nDim + xsd][cellId]
856 * (m_cells->cornerMetrics[ysd * nDim + ysd][cellId] * m_cells->cornerMetrics[zsd * nDim + zsd][cellId]
857 - m_cells->cornerMetrics[ysd * nDim + zsd][cellId]
858 * m_cells->cornerMetrics[zsd * nDim + ysd][cellId])
859 - m_cells->cornerMetrics[ysd * nDim + xsd][cellId]
860 * (m_cells->cornerMetrics[xsd * nDim + ysd][cellId] * m_cells->cornerMetrics[zsd * nDim + zsd][cellId]
861 - m_cells->cornerMetrics[xsd * nDim + zsd][cellId]
862 * m_cells->cornerMetrics[zsd * nDim + ysd][cellId])
863 + m_cells->cornerMetrics[zsd * nDim + xsd][cellId]
864 * (m_cells->cornerMetrics[xsd * nDim + ysd][cellId] * m_cells->cornerMetrics[ysd * nDim + zsd][cellId]
865 - m_cells->cornerMetrics[xsd * nDim + zsd][cellId]
866 * m_cells->cornerMetrics[ysd * nDim + ysd][cellId]);
867
868 // since metric terms are with omitted jacobian
869 // there is factor of J^3; multiplied with J^-1 (invJac) we get J^2
870 // --> take square root to get J
871 this->m_cells->cornerJac[cellId] = sqrt(invJac);
872 });
873}
874
875
879template <>
881 TRACE();
882 constexpr MInt nDim = 3;
883
884 MFloat** __restrict coords = m_coordinates;
885
886 constexpr MFloat fsqrttwo = F1 / SQRT2;
887
888 constexpr MInt noSubJ = 8;
889 MFloatScratchSpace subJ_(m_noCells, noSubJ, AT_, "subJ");
890 MFloatScratchSpace subJtmp_(m_noCells, noSubJ, AT_, "subJtmp");
891 // Aliasing the scratch space to a raw point is needed for PSTL on NVHPC
892 MFloat* subJ = subJ_.data();
893 MFloat* subJtmp = subJ_.data();
894
895 maia::parallelFor<true, nDim>(
896 cellBegin(m_noGhostLayers), cellEnd(m_noGhostLayers), [=](const MInt& i, const MInt& j, const MInt& k) {
897 // tmp storage for vectors
898 MFloat CP1[3];
899 MFloat CP2[3];
900 MFloat CP3[3];
901 MFloat CP4[3];
902 MFloat CP5[3];
903 MFloat CP6[3];
904 MFloat CP7[3];
905 MFloat CP8[3];
906 MFloat CP9[3];
907 MFloat CP10[3];
908 MFloat CP11[3];
909 MFloat CP12[3];
910 // vectors for metrics
911 MFloat tmpX1[3];
912 MFloat tmpX2[3];
913 MFloat tmpX3[3];
914 MFloat tmpX4[3];
915 MFloat tmpX5[3];
916 MFloat tmpX6[3];
917 // tmp metric storage dxi
918 MFloat DX1[3];
919 // tmp metric storage deta
920 MFloat DX2[3];
921 // tmp metric storage dzeta
922 MFloat DX3[3];
923
924 // auxilliary variables for surface values
925 MFloat S1[3];
926 MFloat S2[3];
927 MFloat S3[3];
928 MFloat S1P[3];
929 MFloat S2P[3];
930 MFloat S3P[3];
931
932 const MInt cellId = cellIndex(i, j, k);
933 const MInt centCellId = cellIndex(i + 1, j + 1, k + 1);
934 const MInt tmpId = getPointIdFromCell(i, j, k);
935
936 const MInt ijk = getPointIdFromPoint(tmpId, 1, 1, 1);
937 const MInt ijpk = getPointIdFromPoint(ijk, 0, 1, 0);
938 const MInt ijkp = getPointIdFromPoint(ijk, 0, 0, 1);
939 const MInt ijpkp = getPointIdFromPoint(ijk, 0, 1, 1);
940 const MInt ipjk = getPointIdFromPoint(ijk, 1, 0, 0);
941 const MInt ipjpk = getPointIdFromPoint(ijk, 1, 1, 0);
942 const MInt ipjkp = getPointIdFromPoint(ijk, 1, 0, 1);
943 const MInt ipjpkp = getPointIdFromPoint(ijk, 1, 1, 1);
944
945 for(MInt isd = xsd; isd < nDim; isd++) {
946 // averaging of the grid points of surface 1 (j+1/2,k+1/2) around corner point
947 S1[isd] = F1B4 * (coords[isd][ijpkp] + coords[isd][ijk] + coords[isd][ijkp] + coords[isd][ijpk]);
948 // averaging of the grid points of surface 2 (i+1/2,k+1/2) around corner point
949 S2[isd] = F1B4 * (coords[isd][ipjk] + coords[isd][ijk] + coords[isd][ipjkp] + coords[isd][ijkp]);
950 // averaging of the grid points of surface 3 (i+1/2,j+1/2) around corner point
951 S3[isd] = F1B4 * (coords[isd][ipjk] + coords[isd][ijk] + coords[isd][ipjpk] + coords[isd][ijpk]);
952 // averaging of the grid points of surface 1p (j+1/2,k+1/2) around corner point
953 S1P[isd] = F1B4 * (coords[isd][ipjpkp] + coords[isd][ipjk] + coords[isd][ipjkp] + coords[isd][ipjpk]);
954 // averaging of the grid points of surface 2p (i+1/2,k+1/2)
955 S2P[isd] = F1B4 * (coords[isd][ipjpk] + coords[isd][ijpk] + coords[isd][ipjpkp] + coords[isd][ijpkp]);
956 // averaging of the grid oints of surface 3p (i+1/2,j+1/2)
957 S3P[isd] = F1B4 * (coords[isd][ipjkp] + coords[isd][ijkp] + coords[isd][ipjpkp] + coords[isd][ijpkp]);
958 }
959
960
964
965 for(MInt isd = xsd; isd < nDim; isd++) {
966 // averaging corner points
967 CP1[isd] = F1B2 * (coords[isd][ipjk] + coords[isd][ijk]);
968 CP2[isd] = F1B2 * (coords[isd][ijpk] + coords[isd][ijk]);
969 CP3[isd] = F1B2 * (coords[isd][ijkp] + coords[isd][ijk]);
970
971 // setting up vectors for new metric terms
972 tmpX1[isd] = (CP2[isd] - CP3[isd]) * fsqrttwo;
973 tmpX2[isd] = (S1[isd] - coords[isd][ijk]) * fsqrttwo;
974
975 tmpX3[isd] = (CP3[isd] - CP1[isd]) * fsqrttwo;
976 tmpX4[isd] = (S2[isd] - coords[isd][ijk]) * fsqrttwo;
977
978 tmpX5[isd] = (S3[isd] - coords[isd][ijk]) * fsqrttwo;
979 tmpX6[isd] = (CP2[isd] - CP1[isd]) * fsqrttwo;
980 }
981
982 this->crossProduct(DX1, tmpX1, tmpX2);
983 this->crossProduct(DX2, tmpX3, tmpX4);
984 this->crossProduct(DX3, tmpX5, tmpX6);
985
986 subJ[noSubJ * cellId + 0] = F0;
987 for(MInt isd = xsd; isd < nDim; isd++) {
988 subJ[noSubJ * cellId + 0] +=
989 (m_cells->coordinates[isd][centCellId] - coords[isd][ijk]) * (DX1[isd] + DX2[isd] + DX3[isd]);
990 }
991
995
996 for(MInt isd = xsd; isd < nDim; isd++) {
997 CP4[isd] = F1B2 * (coords[isd][ipjk] + coords[isd][ipjpk]);
998 CP5[isd] = F1B2 * (coords[isd][ipjk] + coords[isd][ipjkp]);
999
1000 tmpX1[isd] = (S3[isd] - S2[isd]) * fsqrttwo;
1001 tmpX2[isd] = (m_cells->coordinates[isd][centCellId] - CP1[isd]) * fsqrttwo;
1002
1003 tmpX3[isd] = (S2[isd] - coords[isd][ipjk]) * fsqrttwo;
1004 tmpX4[isd] = (CP5[isd] - CP1[isd]) * fsqrttwo;
1005
1006 tmpX5[isd] = (CP4[isd] - CP1[isd]) * fsqrttwo;
1007 tmpX6[isd] = (S3[isd] - coords[isd][ipjk]) * fsqrttwo;
1008 }
1009
1010 this->crossProduct(DX1, tmpX1, tmpX2);
1011 this->crossProduct(DX2, tmpX3, tmpX4);
1012 this->crossProduct(DX3, tmpX5, tmpX6);
1013
1014 subJ[noSubJ * cellId + 1] = F0;
1015 for(MInt isd = xsd; isd < nDim; isd++) {
1016 subJ[noSubJ * cellId + 1] += (S1P[isd] - CP1[isd]) * (DX1[isd] + DX2[isd] + DX3[isd]);
1017 }
1018
1022
1023 for(MInt isd = xsd; isd < nDim; isd++) {
1024 CP6[isd] = F1B2 * (coords[isd][ipjpk] + coords[isd][ijpk]);
1025 CP7[isd] = F1B2 * (coords[isd][ijpkp] + coords[isd][ijpk]);
1026
1027 tmpX1[isd] = (coords[isd][ijpk] - S1[isd]) * fsqrttwo;
1028 tmpX2[isd] = (CP7[isd] - CP2[isd]) * fsqrttwo;
1029
1030 tmpX3[isd] = (S1[isd] - S3[isd]) * fsqrttwo;
1031 tmpX4[isd] = (m_cells->coordinates[isd][centCellId] - CP2[isd]) * fsqrttwo;
1032
1033 tmpX5[isd] = (CP6[isd] - CP2[isd]) * fsqrttwo;
1034 tmpX6[isd] = (coords[isd][ijpk] - S3[isd]) * fsqrttwo;
1035 }
1036
1037 this->crossProduct(DX1, tmpX1, tmpX2);
1038 this->crossProduct(DX2, tmpX3, tmpX4);
1039 this->crossProduct(DX3, tmpX5, tmpX6);
1040
1041 subJ[noSubJ * cellId + 2] = F0;
1042 for(MInt isd = xsd; isd < nDim; isd++) {
1043 subJ[noSubJ * cellId + 2] += (S2P[isd] - CP2[isd]) * (DX1[isd] + DX2[isd] + DX3[isd]);
1044 }
1045
1049
1050 for(MInt isd = xsd; isd < nDim; isd++) {
1051 CP8[isd] = F1B2 * (coords[isd][ipjpkp] + coords[isd][ipjpk]);
1052
1053 tmpX1[isd] = (CP6[isd] - m_cells->coordinates[isd][centCellId]) * fsqrttwo;
1054 tmpX2[isd] = (S2P[isd] - S3[isd]) * fsqrttwo;
1055
1056 tmpX3[isd] = (m_cells->coordinates[isd][centCellId] - CP4[isd]) * fsqrttwo;
1057 tmpX4[isd] = (S1P[isd] - S3[isd]) * fsqrttwo;
1058
1059 tmpX5[isd] = (coords[isd][ipjpk] - S3[isd]) * fsqrttwo;
1060 tmpX6[isd] = (CP6[isd] - CP4[isd]) * fsqrttwo;
1061 }
1062
1063 this->crossProduct(DX1, tmpX1, tmpX2);
1064 this->crossProduct(DX2, tmpX3, tmpX4);
1065 this->crossProduct(DX3, tmpX5, tmpX6);
1066
1067 subJ[noSubJ * cellId + 3] = F0;
1068 for(MInt isd = xsd; isd < nDim; isd++) {
1069 subJ[noSubJ * cellId + 3] += (CP8[isd] - S3[isd]) * (DX1[isd] + DX2[isd] + DX3[isd]);
1070 }
1071
1075
1076 for(MInt isd = xsd; isd < nDim; isd++) {
1077 CP9[isd] = F1B2 * (coords[isd][ipjkp] + coords[isd][ijkp]);
1078 CP10[isd] = F1B2 * (coords[isd][ijpkp] + coords[isd][ijkp]);
1079
1080 tmpX1[isd] = (S1[isd] - coords[isd][ijkp]) * fsqrttwo;
1081 tmpX2[isd] = (CP10[isd] - CP3[isd]) * fsqrttwo;
1082
1083 tmpX3[isd] = (coords[isd][ijkp] - S2[isd]) * fsqrttwo;
1084 tmpX4[isd] = (CP9[isd] - CP3[isd]) * fsqrttwo;
1085
1086 tmpX5[isd] = (m_cells->coordinates[isd][centCellId] - CP3[isd]) * fsqrttwo;
1087 tmpX6[isd] = (S1[isd] - S2[isd]) * fsqrttwo;
1088 }
1089
1090 this->crossProduct(DX1, tmpX1, tmpX2);
1091 this->crossProduct(DX2, tmpX3, tmpX4);
1092 this->crossProduct(DX3, tmpX5, tmpX6);
1093
1094 subJ[noSubJ * cellId + 4] = F0;
1095 for(MInt isd = xsd; isd < nDim; isd++) {
1096 subJ[noSubJ * cellId + 4] += (S3P[isd] - CP3[isd]) * (DX1[isd] + DX2[isd] + DX3[isd]);
1097 }
1098
1102
1103 for(MInt isd = xsd; isd < nDim; isd++) {
1104 CP11[isd] = F1B2 * (coords[isd][ipjkp] + coords[isd][ipjpkp]);
1105
1106 tmpX1[isd] = (m_cells->coordinates[isd][centCellId] - CP9[isd]) * fsqrttwo;
1107 tmpX2[isd] = (S3P[isd] - S2[isd]) * fsqrttwo;
1108
1109 tmpX3[isd] = (CP9[isd] - CP5[isd]) * fsqrttwo;
1110 tmpX4[isd] = (coords[isd][ipjkp] - S2[isd]) * fsqrttwo;
1111
1112 tmpX5[isd] = (S1P[isd] - S2[isd]) * fsqrttwo;
1113 tmpX6[isd] = (m_cells->coordinates[isd][centCellId] - CP5[isd]) * fsqrttwo;
1114 }
1115
1116 this->crossProduct(DX1, tmpX1, tmpX2);
1117 this->crossProduct(DX2, tmpX3, tmpX4);
1118 this->crossProduct(DX3, tmpX5, tmpX6);
1119
1120 subJ[noSubJ * cellId + 5] = F0;
1121 for(MInt isd = xsd; isd < nDim; isd++) {
1122 subJ[noSubJ * cellId + 5] += (CP11[isd] - S2[isd]) * (DX1[isd] + DX2[isd] + DX3[isd]);
1123 }
1124
1128
1129 for(MInt isd = xsd; isd < nDim; isd++) {
1130 CP12[isd] = F1B2 * (coords[isd][ipjpkp] + coords[isd][ijpkp]);
1131
1132 tmpX1[isd] = (CP7[isd] - CP10[isd]) * fsqrttwo;
1133 tmpX2[isd] = (coords[isd][ijpkp] - S1[isd]) * fsqrttwo;
1134
1135 tmpX3[isd] = (CP10[isd] - m_cells->coordinates[isd][centCellId]) * fsqrttwo;
1136 tmpX4[isd] = (S3P[isd] - S1[isd]) * fsqrttwo;
1137
1138 tmpX5[isd] = (S2P[isd] - S1[isd]) * fsqrttwo;
1139 tmpX6[isd] = (CP7[isd] - m_cells->coordinates[isd][centCellId]) * fsqrttwo;
1140 }
1141
1142 this->crossProduct(DX1, tmpX1, tmpX2);
1143 this->crossProduct(DX2, tmpX3, tmpX4);
1144 this->crossProduct(DX3, tmpX5, tmpX6);
1145
1146 subJ[noSubJ * cellId + 6] = F0;
1147 for(MInt isd = xsd; isd < nDim; isd++) {
1148 subJ[noSubJ * cellId + 6] += (CP12[isd] - S1[isd]) * (DX1[isd] + DX2[isd] + DX3[isd]);
1149 }
1150
1154
1155 for(MInt isd = xsd; isd < nDim; isd++) {
1156 tmpX1[isd] = (S2P[isd] - S3P[isd]) * fsqrttwo;
1157 tmpX2[isd] = (CP12[isd] - m_cells->coordinates[isd][centCellId]) * fsqrttwo;
1158
1159 tmpX3[isd] = (S3P[isd] - S1P[isd]) * fsqrttwo;
1160 tmpX4[isd] = (CP11[isd] - m_cells->coordinates[isd][centCellId]) * fsqrttwo;
1161
1162 tmpX5[isd] = (CP8[isd] - m_cells->coordinates[isd][centCellId]) * fsqrttwo;
1163 tmpX6[isd] = (S2P[isd] - S1P[isd]) * fsqrttwo;
1164 }
1165
1166 this->crossProduct(DX1, tmpX1, tmpX2);
1167 this->crossProduct(DX2, tmpX3, tmpX4);
1168 this->crossProduct(DX3, tmpX5, tmpX6);
1169
1170 subJ[noSubJ * cellId + 7] = F0;
1171 for(MInt isd = xsd; isd < nDim; isd++) {
1172 subJ[noSubJ * cellId + 7] +=
1173 (coords[isd][ipjpkp] - m_cells->coordinates[isd][centCellId]) * (DX1[isd] + DX2[isd] + DX3[isd]);
1174 }
1175 });
1176
1180
1181 // copy into dummy array
1182 maia::parallelFor<true>(0, m_noCells, [=](const MInt& cellId) {
1183 for(MInt j = 0; j < 8; j++) {
1184 subJtmp[noSubJ * cellId + j] = subJ[noSubJ * cellId + j];
1185 }
1186 });
1187
1188 // shift subjacobians
1189 maia::parallelFor<true, nDim>(cellBegin(m_noGhostLayers), cellEnd(m_noGhostLayers),
1190 [=](const MInt& i, const MInt& j, const MInt& k) {
1191 const MInt cellId = cellIndex(i, j, k);
1192
1193 subJ[noSubJ * cellId + 0] = subJ[noSubJ * cellIndex(i - 1, j - 1, k - 1) + 7];
1194 subJ[noSubJ * cellId + 1] = subJ[noSubJ * cellIndex(i, j - 1, k - 1) + 6];
1195 subJ[noSubJ * cellId + 2] = subJ[noSubJ * cellIndex(i - 1, j, k - 1) + 5];
1196 subJ[noSubJ * cellId + 3] = subJ[noSubJ * cellIndex(i, j, k - 1) + 4];
1197 });
1198
1199 maia::parallelFor<true, nDim>(cellBegin(m_noGhostLayers - 1), cellEnd(m_noGhostLayers),
1200 [=](const MInt& i, const MInt& j, const MInt& k) {
1201 const MInt cellId = cellIndex(i, j, k);
1202 subJ[noSubJ * cellId + 4] = subJtmp[noSubJ * cellIndex(i - 1, j - 1, k) + 3];
1203 subJ[noSubJ * cellId + 5] = subJtmp[noSubJ * cellIndex(i, j - 1, k) + 2];
1204 subJ[noSubJ * cellId + 6] = subJtmp[noSubJ * cellIndex(i - 1, j, k) + 1];
1205 subJ[noSubJ * cellId + 7] = subJtmp[noSubJ * cellId + 0];
1206 });
1207
1208 // finally jacobian at corner point!
1209 maia::parallelFor<true, nDim>(cellBegin(m_noGhostLayers - 1), cellEnd(m_noGhostLayers),
1210 [=](const MInt& i, const MInt& j, const MInt& k) {
1211 const MInt cellId = cellIndex(i, j, k);
1212
1213 m_cells->cornerJac[cellId] = F0;
1214 for(MInt jacId = 0; jacId < 8; jacId++) {
1215 m_cells->cornerJac[cellId] += subJ[noSubJ * cellId + jacId];
1216 }
1217
1218 m_cells->cornerJac[cellId] = F1B3 * m_cells->cornerJac[cellId];
1219 });
1220}
1221
1225template <>
1227 TRACE();
1228 constexpr MInt nDim = 2;
1229 MFloatScratchSpace subJ(this->m_noCells, 4, AT_, "subJ");
1230 MFloatScratchSpace subJtmp(this->m_noCells, 4, AT_, "subJtmp");
1231
1232 MFloat** __restrict coords = m_coordinates;
1233
1234 subJ.fill(1234.56);
1235 subJtmp.fill(5678.9);
1236
1237 for(MInt j = m_noGhostLayers - 2; j < this->m_nCells[0] - m_noGhostLayers; ++j) {
1238 for(MInt i = m_noGhostLayers - 2; i < this->m_nCells[1] - m_noGhostLayers; ++i) {
1239 const MInt cellId = cellIndex(i, j);
1240 const MInt centCellId = cellIndex(i + 1, j + 1);
1241 const MInt tmpId = getPointIdFromCell(i, j);
1242
1243 const MInt ij = getPointIdFromPoint(tmpId, 1, 1);
1244 const MInt ipj = getPointIdFromPoint(ij, 1, 0);
1245 const MInt ijp = getPointIdFromPoint(ij, 0, 1);
1246 const MInt ipjp = getPointIdFromPoint(ij, 1, 1);
1247
1248 // auxilliary variables for surface values
1249 MFloat S1[2];
1250 MFloat S2[2];
1251 MFloat S1P[2];
1252 MFloat S2P[2];
1253
1254
1255 for(MInt isd = xsd; isd < nDim; isd++) {
1256 S1[isd] = F1B2 * (coords[isd][ijp] + coords[isd][ij]);
1257 S2[isd] = F1B2 * (coords[isd][ipj] + coords[isd][ij]);
1258 S1P[isd] = F1B2 * (coords[isd][ipjp] + coords[isd][ipj]);
1259 S2P[isd] = F1B2 * (coords[isd][ipjp] + coords[isd][ijp]);
1260 }
1261
1262
1263 // vectors for metrics
1264 MFloat tmpX1[2];
1265 MFloat tmpX2[2];
1266
1270
1271 for(MInt isd = xsd; isd < nDim; isd++) {
1272 // averaging corner points is in 2D not necessary, cause of calculated surfaces mid points above
1273
1274 // setting up vectors for new metric terms
1275 tmpX1[isd] = (m_cells->coordinates[isd][centCellId] - coords[isd][ij]) / sqrt(2);
1276 tmpX2[isd] = (S1[isd] - S2[isd]) / sqrt(2);
1277 }
1278
1279 subJ(cellId, 0) = F0;
1280 subJ(cellId, 0) = crossProduct(tmpX1, tmpX2);
1281
1285
1286 for(MInt isd = xsd; isd < nDim; isd++) {
1287 tmpX1[isd] = (S1P[isd] - S2[isd]) / sqrt(2);
1288 tmpX2[isd] = (m_cells->coordinates[isd][centCellId] - m_coordinates[isd][ipj]) / sqrt(2);
1289 }
1290
1291 subJ(cellId, 1) = F0;
1292 subJ(cellId, 1) = crossProduct(tmpX1, tmpX2);
1293
1297
1298 for(MInt isd = xsd; isd < nDim; isd++) {
1299 tmpX1[isd] = (S2P[isd] - S1[isd]) / sqrt(2);
1300 tmpX2[isd] = (m_coordinates[isd][ijp] - m_cells->coordinates[isd][centCellId]) / sqrt(2);
1301 }
1302
1303 subJ(cellId, 2) = F0;
1304 subJ(cellId, 2) = crossProduct(tmpX1, tmpX2);
1305
1309
1310 for(MInt isd = xsd; isd < nDim; isd++) {
1311 tmpX1[isd] = (m_coordinates[isd][ipjp] - m_cells->coordinates[isd][centCellId]) / sqrt(2);
1312 tmpX2[isd] = (S2P[isd] - S1P[isd]) / sqrt(2);
1313 }
1314
1315 subJ(cellId, 3) = F0;
1316 subJ(cellId, 3) = crossProduct(tmpX1, tmpX2);
1317 }
1318 }
1319
1320
1324
1325 // copy into dummy array
1326 for(MInt i = 0; i < m_noCells; i++) {
1327 for(MInt j = 0; j < 4; j++) {
1328 subJtmp(i, j) = subJ(i, j);
1329 }
1330 }
1331
1332 // shift subjacobians
1333
1334 for(MInt j = m_noGhostLayers - 1; j < this->m_nCells[0] - m_noGhostLayers; j++) {
1335 for(MInt i = m_noGhostLayers - 1; i < this->m_nCells[1] - m_noGhostLayers; i++) {
1336 MInt cellId = cellIndex(i, j);
1337
1338 subJ(cellId, 0) = subJtmp(cellIndex(i - 1, j - 1), 3);
1339 subJ(cellId, 1) = subJtmp(cellIndex(i, j - 1), 2);
1340 subJ(cellId, 2) = subJtmp(cellIndex(i - 1, j), 1);
1341 subJ(cellId, 3) = subJtmp(cellIndex(i, j), 0);
1342 }
1343 }
1344
1345
1346 // finally jacobian at corner point!
1347 for(MInt j = m_noGhostLayers - 1; j < this->m_nCells[0] - m_noGhostLayers; j++) {
1348 for(MInt i = m_noGhostLayers - 1; i < this->m_nCells[1] - m_noGhostLayers; i++) {
1349 MInt cellId = cellIndex(i, j);
1350
1351 m_cells->cornerJac[cellId] = F0;
1352 for(MInt jacId = 0; jacId < 4; jacId++) {
1353 m_cells->cornerJac[cellId] += subJ(cellId, jacId);
1354 }
1355
1356
1357 m_cells->cornerJac[cellId] = m_cells->cornerJac[cellId];
1358 }
1359 }
1360}
1361
1365template <>
1367 TRACE();
1368 constexpr MInt nDim = 3;
1369 MFloat** __restrict coords = m_coordinates;
1370
1371 maia::parallelFor<true, nDim>(
1372 cellBegin(m_noGhostLayers - 1), cellEnd(1), [=](const MInt& i, const MInt& j, const MInt& k) {
1373 const MInt cellId = cellIndex(i, j, k);
1374
1375 const MInt ijk = getPointIdFromCell(i, j, k);
1376 const MInt ijpk = getPointIdFromPoint(ijk, 0, 1, 0);
1377 const MInt ijkp = getPointIdFromPoint(ijk, 0, 0, 1);
1378 const MInt ijpkp = getPointIdFromPoint(ijk, 0, 1, 1);
1379 const MInt ipjk = getPointIdFromPoint(ijk, 1, 0, 0);
1380 const MInt ipjpk = getPointIdFromPoint(ijk, 1, 1, 0);
1381 const MInt ipjkp = getPointIdFromPoint(ijk, 1, 0, 1);
1382 const MInt ipjpkp = getPointIdFromPoint(ijk, 1, 1, 1);
1383
1384 MFloat DX1[3] = {F0, F0, F0};
1385 MFloat DX2[3] = {F0, F0, F0};
1386 MFloat DX3[3] = {F0, F0, F0};
1387
1388 MFloat tmpX1[3] = {F0, F0, F0};
1389 MFloat tmpX2[3] = {F0, F0, F0};
1390 MFloat tmpX3[3] = {F0, F0, F0};
1391 MFloat tmpX4[3] = {F0, F0, F0};
1392 MFloat tmpX5[3] = {F0, F0, F0};
1393 MFloat tmpX6[3] = {F0, F0, F0};
1394
1395 for(MInt isd = xsd; isd < nDim; isd++) {
1396 // setting up vectors for new metric terms
1397 tmpX1[isd] = (coords[isd][ijpk] - coords[isd][ijkp]);
1398 tmpX2[isd] = (coords[isd][ijpkp] - coords[isd][ijk]);
1399
1400 tmpX3[isd] = (coords[isd][ijkp] - coords[isd][ipjk]);
1401 tmpX4[isd] = (coords[isd][ipjkp] - coords[isd][ijk]);
1402
1403 tmpX5[isd] = (coords[isd][ipjpk] - coords[isd][ijk]);
1404 tmpX6[isd] = (coords[isd][ijpk] - coords[isd][ipjk]);
1405 }
1406
1407 this->crossProduct(DX1, tmpX1, tmpX2);
1408 this->crossProduct(DX2, tmpX3, tmpX4);
1409 this->crossProduct(DX3, tmpX5, tmpX6);
1410
1411 MFloat jac = F0;
1412 for(MInt isd = xsd; isd < nDim; isd++) {
1413 jac += (coords[isd][ipjpkp] - coords[isd][ijk]) * F1B2 * (DX1[isd] + DX2[isd] + DX3[isd]);
1414 }
1415
1416
1417 m_cells->cellJac[cellId] = F1B3 * fabs(jac);
1418 });
1419}
1420
1424template <>
1426 TRACE();
1427 constexpr MInt nDim = 2;
1428 const MFloat* const* const RESTRICT coords = m_coordinates;
1429
1430 maia::parallelFor<true, nDim>(cellBegin(m_noGhostLayers - 1), cellEnd(1), [=](const MInt& i, const MInt& j) {
1431 const MInt cellId = cellIndex(i, j);
1432 const MInt IJ = getPointIdFromCell(i, j);
1433 const MInt IPJ = getPointIdFromPoint(IJ, 1, 0);
1434 const MInt IJP = getPointIdFromPoint(IJ, 0, 1);
1435 const MInt IPJP = getPointIdFromPoint(IJ, 1, 1);
1436
1437 MFloat diag1[2] = {F0, F0};
1438 MFloat diag2[2] = {F0, F0};
1439
1440 for(MInt isd = xsd; isd < nDim; isd++) {
1441 diag1[isd] = (coords[isd][IPJP] - coords[isd][IJ]);
1442 diag2[isd] = (coords[isd][IJP] - coords[isd][IPJ]);
1443 }
1444
1445 const MFloat area = F1B2 * this->crossProduct(diag1, diag2);
1446
1447 m_cells->cellJac[cellId] = area;
1448 });
1449}
1450
1451
1456template <>
1458 TRACE();
1459
1460 // Jacobian: Dxi/Dx * Deta/Dy - Deta/Dx * Dxi/Dy
1461 constexpr MInt nDim = 2;
1462 maia::parallelFor<true, nDim>(cellBegin(0), cellEnd(1), [=](const MInt& i, const MInt& j) {
1463 const MInt IJ = cellIndex(i, j);
1464 const MInt IPJ = cellIndex(i + 1, j);
1465 const MInt IJP = cellIndex(i, j + 1);
1466 const MInt ipjp = getPointIdFromPoint(getPointIdFromCell(i, j), 1, 1);
1467 const MInt ipj = getPointIdFromPoint(getPointIdFromCell(i, j), 1, 0);
1468 const MInt ijp = getPointIdFromPoint(getPointIdFromCell(i, j), 0, 1);
1469
1470 MFloat DcoordDxi[nDim];
1471 MFloat DcoordDeta[nDim];
1472
1473 for(MInt dim = 0; dim < nDim; ++dim) {
1474 // compute d(x,y,z)/dxi
1475 DcoordDxi[dim] = m_cells->coordinates[dim][IPJ] - m_cells->coordinates[dim][IJ];
1476
1477 // compute d(x,y,z)/deta
1478 DcoordDeta[dim] = m_coordinates[dim][ipjp] - m_coordinates[dim][ipj];
1479 }
1480
1481 this->m_cells->surfJac[IJ] = DcoordDeta[1] * DcoordDxi[0] - DcoordDxi[1] * DcoordDeta[0];
1482
1483 for(MInt dim = 0; dim < nDim; ++dim) {
1484 // compute d(x,y,z)/dxi
1485 DcoordDxi[dim] = m_coordinates[dim][ipjp] - m_coordinates[dim][ijp];
1486
1487 // compute d(x,y,z)/deta
1488 DcoordDeta[dim] = m_cells->coordinates[dim][IJP] - m_cells->coordinates[dim][IJ];
1489 }
1490
1491 this->m_cells->surfJac[m_noCells + IJ] = DcoordDeta[1] * DcoordDxi[0] - DcoordDxi[1] * DcoordDeta[0];
1492 });
1493}
1494
1495
1500template <>
1502 TRACE();
1503 mTerm(1, AT_, "Not implemented for 3D");
1504}
1505
1509template <>
1511 TRACE();
1512 constexpr MInt nDim = 2;
1513 maia::parallelFor<true, nDim>(cellBegin(m_noGhostLayers - 1), cellEnd(1), [=](const MInt& i, const MInt& j) {
1514 const MInt cellId = cellIndex(i, j);
1515 // auxilliary variables
1516 MFloat DcoordDxi[2];
1517 MFloat DcoordDeta[2];
1518
1519 for(MInt isd = xsd; isd < nDim; isd++) {
1520 DcoordDxi[isd] =
1521 (m_cells->coordinates[isd][cellIndex(i + 1, j)] - m_cells->coordinates[isd][cellIndex(i - 1, j)]) * F1B2;
1522
1523 DcoordDeta[isd] =
1524 (m_cells->coordinates[isd][cellIndex(i, j + 1)] - m_cells->coordinates[isd][cellIndex(i, j - 1)]) * F1B2;
1525 }
1526
1527 m_cells->cellMetrics[0][cellId] = DcoordDeta[1]; // DxiDx
1528 m_cells->cellMetrics[1][cellId] = -DcoordDeta[0]; // DxiDy
1529 m_cells->cellMetrics[2][cellId] = -DcoordDxi[1]; // DetaDx
1530 m_cells->cellMetrics[3][cellId] = DcoordDxi[0]; // DetaDy
1531 });
1532}
1533
1537template <>
1539 TRACE();
1540 constexpr MInt nDim = 3;
1541 const MFloat* const* const RESTRICT coords = m_cells->coordinates;
1542
1543 maia::parallelFor<true, nDim>(
1544 cellBegin(m_noGhostLayers - 1), cellEnd(1), [=](const MInt& i, const MInt& j, const MInt& k) {
1545 const MInt cellId = cellIndex(i, j, k);
1546 // auxilliary variables
1547 MFloat DcoordDxi[3];
1548 MFloat DcoordDeta[3];
1549 MFloat DcoordDzeta[3];
1550
1551 MFloat metricTmp[3];
1552
1553 for(MInt isd = xsd; isd < nDim; isd++) {
1554 DcoordDxi[isd] = (coords[isd][cellIndex(i + 1, j, k)] - coords[isd][cellIndex(i - 1, j, k)]) * F1B2;
1555
1556 DcoordDeta[isd] = (coords[isd][cellIndex(i, j + 1, k)] - coords[isd][cellIndex(i, j - 1, k)]) * F1B2;
1557
1558 DcoordDzeta[isd] = (coords[isd][cellIndex(i, j, k + 1)] - coords[isd][cellIndex(i, j, k - 1)]) * F1B2;
1559 }
1560
1561 // compute metric terms and store them
1562
1563 // dxi
1564 this->crossProduct(metricTmp, DcoordDeta, DcoordDzeta);
1565 for(MInt isd = xsd; isd < nDim; isd++) {
1566 m_cells->cellMetrics[xsd * nDim + isd][cellId] = metricTmp[isd];
1567 }
1568 // deta
1569 this->crossProduct(metricTmp, DcoordDzeta, DcoordDxi);
1570 for(MInt isd = xsd; isd < nDim; isd++) {
1571 m_cells->cellMetrics[ysd * nDim + isd][cellId] = metricTmp[isd];
1572 }
1573 // dzeta
1574 this->crossProduct(metricTmp, DcoordDxi, DcoordDeta);
1575 for(MInt isd = xsd; isd < nDim; isd++) {
1576 m_cells->cellMetrics[zsd * nDim + isd][cellId] = metricTmp[isd];
1577 }
1578 });
1579}
1580
1584template <>
1586 TRACE();
1587 constexpr MInt nDim = 3;
1588 const MFloat* const* const RESTRICT coords = m_coordinates;
1589
1590 maia::parallelFor<true, nDim>(cellBegin(0), cellEnd(0), [=](const MInt& i, const MInt& j, const MInt& k) {
1591 // determine global cell ID
1592 const MInt cellId = cellIndex(i, j, k);
1593 // determine global point ID for local cell IDs
1594 const MInt ijk = getPointIdFromCell(i, j, k);
1595 const MInt ipjk = getPointIdFromPoint(ijk, 1, 0, 0);
1596 const MInt ipjpk = getPointIdFromPoint(ijk, 1, 1, 0);
1597 const MInt ipjkp = getPointIdFromPoint(ijk, 1, 0, 1);
1598 const MInt ipjpkp = getPointIdFromPoint(ijk, 1, 1, 1);
1599 const MInt ijpk = getPointIdFromPoint(ijk, 0, 1, 0);
1600 const MInt ijpkp = getPointIdFromPoint(ijk, 0, 1, 1);
1601 const MInt ijkp = getPointIdFromPoint(ijk, 0, 0, 1);
1602
1603 // auxilliary variables
1604 MFloat DcoordDxi[3] = {F0, F0, F0};
1605 MFloat DcoordDeta[3] = {F0, F0, F0};
1606 MFloat DcoordDzeta[3] = {F0, F0, F0};
1607
1608 MFloat metricTmp[3] = {F0, F0, F0};
1609
1613
1614 for(MInt isd = xsd; isd < nDim; isd++) {
1615 DcoordDeta[isd] = ((coords[isd][ipjpkp] + coords[isd][ipjpk]) - (coords[isd][ipjkp] + coords[isd][ipjk])) * F1B2;
1616 DcoordDzeta[isd] = ((coords[isd][ipjpkp] + coords[isd][ipjkp]) - (coords[isd][ipjpk] + coords[isd][ipjk])) * F1B2;
1617 }
1618
1619 // compute Dxi and store
1620 crossProduct(metricTmp, DcoordDeta, DcoordDzeta);
1621
1622 for(MInt isd = xsd; isd < nDim; isd++) {
1623 m_cells->surfaceMetrics[xsd * nDim + isd][cellId] = metricTmp[isd];
1624 }
1625
1629
1630 for(MInt isd = xsd; isd < nDim; isd++) {
1631 DcoordDxi[isd] = ((coords[isd][ipjpkp] + coords[isd][ipjpk]) - (coords[isd][ijpkp] + coords[isd][ijpk])) * F1B2;
1632
1633 DcoordDzeta[isd] = ((coords[isd][ijpkp] + coords[isd][ipjpkp]) - (coords[isd][ipjpk] + coords[isd][ijpk])) * F1B2;
1634 }
1635
1636 // compute Deta and store
1637 crossProduct(metricTmp, DcoordDzeta, DcoordDxi);
1638
1639 for(MInt isd = xsd; isd < nDim; isd++) {
1640 m_cells->surfaceMetrics[ysd * nDim + isd][cellId] = metricTmp[isd];
1641 }
1642
1646
1647 for(MInt isd = xsd; isd < nDim; isd++) {
1648 DcoordDxi[isd] = ((coords[isd][ipjpkp] + coords[isd][ipjkp]) - (coords[isd][ijpkp] + coords[isd][ijkp])) * F1B2;
1649
1650 DcoordDeta[isd] = ((coords[isd][ipjpkp] + coords[isd][ijpkp]) - (coords[isd][ipjkp] + coords[isd][ijkp])) * F1B2;
1651 }
1652
1653 // compute Dzeta and store
1654 crossProduct(metricTmp, DcoordDxi, DcoordDeta);
1655
1656 for(MInt isd = xsd; isd < nDim; isd++) {
1657 m_cells->surfaceMetrics[zsd * nDim + isd][cellId] = metricTmp[isd];
1658 }
1659 });
1660}
1661
1665template <>
1667 TRACE();
1668 constexpr MInt nDim = 2;
1669 maia::parallelFor<true, nDim>(cellBegin(0), cellEnd(1), [=](const MInt& i, const MInt& j) {
1670 // determine global cellID
1671 const MInt cellId = this->cellIndex(i, j);
1672 // determine global point ID for local cell IDs
1673 const MInt IJ = getPointIdFromCell(i, j);
1674 const MInt IPJ = getPointIdFromPoint(IJ, 1, 0);
1675 const MInt IPJP = getPointIdFromPoint(IJ, 1, 1);
1676 const MInt IJP = getPointIdFromPoint(IJ, 0, 1);
1677
1678 // auxiliary variables
1679 MFloat DcoordDxi[2];
1680
1681 // Face I //
1682 for(MInt isd = xsd; isd < nDim; ++isd) {
1683 DcoordDxi[isd] = m_coordinates[isd][IPJP] - m_coordinates[isd][IPJ];
1684 }
1685
1686 // compute Dxi
1687 m_cells->surfaceMetrics[0][cellId] = DcoordDxi[1];
1688 m_cells->surfaceMetrics[1][cellId] = -DcoordDxi[0];
1689 // store Dxi
1690
1691 // Face I //
1692 for(MInt isd = xsd; isd < nDim; ++isd) {
1693 DcoordDxi[isd] = m_coordinates[isd][IPJP] - m_coordinates[isd][IJP];
1694 }
1695
1696 m_cells->surfaceMetrics[2][cellId] = -DcoordDxi[1];
1697 m_cells->surfaceMetrics[3][cellId] = DcoordDxi[0];
1698 });
1699}
1700
1705template <MInt nDim>
1707 TRACE();
1708
1709 IF_CONSTEXPR(nDim == 3) TERMM(1, "Not implemented in 3D!");
1710
1711 for(MInt i = 0; i < m_hasSingularity; ++i) {
1712 // only correct for bc 6000 not for bc 4000-5000
1713 if(m_singularity[i].BC == -6000) {
1714 // Sanity check
1715 for(MInt j = 0; j < nDim; j++) {
1716 ASSERT(m_singularity[i].end[j] - m_singularity[i].start[j] == 1, "");
1717 }
1718
1719 for(MInt jj = m_singularity[i].start[1]; jj < m_singularity[i].end[1]; ++jj) {
1720 for(MInt ii = m_singularity[i].start[0]; ii < m_singularity[i].end[0]; ++ii) {
1721 // Cell Id of singularity cell
1722 const MInt IJ = cellIndex(ii, jj);
1723
1724 const MInt sign_xi = 2 * m_singularity[i].Viscous[0] + 1;
1725 const MInt sign_eta = 2 * m_singularity[i].Viscous[1] + 1;
1726
1727 const MInt IPMJ = getCellIdFromCell(IJ, sign_xi, 0);
1728 const MInt IJPM = getCellIdFromCell(IJ, 0, sign_eta);
1729
1730 // auxiliary variables
1731 MFloat DcoordD[2];
1732
1733 // Face I //
1734 for(MInt isd = xsd; isd < nDim; ++isd) {
1735 DcoordD[isd] = sign_xi * (m_cells->coordinates[isd][IPMJ] - m_cells->coordinates[isd][IJ]);
1736 }
1737
1738 // compute Deta
1739 m_cells->surfaceMetricsSingularity[2][i] = -DcoordD[1];
1740 m_cells->surfaceMetricsSingularity[3][i] = DcoordD[0];
1741 // store Deta
1742
1743 // Face I //
1744 for(MInt isd = xsd; isd < nDim; ++isd) {
1745 DcoordD[isd] = sign_eta * (m_cells->coordinates[isd][IJPM] - m_cells->coordinates[isd][IJ]);
1746 }
1747
1748 m_cells->surfaceMetricsSingularity[0][i] = DcoordD[1];
1749 m_cells->surfaceMetricsSingularity[1][i] = -DcoordD[0];
1750
1751 // cout << "dom=" << domainId() << " x|y=" << setprecision(10) << m_cells->coordinates[0][IJ] << "|"
1752 // << m_cells->coordinates[1][IJ]
1753 // << " " << m_cells->surfaceMetricsSingularity[i][0] << "|" <<
1754 // m_cells->surfaceMetricsSingularity[i][1]
1755 // << " " << m_cells->surfaceMetricsSingularity[i][2] << "|" <<
1756 // m_cells->surfaceMetricsSingularity[i][3]
1757 // << " IPMJ=" << m_cells->coordinates[0][IPMJ] << "|" << m_cells->coordinates[1][IPMJ]
1758 // << " IJPM=" << m_cells->coordinates[0][IJPM] << "|" << m_cells->coordinates[1][IJPM] << endl;
1759 }
1760 }
1761 }
1762 }
1763}
1764
1768template <>
1770 TRACE();
1771 constexpr MInt nDim = 3;
1772
1773 const MFloat* const* const RESTRICT coords = m_coordinates;
1774
1775 for(MInt k = m_noGhostLayers - 1; k < this->m_nCells[0] - m_noGhostLayers; k++) {
1776 for(MInt j = m_noGhostLayers - 1; j < this->m_nCells[1] - m_noGhostLayers; j++) {
1777 for(MInt i = m_noGhostLayers - 1; i < this->m_nCells[2] - m_noGhostLayers; i++) {
1778 // determine global cell ID
1779 MInt cellId = this->cellIndex(i, j, k); // i + ( k * m_nCells[1] + j ) * m_nCells[2];
1780
1781 // auxilliary variables
1782 MFloat DcoordDxi[3] = {F0, F0, F0};
1783 MFloat DcoordDeta[3] = {F0, F0, F0};
1784 MFloat DcoordDzeta[3] = {F0, F0, F0};
1785
1786 MFloat metricTmp[3];
1787
1788 for(MInt isd = xsd; isd < nDim; isd++) {
1789 // compute d(x,y,z)/dxi
1790 DcoordDxi[isd] = F1B2
1791 * (coords[isd][getPointIdFromPoint(getPointIdFromCell(i + 1, j, k), 1, 1, 1)]
1792 - coords[isd][getPointIdFromPoint(getPointIdFromCell(i - 1, j, k), 1, 1, 1)]);
1793
1794 // compute d(x,y,z)/deta
1795 DcoordDeta[isd] = F1B2
1796 * (coords[isd][getPointIdFromPoint(getPointIdFromCell(i, j + 1, k), 1, 1, 1)]
1797 - coords[isd][getPointIdFromPoint(getPointIdFromCell(i, j - 1, k), 1, 1, 1)]);
1798
1799 // compute d(x,y,z)/dzeta
1800 DcoordDzeta[isd] = F1B2
1801 * (coords[isd][getPointIdFromPoint(getPointIdFromCell(i, j, k + 1), 1, 1, 1)]
1802 - coords[isd][getPointIdFromPoint(getPointIdFromCell(i, j, k - 1), 1, 1, 1)]);
1803 }
1804
1805 // compute metric terms and store them
1806
1807 // dxi
1808 this->crossProduct(metricTmp, DcoordDeta, DcoordDzeta);
1809 for(MInt isd = xsd; isd < nDim; isd++) {
1810 m_cells->cornerMetrics[xsd * nDim + isd][cellId] = metricTmp[isd];
1811 }
1812 // deta
1813 this->crossProduct(metricTmp, DcoordDzeta, DcoordDxi);
1814 for(MInt isd = xsd; isd < nDim; isd++) {
1815 m_cells->cornerMetrics[ysd * nDim + isd][cellId] = metricTmp[isd];
1816 }
1817 // dzeta
1818 this->crossProduct(metricTmp, DcoordDxi, DcoordDeta);
1819 for(MInt isd = xsd; isd < nDim; isd++) {
1820 m_cells->cornerMetrics[zsd * nDim + isd][cellId] = metricTmp[isd];
1821 }
1822 }
1823 }
1824 }
1825}
1826
1830template <>
1832 TRACE();
1833 constexpr MInt nDim = 2;
1834 for(MInt j = m_noGhostLayers - 1; j < m_nCells[0] - m_noGhostLayers; ++j) {
1835 for(MInt i = m_noGhostLayers - 1; i < m_nCells[1] - m_noGhostLayers; ++i) {
1836 // determine global cell ID
1837 const MInt cellId = cellIndex(i, j);
1838
1839 // auxilliary variables
1840 MFloat DcoordDxi[2];
1841 MFloat DcoordDeta[2];
1842
1843 for(MInt isd = xsd; isd < nDim; ++isd) {
1844 // looks complicated, but what happens is that we always catch the point Id of ipjp
1845 // from the neighboring cell and build the centered difference
1846
1847 // compute d(x,y,z)/dxi
1848 DcoordDxi[isd] = F1B2
1849 * (m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i + 1, j), 1, 1)]
1850 - m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i - 1, j), 1, 1)]);
1851
1852 // compute d(x,y,z)/deta
1853 DcoordDeta[isd] = F1B2
1854 * (m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j + 1), 1, 1)]
1855 - m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j - 1), 1, 1)]);
1856 }
1857 m_cells->cornerMetrics[0][cellId] = DcoordDeta[1]; // DxiDx
1858 m_cells->cornerMetrics[1][cellId] = -DcoordDeta[0]; // DxiDy
1859 m_cells->cornerMetrics[2][cellId] = -DcoordDxi[1]; // DetaDx
1860 m_cells->cornerMetrics[3][cellId] = DcoordDxi[0]; // DetaDy
1861 }
1862 }
1863}
1864
1868template <>
1870 TRACE();
1871 computeCornerMetrics();
1872}
1873
1877template <>
1879 TRACE();
1880 m_log << "computing corner metrics ..." << endl;
1881 constexpr MInt nDim = 3;
1882
1883 for(MInt k = m_noGhostLayers - 1; k < this->m_nCells[0] - m_noGhostLayers; k++) {
1884 for(MInt j = m_noGhostLayers - 1; j < this->m_nCells[1] - m_noGhostLayers; j++) {
1885 for(MInt i = m_noGhostLayers - 1; i < this->m_nCells[2] - m_noGhostLayers; i++) {
1886 // determine global cell ID
1887 MInt cellId = this->cellIndex(i, j, k); // i + ( k * m_nCells[1] + j ) * m_nCells[2];
1888 MFloat metricTmp[3];
1889
1890 MFloat p1[3];
1891 MFloat p2[3];
1892 MFloat p3[3];
1893 MFloat p4[3];
1894
1895 MFloat diag1[3];
1896 MFloat diag2[3];
1897
1898
1902
1903 for(MInt isd = xsd; isd < nDim; isd++) {
1904 // looks complicated, but what happens is that we always catch the point Id of ipjpkp
1905 // from the neighboring cell and build the centered difference
1906
1907 p1[isd] = F1B4
1908 * (m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j + 1, k + 1), 1, 0, 0)]
1909 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j + 1, k + 1), 1, 0, 1)]
1910 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j + 1, k + 1), 1, 1, 0)]
1911 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j + 1, k + 1), 1, 1, 1)]);
1912
1913
1914 p2[isd] = F1B4
1915 * (m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j, k), 1, 0, 0)]
1916 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j, k), 1, 0, 1)]
1917 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j, k), 1, 1, 0)]
1918 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j, k), 1, 1, 1)]);
1919
1920
1921 p3[isd] = F1B4
1922 * (m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j, k + 1), 1, 0, 0)]
1923 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j, k + 1), 1, 0, 1)]
1924 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j, k + 1), 1, 1, 0)]
1925 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j, k + 1), 1, 1, 1)]);
1926
1927 p4[isd] = F1B4
1928 * (m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j + 1, k), 1, 0, 0)]
1929 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j + 1, k), 1, 0, 1)]
1930 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j + 1, k), 1, 1, 0)]
1931 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j + 1, k), 1, 1, 1)]);
1932
1933 diag1[isd] = p1[isd] - p2[isd];
1934 diag2[isd] = p3[isd] - p4[isd];
1935 }
1936
1937 this->crossProduct(metricTmp, diag1, diag2);
1938 for(MInt isd = xsd; isd < nDim; isd++) {
1939 m_cells->cornerMetrics[xsd * nDim + isd][cellId] = F1B2 * metricTmp[isd];
1940 }
1941
1942
1946
1947 for(MInt isd = xsd; isd < nDim; isd++) {
1948 // looks complicated, but what happens is that we always catch the point Id of ipjpkp
1949 // from the neighboring cell and build the centered difference
1950
1951 p1[isd] = F1B4
1952 * (m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i + 1, j, k + 1), 0, 1, 0)]
1953 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i + 1, j, k + 1), 1, 1, 0)]
1954 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i + 1, j, k + 1), 0, 1, 1)]
1955 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i + 1, j, k + 1), 1, 1, 1)]);
1956
1957
1958 p2[isd] = F1B4
1959 * (m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j, k), 0, 1, 0)]
1960 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j, k), 1, 1, 0)]
1961 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j, k), 0, 1, 1)]
1962 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j, k), 1, 1, 1)]);
1963
1964 p3[isd] = F1B4
1965 * (m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i + 1, j, k), 0, 1, 0)]
1966 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i + 1, j, k), 1, 1, 0)]
1967 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i + 1, j, k), 0, 1, 1)]
1968 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i + 1, j, k), 1, 1, 1)]);
1969
1970 p4[isd] = F1B4
1971 * (m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j, k + 1), 0, 1, 0)]
1972 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j, k + 1), 1, 1, 0)]
1973 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j, k + 1), 0, 1, 1)]
1974 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j, k + 1), 1, 1, 1)]);
1975
1976 diag1[isd] = p1[isd] - p2[isd];
1977 diag2[isd] = p3[isd] - p4[isd];
1978 }
1979
1980 this->crossProduct(metricTmp, diag1, diag2);
1981 for(MInt isd = xsd; isd < nDim; isd++) {
1982 m_cells->cornerMetrics[ysd * nDim + isd][cellId] = F1B2 * metricTmp[isd];
1983 }
1984
1988
1989 for(MInt isd = xsd; isd < nDim; isd++) {
1990 p1[isd] = F1B4
1991 * (m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i + 1, j + 1, k), 1, 1, 1)]
1992 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i + 1, j + 1, k), 0, 1, 1)]
1993 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i + 1, j + 1, k), 1, 0, 1)]
1994 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i + 1, j + 1, k), 0, 0, 1)]);
1995
1996
1997 p2[isd] = F1B4
1998 * (m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j, k), 1, 1, 1)]
1999 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j, k), 0, 1, 1)]
2000 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j, k), 1, 0, 1)]
2001 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j, k), 0, 0, 1)]);
2002
2003 p3[isd] = F1B4
2004 * (m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j + 1, k), 1, 1, 1)]
2005 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j + 1, k), 0, 1, 1)]
2006 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j + 1, k), 1, 0, 1)]
2007 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i, j + 1, k), 0, 0, 1)]);
2008
2009 p4[isd] = F1B4
2010 * (m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i + 1, j, k), 1, 1, 1)]
2011 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i + 1, j, k), 0, 1, 1)]
2012 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i + 1, j, k), 1, 0, 1)]
2013 + m_coordinates[isd][getPointIdFromPoint(getPointIdFromCell(i + 1, j, k), 0, 0, 1)]);
2014
2015 diag1[isd] = p1[isd] - p2[isd];
2016 diag2[isd] = p3[isd] - p4[isd];
2017 }
2018
2019 this->crossProduct(metricTmp, diag1, diag2);
2020 for(MInt isd = xsd; isd < nDim; isd++) {
2021 m_cells->cornerMetrics[zsd * nDim + isd][cellId] = F1B2 * metricTmp[isd];
2022 }
2023 }
2024 }
2025 }
2026}
2027
2038template <>
2039void StructuredGrid<3>::computeDxt(MFloat timeStep, MFloat* RKalpha, MInt RKStep) {
2040 TRACE();
2041 const MFloat frk = F1 / (timeStep * RKalpha[RKStep]);
2042 constexpr MInt nDim = 3;
2043
2044 const MInt IJK[3] = {m_nCells[2], m_nCells[1], m_nCells[0]};
2045
2046 const MFloat* const* const RESTRICT coords = m_coordinates;
2047 const MFloat* const* const RESTRICT oldCoords = m_oldCoordinates;
2048
2049 const MInt inc[12] = {getPointIdFromPoint(0, 1, 0, 0), getPointIdFromPoint(0, 1, 1, 0),
2050 getPointIdFromPoint(0, 1, 0, 1), getPointIdFromPoint(0, 1, 1, 1),
2051
2052 getPointIdFromPoint(0, 0, 1, 0), getPointIdFromPoint(0, 0, 1, 1),
2053 getPointIdFromPoint(0, 1, 1, 0), getPointIdFromPoint(0, 1, 1, 1),
2054
2055 getPointIdFromPoint(0, 0, 0, 1), getPointIdFromPoint(0, 1, 0, 1),
2056 getPointIdFromPoint(0, 0, 1, 1), getPointIdFromPoint(0, 1, 1, 1)};
2057
2058
2059 for(MInt dim = 0; dim < nDim; ++dim) {
2060 for(MInt k = 0; k < IJK[2]; ++k) {
2061 for(MInt j = 0; j < IJK[1]; ++j) {
2062 for(MInt i = 0; i < IJK[0]; ++i) {
2063 // determine global cell ID
2064 const MInt cellId = cellIndex(i, j, k);
2065
2066 // determine global point ID for local cell IDs
2067 const MInt ijk = getPointIdFromCell(i, j, k);
2068
2069 const MInt p0 = ijk + inc[dim * 4 + 0];
2070 const MInt p1 = ijk + inc[dim * 4 + 1];
2071 const MInt p2 = ijk + inc[dim * 4 + 2];
2072 const MInt p3 = ijk + inc[dim * 4 + 3];
2073
2074 // reset the volume flux
2075 m_cells->dxt[dim][cellId] = F0;
2076
2077 MFloat diag1[3] = {F0, F0, F0};
2078 MFloat diag2[3] = {F0, F0, F0};
2079 MFloat oldNormal[3] = {F0, F0, F0};
2080 MFloat newNormal1[3] = {F0, F0, F0};
2081 MFloat newNormal2[3] = {F0, F0, F0};
2082
2083 //(i+1/2,j-1/4,k-1/4)
2084
2085 for(MInt isd = xsd; isd < nDim; isd++) {
2086 diag1[isd] = (oldCoords[isd][p3] - oldCoords[isd][p0]);
2087 diag2[isd] = (oldCoords[isd][p2] - oldCoords[isd][p1]);
2088 }
2089
2090 this->crossProduct(oldNormal, diag1, diag2);
2091
2092 for(MInt isd = xsd; isd < nDim; isd++) {
2093 diag1[isd] = (coords[isd][p2] - oldCoords[isd][p0]);
2094 diag2[isd] = (coords[isd][p0] - oldCoords[isd][p2]);
2095 }
2096
2097 this->crossProduct(newNormal1, diag1, diag2);
2098
2099 for(MInt isd = xsd; isd < nDim; isd++) {
2100 diag1[isd] = (coords[isd][p0] - oldCoords[isd][p1]);
2101 diag2[isd] = (coords[isd][p1] - oldCoords[isd][p0]);
2102 }
2103
2104 this->crossProduct(newNormal2, diag1, diag2);
2105
2106 const MFloat jac =
2107 F1B3
2108 * ((coords[0][p3] - oldCoords[0][p0]) * (oldNormal[0] + newNormal1[0] + newNormal2[0]) * F1B2
2109 + (coords[1][p3] - oldCoords[1][p0]) * (oldNormal[1] + newNormal1[1] + newNormal2[1]) * F1B2
2110 + (coords[2][p3] - oldCoords[2][p0]) * (oldNormal[2] + newNormal1[2] + newNormal2[2]) * F1B2);
2111
2112 m_cells->dxt[dim][cellId] = jac * frk;
2113 }
2114 }
2115 }
2116 }
2117}
2118
2129template <>
2130void StructuredGrid<2>::computeDxt(MFloat timeStep, MFloat* RKalpha, MInt RKStep) {
2131 const MFloat frk = F1 / (timeStep * RKalpha[RKStep]);
2132 constexpr MInt nDim = 2;
2133
2134 const MInt IJ[2] = {m_nCells[0], m_nCells[1]};
2135
2136 const MFloat* const* const RESTRICT coords = m_coordinates;
2137 const MFloat* const* const RESTRICT oldCoords = m_oldCoordinates;
2138
2139 const MInt inc[4] = {
2140 getPointIdFromPoint(0, 1, 1),
2141 getPointIdFromPoint(0, 1, 0),
2142 getPointIdFromPoint(0, 0, 1),
2143 getPointIdFromPoint(0, 1, 1),
2144 };
2145
2146 for(MInt dim = 0; dim < nDim; ++dim) {
2147 for(MInt j = 0; j < IJ[0]; ++j) {
2148 for(MInt i = 0; i < IJ[1]; ++i) {
2149 // determine global cell ID
2150 const MInt cellId = cellIndex(i, j);
2151
2152 // determine global point ID for local cell IDs
2153 const MInt ij = getPointIdFromCell(i, j);
2154
2155 const MInt p0 = ij + inc[dim * 2 + 0];
2156 const MInt p1 = ij + inc[dim * 2 + 1];
2157
2158 // reset the volume flux
2159 m_cells->dxt[dim][cellId] = F0;
2160
2161 MFloat diag1[2] = {F0, F0};
2162 MFloat diag2[2] = {F0, F0};
2163
2164 for(MInt isd = xsd; isd < nDim; isd++) {
2165 diag1[isd] = (oldCoords[isd][p0] - coords[isd][p1]);
2166 diag2[isd] = (oldCoords[isd][p1] - coords[isd][p0]);
2167 }
2168
2169 const MFloat area = F1B2 * (diag1[0] * diag2[1] - diag1[1] * diag2[0]);
2170
2171 m_cells->dxt[dim][cellId] = area * frk;
2172 }
2173 }
2174 }
2175}
2176
2180template <>
2182 TRACE();
2183 constexpr MInt nDim = 3;
2184 for(MInt k = 0; k < m_nPoints[0]; ++k) {
2185 for(MInt j = 0; j < m_nPoints[1]; ++j) {
2186 for(MInt i = 0; i < m_nPoints[2]; ++i) {
2187 const MInt pointId = pointIndex(i, j, k);
2188 for(MInt isd = xsd; isd < nDim; ++isd) {
2189 m_oldCoordinates[isd][pointId] = m_coordinates[isd][pointId];
2190 }
2191 }
2192 }
2193 }
2194}
2195
2199template <>
2201 TRACE();
2202 constexpr MInt nDim = 2;
2203 for(MInt j = 0; j < m_nPoints[0]; ++j) {
2204 for(MInt i = 0; i < m_nPoints[1]; ++i) {
2205 const MInt pointId = pointIndex(i, j);
2206 for(MInt isd = xsd; isd < nDim; ++isd) {
2207 m_oldCoordinates[isd][pointId] = m_coordinates[isd][pointId];
2208 }
2209 }
2210 }
2211}
2212
2216template <MInt nDim>
2217void StructuredGrid<nDim>::saveCellJacobian() // saves the old cell Jacobian
2218{
2219 TRACE();
2220 MFloat* const RESTRICT oldCellJac = ALIGNED_MF(m_cells->oldCellJac);
2221 const MFloat* const RESTRICT cellJac = ALIGNED_MF(m_cells->cellJac);
2222 for(MInt cellId = 0; cellId < m_noCells; cellId++) {
2223 oldCellJac[cellId] = cellJac[cellId];
2224 }
2225}
2226
2230template <>
2232 TRACE();
2233 // This function mirrors the grid points on the faces
2234 constexpr MInt nDim = 3;
2235 // i-direction
2236 MInt pointId, FixPointId, MirrorPointId;
2237
2238 for(MInt k = m_noGhostLayers; k < (m_nPoints[0] - m_noGhostLayers); k++) {
2239 for(MInt j = m_noGhostLayers; j < (m_nPoints[1] - m_noGhostLayers); j++) {
2240 for(MInt i = 0; i < m_noGhostLayers; i++) {
2241 pointId = (m_noGhostLayers - 1 - i) + (j + k * m_nPoints[1]) * m_nPoints[2]; // pointId in Array
2242 FixPointId =
2243 (m_noGhostLayers - i) + (j + k * m_nPoints[1]) * m_nPoints[2]; // point about which everything is mirrored
2244 MirrorPointId = (m_noGhostLayers + 1 - i) + (j + k * m_nPoints[1]) * m_nPoints[2];
2245 for(MInt dim = 0; dim < nDim; dim++) {
2246 m_coordinates[dim][pointId] = (2 * m_coordinates[dim][FixPointId] - m_coordinates[dim][MirrorPointId]);
2247 }
2248 // coordinates at the other end!!
2249
2250 pointId = (m_nPoints[2] - i - 1) + (j + k * m_nPoints[1]) * m_nPoints[2];
2251 FixPointId = (m_nPoints[2] - m_noGhostLayers - 1) + (j + k * m_nPoints[1]) * m_nPoints[2];
2252 MirrorPointId = (m_nPoints[2] - 1 - (2 * m_noGhostLayers - i)) + (j + k * m_nPoints[1]) * m_nPoints[2];
2253 for(MInt dim = 0; dim < nDim; dim++) {
2254 m_coordinates[dim][pointId] = (2 * m_coordinates[dim][FixPointId] - m_coordinates[dim][MirrorPointId]);
2255 }
2256 }
2257 }
2258 }
2259
2260 // j-direction
2261
2262 for(MInt k = m_noGhostLayers; k < (m_nPoints[0] - m_noGhostLayers); k++) {
2263 for(MInt j = 0; j < m_noGhostLayers; j++) {
2264 for(MInt i = m_noGhostLayers; i < (m_nPoints[2] - m_noGhostLayers); i++) {
2265 pointId = i + ((m_noGhostLayers - j - 1) + k * m_nPoints[1]) * m_nPoints[2]; // pointId in Array
2266 FixPointId =
2267 i + ((m_noGhostLayers - j) + k * m_nPoints[1]) * m_nPoints[2]; // point about which everything is mirrored
2268 MirrorPointId = i + ((m_noGhostLayers + 1 - j) + k * m_nPoints[1]) * m_nPoints[2];
2269 for(MInt dim = 0; dim < nDim; dim++) {
2270 m_coordinates[dim][pointId] = (2 * m_coordinates[dim][FixPointId] - m_coordinates[dim][MirrorPointId]);
2271 }
2272 // coordinates at the other end!!
2273 pointId = i + ((m_nPoints[1] - j - 1) + k * m_nPoints[1]) * m_nPoints[2];
2274 FixPointId = i + ((m_nPoints[1] - m_noGhostLayers - 1) + k * m_nPoints[1]) * m_nPoints[2];
2275 MirrorPointId = i + ((m_nPoints[1] - 1 - (2 * m_noGhostLayers - j)) + k * m_nPoints[1]) * m_nPoints[2];
2276 for(MInt dim = 0; dim < nDim; dim++) {
2277 m_coordinates[dim][pointId] = (2 * m_coordinates[dim][FixPointId] - m_coordinates[dim][MirrorPointId]);
2278 }
2279 }
2280 }
2281 }
2282
2283 // k-direction
2284 for(MInt k = 0; k < m_noGhostLayers; k++) {
2285 for(MInt j = 0; j < (m_nPoints[1] - m_noGhostLayers); j++) {
2286 for(MInt i = m_noGhostLayers; i < (m_nPoints[2] - m_noGhostLayers); i++) {
2287 pointId = i + (j + (m_noGhostLayers - 1 - k) * m_nPoints[1]) * m_nPoints[2]; // pointId in Array
2288 FixPointId =
2289 i + (j + (m_noGhostLayers - k) * m_nPoints[1]) * m_nPoints[2]; // point about which everything is mirrored
2290 MirrorPointId =
2291 i + (j + (m_noGhostLayers + 1 - k) * m_nPoints[1]) * m_nPoints[2]; // m_noGhostLayers+(m_noGhostLayers-i)
2292 for(MInt dim = 0; dim < nDim; dim++) {
2293 m_coordinates[dim][pointId] = (2 * m_coordinates[dim][FixPointId] - m_coordinates[dim][MirrorPointId]);
2294 }
2295
2296
2297 // coordinates at the other end!!
2298 pointId = i + (j + (m_nPoints[0] - k - 1) * m_nPoints[1]) * m_nPoints[2];
2299 FixPointId = i + (j + (m_nPoints[0] - m_noGhostLayers - 1) * m_nPoints[1]) * m_nPoints[2];
2300 MirrorPointId = i + (j + (m_nPoints[0] - 1 - (2 * m_noGhostLayers - k)) * m_nPoints[1]) * m_nPoints[2];
2301 for(MInt dim = 0; dim < nDim; dim++) {
2302 m_coordinates[dim][pointId] = (2 * m_coordinates[dim][FixPointId] - m_coordinates[dim][MirrorPointId]);
2303 }
2304 }
2305 }
2306 }
2307
2308 // corner points missing yet!! They only need to be calculated if a Visualisation tool is used to
2309 // show the ghost points and the grid
2310
2311
2312 // in i-direction
2313
2314 for(MInt k = 0; k < (m_nPoints[0]); k++) {
2315 for(MInt j = 0; j < (m_nPoints[1]); j++) {
2316 for(MInt i = 0; i < m_noGhostLayers; i++) {
2317 pointId = (m_noGhostLayers - 1 - i) + (j + k * m_nPoints[1]) * m_nPoints[2]; // pointId in Array
2318 FixPointId =
2319 (m_noGhostLayers - i) + (j + k * m_nPoints[1]) * m_nPoints[2]; // point about which everything is mirrored
2320 MirrorPointId =
2321 (m_noGhostLayers + 1 - i) + (j + k * m_nPoints[1]) * m_nPoints[2]; // m_noGhostLayers+(m_noGhostLayers-i)
2322 for(MInt dim = 0; dim < nDim; dim++) {
2323 m_coordinates[dim][pointId] = (2 * m_coordinates[dim][FixPointId] - m_coordinates[dim][MirrorPointId]);
2324 }
2325 // coordinates at the other end!!
2326
2327 pointId = (m_nPoints[2] - i - 1) + (j + k * m_nPoints[1]) * m_nPoints[2];
2328 FixPointId = (m_nPoints[2] - m_noGhostLayers - 1) + (j + k * m_nPoints[1]) * m_nPoints[2];
2329 MirrorPointId = (m_nPoints[2] - 1 - (2 * m_noGhostLayers - i)) + (j + k * m_nPoints[1]) * m_nPoints[2];
2330 for(MInt dim = 0; dim < nDim; dim++) {
2331 m_coordinates[dim][pointId] = (2 * m_coordinates[dim][FixPointId] - m_coordinates[dim][MirrorPointId]);
2332 }
2333 }
2334 }
2335 }
2336
2337 for(MInt k = 0; k < (m_nPoints[0]); k++) {
2338 for(MInt j = 0; j < m_noGhostLayers; j++) {
2339 for(MInt i = 0; i < (m_nPoints[2]); i++) {
2340 pointId = i + ((m_noGhostLayers - j - 1) + k * m_nPoints[1]) * m_nPoints[2]; // pointId in Array
2341 FixPointId =
2342 i + ((m_noGhostLayers - j) + k * m_nPoints[1]) * m_nPoints[2]; // point about which everything is mirrored
2343 MirrorPointId = i + ((m_noGhostLayers + 1 - j) + k * m_nPoints[1]) * m_nPoints[2];
2344 for(MInt dim = 0; dim < nDim; dim++) {
2345 m_coordinates[dim][pointId] = (2 * m_coordinates[dim][FixPointId] - m_coordinates[dim][MirrorPointId]);
2346 }
2347 // coordinates at the other end!!
2348 pointId = i + ((m_nPoints[1] - j - 1) + k * m_nPoints[1]) * m_nPoints[2];
2349 FixPointId = i + ((m_nPoints[1] - m_noGhostLayers - 1) + k * m_nPoints[1]) * m_nPoints[2];
2350 MirrorPointId = i + ((m_nPoints[1] - 1 - (2 * m_noGhostLayers - j)) + k * m_nPoints[1]) * m_nPoints[2];
2351 for(MInt dim = 0; dim < nDim; dim++) {
2352 m_coordinates[dim][pointId] = (2 * m_coordinates[dim][FixPointId] - m_coordinates[dim][MirrorPointId]);
2353 }
2354 }
2355 }
2356 }
2357
2358 for(MInt k = 0; k < m_noGhostLayers; k++) {
2359 for(MInt j = 0; j < (m_nPoints[1]); j++) {
2360 for(MInt i = 0; i < (m_nPoints[2]); i++) {
2361 pointId = i + (j + (m_noGhostLayers - 1 - k) * m_nPoints[1]) * m_nPoints[2]; // pointId in Array
2362 FixPointId =
2363 i + (j + (m_noGhostLayers - k) * m_nPoints[1]) * m_nPoints[2]; // point about which everything is mirrored
2364 MirrorPointId = i + (j + (m_noGhostLayers + 1 - k) * m_nPoints[1]) * m_nPoints[2];
2365 for(MInt dim = 0; dim < nDim; dim++) {
2366 m_coordinates[dim][pointId] = (2 * m_coordinates[dim][FixPointId] - m_coordinates[dim][MirrorPointId]);
2367 }
2368
2369 // coordinates at the other end!!
2370 pointId = i + (j + (m_nPoints[0] - k - 1) * m_nPoints[1]) * m_nPoints[2];
2371 FixPointId = i + (j + (m_nPoints[0] - m_noGhostLayers - 1) * m_nPoints[1]) * m_nPoints[2];
2372 MirrorPointId = i + (j + (m_nPoints[0] - 1 - (2 * m_noGhostLayers - k)) * m_nPoints[1]) * m_nPoints[2];
2373 for(MInt dim = 0; dim < nDim; dim++) {
2374 m_coordinates[dim][pointId] = (2 * m_coordinates[dim][FixPointId] - m_coordinates[dim][MirrorPointId]);
2375 }
2376 }
2377 }
2378 }
2379}
2380
2384template <>
2386 TRACE();
2387 // This function mirrors the grid points on the faces
2388 constexpr MInt nDim = 2;
2389
2390 // i-direction
2391 MInt pointId, FixPointId, MirrorPointId;
2392
2393 for(MInt j = m_noGhostLayers; j < (m_nPoints[0] - m_noGhostLayers); ++j) {
2394 for(MInt i = 0; i < m_noGhostLayers; ++i) {
2395 pointId = (m_noGhostLayers - 1 - i) + (j * m_nPoints[1]); // pointId in Array
2396 FixPointId = (m_noGhostLayers - i) + (j * m_nPoints[1]); // point about which everything is mirrored
2397 MirrorPointId = (m_noGhostLayers + 1 - i) + (j * m_nPoints[1]);
2398
2399 for(MInt dim = 0; dim < nDim; ++dim) {
2400 m_coordinates[dim][pointId] = (2 * m_coordinates[dim][FixPointId] - m_coordinates[dim][MirrorPointId]);
2401 }
2402
2403 // coordinates at the other end!!
2404 pointId = (m_nPoints[1] - i - 1) + (j * m_nPoints[1]);
2405 FixPointId = (m_nPoints[1] - m_noGhostLayers - 1) + (j * m_nPoints[1]);
2406 MirrorPointId = (m_nPoints[1] - 1 - (2 * m_noGhostLayers - i)) + (j * m_nPoints[1]);
2407 for(MInt dim = 0; dim < nDim; ++dim) {
2408 m_coordinates[dim][pointId] = (2 * m_coordinates[dim][FixPointId] - m_coordinates[dim][MirrorPointId]);
2409 }
2410 }
2411 }
2412
2413 // j-direction
2414
2415 for(MInt j = 0; j < m_noGhostLayers; ++j) {
2416 for(MInt i = m_noGhostLayers; i < (m_nPoints[1] - m_noGhostLayers); ++i) {
2417 pointId = i + (m_noGhostLayers - j - 1) * m_nPoints[1]; // pointId in Array
2418 FixPointId = i + (m_noGhostLayers - j) * m_nPoints[1]; // point about which everything is mirrored
2419 MirrorPointId = i + (m_noGhostLayers + 1 - j) * m_nPoints[1];
2420 for(MInt dim = 0; dim < nDim; ++dim) {
2421 m_coordinates[dim][pointId] = (2 * m_coordinates[dim][FixPointId] - m_coordinates[dim][MirrorPointId]);
2422 }
2423
2424 // coordinates at the other end!!
2425 pointId = i + (m_nPoints[0] - j - 1) * m_nPoints[1];
2426 FixPointId = i + (m_nPoints[0] - m_noGhostLayers - 1) * m_nPoints[1];
2427 MirrorPointId = i + (m_nPoints[0] - 1 - (2 * m_noGhostLayers - j)) * m_nPoints[1];
2428 for(MInt dim = 0; dim < nDim; ++dim) {
2429 m_coordinates[dim][pointId] = (2 * m_coordinates[dim][FixPointId] - m_coordinates[dim][MirrorPointId]);
2430 }
2431 }
2432 }
2433
2434
2435 // corner points missing yet!! They only need to be calculated if a Visualisation tool is used to
2436 // show the ghost points and the grid
2437
2438
2439 // in i-direction
2440 for(MInt j = 0; j < (m_nPoints[0]); ++j) {
2441 for(MInt i = 0; i < m_noGhostLayers; ++i) {
2442 pointId = (m_noGhostLayers - 1 - i) + (j * m_nPoints[1]); // pointId in Array
2443 FixPointId = (m_noGhostLayers - i) + (j * m_nPoints[1]); // point about which everything is mirrored
2444 MirrorPointId = (m_noGhostLayers + 1 - i) + (j * m_nPoints[1]); // m_noGhostLayers+(m_noGhostLayers-i)
2445 for(MInt dim = 0; dim < nDim; ++dim) {
2446 m_coordinates[dim][pointId] = (2 * m_coordinates[dim][FixPointId] - m_coordinates[dim][MirrorPointId]);
2447 }
2448 // coordinates at the other end!!
2449
2450 pointId = (m_nPoints[1] - i - 1) + (j * m_nPoints[1]);
2451 FixPointId = (m_nPoints[1] - m_noGhostLayers - 1) + (j * m_nPoints[1]);
2452 MirrorPointId = (m_nPoints[1] - 1 - (2 * m_noGhostLayers - i)) + (j * m_nPoints[1]);
2453 for(MInt dim = 0; dim < nDim; ++dim) {
2454 m_coordinates[dim][pointId] = (2 * m_coordinates[dim][FixPointId] - m_coordinates[dim][MirrorPointId]);
2455 }
2456 }
2457 }
2458
2459 // in j-direction
2460
2461 for(MInt j = 0; j < m_noGhostLayers; ++j) {
2462 for(MInt i = 0; i < (m_nPoints[1]); ++i) {
2463 pointId = i + (m_noGhostLayers - j - 1) * m_nPoints[1]; // pointId in Array
2464 FixPointId = i + (m_noGhostLayers - j) * m_nPoints[1]; // point about which everything is mirrored
2465 MirrorPointId = i + (m_noGhostLayers + 1 - j) * m_nPoints[1];
2466 for(MInt dim = 0; dim < nDim; ++dim) {
2467 m_coordinates[dim][pointId] = (2 * m_coordinates[dim][FixPointId] - m_coordinates[dim][MirrorPointId]);
2468 }
2469
2470 // coordinates at the other end!!
2471 pointId = i + (m_nPoints[0] - j - 1) * m_nPoints[1];
2472 FixPointId = i + (m_nPoints[0] - m_noGhostLayers - 1) * m_nPoints[1];
2473 MirrorPointId = i + (m_nPoints[0] - 1 - (2 * m_noGhostLayers - j)) * m_nPoints[1];
2474 for(MInt dim = 0; dim < nDim; ++dim) {
2475 m_coordinates[dim][pointId] = (2 * m_coordinates[dim][FixPointId] - m_coordinates[dim][MirrorPointId]);
2476 }
2477 }
2478 }
2479}
2480
2485template <MInt nDim>
2487
2488// Explicit instantations for 2D and 3D
2489template class StructuredGrid<2>;
2490template class StructuredGrid<3>;
void mAlloc(T *&a, const MLong N, const MString &objectName, MString function)
allocates memory for one-dimensional array 'a' of size N
Definition: alloc.h:173
static MBool propertyExists(const MString &name, MInt solver=m_noSolvers)
This function checks if a property exists in general.
Definition: context.cpp:494
void defineArray(maiabd_type type, const MString &name, size_type totalCount)
Create a new array in the file.
Definition: parallelio.h:783
void writeArray(const T *array, const MString &name, size_type memoryStride=-1, size_type diskStride=-1)
Write array data to file. [MPI]
Definition: parallelio.h:1046
void setAttribute(const T &value, const MString &name, const MString &datasetName="")
Set a file or dataset attribute. [MPI]
Definition: parallelio.h:1438
void readArray(T *array, const MString &name, size_type memoryStride=-1, size_type diskStride=-1)
Read array data from file. [MPI]
Definition: parallelio.h:1523
This class is a ScratchSpace.
Definition: scratch.h:758
pointer data()
Definition: scratch.h:289
void fill(T val)
fill the scratch with a given value
Definition: scratch.h:311
Structured grid class.
void gridDecomposition(MBool)
Create decomposition of the grid into partitions for MPI parallelization.
void computeCellJacobian()
void computeMetrics()
Computes all metrics by calling the functions for each type of metric computation (cell,...
void extrapolateGhostPointCoordinates()
void saveCellJacobian()
Copies the current state of the cell Jacobians to m_cells->oldCellJacobian.
void periodicPointsChange(MFloat &, const MInt, const MInt)
Displaces the points on periodic boundaries by the distance between the two periodic boundaries.
void exchangePoints(std::vector< std::unique_ptr< StructuredComm< nDim > > > &, std::vector< std::unique_ptr< StructuredComm< nDim > > > &, StructuredCommType)
Exchanges the boundary grid points between MPI partitions.
void writeGrid(MString, MString)
Writes the current grid (including deformations for moving grids) to a file.
void computeCornerMetrics()
void computeModCornerJacobian()
void computeCornerJacobian()
void computeCellMetrics()
~StructuredGrid()
Destructor of the structured grid class.
void readGrid()
Reads in the coordinates (x,y,z) from the grid file.
void computeJacobian()
Computes the Jacobians by calling the functions for each type of Jacobian computation (corner,...
void sendPoints(std::vector< std::unique_ptr< StructuredComm< nDim > > > &, StructuredCommType, std::vector< MPI_Request > &)
Send the coordinates between partitions to other partitions.
void computeDxt(MFloat, MFloat *, MInt)
void computeModCornerMetrics()
void computeSurfaceJacobian()
void setCellReference(StructuredCell *)
Sets the reference to the cell object.
void writePartitionedGrid()
Saves coordinates for partitioned grid with ghost points. Useful for debugging.
void computeSurfaceMetricsSingularity()
Computes the surface metrics for the cell surfaces at the surface centroids (2D) Special version for ...
void computeCellCenterCoordinates()
void scatterPoints(std::vector< std::unique_ptr< StructuredComm< nDim > > > &, StructuredCommType)
Distributes the exchanged points from the receiving buffers to the actual coordinates of the grid.
void gatherPoints(std::vector< std::unique_ptr< StructuredComm< nDim > > > &, StructuredCommType)
Gathers the coordinates of the points for all given sending maps and copies them to a sending buffer.
void prepareReadGrid()
Prepares the arrays containing the size of the grid (points/cells) before the grid coordinates are ac...
void allocateMetricsAndJacobians()
Allocates memory for the metrics and the Jacobians.
StructuredGrid(const MInt, const MPI_Comm)
Constructor for structured grids.
void receivePoints(std::vector< std::unique_ptr< StructuredComm< nDim > > > &, StructuredCommType, std::vector< MPI_Request > &)
Receives the coordinates between partitions to other partitions.
void moveCellPoints()
void computeSurfaceMetrics()
StructuredCommType
Definition: enums.h:343
@ PERIODIC_BC_SINGULAR
Definition: enums.h:343
@ PERIODIC_BC
Definition: enums.h:343
@ SINGULAR
Definition: enums.h:343
void mTerm(const MInt errorCode, const MString &location, const MString &message)
Definition: functions.cpp:29
MInt globalTimeStep
InfoOutFile m_log
int32_t MInt
Definition: maiatypes.h:62
std::basic_string< char > MString
Definition: maiatypes.h:55
double MFloat
Definition: maiatypes.h:52
int64_t MLong
Definition: maiatypes.h:64
bool MBool
Definition: maiatypes.h:58
int MPI_Isend(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request, const MString &name, const MString &varname)
same as MPI_Isend
int MPI_Irecv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Request *request, const MString &name, const MString &varname)
same as MPI_Irecv
int MPI_Waitall(int count, MPI_Request *request, MPI_Status *status, const MString &name)
same as MPI_Waitall
const MInt PIO_REPLACE
Definition: parallelio.h:36
const MInt PIO_FLOAT
Definition: parallelio.h:46
const MInt PIO_READ
Definition: parallelio.h:40