MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
fvstructuredinterpolation.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
8#include "COMM/mpioverride.h"
9#if defined(WITH_HDF5)
10#include "IO/parallelio.h"
11#endif
12#include "fvstructuredsolver.h"
13
14using namespace std;
15
16template <MInt nDim>
26#if defined(WITH_HDF5)
27template <MInt nDim>
28StructuredInterpolation<nDim>::StructuredInterpolation(const MPI_Comm structuredCommunicator)
29 : m_StructuredComm(structuredCommunicator),
30 m_donorIsCellCentered(true),
31 m_isFieldInterpolation(false),
32 m_eps(std::numeric_limits<MFloat>::epsilon()) {
33 MPI_Comm_rank(m_StructuredComm, &m_domainId);
34
35 loadDonorGrid();
38#else
39template <MInt nDim>
40StructuredInterpolation<nDim>::StructuredInterpolation(const MPI_Comm structuredCommunicator)
41 : m_StructuredComm(structuredCommunicator),
42 m_donorIsCellCentered(true),
43 m_isFieldInterpolation(false),
44 m_eps(std::numeric_limits<MFloat>::epsilon()) {
45 MPI_Comm_rank(m_StructuredComm, &m_domainId);
46 TERMM(1, "Activate HDF5 to use this function!");
48#endif
59template <MInt nDim>
61 MFloat** donorCoordinates,
62 MFloat** donorVariables,
63 const MPI_Comm structuredCommunicator)
64 : m_donorCoordinates(donorCoordinates),
65 m_donorVariables(donorVariables),
66 m_noBlocks(1),
67 m_StructuredComm(structuredCommunicator),
68 m_noDonorVariables(5),
69 m_donorIsCellCentered(true),
70 m_isFieldInterpolation(false),
71 m_eps(std::numeric_limits<MFloat>::epsilon()) {
72 MPI_Comm_rank(m_StructuredComm, &m_domainId);
73 mAlloc(m_noDonorCellsDir, m_noBlocks, nDim, AT_, 0, "m_noDonorCellsDir");
74 mAlloc(m_donorBlockOffsets, m_noBlocks, AT_, 0, "m_donorBlockOffset");
75
77 for(MInt dim = 0; dim < nDim; dim++) {
78 m_noDonorCellsDir[0][dim] = noDonorCellsDir[dim];
79 m_totalNoDonorCells *= noDonorCellsDir[dim];
80 }
81
83}
84
85template <MInt nDim>
87 MFloat** donorCoordinates,
88 const MPI_Comm structuredCommunicator)
89 : m_donorCoordinates(donorCoordinates),
90 m_noBlocks(1),
91 m_StructuredComm(structuredCommunicator),
92 m_noDonorVariables(5),
93 m_donorIsCellCentered(true),
94 m_isFieldInterpolation(false),
95 m_eps(std::numeric_limits<MFloat>::epsilon()) {
96 MPI_Comm_rank(m_StructuredComm, &m_domainId);
97 mAlloc(m_noDonorCellsDir, m_noBlocks, nDim, AT_, 0, "m_noDonorCellsDir");
98 mAlloc(m_donorBlockOffsets, m_noBlocks, AT_, 0, "m_donorBlockOffset");
99
101 for(MInt dim = 0; dim < nDim; dim++) {
102 m_noDonorCellsDir[0][dim] = noDonorCellsDir[dim];
103 m_totalNoDonorCells *= noDonorCellsDir[dim];
104 }
105
107}
108
109
110template <MInt nDim>
112 if(m_isFieldInterpolation) {
113 mDeallocate(m_donorOriginId);
114 mDeallocate(m_transformedReceiverPoints);
115 mDeallocate(m_hasInterpolationPartners);
116 mDeallocate(m_donorVar);
117 mDeallocate(m_hasInterpolationPartnersZonal);
118 mDeallocate(m_hasInterpolationPartnersZonalGlobal);
119 mDeallocate(m_globalDonorDistanceMin);
120 } else {
121 mDeallocate(m_donorOriginId);
122 mDeallocate(m_interpolationCoefficients);
123 mDeallocate(m_hasInterpolationPartners);
124 mDeallocate(m_hasInterpolationPartnersZonal);
125 mDeallocate(m_hasInterpolationPartnersZonalGlobal);
126 mDeallocate(m_globalDonorDistanceMin);
127 }
128
129 delete m_donorTree;
130}
131
132
139template <MInt nDim>
141 m_log << "Building up kd-tree..." << endl;
142
143 // cout << "totalNoCells: " << m_totalNoDonorCells << endl;
144
145 // first create kd tree from whole grid
146 for(MInt globalId = 0; globalId < m_totalNoDonorCells; globalId++) {
147 Point<3> a(m_donorCoordinates[0][globalId], m_donorCoordinates[1][globalId], m_donorCoordinates[2][globalId],
148 globalId);
149 m_donorPoints.push_back(a);
150 }
151
152 m_log << "Created points for kd-tree" << endl;
153
154 // build up the tree and fill it
155 m_donorTree = new KDtree<3>(m_donorPoints);
156
157 m_log << "Building up kd-tree... FINISHED!" << endl;
158}
159
166template <MInt nDim>
168 // now go through own, fine cells and look for closest partner neighbour
169 MFloat distance = 0;
170 Point<3> pt(intPoint[0], intPoint[1], intPoint[2]);
171 cout << "Finding nearest point..." << endl;
172 // find point on the grid that is closest to intPoint
173 MInt centerCellId = m_donorTree->nearest(pt, distance);
174 cout << "Finding nearest point... FINISHED! Point"
175 << " x: " << m_donorCoordinates[0][centerCellId] << " y: " << m_donorCoordinates[1][centerCellId]
176 << " z: " << m_donorCoordinates[2][centerCellId] << endl;
177 cout << "Finding surrounding hexahedron..." << endl;
178 // now eight hexahedron could be candidates for a new home for intPoint,
179 // all around centerCellId
180 MInt hexahedronOriginId = findSurroundingHexahedron(intPoint, centerCellId, 1);
181 MFloat interpolatedVariables[5];
182
183 if(hexahedronOriginId != -1) {
184 MFloat transformedPoint[3];
185 // now hexahedronOriginId is the id of the hexahedron in which intPoint is immersed
186 transformPoint(hexahedronOriginId, intPoint, transformedPoint);
187 MInt currentBlockId = getBlockId(hexahedronOriginId);
188 // interpolate variables at transformed coordinate
189 trilinearInterpolation(transformedPoint, hexahedronOriginId, interpolatedVariables, currentBlockId);
190 } else {
191 // fallback to nearest neighbour interpolation
192 nearestNeighbourInterpolation(centerCellId, interpolatedVariables);
193 }
194}
195
202#if defined(WITH_HDF5)
203template <MInt nDim>
205 // first load the current variable
206 loadDonorVariable(varName);
207 for(MInt cellId = 0; cellId < m_noReceiverCells; cellId++) {
208 if(cellId % 50000 == 0 && m_domainId == 0) {
209 cout << "Variable " << varName
210 << " interpolation progress: " << (MInt)((MFloat)cellId / ((MFloat)m_noReceiverCells) * 100.0) << " percent"
211 << endl;
212 }
213
214 if(m_hasInterpolationPartners[cellId]) {
215 MFloat transformedPoint[3] = {m_transformedReceiverPoints[0][cellId], m_transformedReceiverPoints[1][cellId],
216 m_transformedReceiverPoints[2][cellId]};
217
218 // interpolate variables at transformed coordinate
219 MInt currentBlockId = getBlockId(m_donorOriginId[cellId]);
220 trilinearInterpolation(transformedPoint, m_donorOriginId[cellId], cellId, receiverVar, currentBlockId);
221 } else {
222 // fallback to nearest neighbour interpolation
223 nearestNeighbourInterpolation(m_donorOriginId[cellId], cellId, receiverVar);
224 }
225 }
226}
227#else
228template <MInt nDim>
230 (void)varName;
231 (void)receiverVar;
232 TERMM(1, "Activate HDF5 to use this function!");
233}
234#endif
235
243template <MInt nDim>
244void StructuredInterpolation<nDim>::prepareInterpolationField(MInt* noReceiverCells, MFloat** receiverCoordinates) {
245 m_isFieldInterpolation = true;
246 m_noReceiverCells = noReceiverCells[0] * noReceiverCells[1] * noReceiverCells[2];
247 MInt noTrilinear = 0;
248 MInt noFallback = 0;
249 mAlloc(m_donorOriginId, m_noReceiverCells, AT_, -1, "m_donorOriginId");
250 mAlloc(m_transformedReceiverPoints, nDim, m_noReceiverCells, AT_, F0, "m_interpolationCoefficients");
251 mAlloc(m_hasInterpolationPartners, m_noReceiverCells, AT_, "m_hasInterpolationPartners");
252 mAlloc(m_donorVar, m_totalNoDonorCells, "m_donorVariables", F0, AT_);
253
254 for(MInt cellId = 0; cellId < m_noReceiverCells; cellId++) {
255 if(cellId % 50000 == 0) {
256 cout << "Interpolation progress: " << (MInt)((MFloat)cellId / ((MFloat)m_noReceiverCells) * 100.0) << " percent"
257 << endl;
258 }
259 m_currentReceiverId = cellId;
260 MFloat intPoint[3] = {receiverCoordinates[0][cellId], receiverCoordinates[1][cellId],
261 receiverCoordinates[2][cellId]};
262 // now go through own, fine cells and look for closest partner neighbour
263 MFloat distance = 0;
264 Point<3> pt(intPoint[0], intPoint[1], intPoint[2]);
265 // find point on the grid that is closest to intPoint
266 MInt centerCellId = m_donorTree->nearest(pt, distance);
267
268 // now eight hexahedron could be candidates for a new home for intPoint,
269 // all around centerCellId
270 MInt hexahedronOriginId = -1;
271 const MInt maxNghbrRadius = 4;
272 for(MInt nghbrRadius = 1; nghbrRadius < maxNghbrRadius; nghbrRadius++) {
273 hexahedronOriginId = findSurroundingHexahedron(intPoint, centerCellId, nghbrRadius);
274 if(hexahedronOriginId != -1) {
275 break;
276 }
277 }
278
279 if(hexahedronOriginId != -1) {
280 MFloat transformedPoint[3] = {F0, F0, F0};
281 // now hexahedronOriginId is the id of the hexahedron in which intPoint is immersed
282 transformPoint(hexahedronOriginId, intPoint, transformedPoint);
283 // interpolate variables at transformed coordinate
284
285 for(MInt dim = 0; dim < nDim; dim++) {
286 m_transformedReceiverPoints[dim][cellId] = transformedPoint[dim];
287 }
288 m_donorOriginId[cellId] = hexahedronOriginId;
289 m_hasInterpolationPartners[cellId] = true;
290 noTrilinear++;
291 } else {
292 // fallback to nearest neighbour interpolation
293 m_hasInterpolationPartners[cellId] = false;
294 m_donorOriginId[cellId] = centerCellId;
295 noFallback++;
296 }
297 }
298
299 MInt noLocal[3] = {noTrilinear, noFallback, m_noReceiverCells};
300 MInt noGlobal[3] = {0, 0, 0};
301 MPI_Allreduce(noLocal, noGlobal, 3, MPI_INT, MPI_SUM, m_StructuredComm, AT_, "noLocal", "noGlobal");
302 if(m_domainId == 0) {
303 cout << "Trilinear: " << noGlobal[0] << " (" << 100.0 * ((MFloat)noGlobal[0]) / ((MFloat)noGlobal[2]) << "%) "
304 << "Fallback: " << noGlobal[1] << " (" << 100.0 * ((MFloat)noGlobal[1]) / ((MFloat)noGlobal[2]) << "%)"
305 << endl;
306 }
307}
308
316template <MInt nDim>
317void StructuredInterpolation<nDim>::prepareInterpolation(MInt noReceiverCells, MFloat** receiverCellCoordinates,
318 MInt* interpolationPartner) {
319 m_isFieldInterpolation = false;
320 MInt noTrilinear = 0;
321 MInt noFallback = 0;
322 m_noReceiverCells = noReceiverCells;
323
324 if(noReceiverCells > 0) {
325 mAlloc(m_donorOriginId, m_noReceiverCells, AT_, "m_donorOriginId");
326 mAlloc(m_interpolationCoefficients, m_noReceiverCells, 8, AT_, "m_interpolationCoefficients");
327 mAlloc(m_hasInterpolationPartners, m_noReceiverCells, AT_, "m_hasInterpolationPartners");
328
329 for(MInt receiverId = 0; receiverId < m_noReceiverCells; receiverId++) {
330 if(m_domainId == 0 && receiverId % 10000 == 0) {
331 cout << "receiver no: " << receiverId << endl;
332 }
333 // now go through own, fine cells and look for closest partner neighbour
334 MFloat intPoint[3] = {receiverCellCoordinates[0][receiverId], receiverCellCoordinates[1][receiverId],
335 receiverCellCoordinates[2][receiverId]};
336 Point<3> pt(intPoint[0], intPoint[1], intPoint[2]);
337 MFloat dist = 0;
338 MInt closestCellId = m_donorTree->nearest(pt, dist);
339
340 // now eight hexahedron could be candidates for a new home for intPoint,
341 // all around closestCellId
342 // MInt hexahedronOriginId = findSurroundingHexahedron(intPoint, closestCellId, 1);
343 MInt hexahedronOriginId = -1;
344 const MInt maxNghbrRadius = 8;
345 for(MInt nghbrRadius = 1; nghbrRadius < maxNghbrRadius; nghbrRadius++) {
346 hexahedronOriginId = findSurroundingHexahedron(intPoint, closestCellId, nghbrRadius);
347 if(hexahedronOriginId != -1) {
348 break;
349 }
350 }
351
352 if(hexahedronOriginId != -1) {
353 m_hasInterpolationPartners[receiverId] = true;
354 m_donorOriginId[receiverId] = hexahedronOriginId;
355 MFloat transformedPoint[3];
356 // now hexahedronOriginId is the id of the hexahedron in which intPoint is immersed
357 transformPoint(hexahedronOriginId, intPoint, transformedPoint);
358 // interpolate variables at transformed coordinate
359 computeInterpolationCoefficients(transformedPoint, receiverId);
360 noTrilinear++;
361 } else {
362 // fallback to nearest neighbour interpolation
363 m_hasInterpolationPartners[receiverId] = false;
364 m_donorOriginId[receiverId] = closestCellId;
365
366 cout << "Fallback x: " << intPoint[0] << " y: " << intPoint[1] << " z: " << intPoint[2] << endl;
367 noFallback++;
368 }
369 interpolationPartner[receiverId] = m_hasInterpolationPartners[receiverId];
370 }
371 }
372
373 cout << "trilinar: " << noTrilinear << " fallback: " << noFallback << " noReceiverCells: " << noReceiverCells << endl;
374
375 MInt noLocal[3] = {noTrilinear, noFallback, noReceiverCells};
376 MInt noGlobal[3] = {0, 0, 0};
377 MPI_Allreduce(noLocal, noGlobal, 3, MPI_INT, MPI_SUM, m_StructuredComm, AT_, "noLocal", "noGlobal");
378 if(m_domainId == 0) {
379 cout << "Trilinear: " << noGlobal[0] << " (" << 100.0 * ((MFloat)noGlobal[0]) / ((MFloat)noGlobal[2]) << "%)"
380 << "Fallback: " << noGlobal[1] << " (" << 100.0 * ((MFloat)noGlobal[1]) / ((MFloat)noGlobal[2]) << "%)"
381 << endl;
382 }
383}
384
391template <MInt nDim>
393 MFloat** receiverCellCoordinates,
394 MInt* interpolationPartner,
395 MBool hasInterpolationPartnerDomain) {
396 m_isFieldInterpolation = false;
397 MInt noTrilinear = 0;
398 MInt noFallback = 0;
399 m_noReceiverCells = noReceiverCells;
400 m_hasInterpolationPartnerDomain = hasInterpolationPartnerDomain;
401
402 mAlloc(m_donorOriginId, m_noReceiverCells, AT_, "m_donorOriginId");
403 mAlloc(m_interpolationCoefficients, m_noReceiverCells, 8, AT_, "m_interpolationCoefficients");
404 mAlloc(m_hasInterpolationPartnersZonal, m_noReceiverCells, AT_, 0, "m_hasInterpolationPartnersZonal");
405 mAlloc(m_hasInterpolationPartnersZonalGlobal, m_noReceiverCells, AT_, 0, "m_hasInterpolationPartnersZonalGlobal");
406 mAlloc(m_donorDistance, m_noReceiverCells, AT_, "m_donorDistance");
407 mAlloc(m_globalDonorDistanceMin, m_noReceiverCells, AT_, F0, "m_globalDonorDistanceMin");
408
409 if(m_hasInterpolationPartnerDomain == true) {
410 for(MInt receiverId = 0; receiverId < m_noReceiverCells; receiverId++) {
411 // if(m_domainId==0 && receiverId % 10000 == 0) {cout << "receiver no: " << receiverId << endl;}
412 // now go through own, fine cells and look for closest partner neighbour
413 MFloat intPoint[3] = {receiverCellCoordinates[0][receiverId], receiverCellCoordinates[1][receiverId],
414 receiverCellCoordinates[2][receiverId]};
415 Point<3> pt(intPoint[0], intPoint[1], intPoint[2]);
416 MFloat dist = 0;
417 MInt closestCellId;
418 closestCellId = m_donorTree->nearest(pt, dist);
419 // now eight hexahedron could be candidates for a new home for intPoint,
420 // all around closestCellId
421 // MInt hexahedronOriginId = findSurroundingHexahedron(intPoint, closestCellId, 1);
422 MInt hexahedronOriginId = -1;
423 const MInt maxNghbrRadius = 4;
424 for(MInt nghbrRadius = 1; nghbrRadius < maxNghbrRadius; nghbrRadius++) {
425 hexahedronOriginId = findSurroundingHexahedron(intPoint, closestCellId, nghbrRadius);
426 if(hexahedronOriginId != -1) {
427 break;
428 }
429 }
430 if(hexahedronOriginId != -1) {
431 m_hasInterpolationPartnersZonal[receiverId] = true;
432 m_donorOriginId[receiverId] = hexahedronOriginId;
433 MFloat transformedPoint[3];
434 // now hexahedronOriginId is the id of the hexahedron in which intPoint is immersed
435 transformPoint(hexahedronOriginId, intPoint, transformedPoint);
436 // interpolate variables at transformed coordinate
437 computeInterpolationCoefficients(transformedPoint, receiverId);
438 noTrilinear++;
439 } else {
440 // fallback to nearest neighbour interpolation
441 m_hasInterpolationPartnersZonal[receiverId] = false;
442 m_donorOriginId[receiverId] = closestCellId;
443 m_donorDistance[receiverId] = dist;
444 noFallback++;
445 }
446 }
447 } else {
448 for(MInt receiverId = 0; receiverId < m_noReceiverCells; receiverId++) {
449 m_donorDistance[receiverId] =
450 1000; // avoid to pick interpolation cells in receiverDomain using MPI_Allreduce(MIN) below
451 m_hasInterpolationPartnersZonal[receiverId] = false;
452 }
453 }
454
455 MPI_Allreduce(m_hasInterpolationPartnersZonal, m_hasInterpolationPartnersZonalGlobal, m_noReceiverCells, MPI_INT,
456 MPI_SUM, m_StructuredComm, AT_, "m_hasInterpolationPartnersZonal",
457 "m_hasInterpolationPartnersZonalGlobal");
458
459 MPI_Allreduce(m_donorDistance, m_globalDonorDistanceMin, m_noReceiverCells, MPI_DOUBLE, MPI_MIN, m_StructuredComm,
460 AT_, "m_donorDistance", "m_globalDonorDistanceMin");
461
462 if(m_hasInterpolationPartnerDomain == true) {
463 for(MInt receiverId = 0; receiverId < m_noReceiverCells; receiverId++) {
464 if(m_hasInterpolationPartnersZonalGlobal[receiverId] == 0
465 && approx(m_donorDistance[receiverId], m_globalDonorDistanceMin[receiverId], m_eps)) {
466 m_hasInterpolationPartnersZonal[receiverId] = true;
467 }
468 }
469 }
470
471 for(MInt receiverId = 0; receiverId < m_noReceiverCells; receiverId++) {
472 interpolationPartner[receiverId] = m_hasInterpolationPartnersZonal[receiverId];
473 }
474
475
476 MInt noLocal[3] = {noTrilinear, noFallback, noReceiverCells};
477 MInt noGlobal[3] = {0, 0, 0};
478 MPI_Allreduce(noLocal, noGlobal, 3, MPI_INT, MPI_SUM, m_StructuredComm, AT_, "noLocal", "noGlobal");
479}
480
481
482template <MInt nDim>
484 MFloat interpolatedVariable = 0.0;
485
486 if(m_hasInterpolationPartnersZonalGlobal[cellIdBC] > 0) {
487 interpolatedVariable = getInterpolatedVariableZonal(donorVars, cellIdBC);
488 } else if(m_hasInterpolationPartnersZonalGlobal[cellIdBC] == 0) {
489 interpolatedVariable = donorVars[m_donorOriginId[cellIdBC]];
490 }
491
492 return interpolatedVariable;
493}
494
495
496template <MInt nDim>
498 for(MInt receiverId = 0; receiverId < m_noReceiverCells; receiverId++) {
499 if(m_hasInterpolationPartners[receiverId]) {
500 for(MInt var = 0; var < m_noDonorVariables; var++) {
501 interpolatedVariables[var][receiverId] = getInterpolatedVariable(receiverId, var);
502 }
503 } else {
504 for(MInt var = 0; var < m_noDonorVariables; var++) {
505 interpolatedVariables[var][receiverId] = m_donorVariables[var][m_donorOriginId[receiverId]];
506 }
507 }
508 }
509}
510
521template <MInt nDim>
523 MInt stencil) {
524 MFloat v1[3] = {F0, F0, F0};
525 MFloat v2[3] = {F0, F0, F0};
526 MFloat v3[3] = {F0, F0, F0};
527 MFloat vp[3] = {F0, F0, F0};
528 MFloat vn[3] = {F0, F0, F0};
529
530 MBool isInside = false;
531
532 for(MInt i = -stencil; i < stencil; i++) {
533 for(MInt j = -stencil; j < stencil; j++) {
534 for(MInt k = -stencil; k < stencil; k++) {
535 // find out current blockId
536 const MInt currentBlockId = getBlockId(centerCellId);
537 const MInt currentOffset = m_donorBlockOffsets[currentBlockId];
538 const MInt IJK = getCellIdfromCell(centerCellId, i, j, k, currentBlockId);
539
540 // compute i,j,k from cellId, but use local cellIds
541 MInt noLocalCellsDir[3] = {m_noDonorCellsDir[currentBlockId][0] - currentOffset,
542 m_noDonorCellsDir[currentBlockId][1] - currentOffset,
543 m_noDonorCellsDir[currentBlockId][2] - currentOffset};
544 MInt trueI = (IJK % (noLocalCellsDir[2] * noLocalCellsDir[1])) % noLocalCellsDir[2];
545 MInt trueJ = ((IJK - trueI) / noLocalCellsDir[2]) % noLocalCellsDir[1];
546 MInt trueK = ((IJK - trueI) / noLocalCellsDir[2] - trueJ) / noLocalCellsDir[1];
547
548 // check if inside regular grid
549 if(trueI < 0 || trueI >= noLocalCellsDir[2] - 1 || trueJ < 0 || trueJ >= noLocalCellsDir[1] - 1 || trueK < 0
550 || trueK >= noLocalCellsDir[0] - 1) {
551 continue;
552 }
553
554 // now loop over all 6 possible tetragonal pyramids
555 for(MInt tetra = 0; tetra < 6; tetra++) {
556 // and now loop over all 4 sides of the pyramid
557 isInside = true;
558 for(MInt side = 0; side < 4; side++) {
559 MInt ixp = (side + 1) % 4;
560 MInt ixp2 = (ixp + 1) % 4;
561 MInt ixp3 = (ixp2 + 1) % 4;
562
563 // compute vectors
564 for(MInt dim = 0; dim < nDim; dim++) {
565 v1[dim] = m_donorCoordinates[dim][getCellIdfromCell(IJK, ic(tetra, side, 0), ic(tetra, side, 1),
566 ic(tetra, side, 2), currentBlockId)]
567 - m_donorCoordinates[dim][getCellIdfromCell(IJK, ic(tetra, ixp, 0), ic(tetra, ixp, 1),
568 ic(tetra, ixp, 2), currentBlockId)];
569 v2[dim] = m_donorCoordinates[dim][getCellIdfromCell(IJK, ic(tetra, ixp2, 0), ic(tetra, ixp2, 1),
570 ic(tetra, ixp2, 2), currentBlockId)]
571 - m_donorCoordinates[dim][getCellIdfromCell(IJK, ic(tetra, ixp, 0), ic(tetra, ixp, 1),
572 ic(tetra, ixp, 2), currentBlockId)];
573 v3[dim] = m_donorCoordinates[dim][getCellIdfromCell(IJK, ic(tetra, ixp3, 0), ic(tetra, ixp3, 1),
574 ic(tetra, ixp3, 2), currentBlockId)]
575 - m_donorCoordinates[dim][getCellIdfromCell(IJK, ic(tetra, ixp, 0), ic(tetra, ixp, 1),
576 ic(tetra, ixp, 2), currentBlockId)];
577 vp[dim] = intPoint[dim]
578 - m_donorCoordinates[dim][getCellIdfromCell(IJK, ic(tetra, ixp, 0), ic(tetra, ixp, 1),
579 ic(tetra, ixp, 2), currentBlockId)];
580 }
581
582 // compute perpendicular vector vn
583 crossProduct(vn, v1, v2);
584
585 // check direction of normal vector and correct if necessary
586 if(scalarProduct(v3, vn) > m_eps) {
587 // invert direction of vn
588 for(MInt dim = 0; dim < nDim; dim++) {
589 vn[dim] = -vn[dim];
590 }
591 }
592
593 // check scalar product, if vp*vn > 0 then point is outside of this pyramid
594 if(scalarProduct(vp, vn) > m_eps) {
595 // not inside pyramid
596 isInside = false;
597 break;
598 }
599 }
600
601 // point is inside the current tetra and
602 // thus inside the current hexahedron
603 if(isInside) {
604 return IJK;
605 }
606 }
607 }
608 }
609 }
610
611 // surprisingly the point isn't inside any of the 8 hexahedrons, return invalid cellId
612 return -1;
613}
614
625template <MInt nDim>
627 MFloat transformedPoint[3]) {
628 MFloatScratchSpace a(3, 8, AT_, "a");
629 const MInt currentBlockId = getBlockId(hexOrigin);
630
631 for(MInt dim = 0; dim < nDim; dim++) {
632 a(dim, 0) = m_donorCoordinates[dim][hexOrigin];
633 a(dim, 1) = m_donorCoordinates[dim][getCellIdfromCell(hexOrigin, 1, 0, 0, currentBlockId)] - a(dim, 0);
634 a(dim, 2) = m_donorCoordinates[dim][getCellIdfromCell(hexOrigin, 0, 1, 0, currentBlockId)] - a(dim, 0);
635 a(dim, 3) = m_donorCoordinates[dim][getCellIdfromCell(hexOrigin, 0, 0, 1, currentBlockId)] - a(dim, 0);
636 a(dim, 4) = m_donorCoordinates[dim][getCellIdfromCell(hexOrigin, 1, 1, 0, currentBlockId)] - a(dim, 0) - a(dim, 1)
637 - a(dim, 2);
638 a(dim, 5) = m_donorCoordinates[dim][getCellIdfromCell(hexOrigin, 1, 0, 1, currentBlockId)] - a(dim, 0) - a(dim, 1)
639 - a(dim, 3);
640 a(dim, 6) = m_donorCoordinates[dim][getCellIdfromCell(hexOrigin, 0, 1, 1, currentBlockId)] - a(dim, 0) - a(dim, 2)
641 - a(dim, 3);
642 a(dim, 7) = m_donorCoordinates[dim][getCellIdfromCell(hexOrigin, 1, 1, 1, currentBlockId)] - a(dim, 0) - a(dim, 1)
643 - a(dim, 2) - a(dim, 3) - a(dim, 4) - a(dim, 5) - a(dim, 6) - a(dim, 7);
644 }
645
646 // set initial values 0.5
647 MFloatScratchSpace dxezdxyz(3, 3, AT_, "dxezdxyz");
648 MFloatScratchSpace rhs(3, AT_, "rhs");
649
650 MFloat xi = F1B2;
651 MFloat eta = F1B2;
652 MFloat zeta = F1B2;
653
654 MFloat xicor, etacor, zetacor;
655
656 MInt noIterations = 50;
657 for(MInt newton = 0; newton < noIterations; newton++) {
658 for(MInt dim = 0; dim < nDim; dim++) {
659 dxezdxyz(dim, 0) = a(dim, 1) + a(dim, 4) * eta + a(dim, 5) * zeta + a(dim, 7) * eta * zeta;
660 dxezdxyz(dim, 1) = a(dim, 2) + a(dim, 4) * xi + a(dim, 6) * zeta + a(dim, 7) * xi * zeta;
661 dxezdxyz(dim, 2) = a(dim, 3) + a(dim, 5) * xi + a(dim, 6) * eta + a(dim, 7) * xi * eta;
662
663 rhs[dim] = intPoint[dim]
664 - (a(dim, 0) + a(dim, 1) * xi + a(dim, 2) * eta + a(dim, 3) * zeta + a(dim, 4) * xi * eta
665 + a(dim, 5) * xi * zeta + a(dim, 6) * eta * zeta + a(dim, 7) * xi * eta * zeta);
666 }
667
668 MFloat jac = dxezdxyz(0, 0) * (dxezdxyz(1, 1) * dxezdxyz(2, 2) - dxezdxyz(1, 2) * dxezdxyz(2, 1))
669 + dxezdxyz(0, 1) * (dxezdxyz(1, 2) * dxezdxyz(2, 0) - dxezdxyz(1, 0) * dxezdxyz(2, 2))
670 + dxezdxyz(0, 2) * (dxezdxyz(1, 0) * dxezdxyz(2, 1) - dxezdxyz(1, 1) * dxezdxyz(2, 0));
671
672 if(fabs(jac) < m_eps) {
673 xicor = F0;
674 etacor = F0;
675 zetacor = F0;
676 } else {
677 xicor = (rhs[0] * (dxezdxyz(1, 1) * dxezdxyz(2, 2) - dxezdxyz(1, 2) * dxezdxyz(2, 1))
678 + dxezdxyz(0, 1) * (dxezdxyz(1, 2) * rhs[2] - rhs[1] * dxezdxyz(2, 2))
679 + dxezdxyz(0, 2) * (rhs[1] * dxezdxyz(2, 1) - dxezdxyz(1, 1) * rhs[2]))
680 / jac;
681 etacor = (dxezdxyz(0, 0) * (rhs[1] * dxezdxyz(2, 2) - dxezdxyz(1, 2) * rhs[2])
682 + rhs[0] * (dxezdxyz(1, 2) * dxezdxyz(2, 0) - dxezdxyz(1, 0) * dxezdxyz(2, 2))
683 + dxezdxyz(0, 2) * (dxezdxyz(1, 0) * rhs[2] - rhs[1] * dxezdxyz(2, 0)))
684 / jac;
685 zetacor = (dxezdxyz(0, 0) * (dxezdxyz(1, 1) * rhs[2] - rhs[1] * dxezdxyz(2, 1))
686 + dxezdxyz(0, 1) * (rhs[1] * dxezdxyz(2, 0) - dxezdxyz(1, 0) * rhs[2])
687 + rhs[0] * (dxezdxyz(1, 0) * dxezdxyz(2, 1) - dxezdxyz(1, 1) * dxezdxyz(2, 0)))
688 / jac;
689 }
690
691 xi = xi + xicor;
692 eta = eta + etacor;
693 zeta = zeta + zetacor;
694
695 MFloat sumcor = fabs(xicor) + fabs(etacor) + fabs(zetacor);
696
697 if(sumcor < m_eps) {
698 break;
699 }
700 }
701
702 xi = mMax(mMin(xi, F1), F0);
703 eta = mMax(mMin(eta, F1), F0);
704 zeta = mMax(mMin(zeta, F1), F0);
705
706 transformedPoint[0] = xi;
707 transformedPoint[1] = eta;
708 transformedPoint[2] = zeta;
709}
710
719template <MInt nDim>
720inline void StructuredInterpolation<nDim>::trilinearInterpolation(MFloat dx[3], MInt hexOrigin, MInt receiverId,
721 MFloat* receiverVar, MInt currentBlockId) {
722 MFloatScratchSpace v(8, AT_, "v");
723
724 v[0] = dx[0] * dx[1] * dx[2];
725 v[1] = (F1 - dx[0]) * dx[1] * dx[2];
726 v[2] = dx[0] * (F1 - dx[1]) * dx[2];
727 v[3] = dx[0] * dx[1] * (F1 - dx[2]);
728 v[4] = (F1 - dx[0]) * (F1 - dx[1]) * dx[2];
729 v[5] = (F1 - dx[0]) * dx[1] * (F1 - dx[2]);
730 v[6] = dx[0] * (F1 - dx[1]) * (F1 - dx[2]);
731 v[7] = (F1 - dx[0]) * (F1 - dx[1]) * (F1 - dx[2]);
732
733 // now the actual interpolation
734 receiverVar[receiverId] = v[0] * m_donorVar[getCellIdfromCell(hexOrigin, 1, 1, 1, currentBlockId)]
735 + v[1] * m_donorVar[getCellIdfromCell(hexOrigin, 0, 1, 1, currentBlockId)]
736 + v[2] * m_donorVar[getCellIdfromCell(hexOrigin, 1, 0, 1, currentBlockId)]
737 + v[3] * m_donorVar[getCellIdfromCell(hexOrigin, 1, 1, 0, currentBlockId)]
738 + v[4] * m_donorVar[getCellIdfromCell(hexOrigin, 0, 0, 1, currentBlockId)]
739 + v[5] * m_donorVar[getCellIdfromCell(hexOrigin, 0, 1, 0, currentBlockId)]
740 + v[6] * m_donorVar[getCellIdfromCell(hexOrigin, 1, 0, 0, currentBlockId)]
741 + v[7] * m_donorVar[getCellIdfromCell(hexOrigin, 0, 0, 0, currentBlockId)];
742}
743
752template <MInt nDim>
754 MInt hexOrigin,
755 MFloat* receiverVariables,
756 MInt currentBlockId) {
757 MFloatScratchSpace v(8, AT_, "v");
758
759 v[0] = dx[0] * dx[1] * dx[2];
760 v[1] = (F1 - dx[0]) * dx[1] * dx[2];
761 v[2] = dx[0] * (F1 - dx[1]) * dx[2];
762 v[3] = dx[0] * dx[1] * (F1 - dx[2]);
763 v[4] = (F1 - dx[0]) * (F1 - dx[1]) * dx[2];
764 v[5] = (F1 - dx[0]) * dx[1] * (F1 - dx[2]);
765 v[6] = dx[0] * (F1 - dx[1]) * (F1 - dx[2]);
766 v[7] = (F1 - dx[0]) * (F1 - dx[1]) * (F1 - dx[2]);
767
768 // now the actual interpolation
769 for(MInt var = 0; var < m_noDonorVariables; var++) {
770 receiverVariables[var] = v[0] * m_donorVariables[var][getCellIdfromCell(hexOrigin, 1, 1, 1, currentBlockId)]
771 + v[1] * m_donorVariables[var][getCellIdfromCell(hexOrigin, 0, 1, 1, currentBlockId)]
772 + v[2] * m_donorVariables[var][getCellIdfromCell(hexOrigin, 1, 0, 1, currentBlockId)]
773 + v[3] * m_donorVariables[var][getCellIdfromCell(hexOrigin, 1, 1, 0, currentBlockId)]
774 + v[4] * m_donorVariables[var][getCellIdfromCell(hexOrigin, 0, 0, 1, currentBlockId)]
775 + v[5] * m_donorVariables[var][getCellIdfromCell(hexOrigin, 0, 1, 0, currentBlockId)]
776 + v[6] * m_donorVariables[var][getCellIdfromCell(hexOrigin, 1, 0, 0, currentBlockId)]
777 + v[7] * m_donorVariables[var][getCellIdfromCell(hexOrigin, 0, 0, 0, currentBlockId)];
778 }
779}
780
781
786template <MInt nDim>
788 m_interpolationCoefficients[receiverId][0] = dx[0] * dx[1] * dx[2];
789 m_interpolationCoefficients[receiverId][1] = (F1 - dx[0]) * dx[1] * dx[2];
790 m_interpolationCoefficients[receiverId][2] = dx[0] * (F1 - dx[1]) * dx[2];
791 m_interpolationCoefficients[receiverId][3] = dx[0] * dx[1] * (F1 - dx[2]);
792 m_interpolationCoefficients[receiverId][4] = (F1 - dx[0]) * (F1 - dx[1]) * dx[2];
793 m_interpolationCoefficients[receiverId][5] = (F1 - dx[0]) * dx[1] * (F1 - dx[2]);
794 m_interpolationCoefficients[receiverId][6] = dx[0] * (F1 - dx[1]) * (F1 - dx[2]);
795 m_interpolationCoefficients[receiverId][7] = (F1 - dx[0]) * (F1 - dx[1]) * (F1 - dx[2]);
796}
797
806template <MInt nDim>
808 const MInt donorOrigin = m_donorOriginId[receiverId];
809 const MInt currentBlockId = getBlockId(donorOrigin);
810 const MFloat interpolatedVar = m_interpolationCoefficients[receiverId][0]
811 * m_donorVariables[var][getCellIdfromCell(donorOrigin, 1, 1, 1, currentBlockId)]
812 + m_interpolationCoefficients[receiverId][1]
813 * m_donorVariables[var][getCellIdfromCell(donorOrigin, 0, 1, 1, currentBlockId)]
814 + m_interpolationCoefficients[receiverId][2]
815 * m_donorVariables[var][getCellIdfromCell(donorOrigin, 1, 0, 1, currentBlockId)]
816 + m_interpolationCoefficients[receiverId][3]
817 * m_donorVariables[var][getCellIdfromCell(donorOrigin, 1, 1, 0, currentBlockId)]
818 + m_interpolationCoefficients[receiverId][4]
819 * m_donorVariables[var][getCellIdfromCell(donorOrigin, 0, 0, 1, currentBlockId)]
820 + m_interpolationCoefficients[receiverId][5]
821 * m_donorVariables[var][getCellIdfromCell(donorOrigin, 0, 1, 0, currentBlockId)]
822 + m_interpolationCoefficients[receiverId][6]
823 * m_donorVariables[var][getCellIdfromCell(donorOrigin, 1, 0, 0, currentBlockId)]
824 + m_interpolationCoefficients[receiverId][7]
825 * m_donorVariables[var][getCellIdfromCell(donorOrigin, 0, 0, 0, currentBlockId)];
826
827 return interpolatedVar;
828}
829
830template <MInt nDim>
832 const MInt donorOrigin = m_donorOriginId[receiverId];
833 const MInt currentBlockId = getBlockId(donorOrigin);
834 const MFloat interpolatedVar =
835 m_interpolationCoefficients[receiverId][0] * donorVars[getCellIdfromCell(donorOrigin, 1, 1, 1, currentBlockId)]
836 + m_interpolationCoefficients[receiverId][1] * donorVars[getCellIdfromCell(donorOrigin, 0, 1, 1, currentBlockId)]
837 + m_interpolationCoefficients[receiverId][2] * donorVars[getCellIdfromCell(donorOrigin, 1, 0, 1, currentBlockId)]
838 + m_interpolationCoefficients[receiverId][3] * donorVars[getCellIdfromCell(donorOrigin, 1, 1, 0, currentBlockId)]
839 + m_interpolationCoefficients[receiverId][4] * donorVars[getCellIdfromCell(donorOrigin, 0, 0, 1, currentBlockId)]
840 + m_interpolationCoefficients[receiverId][5] * donorVars[getCellIdfromCell(donorOrigin, 0, 1, 0, currentBlockId)]
841 + m_interpolationCoefficients[receiverId][6] * donorVars[getCellIdfromCell(donorOrigin, 1, 0, 0, currentBlockId)]
842 + m_interpolationCoefficients[receiverId][7] * donorVars[getCellIdfromCell(donorOrigin, 0, 0, 0, currentBlockId)];
843
844 return interpolatedVar;
845}
846
847
859#if defined(WITH_HDF5)
860template <MInt nDim>
862 if(m_domainId == 0) {
863 cout << "Reading in donor grid file..." << endl;
864 }
865
878 MString donorGridName = Context::getSolverProperty<MString>("donorGridName", 0, AT_);
879
880 MFloat translation[3] = {F0, F0, F0};
881 MFloat scale[3] = {F1, F1, F1};
882
895 if(Context::propertyExists("donorTranslation", 0)) {
896 for(MInt dim = 0; dim < nDim; dim++) {
897 translation[dim] = Context::getSolverProperty<MFloat>("donorTranslation", 0, AT_, &translation[dim], dim);
898 }
899 }
900
913 if(Context::propertyExists("donorScale", 0)) {
914 for(MInt dim = 0; dim < nDim; dim++) {
915 scale[dim] = Context::getSolverProperty<MFloat>("donorScale", 0, AT_, &scale[dim], dim);
916 }
917 }
918
919 if(m_domainId == 0) {
920 cout << "Translating donorGrid by deltaX: " << translation[0] << " deltaY: " << translation[1]
921 << " deltaZ: " << translation[2] << endl;
922 cout << "Scaling donorGrid by scaleX: " << scale[0] << " scaleY: " << scale[1] << " scaleZ: " << scale[2] << endl;
923 }
924
925 ParallelIoHdf5 pio(donorGridName, maia::parallel_io::PIO_READ, m_StructuredComm);
926 // create the string to contain the datasetname in the file
927 MInt blockId1 = 0;
928 MString sBlockName = "/block";
929 stringstream dummy1;
930 dummy1 << blockId1 << "/";
931 sBlockName += dummy1.str();
932 m_noDonorDims = pio.getDatasetNoDims("x", sBlockName);
933
934 if(m_domainId == 0) {
935 cout << "Donor grid has " << m_noDonorDims << " dimensions" << endl;
936 }
937
938 m_noBlocks = -1;
939 MInt noBlocksType = pio.getAttributeType("noBlocks", "");
940 if(noBlocksType == 1) {
941 pio.getAttribute(&m_noBlocks, "noBlocks", "");
942 } else if(noBlocksType == 0) {
943 MFloat noBlocksFloat = -1.0;
944 pio.getAttribute<MFloat>(&noBlocksFloat, "noBlocks", "");
945 m_noBlocks = (MInt)noBlocksFloat;
946 }
947
948 mAlloc(m_noDonorCellsDir, m_noBlocks, nDim, AT_, 0, "m_noDonorCellsDir");
949 mAlloc(m_noDonorPointsDir, m_noBlocks, nDim, AT_, 0, "m_noDonorPointsDir");
950 mAlloc(m_noDonorPoints, m_noBlocks, AT_, 1, "m_noDonorPoints");
951 mAlloc(m_noDonorCells, m_noBlocks, AT_, 1, "m_noDonorCells");
952 m_totalNoDonorCells = 0;
953 for(MInt blockId = 0; blockId < m_noBlocks; blockId++) {
954 MInt ijk_max[MAX_SPACE_DIMENSIONS] = {0};
955 stringstream blockName;
956 blockName << "/block" << blockId << "/";
957 MString blockNameStr = blockName.str();
958 std::vector<ParallelIo::size_type> tmp(nDim, 0);
959 pio.getArraySize("x", blockNameStr, &tmp[0]);
960 std::copy(tmp.begin(), tmp.end(), &ijk_max[0]);
961
962 for(MInt j = 0; j < m_noDonorDims; j++) {
963 if(m_donorIsCellCentered == true) {
964 m_noDonorCellsDir[blockId][j] = ijk_max[j] - 1;
965 } else {
966 m_noDonorCellsDir[blockId][j] = ijk_max[j];
967 }
968 m_noDonorPointsDir[blockId][j] = ijk_max[j];
969 // no of points in each solver
970 m_noDonorPoints[blockId] *= m_noDonorPointsDir[blockId][j];
971 // no of cells in each solver
972 m_noDonorCells[blockId] *= m_noDonorCellsDir[blockId][j];
973 }
974 if(m_domainId == 0) {
975 cout << "Donor solver " << blockId << " has " << m_noDonorCells[blockId] << " cells" << endl;
976 }
977 // total number of cells in all solvers together
978 m_totalNoDonorCells += m_noDonorCells[blockId];
979 }
980
981 if(m_domainId == 0) {
982 cout << "totalNoDonorCells: " << m_totalNoDonorCells << endl;
983 }
984
985 if(m_noDonorDims == 2) {
986 m_totalNoDonorCells = 0;
987 for(MInt blockId = 0; blockId < m_noBlocks; blockId++) {
988 m_noDonorPointsDir[blockId][2] = m_noDonorPointsDir[blockId][1];
989 m_noDonorPointsDir[blockId][1] = m_noDonorPointsDir[blockId][0];
990 m_noDonorPointsDir[blockId][0] = 3;
991 m_noDonorCellsDir[blockId][2] = m_noDonorCellsDir[blockId][1];
992 m_noDonorCellsDir[blockId][1] = m_noDonorCellsDir[blockId][0];
993 m_noDonorCellsDir[blockId][0] = 2;
994 m_noDonorCells[blockId] =
995 m_noDonorCellsDir[blockId][0] * m_noDonorCellsDir[blockId][1] * m_noDonorCellsDir[blockId][2];
996 m_noDonorPoints[blockId] =
997 m_noDonorPointsDir[blockId][0] * m_noDonorPointsDir[blockId][1] * m_noDonorPointsDir[blockId][2];
998 m_totalNoDonorCells += m_noDonorCells[blockId];
999 }
1000 }
1001
1002 mAlloc(m_donorBlockOffsets, m_noBlocks, AT_, 0, "m_donorBlockOffset");
1003 if(m_noBlocks > 1) {
1004 for(MInt blockId = 1; blockId < m_noBlocks; blockId++) {
1005 m_donorBlockOffsets[blockId] = m_donorBlockOffsets[blockId - 1] + m_noDonorCells[blockId - 1];
1006 }
1007 }
1008
1009 mAlloc(m_donorCoordinates, nDim, m_totalNoDonorCells, "m_donorGridCoordinates", AT_);
1010 for(MInt blockId = 0; blockId < m_noBlocks; blockId++) {
1011 MInt offset = m_donorBlockOffsets[blockId];
1012 stringstream blockName;
1013 blockName << "/block" << blockId << "/";
1014 MString blockNameStr = blockName.str();
1015
1016 if(m_noDonorDims == 3) {
1017 MFloatScratchSpace gridCoordinates(m_noDonorPoints[blockId], AT_, "gridCoordinates");
1018 MString coordName[3] = {"x", "y", "z"};
1019 ParallelIo::size_type ioSize[3] = {m_noDonorPointsDir[blockId][0], m_noDonorPointsDir[blockId][1],
1020 m_noDonorPointsDir[blockId][2]};
1021 ParallelIo::size_type ioOffset[3] = {0, 0, 0};
1022 ParallelIo::size_type ioDims = m_noDonorDims;
1023 for(MInt dim = 0; dim < m_noDonorDims; dim++) {
1024 pio.readArray(&gridCoordinates[0], blockNameStr, coordName[dim], ioDims, ioOffset, ioSize);
1025 if(!m_donorIsCellCentered) {
1026 for(MInt cellId = 0; cellId < m_noDonorCells[blockId]; cellId++) {
1027 m_donorCoordinates[dim][offset + cellId] = gridCoordinates[cellId];
1028 }
1029 } else {
1030 computeCellCentreCoordinates(m_noDonorPointsDir[blockId], gridCoordinates, dim, blockId);
1031 }
1032 for(MInt cellId = 0; cellId < m_noDonorCells[blockId]; cellId++) {
1033 m_donorCoordinates[dim][offset + cellId] =
1034 translation[dim] + scale[dim] * m_donorCoordinates[dim][offset + cellId];
1035 }
1036 }
1037 } else {
1038 ParallelIo::size_type ioSize[2] = {m_noDonorPointsDir[blockId][1], m_noDonorPointsDir[blockId][2]};
1039 ParallelIo::size_type ioOffset[3] = {0, 0, 0};
1040 MFloatScratchSpace gridCoordinates(m_noDonorPoints[blockId], AT_, "gridCoordinates");
1041
1042 for(MInt dim = 0; dim < nDim; dim++) {
1043 MString coordName[3] = {"x", "y", "z"};
1044 if(dim < 2) {
1045 pio.readArray(gridCoordinates.begin(), blockNameStr, coordName[dim], m_noDonorDims, ioOffset, ioSize);
1046
1047 // duplicate the values in z-direction
1048 for(MInt i = 0; i < m_noDonorPointsDir[blockId][2]; i++) {
1049 for(MInt j = 0; j < m_noDonorPointsDir[blockId][1]; j++) {
1050 for(MInt k = 1; k < m_noDonorPointsDir[blockId][0]; k++) {
1051 MInt pointId2D = i + j * m_noDonorPointsDir[blockId][2];
1052 MInt pointId = i + (j + k * m_noDonorPointsDir[blockId][1]) * m_noDonorPointsDir[blockId][2];
1053 gridCoordinates(pointId) = gridCoordinates(pointId2D);
1054 }
1055 }
1056 }
1057 } else {
1058 MFloat minZ = F0;
1059 MFloat maxZ = F1;
1060 for(MInt i = 0; i < m_noDonorPointsDir[blockId][2]; i++) {
1061 for(MInt j = 0; j < m_noDonorPointsDir[blockId][1]; j++) {
1062 for(MInt k = 0; k < m_noDonorPointsDir[blockId][0]; k++) {
1063 MInt pointId = i + (j + k * m_noDonorPointsDir[blockId][1]) * m_noDonorPointsDir[blockId][2];
1064 gridCoordinates(pointId) = (maxZ - minZ) / (m_noDonorPointsDir[blockId][0] - 1) * k;
1065 }
1066 }
1067 }
1068 }
1069
1070 computeCellCentreCoordinates(m_noDonorPointsDir[blockId], gridCoordinates, dim, blockId);
1071 for(MInt cellId = 0; cellId < m_noDonorCells[blockId]; cellId++) {
1072 m_donorCoordinates[dim][cellId] = translation[dim] + scale[dim] * m_donorCoordinates[dim][offset + cellId];
1073 }
1074 }
1075 }
1076 }
1077
1078 MBool write2D3DGrid = false;
1079 if(write2D3DGrid) {
1080 const char* fileName = "rescaledGrid.hdf5";
1081 ParallelIoHdf5 rescaledGridFile(fileName, maia::parallel_io::PIO_REPLACE, m_StructuredComm);
1082 for(MInt blockId = 0; blockId < m_noBlocks; blockId++) {
1083 MInt offset = m_donorBlockOffsets[blockId];
1084 stringstream blockName;
1085 blockName << "/block" << blockId << "/";
1086 MString blockNameStr = blockName.str();
1087
1088 ParallelIo::size_type ioSize[3] = {m_noDonorCellsDir[blockId][0], m_noDonorCellsDir[blockId][1],
1089 m_noDonorCellsDir[blockId][2]};
1090 rescaledGridFile.defineArray(maia::parallel_io::PIO_FLOAT, blockNameStr, "x", 3, ioSize);
1091 rescaledGridFile.defineArray(maia::parallel_io::PIO_FLOAT, blockNameStr, "y", 3, ioSize);
1092 rescaledGridFile.defineArray(maia::parallel_io::PIO_FLOAT, blockNameStr, "z", 3, ioSize);
1093 ParallelIo::size_type ioOffset[3] = {0, 0, 0};
1094
1095 if(m_domainId == 0) {
1096 rescaledGridFile.writeArray(&m_donorCoordinates[0][offset + 0], blockNameStr, "x", nDim, ioOffset, ioSize);
1097 rescaledGridFile.writeArray(&m_donorCoordinates[1][offset + 0], blockNameStr, "y", nDim, ioOffset, ioSize);
1098 rescaledGridFile.writeArray(&m_donorCoordinates[2][offset + 0], blockNameStr, "z", nDim, ioOffset, ioSize);
1099 } else {
1100 ParallelIo::size_type ioEmptySize[3] = {0, 0, 0};
1101 MFloat empty = 0;
1102 rescaledGridFile.writeArray(&empty, blockNameStr, "x", nDim, ioOffset, ioEmptySize);
1103 rescaledGridFile.writeArray(&empty, blockNameStr, "y", nDim, ioOffset, ioEmptySize);
1104 rescaledGridFile.writeArray(&empty, blockNameStr, "z", nDim, ioOffset, ioEmptySize);
1105 }
1106 }
1107 }
1108 if(m_domainId == 0) {
1109 cout << "Reading in donor grid file... FINISHED!" << endl;
1110 }
1111}
1112#endif
1113
1120#if defined(WITH_HDF5)
1121template <MInt nDim>
1123 stringstream donorFileName;
1124
1125 if(m_domainId == 0) {
1126 cout << "Reading in " << varName << " from donor file..." << endl;
1127 }
1128 // reading in a specified donor file from the properties file
1129
1142 MString donorFile = Context::getSolverProperty<MString>("donorVars", 0, AT_);
1143
1144 // open the file
1145 ParallelIoHdf5 pio(donorFile, maia::parallel_io::PIO_READ, m_StructuredComm);
1146
1147 for(MInt blockId = 0; blockId < m_noBlocks; blockId++) {
1148 stringstream blockName;
1149 blockName << "/block" << blockId << "/";
1150 MString blockNameStr = blockName.str();
1151
1152 MBool fieldExists = pio.hasDataset(varName, blockNameStr);
1153 if(fieldExists) {
1154 if(m_domainId == 0) {
1155 cout << "Field " << varName << " exist, loading from donorFile. " << endl;
1156 }
1157 MInt offset = m_donorBlockOffsets[blockId];
1158 ParallelIo::size_type ioSize[3] = {0, 0, 0};
1159 ParallelIo::size_type ioOffset[3] = {0, 0, 0};
1160 if(m_noDonorDims == 3) {
1161 ioSize[0] = m_noDonorCellsDir[blockId][0];
1162 ioSize[1] = m_noDonorCellsDir[blockId][1];
1163 ioSize[2] = m_noDonorCellsDir[blockId][2];
1164 } else {
1165 ioSize[0] = m_noDonorCellsDir[blockId][1];
1166 ioSize[1] = m_noDonorCellsDir[blockId][2];
1167 }
1168
1169 pio.readArray(&m_donorVar[offset], blockNameStr, varName, m_noDonorDims, ioOffset, ioSize);
1170
1171 // enlarge 2D field to 3D
1172 if(m_noDonorDims == 2) {
1173 for(MInt k = 1; k < m_noDonorCellsDir[blockId][0]; k++) {
1174 for(MInt j = 0; j < m_noDonorCellsDir[blockId][1]; j++) {
1175 for(MInt i = 0; i < m_noDonorCellsDir[blockId][2]; i++) {
1176 const MInt cellId = cellIndex(i, j, k, blockId);
1177 const MInt cellId2D = cellIndex(i, j, 0, blockId);
1178 m_donorVar[cellId] = m_donorVar[cellId2D];
1179 }
1180 }
1181 }
1182 }
1183 } else {
1184 if(m_domainId == 0) {
1185 cout << "Field " << varName << " doesn't exist, setting zero. " << endl;
1186 }
1187 for(MInt k = 0; k < m_noDonorCellsDir[blockId][0]; k++) {
1188 for(MInt j = 0; j < m_noDonorCellsDir[blockId][1]; j++) {
1189 for(MInt i = 0; i < m_noDonorCellsDir[blockId][2]; i++) {
1190 const MInt cellId = cellIndex(i, j, k, blockId);
1191 m_donorVar[cellId] = F0;
1192 }
1193 }
1194 }
1195 }
1196 }
1197
1198 if(m_domainId == 0) {
1199 cout << "Reading in " << varName << " from donor file... FINISHED!" << endl;
1200 }
1201}
1202#endif
1203
1211template <MInt nDim>
1213 MFloatScratchSpace& coordinates,
1214 MInt dim,
1215 MInt blockId) {
1216 // function to compute the coordinates at cell centre
1217 // do it over I, J, K loop but change to one array
1218
1219 for(MInt k = 0; k < m_noDonorCellsDir[blockId][0]; k++) {
1220 for(MInt j = 0; j < m_noDonorCellsDir[blockId][1]; j++) {
1221 for(MInt i = 0; i < m_noDonorCellsDir[blockId][2]; i++) {
1222 MInt pointId = i + (j + k * noPoints[1]) * noPoints[2];
1223 MInt IJK = pointId;
1224 MInt IP1JK = pointId + 1;
1225 MInt IJP1K = pointId + noPoints[2];
1226 MInt IP1JP1K = IJP1K + 1;
1227 MInt IJKP1 = pointId + noPoints[2] * noPoints[1];
1228 MInt IP1JKP1 = IJKP1 + 1;
1229 MInt IJP1KP1 = pointId + noPoints[2] + noPoints[2] * noPoints[1];
1230 MInt IP1JP1KP1 = IJP1KP1 + 1;
1231 MInt cellId = cellIndex(i, j, k, blockId);
1232
1233 // average the coordinates for cell centre data
1234 m_donorCoordinates[dim][cellId] =
1235 F1B8
1236 * (coordinates[IJK] + coordinates[IP1JK] + coordinates[IJP1K] + coordinates[IP1JP1K] + coordinates[IJKP1]
1237 + coordinates[IP1JKP1] + coordinates[IJP1KP1] + coordinates[IP1JP1KP1]);
1238 }
1239 }
1240 }
1241}
1242
1250template <MInt nDim>
1252 MFloat* receiverVar) {
1253 receiverVar[receiverId] = m_donorVar[donorId];
1254}
1255
1256template <MInt nDim>
1258 for(MInt var = 0; var < m_noDonorVariables; var++) {
1259 receiverVariables[var] = m_donorVariables[var][donorId];
1260 }
1261}
1262
1263template <MInt nDim>
1264inline void StructuredInterpolation<nDim>::crossProduct(MFloat result[3], MFloat vec1[3], MFloat vec2[3]) {
1265 result[xsd] = vec1[ysd] * vec2[zsd] - vec1[zsd] * vec2[ysd];
1266 result[ysd] = vec1[zsd] * vec2[xsd] - vec1[xsd] * vec2[zsd];
1267 result[zsd] = vec1[xsd] * vec2[ysd] - vec1[ysd] * vec2[xsd];
1268}
1269
1270template <MInt nDim>
1272 return vec1[xsd] * vec2[xsd] + vec1[ysd] * vec2[ysd] + vec1[zsd] * vec2[zsd];
1273}
1274
1275template <MInt nDim>
1277 MInt blockId) {
1278 return origin + incI + incJ * m_noDonorCellsDir[blockId][2]
1279 + incK * m_noDonorCellsDir[blockId][2] * m_noDonorCellsDir[blockId][1];
1280}
1281
1282template <MInt nDim>
1284 const MInt offset = m_donorBlockOffsets[blockId];
1285 return offset + i + (j + k * m_noDonorCellsDir[blockId][1]) * m_noDonorCellsDir[blockId][2];
1286}
1287
1288// returns the ijk-coordinate for one of the 4 side
1289// of one of the 6 tetraeders inside a hexahedron
1290template <MInt nDim>
1292 return m_pyramidPoints[dim + side * 3 + tetra * 3 * 4];
1293}
1294
1295template <MInt nDim>
1297 MInt currentBlockId = 0;
1298 if(m_noBlocks > 1) {
1299 for(MInt blockId = 0; blockId < m_noBlocks; blockId++) {
1300 if(cellId < m_donorBlockOffsets[blockId + 1]) {
1301 currentBlockId = blockId;
1302 break;
1303 }
1304 }
1305 }
1306
1307 return currentBlockId;
1308}
1309
1310template <MInt nDim>
1312 return abs(a - b) < eps;
1313}
1314
1315
1316// Explicit instantiations for 2D and 3D
1317template class StructuredInterpolation<2>;
1318template class StructuredInterpolation<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
MBool mDeallocate(T *&a)
deallocates the memory previously allocated for element 'a'
Definition: alloc.h:544
static MBool propertyExists(const MString &name, MInt solver=m_noSolvers)
This function checks if a property exists in general.
Definition: context.cpp:494
This class is a ScratchSpace.
Definition: scratch.h:758
void loadDonorVariable(MString varName)
Loads a Q file.
void trilinearInterpolation(MFloat *, MInt, MInt, MFloat *, MInt)
void prepareInterpolationField(MInt *noReceiverCells, MFloat **receiverCoordinates)
Prepares interpolation for field For a given 3D coordinate field the method computes the transformed ...
void computeInterpolationCoefficients(MFloat *, MInt)
Computes trilinear interpolation coefficients.
void nearestNeighbourInterpolation(MInt, MInt, MFloat *)
Nearest neighbour interpolation.
MFloat getInterpolatedVariable(MInt, MInt)
Trilinear interpolation for single point.
MInt cellIndex(MInt i, MInt j, MInt k, MInt solverId)
MFloat interpolateVariableZonal(MFloat *, MInt)
void prepareInterpolation(MInt, MFloat **, MInt *)
Prepares interpolation neighbours and coefficients For a given number of points the methods computes ...
void transformPoint(MInt hexOrigin, MFloat intPoint[3], MFloat transformedPoint[3])
Transforms point from physical to computational space.
void loadDonorGrid()
Loads a grid file.
void crossProduct(MFloat result[3], MFloat vec1[3], MFloat vec2[3])
void computeCellCentreCoordinates(MInt *, MFloatScratchSpace &, MInt, MInt)
Computes cell centered coordinates.
MBool approx(const MFloat &, const MFloat &, const MFloat)
StructuredInterpolation(const MPI_Comm structuredCommunicator)
Constructor for property given donor.
void interpolateField(MString, MFloat *)
interpolates a field interpolates a given varName and varF
void buildDonorTree()
Builds a kd-tree Creates a kd-tree from the predefined grid-data in m_donorCoordinates.
MInt findSurroundingHexahedron(MFloat intPoint[3], MInt centerCellId, MInt stencil)
Finds surrounding hexahedron for point For a given cellId it finds out which of the 8 eight surroundi...
void interpolateAtPoint(MFloat *intPoint)
interpolates variables at point For a given 3D coordinate the method interpolates from the donor grid
MFloat scalarProduct(MFloat vec1[3], MFloat vec2[3])
MFloat getInterpolatedVariableZonal(MFloat *, MInt)
MInt getCellIdfromCell(MInt origin, MInt incI, MInt incJ, MInt incK, MInt solverId)
void prepareZonalInterpolation(MInt, MFloat **, MInt *, MBool)
computes the interpolation coefficients Interpolates all variables with precomputed interpolation coe...
MBool approx(const T &, const U &, const T)
Definition: functions.h:272
constexpr T mMin(const T &x, const T &y)
Definition: functions.h:90
constexpr T mMax(const T &x, const T &y)
Definition: functions.h:94
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
bool MBool
Definition: maiatypes.h:58
int MPI_Allreduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allreduce
void const MInt cellId
Definition: collector.h:239
const MInt PIO_REPLACE
Definition: parallelio.h:36
const MInt PIO_FLOAT
Definition: parallelio.h:46
const MInt PIO_READ
Definition: parallelio.h:40
MFloat dist(const Point< DIM > &p, const Point< DIM > &q)
Definition: pointbox.h:54
Definition: kdtree.h:73
Definition: pointbox.h:20
Definition: contexttypes.h:19