VirtualFluids 0.2.0
Parallel CFD LBM Solver
Loading...
Searching...
No Matches
GridImp.cpp
Go to the documentation of this file.
1//=======================================================================================
2// ____ ____ __ ______ __________ __ __ __ __
3// \ \ | | | | | _ \ |___ ___| | | | | / \ | |
4// \ \ | | | | | |_) | | | | | | | / \ | |
5// \ \ | | | | | _ / | | | | | | / /\ \ | |
6// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____
7// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______|
8// \ \ | | ________________________________________________________________
9// \ \ | | | ______________________________________________________________|
10// \ \| | | | __ __ __ __ ______ _______
11// \ | | |_____ | | | | | | | | | _ \ / _____)
12// \ | | _____| | | | | | | | | | | \ \ \_______
13// \ | | | | |_____ | \_/ | | | | |_/ / _____ |
14// \ _____| |__| |________| \_______/ |__| |______/ (_______/
15//
16// This file is part of VirtualFluids. VirtualFluids is free software: you can
17// redistribute it and/or modify it under the terms of the GNU General Public
18// License as published by the Free Software Foundation, either version 3 of
19// the License, or (at your option) any later version.
20//
21// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT
22// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24// for more details.
25//
26// SPDX-License-Identifier: GPL-3.0-or-later
27// SPDX-FileCopyrightText: Copyright © VirtualFluids Project contributors, see AUTHORS.md in root folder
28//
33//=======================================================================================
34#include "GridImp.h"
35
36#include <iostream>
37#include <iterator>
38#include <numeric>
39#include <sstream>
40#include <algorithm>
41#include <cmath>
42#include <memory>
43#include <vector>
44
46#include <stdexcept>
47#include "global.h"
48
49#include "geometries/Object.h"
55
57#include "grid/Field.h"
58#include "grid/GridInterface.h"
59#include "grid/NodeValues.h"
60
61#include <logger/Logger.h>
62
64
66#include "utilities/math/Math.h"
68#include "basics/DataTypes.h"
69
71
72using namespace vf::basics::constant;
73
74namespace vf::gpu {
75
76GridImp::GridImp(SPtr<Object> object, real startX, real startY, real startZ, real endX, real endY, real endZ, real delta, Distribution distribution, uint level)
77 : object(object),
78 startX(startX),
79 startY(startY),
80 startZ(startZ),
81 endX(endX),
82 endY(endY),
83 endZ(endZ),
84 delta(delta),
85 distribution(distribution),
86 level(level),
87 periodicityX(false),
88 periodicityY(false),
89 periodicityZ(false),
90 enableFixRefinementIntoTheWall(false),
91 gridInterface(nullptr),
92 neighborIndexX(nullptr),
93 neighborIndexY(nullptr),
94 neighborIndexZ(nullptr),
95 neighborIndexNegative(nullptr),
96 sparseIndices(nullptr),
97 qIndices(nullptr),
98 qValues(nullptr),
99 qPatches(nullptr),
100 innerRegionFromFinerGrid(false),
101 numberOfLayers(0),
102 qComputationStage(qComputationStageType::ComputeQs)
103{
104 initalNumberOfNodesAndSize();
105}
106
107SPtr<GridImp> GridImp::makeShared(SPtr<Object> object, real startX, real startY, real startZ, real endX, real endY, real endZ, real delta, std::string d3Qxx, uint level)
108{
110 SPtr<GridImp> grid(new GridImp(object, startX, startY, startZ, endX, endY, endZ, delta, distribution, level));
111 return grid;
112}
113
114
115void GridImp::initalNumberOfNodesAndSize()
116{
117 const real length = endX - startX;
118 const real width = endY - startY;
119 const real height = endZ - startZ;
120
121 nx = std::lround((length + delta) / delta);
122 ny = std::lround((width + delta) / delta);
123 nz = std::lround((height + delta) / delta);
124
125 this->size = nx * ny * nz;
126 this->sparseSize = size;
127 distribution.setSize(size);
128}
129
130void GridImp::inital(const SPtr<Grid> fineGrid, uint numberOfLayers)
131{
132 field = Field(size);
134
135 this->neighborIndexX = new int[this->size];
136 this->neighborIndexY = new int[this->size];
137 this->neighborIndexZ = new int[this->size];
138 this->neighborIndexNegative = new int[this->size];
139
140 this->sparseIndices = new int[this->size];
141
142 this->qIndices = new uint[this->size];
143 for (uint i = 0; i < this->size; i++)
144 this->qIndices[i] = INVALID_INDEX;
145
146 VF_LOG_TRACE("Start initalNodesToOutOfGrid()");
147
148#pragma omp parallel for
149 for (int index = 0; index < (int)this->size; index++)
150 this->initalNodeToOutOfGrid(index);
151
152 if( this->innerRegionFromFinerGrid ){
153 VF_LOG_TRACE("Start setInnerBasedOnFinerGrid()");
154 this->setInnerBasedOnFinerGrid(fineGrid);
155 }
156 else{
157 VF_LOG_TRACE("Start findInnerNodes()");
158 this->object->findInnerNodes( shared_from_this() );
159 }
160 VF_LOG_TRACE("Start addOverlap()");
161 this->addOverlap();
162
163 VF_LOG_TRACE("Start fixOddCells()");
164#pragma omp parallel for
165 for (int index = 0; index < (int)this->size; index++)
166 this->fixOddCell(index);
167
168 if( enableFixRefinementIntoTheWall )
169 {
170 VF_LOG_TRACE("Start fixRefinementIntoWall()");
171#pragma omp parallel for
172 for (int xIdx = 0; xIdx < (int)this->nx; xIdx++) {
173 for (uint yIdx = 0; yIdx < this->ny; yIdx++) {
174 this->fixRefinementIntoWall( xIdx, yIdx, 0 , 3 );
175 this->fixRefinementIntoWall( xIdx, yIdx, this->nz - 1, -3 );
176 }
177 }
178
179#pragma omp parallel for
180 for (int xIdx = 0; xIdx < (int)this->nx; xIdx++) {
181 for (uint zIdx = 0; zIdx < this->nz; zIdx++) {
182 this->fixRefinementIntoWall( xIdx, 0 , zIdx, 2 );
183 this->fixRefinementIntoWall( xIdx, this->ny - 1, zIdx, -2 );
184 }
185 }
186
187#pragma omp parallel for
188 for (int yIdx = 0; yIdx < (int)this->ny; yIdx++) {
189 for (uint zIdx = 0; zIdx < this->nz; zIdx++) {
190 this->fixRefinementIntoWall( 0 , yIdx, zIdx, 1 );
191 this->fixRefinementIntoWall( this->nx - 1, yIdx, zIdx, -1 );
192 }
193 }
194 }
195 VF_LOG_TRACE("Start findEndOfGridStopperNodes()");
196#pragma omp parallel for
197 for (int index = 0; index < (int)this->size; index++)
198 this->findEndOfGridStopperNode(index);
199
200 VF_LOG_INFO("Grid created: from ({}, {}, {}) to ({}, {}, {})", this->startX, this->startY, this->startZ, this->endX, this->endY, this->endZ);
201 VF_LOG_INFO("nodes: {} x {} x {} = {}", this->nx, this->ny, this->nz, this->size);
202}
203
204void GridImp::setOddStart(bool xOddStart, bool yOddStart, bool zOddStart)
205{
206 this->xOddStart = xOddStart;
207 this->yOddStart = yOddStart;
208 this->zOddStart = zOddStart;
209}
210
214
216{
217 if( this->neighborIndexX != nullptr ) { delete[] this->neighborIndexX; this->neighborIndexX = nullptr; }
218 if( this->neighborIndexY != nullptr ) { delete[] this->neighborIndexY; this->neighborIndexY = nullptr; }
219 if( this->neighborIndexZ != nullptr ) { delete[] this->neighborIndexZ; this->neighborIndexZ = nullptr; }
220 if( this->neighborIndexNegative != nullptr ) { delete[] this->neighborIndexNegative; this->neighborIndexNegative = nullptr; }
221 if( this->sparseIndices != nullptr ) { delete[] this->sparseIndices; this->sparseIndices = nullptr; }
222 if( this->qIndices != nullptr ) { delete[] this->qIndices; this->qIndices = nullptr; }
223 if( this->qValues != nullptr ) { delete[] this->qValues; this->qValues = nullptr; }
224 if( this->qPatches != nullptr ) { delete[] this->qPatches; this->qPatches = nullptr; }
225
227}
228
230{
231#pragma omp parallel for
232 for (int index = 0; index < (int)this->size; index++)
233 this->findInnerNode(index);
234}
235
237{
238 this->sparseIndices[index] = index;
239
240 if( this->level != 0 ){
241 const Cell cell = getOddCellFromIndex(index);
242 if (isInside(cell))
243 this->field.setFieldEntryToFluid(index);
244 }
245 else{
246 real x, y, z;
247 this->transIndexToCoords(index, x, y, z);
248 const uint xIndex = getXIndex(x);
249 const uint yIndex = getYIndex(y);
250 const uint zIndex = getZIndex(z);
251
252 if( xIndex != 0 && xIndex != this->nx-1 &&
253 yIndex != 0 && yIndex != this->ny-1 &&
254 zIndex != 0 && zIndex != this->nz-1 )
255 this->field.setFieldEntryToFluid(index);
256 }
257}
258
260{
261#pragma omp parallel for
262 for (int index = 0; index < (int)this->size; index++)
263 {
264 this->sparseIndices[index] = index;
265
266 if( this->getFieldEntry(index) == innerType ) continue;
267
268 real x, y, z;
269 this->transIndexToCoords(index, x, y, z);
270
271 if( solidObject->isPointInObject(x, y, z, 0.0, 0.0) )
272 this->setFieldEntry(index, innerType);
273 //else
274 // this->setFieldEntry(index, outerType);
275 }
276}
277
278bool GridImp::isInside(const Cell& cell) const
279{
280 return object->isCellInObject(cell);
281}
282
284// Cell numbering:
285// even start odd start
286// +---------+ +---------+
287// | +-----+-----+-----+ | +-----+-----+-----+
288// | | | | | | | | | | | |
289// | +-----+-----+-----+ | +-----+-----+-----+
290// +---------+ +---------+
291// 0 1 2 0 1 2
292// even even even
293// odd odd odd
294//
295Cell GridImp::getOddCellFromIndex(uint index) const
296{
297 real x, y, z;
298 this->transIndexToCoords(index, x, y, z);
299
300 const uint xIndex = getXIndex(x);
301 const uint yIndex = getYIndex(y);
302 const uint zIndex = getZIndex(z);
303
305 if( this->xOddStart ) xCellStart = xIndex % 2 != 0 ? x - this->delta : x;
306 else xCellStart = xIndex % 2 != 0 ? x : x - this->delta;
307
309 if( this->yOddStart ) yCellStart = yIndex % 2 != 0 ? y - this->delta : y;
310 else yCellStart = yIndex % 2 != 0 ? y : y - this->delta;
311
313 if( this->zOddStart ) zCellStart = zIndex % 2 != 0 ? z - this->delta : z;
314 else zCellStart = zIndex % 2 != 0 ? z : z - this->delta;
315
316 return Cell(xCellStart, yCellStart, zCellStart, delta);
317}
318
320{
321 for( uint index = 0; index < this->size; index++ ){
322
323 real x, y, z;
324 this->transIndexToCoords(index, x, y, z);
325
326 uint childIndex[8];
327
328 childIndex[0] = fineGrid->transCoordToIndex( x + 0.25 * this->delta, y + 0.25 * this->delta, z + 0.25 * this->delta );
329 childIndex[1] = fineGrid->transCoordToIndex( x + 0.25 * this->delta, y + 0.25 * this->delta, z - 0.25 * this->delta );
330 childIndex[2] = fineGrid->transCoordToIndex( x + 0.25 * this->delta, y - 0.25 * this->delta, z + 0.25 * this->delta );
331 childIndex[3] = fineGrid->transCoordToIndex( x + 0.25 * this->delta, y - 0.25 * this->delta, z - 0.25 * this->delta );
332 childIndex[4] = fineGrid->transCoordToIndex( x - 0.25 * this->delta, y + 0.25 * this->delta, z + 0.25 * this->delta );
333 childIndex[5] = fineGrid->transCoordToIndex( x - 0.25 * this->delta, y + 0.25 * this->delta, z - 0.25 * this->delta );
334 childIndex[6] = fineGrid->transCoordToIndex( x - 0.25 * this->delta, y - 0.25 * this->delta, z + 0.25 * this->delta );
335 childIndex[7] = fineGrid->transCoordToIndex( x - 0.25 * this->delta, y - 0.25 * this->delta, z - 0.25 * this->delta );
336
337 for( uint i = 0; i < 8; i++ ){
338 if( childIndex[i] != INVALID_INDEX && fineGrid->getFieldEntry( childIndex[i] ) == FLUID ){
339 this->setFieldEntry(index, FLUID);
340 break;
341 }
342 }
343 }
344}
345
347{
348 for( uint layer = 0; layer < this->numberOfLayers; layer++ ){
349#pragma omp parallel for
350 for (int index = 0; index < (int)this->size; index++)
351 this->setOverlapTmp(index);
352
353#pragma omp parallel for
354 for (int index = 0; index < (int)this->size; index++)
355 this->setOverlapFluid(index);
356 }
357}
358
360{
361 if( this->field.is( index, INVALID_OUT_OF_GRID ) ){
362
363 if( this->hasNeighborOfType(index, FLUID) ){
364 this->field.setFieldEntry( index, OVERLAP_TMP );
365 }
366 }
367}
368
370{
371 if( this->field.is( index, OVERLAP_TMP ) ){
372 this->field.setFieldEntry( index, FLUID );
373 }
374}
375
377{
378
379 real x = this->startX + this->delta * xIndex;
380 real y = this->startY + this->delta * yIndex;
381 real z = this->startZ + this->delta * zIndex;
382
383 uint index = this->transCoordToIndex(x, y, z);
384
385 if( !this->xOddStart && ( dir == 1 || dir == -1 ) && ( xIndex % 2 == 1 || xIndex == 0 ) ) return;
386 if( !this->yOddStart && ( dir == 2 || dir == -2 ) && ( yIndex % 2 == 1 || yIndex == 0 ) ) return;
387 if( !this->zOddStart && ( dir == 3 || dir == -3 ) && ( zIndex % 2 == 1 || zIndex == 0 ) ) return;
388
389 // Dont do this if inside of the domain
390 if( this->xOddStart && ( dir == 1 || dir == -1 ) && ( xIndex % 2 == 0 && xIndex != 0 ) ) return;
391 if( this->yOddStart && ( dir == 2 || dir == -2 ) && ( yIndex % 2 == 0 && yIndex != 0 ) ) return;
392 if( this->zOddStart && ( dir == 3 || dir == -3 ) && ( zIndex % 2 == 0 && zIndex != 0 ) ) return;
393
395
396 real dx{ 0.0 }, dy{ 0.0 }, dz{ 0.0 };
397
398 if ( dir == 1 ){ dx = this->delta; dy = 0.0; dz = 0.0; }
399 else if ( dir == -1 ){ dx = - this->delta; dy = 0.0; dz = 0.0; }
400 else if ( dir == 2 ){ dx = 0.0; dy = this->delta; dz = 0.0; }
401 else if ( dir == -2 ){ dx = 0.0; dy = - this->delta; dz = 0.0; }
402 else if ( dir == 3 ){ dx = 0.0; dy = 0.0; dz = this->delta; }
403 else if ( dir == -3 ){ dx = 0.0; dy = 0.0; dz = - this->delta; }
404
406
407 char type = this->field.getFieldEntry(index);
408
409 char type2 = ( type == FLUID ) ? ( INVALID_OUT_OF_GRID ) : ( FLUID );
410 uint distance = ( type == FLUID ) ? ( 9 ) : ( 5 );
411
412 bool allTypesAreTheSame = true;
413
414 for( uint i = 1; i <= distance; i++ ){
415 uint neighborIndex = this->transCoordToIndex(x + i * dx, y + i * dy, z + i * dz);
416
417 if( neighborIndex != INVALID_INDEX && !this->field.is( neighborIndex, type ) )
418 allTypesAreTheSame = false;
419 }
420
422
424 return;
425
426 this->setFieldEntry(index, type2);
427
428 for( uint i = 1; i <= distance; i++ ){
429 uint neighborIndex = this->transCoordToIndex(x + i * dx, y + i * dy, z + i * dz);
430
431 this->setFieldEntry(neighborIndex, type2);
432 }
433}
434
435void GridImp::findStopperNode(uint index) // deprecated
436{
437 if(isValidEndOfGridStopper(index))
439
440 if (isValidSolidStopper(index))
441 this->field.setFieldEntry(index, STOPPER_SOLID);
442}
443
445{
446 if (isValidEndOfGridStopper(index)){
447 if( this->level != 0 )
449 else
451 }
452
453 if (isValidEndOfGridBoundaryStopper(index))
455}
456
458{
459 if (isValidSolidStopper(index))
460 this->field.setFieldEntry(index, STOPPER_SOLID);
461}
462
464{
465 if (shouldBeBoundarySolidNode(index))
466 {
467 this->field.setFieldEntry(index, BC_SOLID);
468 this->qIndices[index] = this->numberOfSolidBoundaryNodes++;
469 //grid->setNumberOfSolidBoundaryNodes(grid->getNumberOfSolidBoundaryNodes() + 1);
470 }
471}
472
474{
475 Cell cell = getOddCellFromIndex(index);
476 if (isOutSideOfGrid(cell))
477 return;
478 if (contains(cell, FLUID))
479 setNodeTo(cell, FLUID);
480}
481
482bool GridImp::isOutSideOfGrid(Cell &cell) const
483{
484 for (const auto point : cell) {
485 if (point.x < startX || point.x > endX
486 || point.y < startY || point.y > endY
487 || point.z < startZ || point.z > endZ)
488 return true;
489 }
490 return false;
491}
492
493bool GridImp::contains(Cell &cell, char type) const
494{
495 for (const auto point : cell) {
496 uint index = transCoordToIndex(point.x, point.y, point.z);
497 if (index == INVALID_INDEX)
498 continue;
499 if (field.is(index, type))
500 return true;
501 }
502 return false;
503}
504
505bool GridImp::cellContainsOnly(Cell &cell, char type) const
506{
507 for (const auto point : cell) {
508 uint index = transCoordToIndex(point.x, point.y, point.z);
509 if (index == INVALID_INDEX)
510 return false;
511 if (!field.is(index, type))
512 return false;
513 }
514 return true;
515}
516
518{
519 for (const auto point : cell) {
520 uint index = transCoordToIndex(point.x, point.y, point.z);
521 if (index == INVALID_INDEX)
522 return false;
523 if (!field.is(index, typeA) && !field.is(index, typeB))
524 return false;
525 }
526 return true;
527}
528
530{
531 return this->object;
532}
533
534void GridImp::setNodeTo(Cell &cell, char type)
535{
536 for (const auto point : cell) {
537 uint index = transCoordToIndex(point.x, point.y, point.z);
538 if (index == INVALID_INDEX)
539 continue;
540 field.setFieldEntry(index, type);
541 }
542}
543
544void GridImp::setNodeTo(uint index, char type)
545{
546 if( index != INVALID_INDEX )
547 field.setFieldEntry(index, type);
548}
549
550bool GridImp::isNode(uint index, char type) const
551{
552 if( index != INVALID_INDEX )
553 return field.is(index, type);
554
555 throw std::runtime_error("GridImp::isNode() -> index == INVALID_INDEX not supported.");
556}
557
558bool GridImp::isValidEndOfGridStopper(uint index) const
559{
560 // Lenz: also includes corner stopper nodes
561 if (!this->field.is(index, INVALID_OUT_OF_GRID))
562 return false;
563
564 return hasNeighborOfType(index, FLUID);
565}
566
567bool GridImp::isValidEndOfGridBoundaryStopper(uint index) const
568{
569 // Lenz: also includes corner stopper nodes
570 if (!this->field.is(index, FLUID))
571 return false;
572
573 return ! hasAllNeighbors(index);
574}
575
576bool GridImp::isValidSolidStopper(uint index) const
577{
578 // Lenz: also includes corner stopper nodes
579 if (!this->field.is(index, INVALID_SOLID))
580 return false;
581
582 return hasNeighborOfType(index, FLUID);
583}
584
585bool GridImp::shouldBeBoundarySolidNode(uint index) const
586{
587 if (!this->field.is(index, FLUID))
588 return false;
589
590 return hasNeighborOfType(index, STOPPER_SOLID);
591}
592
594{
595 // new version by Lenz, utilizes the range based for loop for all directions
596 real x, y, z;
597 this->transIndexToCoords(index, x, y, z);
598 for (const auto dir : this->distribution) {
599 const uint neighborIndex = this->transCoordToIndex(x + dir[0] * this->getDelta(), y + dir[1] * this->getDelta(), z + dir[2] * this->getDelta());
600
601 if (neighborIndex == INVALID_INDEX) return false;
602 }
603
604 return true;
605}
606
607bool GridImp::hasNeighborOfType(uint index, char type) const
608{
609 // new version by Lenz, utilizes the range based for loop for all directions
610 real x, y, z;
611 this->transIndexToCoords(index, x, y, z);
612 for (const auto dir : this->distribution) {
613 const uint neighborIndex = this->transCoordToIndex(x + dir[0] * this->getDelta(), y + dir[1] * this->getDelta(), z + dir[2] * this->getDelta());
614
615 if (neighborIndex == INVALID_INDEX) continue;
616
617 if (this->field.is(neighborIndex, type))
618 return true;
619 }
620
621 return false;
622}
623
624bool GridImp::nodeInNextCellIs(int index, char type) const
625{
626 real x, y, z;
627 this->transIndexToCoords(index, x, y, z);
628
629 const real neighborX = x + this->delta > endX ? endX : x + this->delta;
630 const real neighborY = y + this->delta > endY ? endY : y + this->delta;
631 const real neighborZ = z + this->delta > endZ ? endZ : z + this->delta;
632
633 const uint indexX = transCoordToIndex(neighborX, y, z);
634 const uint indexY = transCoordToIndex(x, neighborY, z);
635 const uint indexZ = transCoordToIndex(x, y, neighborZ);
636
637 const uint indexXY = transCoordToIndex(neighborX, neighborY, z);
638 const uint indexYZ = transCoordToIndex(x, neighborY, neighborZ);
639 const uint indexXZ = transCoordToIndex(neighborX, y, neighborZ);
640
641 const uint indexXYZ = transCoordToIndex(neighborX, neighborY, neighborZ);
642
643 const bool typeX = indexX == INVALID_INDEX ? false : this->field.is(indexX, type);
644 const bool typeY = indexY == INVALID_INDEX ? false : this->field.is(indexY, type);
645 const bool typeXY = indexXY == INVALID_INDEX ? false : this->field.is(indexXY, type);
646 const bool typeZ = indexZ == INVALID_INDEX ? false : this->field.is(indexZ, type);
647 const bool typeYZ = indexYZ == INVALID_INDEX ? false : this->field.is(indexYZ, type);
648 const bool typeXZ = indexXZ == INVALID_INDEX ? false : this->field.is(indexXZ, type);
649 const bool typeXYZ = indexXYZ == INVALID_INDEX ? false : this->field.is(indexXYZ, type);
650
651 return typeX || typeY || typeXY || typeZ || typeYZ
652 || typeXZ || typeXYZ;
653}
654
655bool GridImp::nodeInPreviousCellIs(int index, char type) const
656{
657 real x, y, z;
658 this->transIndexToCoords(index, x, y, z);
659
660 const real neighborX = x - this->delta < startX ? startX : x - this->delta;
661 const real neighborY = y - this->delta < startY ? startY : y - this->delta;
662 const real neighborZ = z - this->delta < startZ ? startZ : z - this->delta;
663
664 const uint indexX = transCoordToIndex(neighborX, y, z);
665 const uint indexY = transCoordToIndex(x, neighborY, z);
666 const uint indexZ = transCoordToIndex(x, y, neighborZ);
667
668 const uint indexXY = transCoordToIndex(neighborX, neighborY, z);
669 const uint indexYZ = transCoordToIndex(x, neighborY, neighborZ);
670 const uint indexXZ = transCoordToIndex(neighborX, y, neighborZ);
671
672 const uint indexXYZ = transCoordToIndex(neighborX, neighborY, neighborZ);
673
674 const bool typeX = indexX == INVALID_INDEX ? false : this->field.is(indexX , type);
675 const bool typeY = indexY == INVALID_INDEX ? false : this->field.is(indexY , type);
676 const bool typeXY = indexXY == INVALID_INDEX ? false : this->field.is(indexXY , type);
677 const bool typeZ = indexZ == INVALID_INDEX ? false : this->field.is(indexZ , type);
678 const bool typeYZ = indexYZ == INVALID_INDEX ? false : this->field.is(indexYZ , type);
679 const bool typeXZ = indexXZ == INVALID_INDEX ? false : this->field.is(indexXZ , type);
680 const bool typeXYZ = indexXYZ == INVALID_INDEX ? false : this->field.is(indexXYZ, type);
681
682 return typeX || typeY || typeXY || typeZ || typeYZ
683 || typeXZ || typeXYZ;
684}
685
686bool GridImp::nodeInCellIs(Cell& cell, char type) const
687{
688 for (const auto node : cell)
689 {
690 const uint index = transCoordToIndex(node.x, node.y, node.z);
691 if (index == INVALID_INDEX)
692 continue;
693 if (field.is(index, type))
694 return true;
695 }
696 return false;
697}
698
699
700void GridImp::setCellTo(uint index, char type)
701{
702 real x, y, z;
703 this->transIndexToCoords(index, x, y, z);
704
705 Cell cell(x, y, z, this->delta);
706 for (const auto node : cell)
707 {
708 const uint nodeIndex = transCoordToIndex(node.x, node.y, node.z);
710 continue;
711 this->field.setFieldEntry(nodeIndex, type);
712 }
713}
714
715
717{
718 real x, y, z;
719 this->transIndexToCoords(index, x, y, z);
720
721 Cell cell(x, y, z, this->delta);
722 for (const auto node : cell)
723 {
724 const uint nodeIndex = transCoordToIndex(node.x, node.y, node.z);
726 continue;
727
728 if( this->getFieldEntry( nodeIndex ) != STOPPER_OUT_OF_GRID &&
729 this->getFieldEntry( nodeIndex ) != STOPPER_OUT_OF_GRID_BOUNDARY )
730 this->field.setFieldEntry(nodeIndex, type);
731 }
732}
733
734bool GridImp::nodeHasBC(uint index) const
735{
736 return (getFieldEntry(index) == vf::gpu::BC_PRESSURE || getFieldEntry(index) == vf::gpu::BC_VELOCITY ||
737 getFieldEntry(index) == vf::gpu::BC_NOSLIP || getFieldEntry(index) == vf::gpu::BC_SLIP ||
738 getFieldEntry(index) == vf::gpu::BC_STRESS);
739}
740
741void GridImp::setPeriodicity(bool periodicityX, bool periodicityY, bool periodicityZ)
742{
743 this->periodicityX = periodicityX;
744 this->periodicityY = periodicityY;
745 this->periodicityZ = periodicityZ;
746}
747
748void GridImp::setPeriodicityX(bool periodicity)
749{
750 this->periodicityX = periodicity;
751}
752
753void GridImp::setPeriodicityY(bool periodicity)
754{
755 this->periodicityY = periodicity;
756}
757
758void GridImp::setPeriodicityZ(bool periodicity)
759{
760 this->periodicityZ = periodicity;
761}
762
764{
765 return this->periodicityX;
766}
767
769{
770 return this->periodicityY;
771}
772
774{
775 return this->periodicityZ;
776}
777
779{
780 if(!this->periodicityY)
781 throw std::runtime_error("Domain needs to be periodic in X and Y to shift periodic boundary!");
782
783 VF_LOG_INFO("Shifting periodicity in X direction by {} in Y direction.", shift);
784 this->periodicShiftOnXinY = shift;
785}
787{
788 if(!this->periodicityX || !this->periodicityZ)
789 throw std::runtime_error("Domain needs to be periodic in X and Z to shift periodic boundary!");
790
791 VF_LOG_INFO("Shifting periodicity in X direction by {} in Z direction.", shift);
792 this->periodicShiftOnXinZ = shift;
793}
795{
796 if(!this->periodicityY || !this->periodicityX)
797 throw std::runtime_error("Domain needs to be periodic in Y and X to shift periodic boundary!");
798
799 VF_LOG_INFO("Shifting periodicity in Y direction by {} in X direction.", shift);
800 this->periodicShiftOnYinX = shift;
801}
803{
804 if(!this->periodicityY || !this->periodicityZ)
805 throw std::runtime_error("Domain needs to be periodic in Y and Z to shift periodic boundary!");
806
807 VF_LOG_INFO("Shifting periodicity in Y direction by {} in Z direction.", shift);
808 this->periodicShiftOnYinZ = shift;
809}
811{
812 if(!this->periodicityZ || !this->periodicityX)
813 throw std::runtime_error("Domain needs to be periodic in Z and X to shift periodic boundary!");
814
815 VF_LOG_INFO("Shifting periodicity in Z direction by {} in X direction.", shift);
816 this->periodicShiftOnZinX = shift;
817}
819{
820 if(!this->periodicityZ || !this->periodicityY)
821 throw std::runtime_error("Domain needs to be periodic in Z and Y to shift periodic boundary!");
822
823 VF_LOG_INFO("Shifting periodicity in Z direction by {} in Y direction.", shift);
824 this->periodicShiftOnZinY = shift;
825}
826
827void GridImp::setEnableFixRefinementIntoTheWall(bool enableFixRefinementIntoTheWall)
828{
829 this->enableFixRefinementIntoTheWall = enableFixRefinementIntoTheWall;
830}
831
832uint GridImp::transCoordToIndex(const real &x, const real &y, const real &z) const
833{
834 const uint xIndex = getXIndex(x);
835 const uint yIndex = getYIndex(y);
836 const uint zIndex = getZIndex(z);
837
838 if (xIndex >= nx || yIndex >= ny || zIndex >= nz)
839 return INVALID_INDEX;
840
841 return xIndex + nx * (yIndex + ny * zIndex);
842}
843
845{
846 if (index == INVALID_INDEX)
847 printf("Function: transIndexToCoords. GridImp Index: %d, size: %d. Exit Program!\n", index, size);
848
849 x = (real)(index % nx);
850 y = (real)((index / nx) % ny);
851 z = (real)(((index / nx) / ny) % nz);
852
853 x = (x * delta) + startX;
854 y = (y * delta) + startY;
855 z = (z * delta) + startZ;
856}
857
859{
860 uint level = 0;
861 real delta = this->delta;
862 while(!vf::Math::equal(delta, startDelta))
863 {
864 delta *= 2;
865 level++;
866 }
867 return level;
868}
869
871{
872 return this->level;
873}
874
876{
877 this->triangularMeshDiscretizationStrategy = triangularMeshDiscretizationStrategy;
878}
879
881{
882 return this->triangularMeshDiscretizationStrategy;
883}
884
886{
887 this->activeWindingSurface = surface;
888}
889
891{
892 return this->activeWindingSurface;
893}
894
896{
897 this->qSourceSurfaces.clear();
898}
899
901{
902 return this->numberOfSolidBoundaryNodes;
903}
904
905void GridImp::setNumberOfSolidBoundaryNodes(uint numberOfSolidBoundaryNodes)
906{
907 if (numberOfSolidBoundaryNodes < INVALID_INDEX)
908 this->numberOfSolidBoundaryNodes = numberOfSolidBoundaryNodes;
909}
910
911real GridImp::getQValue(const uint index, const uint dir) const
912{
913 const int qIndex = dir * this->numberOfSolidBoundaryNodes + this->qIndices[index];
914
915 return this->qValues[qIndex];
916}
917
918uint GridImp::getQPatch(const uint index) const
919{
920 return this->qPatches[ this->qIndices[index] ];
921}
922
923bool GridImp::hasQIndex(uint index) const
924{
925 if (!this->qIndices)
926 return false;
927 if (index >= this->size)
928 return false;
929 return this->qIndices[index] != INVALID_INDEX;
930}
931
933{
934 if (!hasQIndex(index))
935 return INVALID_INDEX;
936 return this->qIndices[index];
937}
938
939void GridImp::setQValue(uint index, int dir, real value)
940{
941 if (!hasQIndex(index) || !this->qValues)
942 return;
943
944 if (dir < this->distribution.dir_start || dir > this->distribution.dir_end)
945 return;
946
947 const uint qIndex = this->qIndices[index];
948 const uint dirIndex = static_cast<uint>(dir);
949 const uint totalDir = static_cast<uint>(this->distribution.dir_end + 1);
950 const uint offset = dirIndex * this->numberOfSolidBoundaryNodes + qIndex;
951 const uint maxSize = this->numberOfSolidBoundaryNodes * totalDir;
952 if (offset >= maxSize)
953 return;
954
955 this->qValues[offset] = value;
956}
957
959{
960 if (!hasQIndex(index) || !this->qPatches)
961 return;
962
963 this->qPatches[this->qIndices[index]] = patch;
964}
965
967{
968 if (!hasQIndex(index) || !this->qValues)
969 return;
970
971 const uint qIndex = this->qIndices[index];
972 const uint totalDir = static_cast<uint>(this->distribution.dir_end + 1);
973 for (uint dir = 0; dir < totalDir; ++dir) {
974 const uint offset = dir * this->numberOfSolidBoundaryNodes + qIndex;
975 if (offset < this->numberOfSolidBoundaryNodes * totalDir)
976 this->qValues[offset] = -1.0;
977 }
978
979 if (this->qPatches)
980 this->qPatches[qIndex] = INVALID_INDEX;
981
982 this->qIndices[index] = INVALID_INDEX;
983}
984
986{
987 if (!this->qValues || this->numberOfSolidBoundaryNodes == 0)
988 return;
989
990 const uint totalDir = static_cast<uint>(this->distribution.dir_end + 1);
991 const uint totalEntries = this->numberOfSolidBoundaryNodes * totalDir;
992
993#pragma omp parallel for
994 for (int idx = 0; idx < static_cast<int>(totalEntries); ++idx) {
995 if (this->qValues[idx] < real(0.0))
996 this->qValues[idx] = defaultValue;
997 }
998}
999
1001{
1002 if (!this->qIndices || !this->qValues || this->numberOfSolidBoundaryNodes == 0)
1003 return;
1004
1005 const uint totalDir = static_cast<uint>(this->distribution.dir_end + 1);
1006 const uint totalEntries = this->numberOfSolidBoundaryNodes * totalDir;
1007
1008 for (uint index = 0; index < this->size; ++index) {
1009 if (!this->field.is(index, BC_SOLID))
1010 continue;
1011 if (!hasQIndex(index))
1012 continue;
1013
1014 real ox = 0.0;
1015 real oy = 0.0;
1016 real oz = 0.0;
1017 this->transIndexToCoords(index, ox, oy, oz);
1018
1019 const uint boundaryIndex = this->qIndices[index];
1020
1021 for (int dir = this->distribution.dir_start; dir <= this->distribution.dir_end; ++dir) {
1022 const auto &direction = this->distribution.directions[dir];
1023 if (direction[0] == 0 && direction[1] == 0 && direction[2] == 0)
1024 continue;
1025
1026 const uint dirIndex = static_cast<uint>(dir);
1027 const uint offset = dirIndex * this->numberOfSolidBoundaryNodes + boundaryIndex;
1028 if (offset >= totalEntries)
1029 continue;
1030 if (this->qValues[offset] >= static_cast<real>(0.0))
1031 continue;
1032
1033 const real nx = static_cast<real>(ox) + static_cast<real>(direction[0]) * this->delta;
1034 const real ny = static_cast<real>(oy) + static_cast<real>(direction[1]) * this->delta;
1035 const real nz = static_cast<real>(oz) + static_cast<real>(direction[2]) * this->delta;
1036 const uint neighbourIndex = this->transCoordToIndex(nx, ny, nz);
1038 continue;
1039
1040 const char neighbourType = this->getFieldEntry(neighbourIndex);
1041 if (neighbourType != STOPPER_SOLID && neighbourType != INVALID_SOLID)
1042 continue;
1043
1044 this->qValues[offset] = defaultValue;
1045 }
1046 }
1047}
1048
1050{
1051 if (!this->qIndices)
1052 return;
1053
1054 uint nextIndex = 0;
1055 for (uint index = 0; index < this->size; ++index) {
1056 if (this->field.is(index, BC_SOLID)) {
1057 this->qIndices[index] = nextIndex++;
1058 } else {
1059 this->qIndices[index] = INVALID_INDEX;
1060 }
1061 }
1062
1063 const int dirStart = this->distribution.dir_start;
1064 const int dirEnd = this->distribution.dir_end;
1065 const real dx = this->delta;
1066
1067 for (uint index = 0; index < this->size; ++index) {
1068 if (!this->field.is(index, FLUID))
1069 continue;
1070
1071 real ox = 0.0;
1072 real oy = 0.0;
1073 real oz = 0.0;
1074 this->transIndexToCoords(index, ox, oy, oz);
1075
1076 bool touchesSolid = false;
1077 for (int dir = dirStart; dir <= dirEnd; ++dir) {
1078 const auto &direction = this->distribution.directions[dir];
1079 const int cx = direction[0];
1080 const int cy = direction[1];
1081 const int cz = direction[2];
1082 if (cx == 0 && cy == 0 && cz == 0)
1083 continue;
1084
1086 ox + static_cast<real>(cx) * dx,
1087 oy + static_cast<real>(cy) * dx,
1088 oz + static_cast<real>(cz) * dx);
1090 continue;
1091
1092 const char neighbourType = this->getFieldEntry(neighbourIndex);
1093 if (neighbourType == STOPPER_SOLID || neighbourType == INVALID_SOLID) {
1094 touchesSolid = true;
1095 break;
1096 }
1097 }
1098
1099 if (touchesSolid) {
1100 this->setFieldEntry(index, BC_SOLID);
1101 this->qIndices[index] = nextIndex++;
1102 }
1103 }
1104
1105 this->numberOfSolidBoundaryNodes = nextIndex;
1106}
1107
1109{
1110 const bool capacityMismatch = (this->qCapacity != this->numberOfSolidBoundaryNodes);
1111
1112 if (capacityMismatch) {
1113 delete[] this->qValues;
1114 delete[] this->qPatches;
1115 this->qValues = nullptr;
1116 this->qPatches = nullptr;
1117 this->qCapacity = 0;
1118 }
1119
1120 if (!this->qValues)
1121 allocateQs();
1122
1123 const uint totalDir = static_cast<uint>(this->distribution.dir_end + 1);
1124 const uint totalEntries = this->numberOfSolidBoundaryNodes * totalDir;
1125#pragma omp parallel for
1126 for (int idx = 0; idx < static_cast<int>(totalEntries); ++idx)
1127 this->qValues[idx] = -1.0;
1128
1129 if (this->qPatches) {
1130#pragma omp parallel for
1131 for (int idx = 0; idx < static_cast<int>(this->numberOfSolidBoundaryNodes); ++idx)
1132 this->qPatches[idx] = INVALID_INDEX;
1133 }
1134}
1135void GridImp::setInnerRegionFromFinerGrid(bool innerRegionFromFinerGrid)
1136{
1137 this->innerRegionFromFinerGrid = innerRegionFromFinerGrid;
1138}
1139
1141{
1142 this->numberOfLayers = numberOfLayers;
1143}
1144
1145// --------------------------------------------------------- //
1146// Set Sparse Indices //
1147// --------------------------------------------------------- //
1148
1150{
1151 VF_LOG_TRACE("Find sparse indices...");
1152 auto fineGrid = std::static_pointer_cast<GridImp>(finerGrid);
1153
1154 this->updateSparseIndices();
1155
1156#pragma omp parallel for
1157 for (int index = 0; index < (int)this->getSize(); index++)
1158 this->setNeighborIndices(index);
1159
1160 if (fineGrid) {
1161 fineGrid->updateSparseIndices();
1163 }
1164
1165 const uint newGridSize = this->getSparseSize();
1166 VF_LOG_TRACE("... done. new size: {}, delete nodes: {}", newGridSize, this->getSize() - newGridSize);
1167}
1168
1170{
1171#pragma omp parallel for
1172 for (int index = 0; index < (int)this->getNumberOfNodesCF(); index++)
1173 this->gridInterface->findForGridInterfaceSparseIndexCF(this, fineGrid.get(), index);
1174
1175#pragma omp parallel for
1176 for (int index = 0; index < (int)this->getNumberOfNodesFC(); index++)
1177 this->gridInterface->findForGridInterfaceSparseIndexFC(this, fineGrid.get(), index);
1178}
1179
1181{
1182 int removedNodes = 0;
1183 int newIndex = 0;
1184 for (uint index = 0; index < size; index++)
1185 {
1186 if (this->field.isInvalidCoarseUnderFine(index) || this->field.isInvalidOutOfGrid(index) || this->field.isInvalidSolid(index))
1187 {
1188 sparseIndices[index] = -1;
1189 removedNodes++;
1190 }
1191 else
1192 {
1193 sparseIndices[index] = newIndex;
1194 newIndex++;
1195 }
1196 }
1197 sparseSize = size - removedNodes;
1198}
1199
1201{
1202 // find sparse index of all fluid nodes
1203 this->fluidNodeIndices.clear();
1204 for (uint index = 0; index < this->size; index++) {
1205 int sparseIndex = this->getSparseIndex(index);
1206 if (sparseIndex == -1)
1207 continue;
1208 if (this->field.isFluid(index))
1209 this->fluidNodeIndices.push_back((uint)sparseIndex+1); // + 1 for numbering shift between GridGenerator and VF_GPU
1210 }
1211
1212 // If splitDomain: find fluidNodeIndicesBorder and remove all indices in fluidNodeIndicesBorder and all receive nodes from fluidNodeIndices
1213 if (!splitDomain) return;
1215 std::sort(this->fluidNodeIndices.begin(), this->fluidNodeIndices.end());
1216 const auto iterator = std::set_difference(this->fluidNodeIndices.begin(), this->fluidNodeIndices.end(),
1217 this->fluidNodeIndicesBorder.begin(), this->fluidNodeIndicesBorder.end(),
1218 this->fluidNodeIndices.begin());
1219 this->fluidNodeIndices.resize(iterator - this->fluidNodeIndices.begin());
1220
1221 // remove all receive indices from fluid nodes
1223 {
1224 std::vector<uint> receiveNodes;
1225 std::transform(ci.receiveIndices.begin(), ci.receiveIndices.end(), std::back_inserter(receiveNodes),
1226 [&](uint index) { return this->getSparseIndex(index) + 1; });
1227 std::sort(receiveNodes.begin(), receiveNodes.end());
1228 receiveNodes.erase(std::unique(receiveNodes.begin(), receiveNodes.end()), receiveNodes.end());
1229 const auto iter = std::set_difference(this->fluidNodeIndices.begin(), this->fluidNodeIndices.end(), receiveNodes.begin(),
1230 receiveNodes.end(), this->fluidNodeIndices.begin());
1231 this->fluidNodeIndices.resize(iter - this->fluidNodeIndices.begin());
1232 }
1233}
1234
1236 this->fluidNodeIndicesBorder.clear();
1237 // resize fluidNodeIndicesBorder (for better performance in copy operation)
1238 size_t newSize = 0;
1240 newSize += ci.sendIndices.size();
1241 this->fluidNodeIndicesBorder.reserve(newSize);
1242
1243 // copy all send indices to fluidNodeIndicesBorder
1245 std::copy(ci.sendIndices.begin(), ci.sendIndices.end(), std::back_inserter(this->fluidNodeIndicesBorder));
1246
1247 // remove duplicate elements
1248 std::sort(this->fluidNodeIndicesBorder.begin(), this->fluidNodeIndicesBorder.end());
1249 this->fluidNodeIndicesBorder.erase(
1250 std::unique(this->fluidNodeIndicesBorder.begin(), this->fluidNodeIndicesBorder.end()),
1251 this->fluidNodeIndicesBorder.end());
1252
1253 // + 1 for numbering shift between GridGenerator and VF_GPU
1254 for (size_t i = 0; i < this->fluidNodeIndicesBorder.size(); i++)
1255 this->fluidNodeIndicesBorder[i] = this->getSparseIndex(this->fluidNodeIndicesBorder[i])+1;
1256}
1257
1259{
1260 real x, y, z;
1261 this->transIndexToCoords(index, x, y, z);
1262
1263 if (this->sparseIndices[index] == -1) {
1264 this->neighborIndexX[index] = -1;
1265 this->neighborIndexY[index] = -1;
1266 this->neighborIndexZ[index] = -1;
1267 this->neighborIndexNegative[index] = -1;
1268 return;
1269 }
1270
1271 if (this->field.isStopper(index) || this->field.is(index, STOPPER_OUT_OF_GRID_BOUNDARY)) {
1272 this->neighborIndexX[index] = getStopperNeighborIndex(x, y, z, 0);
1273 this->neighborIndexY[index] = getStopperNeighborIndex(x, y, z, 1);
1274 this->neighborIndexZ[index] = getStopperNeighborIndex(x, y, z, 2);
1275 this->neighborIndexNegative[index] = this->getNegativeStopperNeighborIndex(x, y, z);
1276 return;
1277 }
1278
1279 this->neighborIndexX[index] = this->getNeighborIndex(x, y, z, 0);
1280 this->neighborIndexY[index] = this->getNeighborIndex(x, y, z, 1);
1281 this->neighborIndexZ[index] = this->getNeighborIndex(x, y, z, 2);
1282 this->neighborIndexNegative[index] = this->getNegativeNeighborIndex(x, y, z);
1283}
1284
1285inline real wrapCoord(real coord, real start, real end)
1286{
1287 const real length = end - start;
1288 if(coord < start)
1289 return coord + length;
1290 if(coord > end)
1291 return coord - length;
1292 return coord;
1293}
1294
1295int GridImp::getStopperNeighborIndex(real x, real y, real z, int direction) const
1296{
1297 real neighborCoords[3] { x, y, z };
1298 neighborCoords[direction] += delta;
1299
1300 if(neighborCoords[direction] > getEnd(direction) + c1o2 * delta)
1301 return -1;
1302
1303 if (isPeriodic(direction) && neighborCoords[direction] > getEnd(direction) - c1o2 * delta)
1304 {
1305 neighborCoords[direction] -= getEnd(direction) - getStart(direction) - delta;
1306 switch(direction)
1307 {
1308 case 0:
1309 neighborCoords[1] = isPeriodic(1) ? wrapCoord(neighborCoords[1] + periodicShiftOnXinY, startY + c1o2*delta, endY - c1o2*delta) : neighborCoords[1];
1310 neighborCoords[2] = isPeriodic(2) ? wrapCoord(neighborCoords[2] + periodicShiftOnXinZ, startZ + c1o2*delta, endZ - c1o2*delta) : neighborCoords[2];
1311 break;
1312 case 1:
1313 neighborCoords[0] = isPeriodic(0) ? wrapCoord(neighborCoords[0] + periodicShiftOnYinX, startX + c1o2*delta, endX - c1o2*delta) : neighborCoords[0];
1314 neighborCoords[2] = isPeriodic(2) ? wrapCoord(neighborCoords[2] + periodicShiftOnYinZ, startZ + c1o2*delta, endZ - c1o2*delta) : neighborCoords[2];
1315 break;
1316 case 2:
1317 neighborCoords[0] = isPeriodic(0) ? wrapCoord(neighborCoords[0] + periodicShiftOnZinX, startX + c1o2*delta, endX - c1o2*delta) : neighborCoords[0];
1318 neighborCoords[1] = isPeriodic(1) ? wrapCoord(neighborCoords[1] + periodicShiftOnZinY, startY + c1o2*delta, endY - c1o2*delta) : neighborCoords[1];
1319 break;
1320 default:
1321 throw std::runtime_error("GridImp::getStopperNeighborIndex() -> direction must be 0, 1 or 2.");
1322 break;
1323 }
1324 }
1325
1326 const uint index = this->transCoordToIndex(neighborCoords[0], neighborCoords[1], neighborCoords[2]);
1327 if(this->field.isInvalidOutOfGrid(index))
1328 return -1;
1329
1331}
1332
1333
1334int GridImp::getNegativeStopperNeighborIndex(real x, real y, real z) const
1335{
1336 real neighborCoords[3] { x-delta, y-delta, z-delta };
1337 const uint index = this->transCoordToIndex(neighborCoords[0], neighborCoords[1], neighborCoords[2]);
1338
1339 if (neighborCoords[0] < getEndX() || neighborCoords[1] < getEndY() || neighborCoords[2] < getEndZ() || index == INVALID_INDEX || this->field.isInvalidOutOfGrid(index))
1340 return -1;
1341
1343}
1344
1345
1346
1347int GridImp::getNeighborIndex(real x, real y, real z, int direction) const
1348{
1349 real neighborCoords[3] = { x, y, z };
1350 neighborCoords[direction] += delta;
1351 if(isPeriodic(direction))
1352 getPeriodicNeighborCoords(x, y, z, neighborCoords, direction);
1353
1355}
1356
1357
1358void GridImp::getPeriodicNeighborCoords(real x, real y, real z, real* neighborCoords, int direction) const
1359{
1360 const uint neighborIndex = this->transCoordToIndex(neighborCoords[0], neighborCoords[1], neighborCoords[2]);
1361 if (neighborIndex == INVALID_INDEX || !field.is(neighborIndex, STOPPER_OUT_OF_GRID_BOUNDARY))
1362 return;
1363
1364 real coords[3] = {x, y, z};
1365 switch(direction)
1366 {
1367 case 0:
1368 neighborCoords[0] = getFirstFluidNode(coords, 0, startX);
1369 neighborCoords[1] = wrapCoord(neighborCoords[1] + periodicShiftOnXinY, startY + c1o2*delta, endY - c1o2*delta);
1370 neighborCoords[2] = wrapCoord(neighborCoords[2] + periodicShiftOnXinZ, startZ + c1o2*delta, endZ - c1o2*delta);
1371 break;
1372 case 1:
1373 neighborCoords[0] = wrapCoord(neighborCoords[0] + periodicShiftOnYinX, startX + c1o2*delta, endX - c1o2*delta);
1374 neighborCoords[1] = getFirstFluidNode(coords, 1, startY);
1375 neighborCoords[2] = wrapCoord(neighborCoords[2] + periodicShiftOnYinZ, startZ + c1o2*delta, endZ - c1o2*delta);
1376 break;
1377 case 2:
1378 neighborCoords[0] = wrapCoord(neighborCoords[0] + periodicShiftOnZinX, startX + c1o2*delta, endX - c1o2*delta);
1379 neighborCoords[1] = wrapCoord(neighborCoords[1] + periodicShiftOnZinY, startY + c1o2*delta, endY - c1o2*delta);
1380 neighborCoords[2] = getFirstFluidNode(coords, 2, startZ);
1381 break;
1382 default:
1383 throw std::runtime_error("GridImp::getPeriodicNeighbor() -> direction must be 0, 1 or 2.");
1384 break;
1385 }
1386}
1387
1388
1389int GridImp::getNegativeNeighborIndex(real x, real y, real z) const
1390{
1391 real neighborCoords[3] = { x-delta, y-delta, z-delta };
1392
1393 if(periodicityX || periodicityY || periodicityZ)
1394 getNegativePeriodicNeighborCoords(x, y, z, neighborCoords);
1395
1397}
1398
1399
1400void GridImp::getNegativePeriodicNeighborCoords(real x, real y, real z, real* neighborCoords) const
1401{
1402 const bool periodicity[3] = {periodicityX, periodicityY, periodicityZ};
1403 real coords[3] = {x, y, z};
1404 bool onBoundary[3] = {false, false, false};
1405
1406 for(uint direction=0; direction<3; direction++){
1407 if(!periodicity[direction]) continue;
1408
1409 real neighborInThisDirection[3] = {x, y, z};
1410 neighborInThisDirection[direction] -= delta;
1411
1414 if (neighborIndex == INVALID_INDEX || !field.is(neighborIndex, STOPPER_OUT_OF_GRID_BOUNDARY))
1415 continue;
1416
1417 onBoundary[direction] = true;
1418 }
1419
1420
1421
1422 for(int direction=0; direction<3; direction++){
1423 switch(direction){
1424
1425 case 0:
1426 if( (onBoundary[1] && periodicShiftOnYinX > 0) || (onBoundary[2] && periodicShiftOnZinX > 0) )
1427 neighborCoords[direction] = wrapCoord(neighborCoords[direction] - (periodicShiftOnYinX + periodicShiftOnZinX), startX + c1o2*delta, endX - c1o2*delta);
1428 else if(onBoundary[direction])
1429 neighborCoords[direction] = getLastFluidNode(coords, direction, endX);
1430 break;
1431 case 1:
1432 if( (onBoundary[0] && periodicShiftOnXinY > 0) || (onBoundary[2] && periodicShiftOnZinY > 0) )
1433 neighborCoords[direction] = wrapCoord(neighborCoords[direction] - (periodicShiftOnXinY + periodicShiftOnZinY), startY + c1o2*delta, endY - c1o2*delta);
1434 else if(onBoundary[direction])
1435 neighborCoords[direction] = getLastFluidNode(coords, direction, endY);
1436 break;
1437 case 2:
1438 if( (onBoundary[0] && periodicShiftOnXinZ > 0) || (onBoundary[1] && periodicShiftOnYinZ > 0) )
1439 neighborCoords[direction] = wrapCoord(neighborCoords[direction] - (periodicShiftOnXinZ + periodicShiftOnYinZ), startZ + c1o2*delta, endZ - c1o2*delta);
1440 else if(onBoundary[direction])
1441 neighborCoords[direction] = getLastFluidNode(coords, direction, endZ);
1442 break;
1443 }
1444 }
1445}
1446
1447
1448
1450{
1451 coords[direction] = startCoord;
1452 uint index = this->transCoordToIndex(coords[0], coords[1], coords[2]);
1453 while (index != INVALID_INDEX && !field.isFluid(index))
1454 {
1455 coords[direction] -= delta;
1456 index = this->transCoordToIndex(coords[0], coords[1], coords[2]);
1457 }
1458 return coords[direction];
1459}
1460
1462{
1463 coords[direction] = startCoord;
1464 uint index = this->transCoordToIndex(coords[0], coords[1], coords[2]);
1465 while (index != INVALID_INDEX && !field.isFluid(index))
1466 {
1467 coords[direction] += delta;
1468 index = this->transCoordToIndex(coords[0], coords[1], coords[2]);
1469 }
1470 if (index == INVALID_INDEX)
1471 return startCoord;
1472 return coords[direction];
1473}
1474
1475
1476int GridImp::getSparseIndex(const real &x, const real &y, const real &z) const
1477{
1479 if (matrixIndex == INVALID_INDEX || matrixIndex >= this->size || this->sparseIndices == nullptr)
1480 return -1;
1481 return sparseIndices[matrixIndex];
1482}
1483
1484// --------------------------------------------------------- //
1485// Find Interface //
1486// --------------------------------------------------------- //
1488{
1489 auto fineGrid = std::static_pointer_cast<GridImp>(finerGrid);
1490 const auto coarseLevel = this->getLevel();
1491 const auto fineLevel = fineGrid->getLevel();
1492
1493 VF_LOG_TRACE("find interface level {} -> {}", coarseLevel, fineLevel);
1494
1495 this->gridInterface = new GridInterface();
1496 // TODO: this is stupid! concave refinements can easily have many more interface cells
1497 const uint sizeCF = 10 * (fineGrid->nx * fineGrid->ny + fineGrid->ny * fineGrid->nz + fineGrid->nx * fineGrid->nz);
1498 this->gridInterface->cf.coarse = new uint[sizeCF];
1499 this->gridInterface->cf.fine = new uint[sizeCF];
1500 this->gridInterface->cf.offset = new uint[sizeCF];
1501 this->gridInterface->fc.coarse = new uint[sizeCF];
1502 this->gridInterface->fc.fine = new uint[sizeCF];
1503 this->gridInterface->fc.offset = new uint[sizeCF];
1504
1505 for (uint index = 0; index < this->getSize(); index++)
1506 this->findGridInterfaceCF(index, *fineGrid);
1507
1508 for (uint index = 0; index < this->getSize(); index++)
1509 this->findGridInterfaceFC(index, *fineGrid);
1510
1511 for (uint index = 0; index < this->getSize(); index++)
1512 this->findOverlapStopper(index, *fineGrid);
1513
1514 VF_LOG_TRACE(" ... done.");
1515}
1516
1518{
1519 this->gridInterface->repairGridInterfaceOnMultiGPU( shared_from_this(), std::static_pointer_cast<GridImp>(fineGrid) );
1520}
1521
1523{
1524 for( uint index = 0; index < this->size; index++ ){
1525
1526 real x, y, z;
1527 this->transIndexToCoords( index, x, y, z );
1528
1529 {
1530 BoundingBox tmpSubDomainBox = *subDomainBox;
1531
1532 // one layer for receive nodes and one for stoppers
1533 tmpSubDomainBox.extend(this->delta);
1534
1535 if (!tmpSubDomainBox.isInside(x, y, z)
1536 && ( this->getFieldEntry(index) == FLUID ||
1537 this->getFieldEntry(index) == FLUID_CFC ||
1538 this->getFieldEntry(index) == FLUID_CFF ||
1539 this->getFieldEntry(index) == FLUID_FCC ||
1540 this->getFieldEntry(index) == FLUID_FCF ||
1541 this->getFieldEntry(index) == BC_SOLID ) )
1542 {
1543 this->setFieldEntry(index, STOPPER_OUT_OF_GRID_BOUNDARY);
1544 }
1545 }
1546
1547 {
1548 BoundingBox tmpSubDomainBox = *subDomainBox;
1549
1550 // one layer for receive nodes and one for stoppers
1551 tmpSubDomainBox.extend(2.0 * this->delta);
1552
1553 if (!tmpSubDomainBox.isInside(x, y, z))
1554 this->setFieldEntry(index, INVALID_OUT_OF_GRID);
1555 }
1556 }
1557}
1558
1560{
1561 gridInterface->findInterfaceCF (index, this, &finerGrid);
1562 gridInterface->findBoundaryGridInterfaceCF(index, this, &finerGrid);
1563}
1564
1566{
1567 gridInterface->findInterfaceFC(index, this, &finerGrid);
1568}
1569
1571{
1572 gridInterface->findOverlapStopper(index, this, &finerGrid);
1573}
1574
1576{
1577 gridInterface->findInvalidBoundaryNodes(index, this);
1578}
1579
1580// --------------------------------------------------------- //
1581// Mesh Triangle //
1582// --------------------------------------------------------- //
1584{
1585 this->setActiveWindingSurface(nullptr);
1586
1587 bool requiresGridFinalization = true;
1588
1589 TriangularMesh *triangularMesh = dynamic_cast<TriangularMesh *>(object);
1590 if (triangularMesh && this->triangularMeshDiscretizationStrategy) {
1591 this->triangularMeshDiscretizationStrategy->discretize(triangularMesh, this, INVALID_SOLID, FLUID);
1592 this->triangularMeshDiscretizationStrategy->appendFastWindingQSurfaces(this, this->qSourceSurfaces);
1593 requiresGridFinalization = this->triangularMeshDiscretizationStrategy->requiresGridFinalization();
1594 } else {
1595 //new method for geometric primitives (not cell based) to be implemented
1596 this->discretize(object, INVALID_SOLID, FLUID);
1597 }
1598
1599 // Grid-generation finalization: close needle cells and derive stopper/boundary solid nodes.
1600 if (!requiresGridFinalization)
1601 return;
1602
1603 this->closeNeedleCells();
1604
1605 #pragma omp parallel for
1606 for (int index = 0; index < (int)this->size; index++)
1607 this->findSolidStopperNode(index);
1608
1609 //#pragma omp parallel for
1610 for (int index = 0; index < (int)this->size; index++) {
1611 this->findBoundarySolidNode(index);
1612 }
1613}
1614
1615
1617{
1618 const clock_t begin = clock();
1619
1620#pragma omp parallel for
1621 for (int i = 0; i < triangularMesh.size; i++)
1622 this->mesh(triangularMesh.triangles[i]);
1623
1624 const clock_t end = clock();
1625 const real time = (real)(real(end - begin) / CLOCKS_PER_SEC);
1626
1627 VF_LOG_INFO("time grid generation: {}s", time);
1628}
1629
1631{
1632 auto box = this->getBoundingBoxOnNodes(triangle);
1633 triangle.initalLayerThickness(getDelta());
1634
1635 for (real x = box.minX; x <= box.maxX; x += delta)
1636 {
1637 for (real y = box.minY; y <= box.maxY; y += delta)
1638 {
1639 for (real z = box.minZ; z <= box.maxZ; z += delta)
1640 {
1641 const uint index = this->transCoordToIndex(x, y, z);
1642 if (!field.isFluid(index))
1643 continue;
1644
1645 const Vertex point(x, y, z);
1646 const char value = triangle.isUnderFace(point);
1647 //setDebugPoint(index, value);
1648
1649 if (value == Q_DEPRECATED)
1650 calculateQs(point, triangle);
1651 }
1652 }
1653 }
1654}
1655
1657{
1658 VF_LOG_TRACE("Start closeNeedleCells()");
1659
1661
1662 do{
1664#pragma omp parallel for reduction(+ : numberOfClosedNeedleCells)
1665 for (int index = 0; index < (int)this->size; index++) {
1666 if (this->closeCellIfNeedle(index))
1668 }
1669
1670 VF_LOG_TRACE("{} cells closed!", numberOfClosedNeedleCells);
1671 }
1672 while( numberOfClosedNeedleCells > 0 );
1673}
1674
1676{
1677 if( !this->getField().is( index, FLUID ) ) return false;
1678
1679 real x, y, z;
1680 this->transIndexToCoords(index, x, y, z);
1681
1682 bool noValidNeighborInX = this->getField().is( this->transCoordToIndex( x + this->delta, y, z ) , INVALID_SOLID ) &&
1683 this->getField().is( this->transCoordToIndex( x - this->delta, y, z ) , INVALID_SOLID );
1684 bool noValidNeighborInY = this->getField().is( this->transCoordToIndex( x, y + this->delta, z ) , INVALID_SOLID ) &&
1685 this->getField().is( this->transCoordToIndex( x, y - this->delta, z ) , INVALID_SOLID );
1686 bool noValidNeighborInZ = this->getField().is( this->transCoordToIndex( x, y, z + this->delta ) , INVALID_SOLID ) &&
1687 this->getField().is( this->transCoordToIndex( x, y, z - this->delta ) , INVALID_SOLID );
1688
1690 this->setFieldEntry(index, INVALID_SOLID);
1691 return true;
1692 }
1693
1694 return false;
1695}
1696
1698{
1699 VF_LOG_TRACE("Start closeNeedleCellsThinWall()");
1700
1702
1703 do{
1705#pragma omp parallel for reduction(+ : numberOfClosedNeedleCells)
1706 for (int index = 0; index < (int)this->size; index++) {
1707 if (this->closeCellIfNeedleThinWall(index))
1709 }
1710 VF_LOG_TRACE("{} cells closed!", numberOfClosedNeedleCells);
1711 }
1712 while( numberOfClosedNeedleCells > 0 );
1713}
1714
1716{
1717 if( !this->getField().is( index, BC_SOLID ) ) return false;
1718
1719 real x, y, z;
1720 this->transIndexToCoords(index, x, y, z);
1721
1722 if( !this->hasNeighborOfType(index, FLUID) ){
1723 this->setFieldEntry(index, STOPPER_SOLID);
1724 return true;
1725 }
1726
1727 return false;
1728}
1729
1730
1731
1732void GridImp::findQs(Object* object) //TODO: enable qs for primitive objects
1733{
1734 TriangularMesh* triangularMesh = dynamic_cast<TriangularMesh*>(object);
1735 if (triangularMesh &&
1736 this->triangularMeshDiscretizationStrategy &&
1737 this->triangularMeshDiscretizationStrategy->usesFastWindingQComputation() &&
1738 this->qComputationStage == qComputationStageType::ComputeQs)
1739 {
1740 return;
1741 }
1742
1743 if (triangularMesh)
1745 else
1746 findQsPrimitive(object);
1747}
1748
1750{
1751 // Paths with immediate Q computation finish during findQs(...). This hook is only
1752 // used by strategies that defer Q computation until all surfaces/objects are collected.
1753 if (!this->triangularMeshDiscretizationStrategy)
1754 return;
1755
1756 if (!this->triangularMeshDiscretizationStrategy->usesFastWindingQComputation())
1757 return;
1758
1759 this->triangularMeshDiscretizationStrategy->computeFastWindingQs(this, this->qSourceSurfaces);
1760}
1761
1762void GridImp::allocateQs()
1763{
1765 this->qCapacity = boundaryCount;
1766
1767 if (boundaryCount == 0) {
1768 this->qValues = nullptr;
1769 this->qPatches = nullptr;
1770 return;
1771 }
1772
1773 this->qPatches = new uint[boundaryCount];
1774
1775 for (uint i = 0; i < boundaryCount; i++)
1776 this->qPatches[i] = INVALID_INDEX;
1777
1778 const uint numberOfQs = boundaryCount * static_cast<uint>(this->distribution.dir_end + 1);
1779 this->qValues = new real[numberOfQs];
1780#pragma omp parallel for
1781 for (int i = 0; i < static_cast<int>(numberOfQs); i++)
1782 this->qValues[i] = -1.0;
1783}
1784
1786{
1787 const clock_t begin = clock();
1788
1789 if( this->qComputationStage == qComputationStageType::ComputeQs )
1790 allocateQs();
1791
1792#pragma omp parallel for
1793 for (int i = 0; i < triangularMesh.size; i++)
1794 this->findQs(triangularMesh.triangles[i]);
1795
1796 // assign default values to missing links
1798
1799 const clock_t end = clock();
1800 const real time = (real)((end - begin) / (real)CLOCKS_PER_SEC);
1801
1802 VF_LOG_TRACE("time finding qs: {}s", time);
1803}
1804
1806{
1807 auto box = this->getBoundingBoxOnNodes(triangle);
1808 triangle.initalLayerThickness(getDelta());
1809
1810 for (real x = box.minX; x <= box.maxX; x += delta)
1811 {
1812 for (real y = box.minY; y <= box.maxY; y += delta)
1813 {
1814 for (real z = box.minZ; z <= box.maxZ; z += delta)
1815 {
1816 const uint index = this->transCoordToIndex(x, y, z);
1817 if( index == INVALID_INDEX ) continue;
1818
1819 const Vertex point(x, y, z);
1820
1821 if( this->qComputationStage == qComputationStageType::ComputeQs ){
1822 if(this->field.is(index, BC_SOLID))
1823 {
1824 calculateQs(index, point, triangle);
1825 }
1826 }
1827 else if( this->qComputationStage == qComputationStageType::FindSolidBoundaryNodes )
1828 {
1829 if( !this->field.is(index, FLUID) ) continue;
1830
1831 if( checkIfAtLeastOneValidQ(index, point, triangle) )
1832 {
1833 this->field.setFieldEntry( index, BC_SOLID );
1834 this->qIndices[index] = this->numberOfSolidBoundaryNodes++;
1835 }
1836 }
1837 }
1838 }
1839 }
1840}
1841
1843{
1844
1845 if( this->qComputationStage == qComputationStageType::ComputeQs )
1846 allocateQs();
1847
1848
1849 for( int index = 0; index < (int)this->size; index++ )
1850 {
1851
1852 if( this->qIndices[index] == INVALID_INDEX ) continue;
1853
1854 real x,y,z;
1855
1856 this->transIndexToCoords(index,x,y,z);
1857
1858 const Vertex point(x, y, z);
1859
1860 if( this->qComputationStage == qComputationStageType::ComputeQs ){
1861 if(this->field.is(index, BC_SOLID))
1862 {
1863 calculateQs(index, point, object);
1864 }
1865 }
1866 else if( this->qComputationStage == qComputationStageType::FindSolidBoundaryNodes )
1867 {
1868 if( !this->field.is(index, FLUID) ) continue;
1869
1870 if( checkIfAtLeastOneValidQ(index, point, object) )
1871 {
1872 // similar as in void GridImp::findBoundarySolidNode(uint index)
1873 this->field.setFieldEntry( index, BC_SOLID );
1874 this->qIndices[index] = this->numberOfSolidBoundaryNodes++;
1875 }
1876 }
1877
1878 }
1879
1880 if (this->qComputationStage == qComputationStageType::ComputeQs)
1882}
1883
1884void GridImp::calculateQs(const uint index, const Vertex &point, Object* object) const
1885{
1886 Vertex pointOnTriangle, direction;
1887
1889 int error;
1890 for (int i = distribution.dir_start; i <= distribution.dir_end; i++)
1891 {
1892 direction = Vertex( real(distribution.dirs[i * DIMENSION + 0]),
1894 real(distribution.dirs[i * DIMENSION + 2]) );
1895
1896 uint neighborIndex = this->transCoordToIndex(point.x + direction.x * this->delta,
1897 point.y + direction.y * this->delta,
1898 point.z + direction.z * this->delta);
1899
1900 if (neighborIndex == INVALID_INDEX) continue;
1901
1902 error = object->getIntersection(point, direction, pointOnTriangle, subdistance);
1903
1904 subdistance /= this->delta;
1905
1907 {
1908 if ( -0.5 > this->qValues[i*this->numberOfSolidBoundaryNodes + this->qIndices[index]] ||
1909 subdistance < this->qValues[i*this->numberOfSolidBoundaryNodes + this->qIndices[index]] )
1910 {
1911
1912 this->qValues[i*this->numberOfSolidBoundaryNodes + this->qIndices[index]] = subdistance;
1913
1914 this->qPatches[ this->qIndices[index] ] = 0;
1915
1916 }
1917 }
1918 }
1919}
1920
1921bool GridImp::checkIfAtLeastOneValidQ(const uint index, const Vertex &point, Object* object) const
1922{
1923 Vertex pointOnTriangle, direction;
1924
1926 int error;
1927 for (int i = distribution.dir_start; i <= distribution.dir_end; i++)
1928 {
1929 direction = Vertex( real(distribution.dirs[i * DIMENSION + 0]),
1931 real(distribution.dirs[i * DIMENSION + 2]) );
1932
1933 uint neighborIndex = this->transCoordToIndex(point.x + direction.x * this->delta,
1934 point.y + direction.y * this->delta,
1935 point.z + direction.z * this->delta);
1936
1937 if (neighborIndex == INVALID_INDEX) continue;
1938
1939 error = object->getIntersection(point, direction, pointOnTriangle, subdistance);
1940
1941 subdistance /= this->delta;
1942
1944 {
1945 return true;
1946 }
1947 }
1948 return false;
1949}
1950
1951void GridImp::setDebugPoint(uint index, int pointValue)
1952{
1953 if (field.isInvalidCoarseUnderFine(index) && pointValue == INVALID_SOLID)
1955
1956 if(!field.isInvalidSolid(index) && !field.isQ(index) && !field.isInvalidCoarseUnderFine(index) && pointValue != 3 && pointValue != 2)
1958}
1959
1960void GridImp::calculateQs(const Vertex &point, const Triangle &triangle) const // NOT USED !!!!
1961{
1962 Vertex pointOnTriangle, direction;
1964 int error;
1965 for (int i = distribution.dir_start; i <= distribution.dir_end; i++)
1966 {
1967#if defined(__CUDA_ARCH__)
1968 direction = Vertex(DIRECTIONS[i][0], DIRECTIONS[i][1], DIRECTIONS[i][2]);
1969#else
1970 direction = Vertex(real(distribution.dirs[i * DIMENSION + 0]), real(distribution.dirs[i * DIMENSION + 1]),
1971 real(distribution.dirs[i * DIMENSION + 2]));
1972#endif
1973
1974 error = triangle.getTriangleIntersection(point, direction, pointOnTriangle, subdistance);
1975
1976 subdistance /= this->delta;
1977
1979 {
1980 distribution.f[i*size + transCoordToIndex(point.x, point.y, point.z)] = subdistance;
1981 }
1982 }
1983}
1984
1985
1986void GridImp::calculateQs(const uint index, const Vertex &point, const Triangle &triangle) const
1987{
1988 Vertex pointOnTriangle, direction;
1990 int error;
1991 for (int i = distribution.dir_start; i <= distribution.dir_end; i++)
1992 {
1993#if defined(__CUDA_ARCH__)
1994 direction = Vertex(DIRECTIONS[i][0], DIRECTIONS[i][1], DIRECTIONS[i][2]);
1995#else
1996 direction = Vertex( real(distribution.dirs[i * DIMENSION + 0]),
1998 real(distribution.dirs[i * DIMENSION + 2]) );
1999#endif
2000
2001 uint neighborIndex = this->transCoordToIndex(point.x + direction.x * this->delta,
2002 point.y + direction.y * this->delta,
2003 point.z + direction.z * this->delta);
2004
2005 if (neighborIndex == INVALID_INDEX) continue;
2006
2007 error = triangle.getTriangleIntersection(point, direction, pointOnTriangle, subdistance);
2008
2009 subdistance /= this->delta;
2010
2012 {
2013 if ( -0.5 > this->qValues[i*this->numberOfSolidBoundaryNodes + this->qIndices[index]] ||
2014 subdistance < this->qValues[i*this->numberOfSolidBoundaryNodes + this->qIndices[index]] )
2015 {
2016 this->qValues[i*this->numberOfSolidBoundaryNodes + this->qIndices[index]] = subdistance;
2017
2018 this->qPatches[ this->qIndices[index] ] = triangle.patchIndex;
2019 }
2020 }
2021 }
2022}
2023
2024bool GridImp::checkIfAtLeastOneValidQ(const uint index, const Vertex & point, const Triangle & triangle) const
2025{
2026 Vertex pointOnTriangle, direction;
2028 int error;
2029 for (int i = distribution.dir_start; i <= distribution.dir_end; i++)
2030 {
2031#if defined(__CUDA_ARCH__)
2032 direction = Vertex(DIRECTIONS[i][0], DIRECTIONS[i][1], DIRECTIONS[i][2]);
2033#else
2034 direction = Vertex(real(distribution.dirs[i * DIMENSION + 0]),
2036 real(distribution.dirs[i * DIMENSION + 2]));
2037#endif
2038
2039 uint neighborIndex = this->transCoordToIndex(point.x + direction.x * this->delta,
2040 point.y + direction.y * this->delta,
2041 point.z + direction.z * this->delta);
2042 if (neighborIndex == INVALID_INDEX) continue;
2043
2044 error = triangle.getTriangleIntersection(point, direction, pointOnTriangle, subdistance);
2045
2046 subdistance /= this->delta;
2047
2049 {
2050 return true;
2051 }
2052 }
2053 return false;
2054}
2055
2057{
2058 real x, y, z;
2059 this->transIndexToCoords(index, x, y, z);
2060
2061 switch (direction)
2062 {
2064 y = wrapCoord(y - (this->periodicShiftOnXinY + delta), startY - c1o2*delta, endY + c1o2*delta);
2065 z = wrapCoord(z - (this->periodicShiftOnXinZ + delta), startZ - c1o2*delta, endZ + c1o2*delta);
2066 break;
2068 y = wrapCoord(y + (this->periodicShiftOnXinY + delta), startY - c1o2*delta, endY + c1o2*delta);
2069 z = wrapCoord(z + (this->periodicShiftOnXinZ + delta), startZ - c1o2*delta, endZ + c1o2*delta);
2070 break;
2072 x = wrapCoord(x - (this->periodicShiftOnYinX + delta), startX - c1o2*delta, endX + c1o2*delta);
2073 z = wrapCoord(z - (this->periodicShiftOnYinZ + delta), startZ - c1o2*delta, endZ + c1o2*delta);
2074 break;
2076 x = wrapCoord(x + (this->periodicShiftOnYinX + delta), startX - c1o2*delta, endX + c1o2*delta);
2077 z = wrapCoord(z + (this->periodicShiftOnYinZ + delta), startZ - c1o2*delta, endZ + c1o2*delta);
2078 break;
2080 x = wrapCoord(x - (this->periodicShiftOnZinX + delta), startX - c1o2*delta, endX + c1o2*delta);
2081 y = wrapCoord(y - (this->periodicShiftOnZinY + delta), startY - c1o2*delta, endY + c1o2*delta);
2082 break;
2084 x = wrapCoord(x + (this->periodicShiftOnZinX + delta), startX - c1o2*delta, endX + c1o2*delta);
2085 y = wrapCoord(y + (this->periodicShiftOnZinY + delta), startY - c1o2*delta, endY + c1o2*delta);
2086 break;
2087 default:
2088 break;
2089 }
2090
2091 return this->transCoordToIndex(x, y, z);
2092}
2093
2094void GridImp::findCommunicationIndices(int direction, SPtr<BoundingBox> subDomainBox, bool doShift)
2095{
2096 for( uint index = 0; index < this->size; index++ ){
2097
2098 int shiftedIndex = doShift ? getShiftedCommunicationIndex(index, direction) : index;
2099
2100 const char fieldEntry = this->getFieldEntry(shiftedIndex);
2101 if( fieldEntry == INVALID_OUT_OF_GRID ||
2102 fieldEntry == INVALID_SOLID ||
2103 fieldEntry == INVALID_COARSE_UNDER_FINE ||
2104 fieldEntry == STOPPER_OUT_OF_GRID ||
2105 fieldEntry == STOPPER_COARSE_UNDER_FINE ||
2106 fieldEntry == STOPPER_OUT_OF_GRID_BOUNDARY ||
2107 fieldEntry == STOPPER_SOLID ) continue;
2108
2109 real x, y, z;
2110 this->transIndexToCoords(shiftedIndex, x, y, z);
2111
2112 switch(direction)
2113 {
2114 case communication_directions::MX: findCommunicationIndex( shiftedIndex, x, subDomainBox->minX, direction); break;
2115 case communication_directions::PX: findCommunicationIndex( shiftedIndex, x, subDomainBox->maxX, direction); break;
2116 case communication_directions::MY: findCommunicationIndex( shiftedIndex, y, subDomainBox->minY, direction); break;
2117 case communication_directions::PY: findCommunicationIndex( shiftedIndex, y, subDomainBox->maxY, direction); break;
2118 case communication_directions::MZ: findCommunicationIndex( shiftedIndex, z, subDomainBox->minZ, direction); break;
2119 case communication_directions::PZ: findCommunicationIndex( shiftedIndex, z, subDomainBox->maxZ, direction); break;
2120 }
2121 }
2122}
2123
2125 // send nodes are outer most layer inside the domain, receive nodes are the inner most layer outside the domain
2126 const real distance = direction % 2 == 1 ? coordinate - limit : limit - coordinate;
2127 if(distance > 0 && std::abs(distance) <= delta)
2128 this->communicationIndices[direction].receiveIndices.push_back(index);
2129 else if(distance <= 0 && std::abs(distance) < delta)
2130 this->communicationIndices[direction].sendIndices.push_back(index);
2131}
2132
2133bool GridImp::isSendNode(int index) const
2134{
2135 bool isSendNode = false;
2136 for (size_t direction = 0; direction < this->communicationIndices.size(); direction++)
2137 if (std::find(this->communicationIndices[direction].sendIndices.begin(),
2138 this->communicationIndices[direction].sendIndices.end(), index) != this->communicationIndices[direction].sendIndices.end())
2139 isSendNode = true;
2140 return isSendNode;
2141}
2142
2143bool GridImp::isReceiveNode(int index) const
2144{
2145 bool isReceiveNode = false;
2146 for (size_t direction = 0; direction < this->communicationIndices.size(); direction++)
2147 if (std::find(this->communicationIndices[direction].receiveIndices.begin(),
2148 this->communicationIndices[direction].receiveIndices.end(),
2149 index) != this->communicationIndices[direction].receiveIndices.end())
2150 isReceiveNode = true;
2151 return isReceiveNode;
2152}
2153
2155{
2156 return (uint)this->communicationIndices[direction].sendIndices.size();
2157}
2158
2160{
2161 return (uint)this->communicationIndices[direction].receiveIndices.size();
2162}
2163
2164uint GridImp::getSendIndex(int direction, uint index)
2165{
2166 return this->communicationIndices[direction].sendIndices[ index ];
2167}
2168
2170{
2171 return this->communicationIndices[direction].receiveIndices[ index ];
2172}
2173
2175{
2176 this->communicationIndices[direction].sendIndices.insert( this->communicationIndices[direction].sendIndices.end(),
2177 this->communicationIndices[direction+1].sendIndices.begin(),
2178 this->communicationIndices[direction+1].sendIndices.end() );
2179
2180
2181
2182 this->communicationIndices[direction+1].receiveIndices.insert( this->communicationIndices[direction+1].receiveIndices.end(),
2183 this->communicationIndices[direction].receiveIndices.begin(),
2184 this->communicationIndices[direction].receiveIndices.end() );
2185
2186 this->communicationIndices[direction].receiveIndices = this->communicationIndices[direction+1].receiveIndices;
2187
2188
2189 VF_LOG_INFO("size send {}", (int)this->communicationIndices[direction].sendIndices.size());
2190 VF_LOG_INFO("recv send {}",(int)this->communicationIndices[direction].receiveIndices.size());
2191}
2192
2193
2194// --------------------------------------------------------- //
2195// Getter //
2196// --------------------------------------------------------- //
2198{
2199 return this->sparseIndices[matrixIndex];
2200}
2201
2203{
2204 return this->distribution.f;
2205}
2206
2207const std::vector<int>& GridImp::getDirection() const
2208{
2209 return this->distribution.dirs;
2210}
2211
2213{
2214 return this->distribution.dir_start;
2215}
2216
2218{
2219 return this->distribution.dir_end;
2220}
2221
2223{
2224 real minX, maxX, minY, maxY, minZ, maxZ;
2225 triangle.setMinMax(minX, maxX, minY, maxY, minZ, maxZ);
2226
2227 int minXIndex = std::lround(floor((minX - this->startX) / this->delta)) - 1;
2228 int minYIndex = std::lround(floor((minY - this->startY) / this->delta)) - 1;
2229 int minZIndex = std::lround(floor((minZ - this->startZ) / this->delta)) - 1;
2230
2231 int maxXIndex = std::lround(ceil((maxX - this->startX) / this->delta)) + 1;
2232 int maxYIndex = std::lround(ceil((maxY - this->startY) / this->delta)) + 1;
2233 int maxZIndex = std::lround(ceil((maxZ - this->startZ) / this->delta)) + 1;
2234
2235 minX = this->startX + minXIndex * this->delta;
2236 minY = this->startY + minYIndex * this->delta;
2237 minZ = this->startZ + minZIndex * this->delta;
2238
2239 maxX = this->startX + maxXIndex * this->delta;
2240 maxY = this->startY + maxYIndex * this->delta;
2241 maxZ = this->startZ + maxZIndex * this->delta;
2242
2243 return BoundingBox(minX, maxX, minY, maxY, minZ, maxZ);
2244}
2245
2247{
2248 const real minX = getMinimumOnNodes(exact.x, vf::Math::getDecimalPart(startX), delta);
2249 const real minY = getMinimumOnNodes(exact.y, vf::Math::getDecimalPart(startY), delta);
2250 const real minZ = getMinimumOnNodes(exact.z, vf::Math::getDecimalPart(startZ), delta);
2251 return Vertex(minX, minY, minZ);
2252}
2253
2254real GridImp::getMinimumOnNodes(const real &minExact, const real &decimalStart, const real &delta) // deprecated
2255{
2256 real minNode = ceil(minExact - 1.0);
2258 while (minNode > minExact)
2259 minNode -= delta;
2260
2261 while (minNode + delta < minExact)
2262 minNode += delta;
2263 return minNode;
2264}
2265
2267{
2268 const real maxX = getMaximumOnNodes(exact.x, vf::Math::getDecimalPart(startX), delta);
2269 const real maxY = getMaximumOnNodes(exact.y, vf::Math::getDecimalPart(startY), delta);
2270 const real maxZ = getMaximumOnNodes(exact.z, vf::Math::getDecimalPart(startZ), delta);
2271 return Vertex(maxX, maxY, maxZ);
2272}
2273
2274real GridImp::getMaximumOnNodes(const real &maxExact, const real &decimalStart, const real &delta) // deprecated
2275{
2276 real maxNode = ceil(maxExact - 1.0);
2278
2279 while (maxNode <= maxExact)
2280 maxNode += delta;
2281 return maxNode;
2282}
2283
2284uint GridImp::getXIndex(real x) const
2285{
2286 return std::lround((x - startX) / delta);
2287}
2288
2289uint GridImp::getYIndex(real y) const
2290{
2291 return std::lround((y - startY) / delta);
2292}
2293
2294uint GridImp::getZIndex(real z) const
2295{
2296 return std::lround((z - startZ) / delta);
2297}
2298
2300{
2301 return delta;
2302}
2303
2305{
2306 return this->size;
2307}
2308
2310{
2311 return this->sparseSize;
2312}
2313
2315 return (uint)this->fluidNodeIndices.size();
2316}
2317
2319{
2320 return this->field;
2321}
2322
2324{
2325 return this->field.getFieldEntry(index);
2326}
2327
2329{
2330 this->field.setFieldEntry(matrixIndex, type);
2331}
2332
2333
2335{
2336 return startX;
2337}
2338
2340{
2341 return startY;
2342}
2343
2345{
2346 return startZ;
2347}
2348
2350{
2351 return endX;
2352}
2353
2355{
2356 return endY;
2357}
2358
2360{
2361 return endZ;
2362}
2363
2365{
2366 return nx;
2367}
2368
2370{
2371 return ny;
2372}
2373
2375{
2376 return nz;
2377}
2378
2379
2381{
2382 return this->neighborIndexX;
2383}
2384
2386{
2387 return this->neighborIndexY;
2388}
2389
2391{
2392 return this->neighborIndexZ;
2393}
2394
2396{
2397 return this->neighborIndexNegative;
2398}
2399
2401{
2402 if(this->gridInterface)
2403 return this->gridInterface->cf.numberOfEntries;
2404 return 0;
2405}
2406
2408{
2409 if (this->gridInterface)
2410 return this->gridInterface->fc.numberOfEntries;
2411 return 0;
2412}
2413
2415{
2416 return this->gridInterface->cf.coarse;
2417}
2418
2420{
2421 return this->gridInterface->cf.fine;
2422}
2423
2425{
2426 return this->gridInterface->cf.offset;
2427}
2428
2430{
2431 return this->gridInterface->fc.coarse;
2432}
2433
2435{
2436 return this->gridInterface->fc.fine;
2437}
2438
2440{
2441 return this->gridInterface->fc.offset;
2442}
2443
2445{
2446 getGridInterface(iCellCfc, this->gridInterface->cf.coarse, this->gridInterface->cf.numberOfEntries);
2447 getGridInterface(iCellCff, this->gridInterface->cf.fine, this->gridInterface->cf.numberOfEntries);
2448 getGridInterface(iCellFcc, this->gridInterface->fc.coarse, this->gridInterface->fc.numberOfEntries);
2449 getGridInterface(iCellFcf, this->gridInterface->fc.fine, this->gridInterface->fc.numberOfEntries);
2450}
2451
2453{
2454 for (uint i = 0; i < size; i++)
2455 gridInterfaceList[i] = oldGridInterfaceList[i] + 1; // + 1 for numbering shift between GridGenerator and VF_GPU
2456}
2457
2459{
2460 return std::find(this->fluidNodeIndicesBorder.begin(), this->fluidNodeIndicesBorder.end(), sparseIndex) !=
2461 this->fluidNodeIndicesBorder.end();
2462}
2463
2464#define GEOFLUID 19
2465#define GEOSOLID 16
2466
2467void GridImp::getNodeValues(real *xCoords, real *yCoords, real *zCoords, uint *neighborX, uint *neighborY, uint *neighborZ, uint *neighborNegative, uint *geo) const
2468{
2469 xCoords[0] = 0;
2470 yCoords[0] = 0;
2471 zCoords[0] = 0;
2472 neighborX[0] = 0;
2473 neighborY[0] = 0;
2474 neighborZ[0] = 0;
2475 geo[0] = GEOSOLID;
2476
2477 int nodeNumber = 0;
2478 for (uint i = 0; i < this->size; i++)
2479 {
2480 if (this->sparseIndices[i] == -1)
2481 continue;
2482
2483 real x, y, z;
2484 this->transIndexToCoords(i, x, y, z);
2485
2486 // + 1 for numbering shift between GridGenerator and VF_GPU
2487 const uint neighborXIndex = uint(this->neighborIndexX[i] + 1);
2488 const uint neighborYIndex = uint(this->neighborIndexY[i] + 1);
2489 const uint neighborZIndex = uint(this->neighborIndexZ[i] + 1);
2491
2492 const uint type = uint(this->field.isFluid(i) ? GEOFLUID : GEOSOLID);
2493
2494 xCoords[nodeNumber + 1] = x;
2495 yCoords[nodeNumber + 1] = y;
2496 zCoords[nodeNumber + 1] = z;
2497
2498 neighborX [nodeNumber + 1] = neighborXIndex;
2499 neighborY [nodeNumber + 1] = neighborYIndex;
2500 neighborZ [nodeNumber + 1] = neighborZIndex;
2502
2503 geo[nodeNumber + 1] = type;
2504 nodeNumber++;
2505 }
2506}
2507
2508void GridImp::getFluidNodeIndices(uint *fluidNodeIndices) const
2509{
2510 for (uint nodeNumber = 0; nodeNumber < (uint)this->fluidNodeIndices.size(); nodeNumber++)
2511 fluidNodeIndices[nodeNumber] = this->fluidNodeIndices[nodeNumber];
2512}
2513
2515{
2516 return (uint)this->fluidNodeIndicesBorder.size();
2517}
2518
2519void GridImp::getFluidNodeIndicesBorder(uint* fluidNodeIndicesBorder) const
2520{
2521 for (uint nodeNumber = 0; nodeNumber < (uint)this->fluidNodeIndicesBorder.size(); nodeNumber++)
2522 fluidNodeIndicesBorder[nodeNumber] = this->fluidNodeIndicesBorder[nodeNumber];
2523}
2524
2525void GridImp::addFluidNodeIndicesMacroVars(std::vector<uint> fluidNodeIndicesMacroVars)
2526{
2527 size_t newSize = this->fluidNodeIndicesMacroVars.size() + fluidNodeIndicesMacroVars.size();
2528 this->fluidNodeIndicesMacroVars.reserve(newSize);
2529 std::copy(fluidNodeIndicesMacroVars.begin(), fluidNodeIndicesMacroVars.end(),
2530 std::back_inserter(this->fluidNodeIndicesMacroVars));
2531}
2532
2533void GridImp::addFluidNodeIndicesApplyBodyForce(std::vector<uint> fluidNodeIndicesApplyBodyForce)
2534{
2535
2536 size_t newSize = this->fluidNodeIndicesApplyBodyForce.size() + fluidNodeIndicesApplyBodyForce.size();
2537 this->fluidNodeIndicesApplyBodyForce.reserve(newSize);
2538 std::copy(fluidNodeIndicesApplyBodyForce.begin(), fluidNodeIndicesApplyBodyForce.end(),
2539 std::back_inserter(this->fluidNodeIndicesApplyBodyForce));
2540}
2541
2542void GridImp::addFluidNodeIndicesAllFeatures(std::vector<uint> fluidNodeIndicesAllFeatures)
2543{
2544
2545 size_t newSize = this->fluidNodeIndicesAllFeatures.size() + fluidNodeIndicesAllFeatures.size();
2546 this->fluidNodeIndicesAllFeatures.reserve(newSize);
2547 std::copy(fluidNodeIndicesAllFeatures.begin(), fluidNodeIndicesAllFeatures.end(),
2548 std::back_inserter(this->fluidNodeIndicesAllFeatures));
2549}
2550
2552{
2553 this->fluidNodeIndicesAllFeatures.clear();
2554 this->fluidNodeIndicesApplyBodyForce.clear();
2555 this->fluidNodeIndicesMacroVars.clear();
2556 this->fluidNodeIndicesAllFeatures.swap(this->fluidNodeIndices);
2557}
2558
2559void cleanFluidNodes(std::vector<uint>& nodes)
2560{
2561 std::sort(nodes.begin(), nodes.end());
2562 // Remove duplicates
2563 nodes.erase(std::unique(nodes.begin(), nodes.end()), nodes.end());
2564}
2565
2566void sortFluidNodes(std::vector<uint>& allNodes, std::vector<uint>& markedNodes)
2567{
2570 // Sort all marked nodes to the end
2571 const auto iter = std::stable_partition(
2572 allNodes.begin(), allNodes.end(), [&](auto x) { return !std::binary_search(markedNodes.begin(), markedNodes.end(), x); });
2573
2574 markedNodes.clear();
2575 std::copy(iter, allNodes.end(), std::back_inserter(markedNodes));
2576 allNodes.erase(iter, allNodes.end());
2577}
2578
2580{
2581 sortFluidNodes(fluidNodeIndices, fluidNodeIndicesMacroVars);
2582}
2583
2585{
2586 sortFluidNodes(fluidNodeIndices, fluidNodeIndicesApplyBodyForce);
2587}
2588
2590{
2591 cleanFluidNodes(fluidNodeIndicesMacroVars);
2592 cleanFluidNodes(fluidNodeIndicesApplyBodyForce);
2593 std::set_intersection(fluidNodeIndicesMacroVars.begin(), fluidNodeIndicesMacroVars.end(),
2594 fluidNodeIndicesApplyBodyForce.begin(), fluidNodeIndicesApplyBodyForce.end(),
2595 std::back_inserter(fluidNodeIndicesAllFeatures));
2596 sortFluidNodes(fluidNodeIndices, fluidNodeIndicesAllFeatures);
2597}
2598
2600{
2601 return (uint)this->fluidNodeIndicesMacroVars.size();
2602}
2603
2605{
2606 return (uint)this->fluidNodeIndicesApplyBodyForce.size();
2607}
2608
2610{
2611 return (uint)this->fluidNodeIndicesAllFeatures.size();
2612}
2613
2614void GridImp::getFluidNodeIndicesMacroVars(uint* fluidNodeIndicesMacroVars) const
2615{
2616 std::copy(this->fluidNodeIndicesMacroVars.begin(), this->fluidNodeIndicesMacroVars.end(), fluidNodeIndicesMacroVars);
2617}
2618void GridImp::getFluidNodeIndicesApplyBodyForce(uint* fluidNodeIndicesApplyBodyForce) const
2619{
2620 std::copy(this->fluidNodeIndicesApplyBodyForce.begin(), this->fluidNodeIndicesApplyBodyForce.end(),
2621 fluidNodeIndicesApplyBodyForce);
2622}
2623void GridImp::getFluidNodeIndicesAllFeatures(uint* fluidNodeIndicesAllFeatures) const
2624{
2625 std::copy(this->fluidNodeIndicesAllFeatures.begin(), this->fluidNodeIndicesAllFeatures.end(),
2626 fluidNodeIndicesAllFeatures);
2627}
2628
2629std::vector<SideType> GridImp::getBCAlreadySet() {
2630 return this->bcAlreadySet;
2631}
2632
2634{
2635 this->bcAlreadySet.push_back(side);
2636}
2637
2638std::vector<SideType> GridImp::getADBCAlreadySet() {
2639 return this->adBCAlreadySet;
2640}
2641
2643{
2644 this->adBCAlreadySet.push_back(side);
2645}
2646
2647
2648void GridImp::print() const
2649{
2650 printf("min: (%2.4f, %2.4f, %2.4f), max: (%2.4f, %2.4f, %2.4f), size: %d, delta: %2.4f\n", startX, startY, startZ,
2651 endX, endY, endZ, size, delta);
2652 if(this->gridInterface)
2653 this->gridInterface->print();
2654}
2655
2657{
2658 return (this->getFieldEntry(index) == vf::gpu::STOPPER_OUT_OF_GRID_BOUNDARY ||
2659 this->getFieldEntry(index) == vf::gpu::STOPPER_OUT_OF_GRID ||
2660 this->getFieldEntry(index) == vf::gpu::STOPPER_SOLID);
2661}
2662
2663}
2664
#define VF_LOG_TRACE(...)
Definition Logger.h:48
#define VF_LOG_INFO(...)
Definition Logger.h:50
static real getDecimalPart(real number)
Definition Math.h:54
void setMinMax(const Triangle &t)
void extend(real delta)
static Distribution getDistribution(std::string name)
void setFieldEntry(uint index, char val)
Definition Field.cpp:138
void setFieldEntryToStopperOutOfGridBoundary(uint index)
Definition Field.cpp:158
void setFieldEntryToStopperOutOfGrid(uint index)
Definition Field.cpp:153
void setFieldEntryToInvalidOutOfGrid(uint index)
Definition Field.cpp:173
bool isQ(uint index) const
Definition Field.cpp:125
char getFieldEntry(uint index) const
Definition Field.cpp:61
void allocateMemory()
Definition Field.cpp:43
bool is(uint index, char type) const
Definition Field.cpp:69
bool isFluid(uint index) const
Definition Field.cpp:84
bool isInvalidOutOfGrid(uint index) const
Definition Field.cpp:95
bool isInvalidCoarseUnderFine(uint index) const
Definition Field.cpp:100
bool isStopper(uint index) const
Definition Field.cpp:120
bool isInvalidSolid(uint index) const
Definition Field.cpp:90
void freeMemory()
Definition Field.cpp:48
void setFieldEntryToFluid(uint index)
Definition Field.cpp:143
SPtr< GbTriFaceMesh3D > getActiveWindingSurface() const
Definition GridImp.cpp:890
void clearQForIndex(uint index)
Definition GridImp.cpp:966
void findForGridInterfaceNewIndices(SPtr< GridImp > fineGrid)
Definition GridImp.cpp:1169
void sortFluidNodeIndicesMacroVars() override
Definition GridImp.cpp:2579
void findSparseIndices(SPtr< Grid > fineGrid) override
Definition GridImp.cpp:1149
static SPtr< GridImp > makeShared(SPtr< Object > object, real startX, real startY, real startZ, real endX, real endY, real endZ, real delta, std::string d3Qxx, uint level)
Definition GridImp.cpp:107
uint getNumberOfFluidNodeIndicesApplyBodyForce() const override
Definition GridImp.cpp:2604
int getEndDirection() const override
Definition GridImp.cpp:2217
void addFluidNodeIndicesApplyBodyForce(std::vector< uint > fluidNodeIndicesApplyBodyForce) override
Definition GridImp.cpp:2533
std::vector< SideType > getADBCAlreadySet() override
Definition GridImp.cpp:2638
uint getNumberOfNodesZ() const override
Definition GridImp.cpp:2374
real getEndY() const override
Definition GridImp.cpp:2354
int getShiftedCommunicationIndex(uint index, int direction)
Definition GridImp.cpp:2056
void addADBCalreadySet(SideType side) override
Definition GridImp.cpp:2642
uint getNumberOfReceiveNodes(int direction) override
Definition GridImp.cpp:2159
void getNodeValues(real *xCoords, real *yCoords, real *zCoords, uint *neighborX, uint *neighborY, uint *neighborZ, uint *neighborNegative, uint *geo) const override
Definition GridImp.cpp:2467
void closeNeedleCells() override
Definition GridImp.cpp:1656
int * neighborIndexY
Definition GridImp.h:139
real getEndZ() const override
Definition GridImp.cpp:2359
uint getLevel() const
Definition GridImp.cpp:870
SPtr< const Object > getObject() const override
Definition GridImp.cpp:529
void mesh(Object *object) override
Definition GridImp.cpp:1583
bool isStopperForBC(uint index) const override
Definition GridImp.cpp:2656
void setPeriodicityY(bool periodicity) override
Definition GridImp.cpp:753
SPtr< TriangularMeshDiscretizationStrategy > getTriangularMeshDiscretizationStrategy()
Definition GridImp.cpp:880
bool hasNeighborOfType(uint index, char type) const
Definition GridImp.cpp:607
bool isSparseIndexInFluidNodeIndicesBorder(uint &sparseIndex) const override
Definition GridImp.cpp:2458
uint getNumberOfSolidBoundaryNodes() const override
Definition GridImp.cpp:900
void setOddStart(bool xOddStart, bool yOddStart, bool zOddStart) override
Definition GridImp.cpp:204
bool isSendNode(int index) const override
Definition GridImp.cpp:2133
uint * getCF_offset() const override
Definition GridImp.cpp:2424
real getLastFluidNode(real coords[3], int direction, real startCoord) const override
Definition GridImp.cpp:1449
void beginQComputation() override
Definition GridImp.cpp:895
uint getNumberOfNodesX() const override
Definition GridImp.cpp:2364
bool nodeHasBC(uint index) const override
Definition GridImp.cpp:734
void findQsPrimitive(Object *object)
Definition GridImp.cpp:1842
uint getQPatch(const uint index) const override
Definition GridImp.cpp:918
real getStartZ() const override
Definition GridImp.cpp:2344
void fillMissingQsWithDefault(real defaultValue=static_cast< real >(vf::grid_winding::defaultMissingQ()))
Definition GridImp.cpp:985
Distribution distribution
Definition GridImp.h:211
real getFirstFluidNode(real coords[3], int direction, real startCoord) const override
Definition GridImp.cpp:1461
void setInnerBasedOnFinerGrid(const SPtr< Grid > fineGrid)
Definition GridImp.cpp:319
void setEnableFixRefinementIntoTheWall(bool enableFixRefinementIntoTheWall) override
Definition GridImp.cpp:827
void findInvalidBoundaryNodes(uint index)
Definition GridImp.cpp:1575
void setPeriodicityZ(bool periodicity) override
Definition GridImp.cpp:758
void findCommunicationIndex(uint index, real coordinate, real limit, int direction)
Definition GridImp.cpp:2124
uint getNumberOfNodesY() const override
Definition GridImp.cpp:2369
std::array< CommunicationIndices, 6 > communicationIndices
Definition GridImp.h:424
uint getReceiveIndex(int direction, uint index) override
Definition GridImp.cpp:2169
bool isInside(const Cell &cell) const
Definition GridImp.cpp:278
bool hasQIndex(uint index) const
Definition GridImp.cpp:923
void findInnerNode(uint index)
Definition GridImp.cpp:236
void setCellTo(uint index, char type)
Definition GridImp.cpp:700
uint getSize() const override
Definition GridImp.cpp:2304
int * neighborIndexZ
Definition GridImp.h:139
void freeMemory() override
Definition GridImp.cpp:215
void findEndOfGridStopperNode(uint index)
Definition GridImp.cpp:444
void findStopperNode(uint index)
Definition GridImp.cpp:435
int getSparseIndex(uint matrixIndex) const override
Definition GridImp.cpp:2197
void ensureQStorageAllocated()
Definition GridImp.cpp:1108
bool isReceiveNode(int index) const override
Definition GridImp.cpp:2143
int getStartDirection() const override
Definition GridImp.cpp:2212
Vertex getMaximumOnNode(Vertex exact) const override
Definition GridImp.cpp:2266
int * getNeighborsZ() const override
Definition GridImp.cpp:2390
const std::vector< int > & getDirection() const override
Definition GridImp.cpp:2207
int * getNeighborsY() const override
Definition GridImp.cpp:2385
void setQValue(uint index, int dir, real value)
Definition GridImp.cpp:939
void addFluidNodeIndicesAllFeatures(std::vector< uint > fluidNodeIndicesAllFeatures) override
Definition GridImp.cpp:2542
int * getNeighborsX() const override
Definition GridImp.cpp:2380
bool closeCellIfNeedleThinWall(uint index)
Definition GridImp.cpp:1715
void setPeriodicBoundaryShiftsOnXinZ(real shift) override
Definition GridImp.cpp:786
uint * getCF_fine() const override
Definition GridImp.cpp:2419
uint getNumberOfNodesCF() const override
Definition GridImp.cpp:2400
void getFluidNodeIndicesBorder(uint *fluidNodeIndicesBorder) const override
Definition GridImp.cpp:2519
std::vector< SideType > getBCAlreadySet() override
Definition GridImp.cpp:2629
GridImp()=default
uint * getCF_coarse() const override
Definition GridImp.cpp:2414
void sortFluidNodeIndicesApplyBodyForce() override
Definition GridImp.cpp:2584
void setPeriodicity(bool periodicityX, bool periodicityY, bool periodicityZ) override
Definition GridImp.cpp:741
uint * getFC_fine() const override
Definition GridImp.cpp:2434
void setActiveWindingSurface(SPtr< GbTriFaceMesh3D > surface)
Definition GridImp.cpp:885
uint getNumberOfFluidNodeIndicesMacroVars() const override
Definition GridImp.cpp:2599
int * neighborIndexX
Definition GridImp.h:139
void getFluidNodeIndicesMacroVars(uint *fluidNodeIndicesMacroVars) const override
Definition GridImp.cpp:2614
void setPeriodicBoundaryShiftsOnZinX(real shift) override
Definition GridImp.cpp:810
void findCommunicationIndices(int direction, SPtr< BoundingBox > subDomainBox, bool doShift) override
Definition GridImp.cpp:2094
uint getSendIndex(int direction, uint index) override
Definition GridImp.cpp:2164
void setPeriodicBoundaryShiftsOnXinY(real shift) override
Definition GridImp.cpp:778
uint * getFC_offset() const override
Definition GridImp.cpp:2439
uint getNumberOfFluidNodesBorder() const override
Definition GridImp.cpp:2514
void getFluidNodeIndices(uint *fluidNodeIndices) const override
Definition GridImp.cpp:2508
void setOverlapTmp(uint index)
Definition GridImp.cpp:359
void addAllFluidNodeIndicesToAllFeatures() override
Definition GridImp.cpp:2551
void limitToSubDomain(SPtr< BoundingBox > subDomainBox) override
Definition GridImp.cpp:1522
bool hasAllNeighbors(uint index) const
Definition GridImp.cpp:593
void findGridInterface(SPtr< Grid > grid) override
Definition GridImp.cpp:1487
Vertex getMinimumOnNode(Vertex exact) const override
Definition GridImp.cpp:2246
void setNonStopperOutOfGridCellTo(uint index, char type)
Definition GridImp.cpp:716
real getStartY() const override
Definition GridImp.cpp:2339
void inital(const SPtr< Grid > fineGrid, uint numberOfLayers) override
Definition GridImp.cpp:130
uint getSparseSize() const override
Definition GridImp.cpp:2309
uint * getFC_coarse() const override
Definition GridImp.cpp:2429
Field getField() const
Definition GridImp.cpp:2318
void setPeriodicityX(bool periodicity) override
Definition GridImp.cpp:748
void setFieldEntry(uint matrixIndex, char type) override
Definition GridImp.cpp:2328
real getEndX() const override
Definition GridImp.cpp:2349
char getFieldEntry(uint index) const override
Definition GridImp.cpp:2323
void setPeriodicBoundaryShiftsOnYinZ(real shift) override
Definition GridImp.cpp:802
void fillMissingQsAlongSolidNeighbours(real defaultValue=static_cast< real >(vf::grid_winding::defaultMissingQ()))
Definition GridImp.cpp:1000
void repairGridInterfaceOnMultiGPU(SPtr< Grid > fineGrid) override
Definition GridImp.cpp:1517
bool closeCellIfNeedle(uint index)
Definition GridImp.cpp:1675
void findQs(Object *object) override
Definition GridImp.cpp:1732
void setTriangularMeshDiscretizationStrategy(SPtr< TriangularMeshDiscretizationStrategy > triangularMeshDiscretizationStrategy)
Definition GridImp.cpp:875
void setNumberOfLayers(uint numberOfLayers) override
Definition GridImp.cpp:1140
void findFluidNodeIndicesBorder() override
Definition GridImp.cpp:1235
uint getNumberOfNodesFC() const override
Definition GridImp.cpp:2407
bool getPeriodicityY() const override
Definition GridImp.cpp:768
void findGridInterfaceCF(uint index, GridImp &finerGrid)
Definition GridImp.cpp:1559
void setQPatch(uint index, uint patch)
Definition GridImp.cpp:958
bool getPeriodicityX() const override
Definition GridImp.cpp:763
bool cellContainsOnly(Cell &cell, char type) const
Definition GridImp.cpp:505
void repairCommunicationIndices(int direction) override
Definition GridImp.cpp:2174
void setPeriodicBoundaryShiftsOnYinX(real shift) override
Definition GridImp.cpp:794
void rebuildBoundaryQIndices()
Definition GridImp.cpp:1049
bool getPeriodicityZ() const override
Definition GridImp.cpp:773
void sortFluidNodeIndicesAllFeatures() override
Definition GridImp.cpp:2589
void updateSparseIndices()
Definition GridImp.cpp:1180
real getStartX() const override
Definition GridImp.cpp:2334
void findInnerNodes()
Definition GridImp.cpp:229
void setNeighborIndices(uint index)
Definition GridImp.cpp:1258
BoundingBox getBoundingBoxOnNodes(Triangle &triangle) const
Definition GridImp.cpp:2222
real getQValue(const uint index, const uint dir) const override
Definition GridImp.cpp:911
static void getGridInterface(uint *gridInterfaceList, const uint *oldGridInterfaceList, uint size)
Definition GridImp.cpp:2452
void findGridInterfaceFC(uint index, GridImp &finerGrid)
Definition GridImp.cpp:1565
void findBoundarySolidNode(uint index)
Definition GridImp.cpp:463
void discretize(Object *object, char innerType, char outerType)
Definition GridImp.cpp:259
void getFluidNodeIndicesAllFeatures(uint *fluidNodeIndicesAllFeatures) const override
Definition GridImp.cpp:2623
int * getNeighborsNegative() const override
Definition GridImp.cpp:2395
void fixOddCell(uint index)
Definition GridImp.cpp:473
bool isNode(uint index, char type) const
Definition GridImp.cpp:550
uint getNumberOfFluidNodes() const override
Definition GridImp.cpp:2314
void getFluidNodeIndicesApplyBodyForce(uint *fluidNodeIndicesApplyBodyForce) const override
Definition GridImp.cpp:2618
void setNumberOfSolidBoundaryNodes(uint numberOfSolidBoundaryNodes) override
Definition GridImp.cpp:905
uint transCoordToIndex(const real &x, const real &y, const real &z) const override
Definition GridImp.cpp:832
bool nodeInNextCellIs(int index, char type) const
Definition GridImp.cpp:624
void addBCalreadySet(SideType side) override
Definition GridImp.cpp:2633
void initalNodeToOutOfGrid(uint index)
Definition GridImp.cpp:211
uint getQIndex(uint index) const
Definition GridImp.cpp:932
void setPeriodicBoundaryShiftsOnZinY(real shift) override
Definition GridImp.cpp:818
real * getDistribution() const override
Definition GridImp.cpp:2202
int * neighborIndexNegative
Definition GridImp.h:139
void setOverlapFluid(uint index)
Definition GridImp.cpp:369
void getGridInterfaceIndices(uint *iCellCfc, uint *iCellCff, uint *iCellFcc, uint *iCellFcf) const override
Definition GridImp.cpp:2444
void findSolidStopperNode(uint index)
Definition GridImp.cpp:457
void setInnerRegionFromFinerGrid(bool innerRegionFromFinerGrid) override
Definition GridImp.cpp:1135
void findOverlapStopper(uint index, GridImp &finerGrid)
Definition GridImp.cpp:1570
void print() const
Definition GridImp.cpp:2648
void closeNeedleCellsThinWall() override
Definition GridImp.cpp:1697
real getDelta() const override
Definition GridImp.cpp:2299
void addFluidNodeIndicesMacroVars(std::vector< uint > fluidNodeIndicesMacroVars) override
Definition GridImp.cpp:2525
void finalizeQComputation() override
Definition GridImp.cpp:1749
uint getNumberOfFluidNodeIndicesAllFeatures() const override
Definition GridImp.cpp:2609
uint getNumberOfSendNodes(int direction) override
Definition GridImp.cpp:2154
void findFluidNodeIndices(bool splitDomain) override
Definition GridImp.cpp:1200
void transIndexToCoords(uint index, real &x, real &y, real &z) const override
Definition GridImp.cpp:844
void fixRefinementIntoWall(uint xIndex, uint yIndex, uint zIndex, int dir)
Definition GridImp.cpp:376
void findOverlapStopper(const uint &indexOnCoarseGrid, GridImp *coarseGrid, GridImp *fineGrid)
void findForGridInterfaceSparseIndexCF(GridImp *coarseGrid, GridImp *fineGrid, uint index)
void findBoundaryGridInterfaceCF(const uint &indexOnCoarseGrid, GridImp *coarseGrid, GridImp *fineGrid)
void findInvalidBoundaryNodes(const uint &indexOnCoarseGrid, GridImp *coarseGrid)
void findForGridInterfaceSparseIndexFC(GridImp *coarseGrid, GridImp *fineGrid, uint index)
struct vf::gpu::GridInterface::Interface fc
struct vf::gpu::GridInterface::Interface cf
void findInterfaceCF(const uint &indexOnCoarseGrid, GridImp *coarseGrid, GridImp *fineGrid)
void findInterfaceFC(const uint &indexOnCoarseGrid, GridImp *coarseGrid, GridImp *fineGrid)
void repairGridInterfaceOnMultiGPU(SPtr< GridImp > coarseGrid, SPtr< GridImp > fineGrid)
std::shared_ptr< T > SPtr
float real
Definition DataTypes.h:42
unsigned int uint
Definition DataTypes.h:47
#define INVALID_INDEX
Definition DataTypes.h:48
@ z
Definition Axis.h:44
@ x
Definition Axis.h:42
@ y
Definition Axis.h:43
#define DIMENSION
Definition global.h:38
#define DIR_END_MAX
#define GEOSOLID
int DIRECTIONS[DIR_END_MAX][DIMENSION]
Definition GridImp.cpp:70
#define GEOFLUID
static bool lessEqual(const real &val1, const real &val2, real maxRelDiff=EPSILON)
Definition Math.cpp:52
static bool greaterEqual(const real &val1, const real &val2, real maxRelDiff=EPSILON)
Definition Math.cpp:59
static bool equal(const real &val1, const real &val2, real maxRelDiff=EPSILON)
Definition Math.cpp:40
void cleanFluidNodes(std::vector< uint > &nodes)
Definition GridImp.cpp:2559
SideType
Definition Side.h:63
void sortFluidNodes(std::vector< uint > &allNodes, std::vector< uint > &markedNodes)
Definition GridImp.cpp:2566
real wrapCoord(real coord, real start, real end)
Definition GridImp.cpp:1285
bool pointOnTriangle(const TriangleInfo &triangle, const Vec3 &p, double planeTol, double baryTol=1.0e-8)
std::vector< Direction > directions
std::vector< int > dirs
void setSize(uint size)