MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
GridgenPar< nDim > Class Template Reference

#include <cartesiangridgenpar.h>

Collaboration diagram for GridgenPar< nDim >:
[legend]

Public Member Functions

MLonga_parentId (const MInt cellId)
 Returns the parent of the cell cellId. More...
 
const MLonga_parentId (const MInt cellId) const
 Returns the parent of the cell cellId. More...
 
MInta_level (const MInt cellId)
 Returns the level of the cell cellId. More...
 
const MInta_level (const MInt cellId) const
 Returns the level of the cell cellId. More...
 
MInta_noSolidLayer (const MInt cellId, const MInt solver)
 Returns the solid layer of the cell cellId. More...
 
const MInta_noSolidLayer (const MInt cellId, const MInt solver) const
 Returns the solid layer of the cell cellId. More...
 
MLonga_globalId (const MInt cellId)
 Returns the globalId of the cell cellId. More...
 
const MLonga_globalId (const MInt cellId) const
 Returns the globalId of the cell cellId. More...
 
MInta_noChildren (const MInt cellId)
 Returns the no. of children of the cell cellId. More...
 
const MInta_noChildren (const MInt cellId) const
 Returns the no. of children of the cell cellId. More...
 
MFloata_coordinate (const MInt cellId, const MInt dim)
 Returns the coordinate of the cell cellId for dimension dim. More...
 
const MFloata_coordinate (const MInt cellId, const MInt dim) const
 Returns the coordinate of the cell cellId for dimension dim. More...
 
MLonga_childId (const MInt cellId, const MInt position)
 Returns the child id of the cell cellId position. More...
 
const MLonga_childId (const MInt cellId, const MInt position) const
 Returns the child id of the cell cellId position. More...
 
MChara_hasProperty (const MInt cellId, const MInt p)
 Returns property p of the cell cellId. More...
 
MChar a_hasProperty (const MInt cellId, const MInt p) const
 Returns property p of the cell cellId. More...
 
MInta_refinementDistance (const MInt cellId)
 Returns rfnDistance of the cell cellId position. More...
 
const MInta_refinementDistance (const MInt cellId) const
 Returns rfnDistance of the cell cellId position. More...
 
MLonga_neighborId (const MInt cellId, const MInt position)
 Returns the neighbor id of the cell cellId position. More...
 
const MLonga_neighborId (const MInt cellId, const MInt position) const
 Returns the neighbor id of the cell cellId position. More...
 
MChara_isInSolver (const MInt cellId, const MInt solver)
 Multisolver grid: does a cell belong to a certain solver. More...
 
MChar a_isInSolver (const MInt cellId, const MInt solver) const
 Multisolver grid: does a cell belong to a certain solver. More...
 
MChara_isSolverBoundary (const MInt cellId, const MInt solver)
 Multisolver grid: does a cell belong to a certain solver. More...
 
MChar a_isSolverBoundary (const MInt cellId, const MInt solver) const
 Multisolver grid: does a cell belong to a certain solver. More...
 
MChara_isToRefineForSolver (const MInt cellId, const MInt solver)
 Multisolver grid: does a cell belong to a certain solver. More...
 
MChar a_isToRefineForSolver (const MInt cellId, const MInt solver) const
 Multisolver grid: does a cell belong to a certain solver. More...
 
 GridgenPar (const MPI_Comm comm, const MInt noSolvers)
 generates a Cartesian grid in parallel More...
 
MPI_Comm mpiComm () const
 
MInt domainId () const
 
MInt noDomains () const
 

Static Public Member Functions

template<class T >
static void quickSort (T *globalIdArray, MInt *lookup, MInt startindex, MInt endindex)
 sorts a list of integers and updates a second one More...
 

Protected Member Functions

void initTimers ()
 
void initMembers ()
 initializes the member variables More...
 
void readProperties ()
 reads necessary properties from the property file More...
 
void readSolverProperties (MInt solver)
 
void initGeometry ()
 initializes the geometry More...
 
void gridAlignCutOff ()
 aligns the cutOffCoordinates with the grid More...
 
void createInitialGrid ()
 creates the initial grid More...
 
void createStartGrid ()
 creates the start grid More...
 
void finalizeGrid ()
 
void createComputationalMultisolverGrid ()
 refinement > minLevel is processed in createComputationalMultisolverGrid More...
 
void checkLBRefinementValidity ()
 checks if this is a valid mesh also for LB computations More...
 
MInt getAdjacentGridCells (MInt cellId, MInt *adjacentCells)
 Retrieves all direct and diagonal neighboring cells of the given cell. More...
 
void refineComputationalGrid (MInt lvl)
 refines cells of the computational grid that are marked for refinement More...
 
void saveGrid ()
 writes the grid to file in parallel More...
 
void saveGridDomain (MInt level_, MInt tag)
 degugging function writing the grid in serial More...
 
void checkMemoryAvailability (MInt stage, MInt level_)
 
void refineGrid (MInt **offsets, MInt level_, MBool halo)
 refines the grid on a given level More...
 
void refineGridPatch (MInt **offsets, MInt level_, MBool halo)
 refines the grid on a given level for a provided patch More...
 
void refineCell (MInt id, MInt *currentChildId)
 refines a single cell More...
 
void deleteOutsideCellsSerial (MInt level_)
 deletes the cells outside of the geometry More...
 
void deleteCoarseSolidCellsSerial ()
 performs deleting solid cells lower than maxRefinementLevel More...
 
void deleteCoarseSolidCellsParallel ()
 performs deleting solid cells lower than maxRefinementLevel More...
 
void performCutOff (MInt **offsets, MInt level_, MBool deleteMode=false)
 performs a cut-off defined by the properties More...
 
void keepOutsideBndryCellChildrenSerial (MInt *offsets, MInt level_)
 
MInt nghborStencil (MInt, MInt)
 
void createSolidCellLayer (MInt cellId, MInt solidLayer, MInt finalLayer_)
 
void keepOutsideBndryCellChildrenParallel (MInt level_)
 
void deleteOutsideCellsParallel (MInt level_)
 deletes outside cells in parallel mode More...
 
MInt getLastNonWindowCell (MInt no_consider, MInt last)
 
void deleteCellReferences (MInt cell, MInt pos)
 deletes the references of a given cell More...
 
void markInsideOutside (MInt **offsets, MInt level_)
 marks inside and outside cells More...
 
void markInsideOutside (MInt **offsets, MInt level_, MInt solver)
 starts the inside-outside flooding for solvers More...
 
void markSolverAffiliation (MInt level_)
 marks cells without solver affiliation as outside cells More...
 
void excludeInsideOutside (MInt **offsets, MInt level_, MInt solver)
 excludes obvious non solver affiliated cells from the inside outside flooding More...
 
void floodCells (std::stack< MInt > *fillStack, MChar marker)
 floods cells More...
 
void floodCells (std::stack< MInt > *fillStack, MChar marker, MInt solver)
 
void findChildLevelNeighbors (MInt **offsets, MInt level_)
 updates the children of a given level More...
 
void reorderCellsHilbert ()
 reorders the cells after Hilbert id More...
 
void parallelizeGrid ()
 parallize the present grid More...
 
void updateHaloOffsets (MInt l, MInt noHalos, MInt *rfnCountHalosDom)
 updates the offsets of the halos More...
 
void updateOffsets (MInt gridLevel)
 updates the offsets More...
 
void updateInterRankNeighbors ()
 updates the neighbors on the neighboring ranks More...
 
void findHaloAndWindowCells (std::vector< std::vector< MInt > > &winCellIdsPerDomain, std::vector< std::vector< MInt > > &haloCellIdsPerDomain)
 find window cells using the known halo cells More...
 
void findHaloAndWindowCellsKD (std::vector< std::vector< MInt > > &winCellIdsPerDomain, std::vector< std::vector< MInt > > &haloCellIdsPerDomain)
 finds halo and window cells using a kd tree More...
 
void updateGlobalIdsReferences ()
 updates the references of all cells to use the global-ids More...
 
void collectHaloChildren (MInt parentId, std::vector< MInt > *cellIdsPerDomain)
 recursively traverse the tree depth-first and collect halo cells More...
 
void collectWindowChildren (MInt parentId, std::vector< MInt > *cellIdsPerDomain)
 recursively traverse the tree depth-first and collect window cells More...
 
void reorderGlobalIdsDF ()
 reorders the globalIds depth-first More...
 
void traverseDFGlobalId (MInt parentId, MLong *globalId_, MLongScratchSpace &partitionCellList, MFloatScratchSpace &workloadPerCell, MFloat *currentWorkload, MFloatScratchSpace &weight, MFloatScratchSpace &workload, MInt *j)
 recursively traverses the octree More...
 
void setCellWeights (MFloatScratchSpace &weight)
 sets the cell weights according to the box system More...
 
void determineRankOffsets (MIntScratchSpace &offsets)
 
void markSolverForRefinement (MInt level_, MInt solver)
 
void concludeSolverRefinement (MInt level_)
 
void markLocalSolverRefinement (MInt level_, MInt solver)
 
void markPatchForSolverRefinement (MInt level_, MInt solver)
 
void markBndForSolverRefinement (MInt level_, MInt solver)
 
void markLocalBox (MInt level_, MInt patch, MInt solver)
 marks cells that lie in a box-type patch More...
 
void markLocalRadius (MInt level_, MInt patch, MInt solver)
 marks cells that lie in a sphere-type patch More...
 
void markLocalCylinder (MInt level_, MInt patch, MInt solver, MString patchStr)
 marks cells that lie in a cylinder-type patch More...
 
void markLocalCone (MInt level_, MInt patch, MInt solver)
 marks cells that lie in a cone-type patch with a smooth hat More...
 
void markLocalRectangleAngled (MInt level_, MInt patch, MInt solver)
 marks cells that lie in a rectangular-angled-type patch More...
 
void markLocalCartesianWedge (MInt level_, MInt patch, MInt solver)
 
void markLocalFlatCone (MInt level_, MInt patch, MInt solver)
 
void markLocalSlicedCone (MInt level_, MInt patch, MInt solver, MString patchStr)
 marks cells that lie in a sliced cone-type patch More...
 
void markLocalHat (MInt level_, MInt patch, MInt solver)
 marks cells that lie in a cone-type patch with a smooth hat More...
 
void markBndDistance (MInt level_, MInt solver)
 marks cells that lie in a certain distance to the boundary More...
 
void propagateDistance (MInt level_, MInt distance, std::vector< MInt > &rfnBoundaryGroup, MInt solver)
 propagates the distance away from the boundary More...
 
void propagationStep (MInt cellId, MInt rfnDistance, MInt finalDistance, MInt solver)
 recursivley marks the cells with a distance More...
 
MBool isInsideSlicedCone (const MFloat *const pointCoord, const MFloat *const leftCoord, const MFloat *const rightCoord, const MFloat *const leftNormal, const MFloat *const rightNormal, const MFloat *const normalDifforigAB, const MFloat leftR, const MFloat rightR)
 checks if point (cell) is inside a sliced cone More...
 
MBool isInsideCylinder (const MFloat *const pointCoord, const MFloat *const leftCoord, const MFloat *const rightCoord, const MFloat *const normalDiffAB, const MFloat *const normalDiffBA, const MFloat radius, const MFloat innerRadius)
 checks if point (cell) is inside a cylinder More...
 
MBool pointIsInside (MFloat *coordinates)
 checks if a given point is inside the geometry More...
 
MBool pointIsInsideSolver (MFloat *coordinates, MInt solver)
 
MBool checkCellForCut (MInt id)
 checks if a cell has a cut with the geometry More...
 
void copyCell (MInt from, MInt to)
 moves a cell from one location in the collector to another More...
 
void swapCells (MInt cellId1, MInt cellId2)
 swaps two cells in memory More...
 
void checkNeighborhood (MInt level_)
 checks if the neighborhood is correct More...
 
void checkNeighborhoodDistance (MInt level_)
 checks if the distance between neighboring cells is alright More...
 
void checkNeighborhoodIntegrity (MInt level_)
 checks if the neighborhood relation of the cells is alright More...
 
void writeGridInformationPar ()
 writes a pseudo solution file with some grid information More...
 
void writeGridInformation (MInt level_, MInt tag)
 debugging function writing debug info to a file More...
 
void writeParallelGeometry ()
 
void checkLoadBalance (MInt in_level)
 checks if a dynamic load balancing is needed. More...
 
void dynamicLoadBalancing ()
 Rebalances the grid dynamicaly while grid building. More...
 
void communicateInt (MIntScratchSpace &recvBuffer, MIntScratchSpace &noCellsToReceive, MIntScratchSpace &sendBuffer, MIntScratchSpace &noCellsToSend)
 Communicates an array of int values. More...
 
void communicateLong (MLongScratchSpace &recvBuffer, MIntScratchSpace &noCellsToReceive, MLongScratchSpace &sendBuffer, MIntScratchSpace &noCellsToSend)
 Communicates an array of int values. More...
 
void communicateDouble (MFloatScratchSpace &recvBuffer, MIntScratchSpace &noCellsToReceive, MFloatScratchSpace &sendBuffer, MIntScratchSpace &noCellsToSend)
 Communicates an array of double values. More...
 
void communicateIntToNeighbors (MIntScratchSpace &recvMem, MIntScratchSpace &noCellsToReceive, MIntScratchSpace &sendMem, MIntScratchSpace &noCellsToSend, MInt noVar)
 Communicates Int values, with a variable nmbr of variables to the Neighbors. More...
 
void communicateHaloGlobalIds (MInt level)
 communicate the global ids of the halo cells. More...
 

Private Attributes

const MPI_Comm m_mpiComm
 
MInt m_domainId
 
MInt m_noDomains
 
std::ostream outStream
 
Collector< GridgenCell< nDim > > * m_cells = nullptr
 
GridgenCell< nDim > * m_pCells = nullptr
 
MInt m_noCells
 
MLong m_partitionCellOffspringThreshold
 
MFloat m_partitionCellWorkloadThreshold
 
MInt m_initialRefinementLevelSerial
 
MInt m_minLevel
 
SolverRefinementm_solverRefinement = nullptr
 
MInt m_maxUniformRefinementLevel
 
MInt m_maxRfnmntLvl
 
MInt m_weightMethod
 
MInt m_weightBndCells
 
MInt m_weightPatchCells
 
MBool m_weightSolverUniformLevel
 
MBool m_writeGridInformation
 
MBool m_checkGridLbValidity = true
 
MFloat m_reductionFactor
 
MString m_targetGridFileName = ""
 
MString m_outputDir = ""
 
MBool m_writeCoordinatesToGridFile = false
 
MInt m_keepOutsideBndryCellChildren
 
MIntm_noSolidLayer = nullptr
 
MBool m_hasMultiSolverBoundingBox = false
 
std::vector< MFloatm_multiSolverBoundingBox {}
 
MInt m_multiSolverMinLevel = -1
 
MFloat m_multiSolverLengthLevel0 = -1.0
 
std::vector< MFloatm_multiSolverCenterOfGravity {}
 
MInt m_maxNoCells
 
MInt m_maxLevels
 
MString m_gridOutputFileName
 
MInt m_rfnCount
 
MInt m_rfnCountHalos
 
MIntm_rfnCountHalosDom = nullptr
 
MInt m_noSolvers
 
MIntm_noBndIdsPerSolver = nullptr
 
MBool ** m_bndCutInfo = nullptr
 
MBool m_cutOff
 
MString m_parallelGeomFileName
 
Geometry< nDim > * m_STLgeometry
 
GeometryRootm_geometry = nullptr
 
MFloatm_boundingBox = nullptr
 
MFloatm_geometryExtents = nullptr
 
MFloatm_centerOfGravity = nullptr
 
MInt m_decisiveDirection
 
MFloatm_lengthOnLevel = nullptr
 
MInt ** m_levelOffsets = nullptr
 
MInt m_maxNoChildren
 
MInt m_noNeighbors
 
MLong m_noTotalCells
 
MInt m_noPartitionCells
 
MLong m_noTotalPartitionCells
 
MInt m_noTotalHaloCells
 
std::vector< std::tuple< MInt, MLong, MFloat > > m_partitionCellList
 
MIntm_noCellsPerDomain = nullptr
 
MIntm_noPartitionCellsPerDomain = nullptr
 
MIntm_noHaloCellsOnLevel = nullptr
 
MInt m_noNeighborDomains
 
MIntm_neighborDomains = nullptr
 
MInt ** m_haloCellOffsetsLevel = nullptr
 
MLong m_cellOffsetPar
 
MInt ** m_haloCellOffsets = nullptr
 
std::map< MInt, MIntm_cellIdLUT
 
MInt m_t_comp_GG = -1
 
MInt m_t_readProperties = -1
 
MInt m_t_initMembers = -1
 
MInt m_t_initGeometry = -1
 
MInt m_t_createInitialGrid = -1
 
MInt m_t_parallelizeGrid = -1
 
MInt m_t_createStartGrid = -1
 
MInt m_t_createComputationalGrid = -1
 
MInt m_t_finalizeGrid = -1
 
MInt m_t_saveGrid = -1
 
MInt m_t_updateInterRankNeighbors = -1
 
MInt m_noMissingParents
 
MBool m_hasBeenLoadBalanced
 

Detailed Description

template<MInt nDim>
class GridgenPar< nDim >

Definition at line 60 of file cartesiangridgenpar.h.

Constructor & Destructor Documentation

◆ GridgenPar()

template<MInt nDim>
GridgenPar< nDim >::GridgenPar ( const MPI_Comm  comm,
const MInt  noSolvers 
)
Author
Andreas Lintermann
Date
11.10.2013

The complete algorithm consitst of the following steps:

  1. Read properties
  2. Init members
  3. Init geometry
  4. Create initial grid 4.1 Creates an initial cube around the geometry. 4.2 Refines the initial cube to the initialGeometricalRfnLvl. In each iteration the following is performed: 4.2.1 update the level offsets: this gets rid of the delettion of lower levels by using the following structure. Based on the m_initialGeometricalRfnLevel the first initial cube is located at the beginning or at the end of the collector:
    • m_initialGeometricalRfnLevel is even: locate at the beginning
    • m_initialGeometricalRfnLevel is odd: locate at the end The next following level is always written to the other end of the collector, i.e., if the first cube is located at the end of the collector, the next higher level starts at the beginning of the collector. This method iterates, cells are written to the front back of the collector continuously. This way it is not necessary to delete the lower levels since they are just overwritten by one of the upcoming levels. This way, at the end of the refinement the initial level is located at the beginning of the collector. Before refining and writing to a level at the end of the collector the offsets are determined by estimating the possible number of cells on the upcoming level. 4.2.2 check if there is enough memory 4.x.x each solver marks its cells for refinement 4.2.3 refine the grid one further level 4.2.4 update the neighborhood and solver information on the newly created cells 4.2.5 cells outside the geometry are deleted 4.2.6 cells outside the individual solvers are unmarked 4.3 Remove the link to the parents on the initial level 4.4 Update the number of generated cells and print information 4.5 Reorder cells after Hilbert id 4.6 If the code runs parallel, parallelize the grid.

Create start grid (if required), can be found in createComputationalMultisolverGrid 5.1. Run over all levels that are still to be refined and do the following: 5.1.1 Update the m_levelOffsets of the next level. This generates a new offset range for the new level to create under the assumption that all cells on the current level are refined. 5.1.2 Update the halo cell offsets. This call the updateHaloCellOffsets(...) function. 5.1.3 Check memory availability. 5.1.4 Refine the normal cells and the halo cells. This calls refineGrid(...) similar to the serial case. To refine the halo cells the new halo cell offsets are provided. 5.1.5 Update the number of cells on this domain, since it has changed. 5.1.6 Find the neighbors for all newly generated normal and halo cells. This calls findChildLevelNeighbors(...) and provides the offsets for the normal cells and the halo cells of the current level. 5.1.7 Delete all normal outside cells. This has still to be done for the halo cells. 5.2 Again update the number of cells.

  1. Create computational multisolver grid (if required) 6.1 This calls either the method for patches or the method for local boundary refinement 6.1a.2 Run over all levels which still need to be refined. Depending on the properties for this level (is it a box patch or a sphere patch?) the grid is refined 6.1a.2.1 Check what type of patch should be used and mark the according cells. This calls either refineLocalBox(...), which marks the cells according to the defined coordinates in a box-style or refineLocalRadius(...), which marks the cells according to the coordinates of the center of a sphere and a radius. If we run in parallel mode, also do this for the halos. The functions refineLocalBox(...) and refineLocalRadius(...) already update the offsets for the normal cells and the halos. 6.1a.2.2 Check memory availability. 6.1a.2.3 Refine the cells that have previously been marked. This calls the function refineGridPatch(...) which only refines cells that have previously been marked. If we run in parallel mode, do this also for the halo cells. 6.1b.2.4 Update the number of cells. 6.1b.2.5 Find the neighbors for the new cells. Calls findChildLevelNeighbors(...). If we run in parallel mode, this is also done for the halo cells. 6.1b.2.6 Delete all outside cells, do this in serial or in parallel. This calls either deleteOutsideCellsSerial(...) or deleteOutsideCellsParallel(...) 6.1a.1 Initialize the distances for all upcoming levels. The distances are based on the value provided by the property localMinBoundaryThreshold and by the property smoothDistance. The first defines the distance in cell units on the current level, which should be refined. The latter property defines how many cells should be inbetween the levels. 6.3b.2 Run over all levels that are still to be refined and do the following: 6.3b.2.1 Do the boundary propagation. This calls boundaryPropagation(...) with the current level and the final distance to use. 6.3b.2.2 Dry run for the normal cells: This finds out how many cells have been marked in boundaryPropagation(...) and recalulcates the new offsets for the new level. Mark the according cells which are inside the given distance: calls markBndDistance(...) 6.2b.2.3 Check memory availability. 6.2b.2.4 Update the distances for the new level. A distance on a given level is twice the distance on a higher level. 6.2b.2.5 Refine the cells that have previously been marked. This calls the function refineGridPatch(...) which only refines cells that have previously been marked. If we run in parallel mode, do this also for the halo cells. 6.2b.2.6 Update the number of cells. 6.2b.2.7 Find the neighbors for the new cells. Calls findChildLevelNeighbors(...). If we run in parallel mode, this is also done for the halo cells. 6.2b.2.8 Delete all outside cells, do this in serial or in parallel. This calls either deleteOutsideCellsSerial(...) or deleteOutsideCellsParallel(...) 6.3 Check the refinement validity for LB. 6.4 We are finished, run the final setup. This calls updateInterRankNeighbors() to exchange the neighborhood.
  2. Write grid to file
  3. Cleaning up
Parameters
[in]dimensionsthe dimensionality of the problem

Definition at line 139 of file cartesiangridgenpar.cpp.

140 : m_mpiComm(comm), outStream(nullptr), m_noSolvers(noSolvers) {
141 TRACE();
142
143 MPI_Comm_rank(mpiComm(), &m_domainId);
144 MPI_Comm_size(mpiComm(), &m_noDomains);
145
146 if(globalDomainId() == 0) {
147 outStream.rdbuf(std::cout.rdbuf());
148 }
149
150 m_log << "Parallel grid generator started on process " << globalDomainId() << endl;
151 std::cout << "Parallel grid generator started on process " << globalDomainId() << endl;
152
153 // 0. Initialize timers
154 initTimers();
155 RECORD_TIMER_START(m_t_comp_GG);
156
157 // 1. Read properties
159
160 // 2. Init members
161 initMembers();
162
163 // 3. Init geometry
164 initGeometry();
165
166 writeMemoryStatistics(mpiComm(), noDomains(), domainId(), AT_, "Gridgen after init");
167
168 // 3 - 4
170
171 // 4. Create initial grid
173
174 if(noDomains() > 1) parallelizeGrid();
175
176 // 5. and 6.
178
179 // 6.4 we are finished, run the final setup
180 finalizeGrid();
181
182 // for debugging
184
185 // 7. Write grid to file
186 saveGrid();
187
188 writeMemoryStatistics(mpiComm(), noDomains(), domainId(), AT_, "Gridgen finalize");
189
190 // 8. Cleaning up
191 m_log << " (8) Cleaning up" << endl;
192 outStream << " (8) Cleaning up" << endl;
193
194 RECORD_TIMER_STOP(m_t_comp_GG);
195}
void initMembers()
initializes the member variables
MInt noDomains() const
void createComputationalMultisolverGrid()
refinement > minLevel is processed in createComputationalMultisolverGrid
MBool m_writeGridInformation
MPI_Comm mpiComm() const
void initGeometry()
initializes the geometry
std::ostream outStream
void saveGrid()
writes the grid to file in parallel
void writeGridInformationPar()
writes a pseudo solution file with some grid information
void gridAlignCutOff()
aligns the cutOffCoordinates with the grid
void readProperties()
reads necessary properties from the property file
void parallelizeGrid()
parallize the present grid
MInt domainId() const
const MPI_Comm m_mpiComm
void createInitialGrid()
creates the initial grid
void writeMemoryStatistics(const MPI_Comm comm, const MInt noDomains, const MInt domainId, const MString at, const MString comment)
Write memory statistics.
Definition: functions.cpp:218
MInt globalDomainId()
Return global domain id.
InfoOutFile m_log
MInt noSolvers
Definition: maiatypes.h:73

Member Function Documentation

◆ a_childId() [1/2]

template<MInt nDim>
MLong & GridgenPar< nDim >::a_childId ( const MInt  cellId,
const MInt  position 
)
inline

Definition at line 91 of file cartesiangridgenpar.h.

91{ return m_pCells [cellId].m_childIds_[position]; }
GridgenCell< nDim > * m_pCells
void const MInt cellId
Definition: collector.h:239

◆ a_childId() [2/2]

template<MInt nDim>
const MLong & GridgenPar< nDim >::a_childId ( const MInt  cellId,
const MInt  position 
) const
inline

Definition at line 93 of file cartesiangridgenpar.h.

93 {
94 return m_pCells [cellId].m_childIds_[position];
95 }

◆ a_coordinate() [1/2]

template<MInt nDim>
MFloat & GridgenPar< nDim >::a_coordinate ( const MInt  cellId,
const MInt  dim 
)
inline

Definition at line 85 of file cartesiangridgenpar.h.

85{ return m_pCells [cellId].m_coordinates_[dim]; }

◆ a_coordinate() [2/2]

template<MInt nDim>
const MFloat & GridgenPar< nDim >::a_coordinate ( const MInt  cellId,
const MInt  dim 
) const
inline

Definition at line 87 of file cartesiangridgenpar.h.

87 {
88 return m_pCells [cellId].m_coordinates_[dim];
89 };

◆ a_globalId() [1/2]

template<MInt nDim>
MLong & GridgenPar< nDim >::a_globalId ( const MInt  cellId)
inline

Definition at line 77 of file cartesiangridgenpar.h.

77{ return *m_pCells[cellId].m_globalId_; }

◆ a_globalId() [2/2]

template<MInt nDim>
const MLong & GridgenPar< nDim >::a_globalId ( const MInt  cellId) const
inline

Definition at line 79 of file cartesiangridgenpar.h.

79{ return *m_pCells[cellId].m_globalId_; };

◆ a_hasProperty() [1/2]

template<MInt nDim>
MChar & GridgenPar< nDim >::a_hasProperty ( const MInt  cellId,
const MInt  p 
)
inline

Definition at line 97 of file cartesiangridgenpar.h.

97{ return m_pCells [cellId].b_properties_[p]; }
constexpr std::underlying_type< FcCell >::type p(const FcCell property)
Converts property name to underlying integer value.

◆ a_hasProperty() [2/2]

template<MInt nDim>
MChar GridgenPar< nDim >::a_hasProperty ( const MInt  cellId,
const MInt  p 
) const
inline

Definition at line 99 of file cartesiangridgenpar.h.

99{ return m_pCells [cellId].b_properties_[p]; };

◆ a_isInSolver() [1/2]

template<MInt nDim>
MChar & GridgenPar< nDim >::a_isInSolver ( const MInt  cellId,
const MInt  solver 
)
inline

Definition at line 115 of file cartesiangridgenpar.h.

115 {
116 return m_pCells [cellId].b_solverAffiliation_[solver];
117 }

◆ a_isInSolver() [2/2]

template<MInt nDim>
MChar GridgenPar< nDim >::a_isInSolver ( const MInt  cellId,
const MInt  solver 
) const
inline

Definition at line 119 of file cartesiangridgenpar.h.

119 {
120 return m_pCells [cellId].b_solverAffiliation_[solver];
121 };

◆ a_isSolverBoundary() [1/2]

template<MInt nDim>
MChar & GridgenPar< nDim >::a_isSolverBoundary ( const MInt  cellId,
const MInt  solver 
)
inline

Definition at line 124 of file cartesiangridgenpar.h.

124 {
125 return m_pCells [cellId].b_solverBoundary_[solver];
126 }

◆ a_isSolverBoundary() [2/2]

template<MInt nDim>
MChar GridgenPar< nDim >::a_isSolverBoundary ( const MInt  cellId,
const MInt  solver 
) const
inline

Definition at line 128 of file cartesiangridgenpar.h.

128 {
129 return m_pCells [cellId].b_solverBoundary_[solver];
130 };

◆ a_isToRefineForSolver() [1/2]

template<MInt nDim>
MChar & GridgenPar< nDim >::a_isToRefineForSolver ( const MInt  cellId,
const MInt  solver 
)
inline

Definition at line 133 of file cartesiangridgenpar.h.

133 {
134 return m_pCells [cellId].b_solverToRefine_[solver];
135 }

◆ a_isToRefineForSolver() [2/2]

template<MInt nDim>
MChar GridgenPar< nDim >::a_isToRefineForSolver ( const MInt  cellId,
const MInt  solver 
) const
inline

Definition at line 137 of file cartesiangridgenpar.h.

137 {
138 return m_pCells [cellId].b_solverToRefine_[solver];
139 };

◆ a_level() [1/2]

template<MInt nDim>
MInt & GridgenPar< nDim >::a_level ( const MInt  cellId)
inline

Definition at line 67 of file cartesiangridgenpar.h.

67{ return *m_pCells [cellId].m_level_; }

◆ a_level() [2/2]

template<MInt nDim>
const MInt & GridgenPar< nDim >::a_level ( const MInt  cellId) const
inline

Definition at line 69 of file cartesiangridgenpar.h.

69{ return *m_pCells [cellId].m_level_; };

◆ a_neighborId() [1/2]

template<MInt nDim>
MLong & GridgenPar< nDim >::a_neighborId ( const MInt  cellId,
const MInt  position 
)
inline

Definition at line 107 of file cartesiangridgenpar.h.

107{ return m_pCells [cellId].m_nghbrIds_[position]; }

◆ a_neighborId() [2/2]

template<MInt nDim>
const MLong & GridgenPar< nDim >::a_neighborId ( const MInt  cellId,
const MInt  position 
) const
inline

Definition at line 110 of file cartesiangridgenpar.h.

110 {
111 return m_pCells [cellId].m_nghbrIds_[position];
112 }

◆ a_noChildren() [1/2]

template<MInt nDim>
MInt & GridgenPar< nDim >::a_noChildren ( const MInt  cellId)
inline

Definition at line 81 of file cartesiangridgenpar.h.

81{ return *m_pCells[cellId].m_noChildIds_; }

◆ a_noChildren() [2/2]

template<MInt nDim>
const MInt & GridgenPar< nDim >::a_noChildren ( const MInt  cellId) const
inline

Definition at line 83 of file cartesiangridgenpar.h.

83{ return *m_pCells[cellId].m_noChildIds_; };

◆ a_noSolidLayer() [1/2]

template<MInt nDim>
MInt & GridgenPar< nDim >::a_noSolidLayer ( const MInt  cellId,
const MInt  solver 
)
inline

Definition at line 71 of file cartesiangridgenpar.h.

71{ return m_pCells [cellId].m_noSolidLayer_[solver]; };

◆ a_noSolidLayer() [2/2]

template<MInt nDim>
const MInt & GridgenPar< nDim >::a_noSolidLayer ( const MInt  cellId,
const MInt  solver 
) const
inline

Definition at line 73 of file cartesiangridgenpar.h.

73 {
74 return m_pCells [cellId].m_noSolidLayer_[solver];
75 };

◆ a_parentId() [1/2]

template<MInt nDim>
MLong & GridgenPar< nDim >::a_parentId ( const MInt  cellId)
inline

Definition at line 63 of file cartesiangridgenpar.h.

63{ return *m_pCells[cellId].m_parentId_; }

◆ a_parentId() [2/2]

template<MInt nDim>
const MLong & GridgenPar< nDim >::a_parentId ( const MInt  cellId) const
inline

Definition at line 65 of file cartesiangridgenpar.h.

65{ return *m_pCells[cellId].m_parentId_; };

◆ a_refinementDistance() [1/2]

template<MInt nDim>
MInt & GridgenPar< nDim >::a_refinementDistance ( const MInt  cellId)
inline

Definition at line 101 of file cartesiangridgenpar.h.

101{ return m_pCells [cellId].m_rfnDistance_; }

◆ a_refinementDistance() [2/2]

template<MInt nDim>
const MInt & GridgenPar< nDim >::a_refinementDistance ( const MInt  cellId) const
inline

Definition at line 104 of file cartesiangridgenpar.h.

104{ return m_pCells [cellId].m_rfnDistance_; }

◆ checkCellForCut()

template<MInt nDim>
MBool GridgenPar< nDim >::checkCellForCut ( MInt  id)
protected
Author
Andreas Lintermann
Date
11.10.2013

This does the following: a. Create a target of the cell for the check b. Do the intersection test this calls getIntersectionElements from Geometry c. Returns the result. If more than one cut has appeared the cell has a cut

Parameters
[in]idthe id of the cell to check
Returns
MBool value if the cell has a cut or not

Definition at line 2150 of file cartesiangridgenpar.cpp.

2150 {
2151 TRACE();
2153}
MBool getCellIntersectingSurfaces(const MFloat *const coords, const MFloat cellHalfLength, MBool *const *const cutInfo)
MFloat & a_coordinate(const MInt cellId, const MInt dim)
Returns the coordinate of the cell cellId for dimension dim.
GeometryRoot * m_geometry
MInt & a_level(const MInt cellId)
Returns the level of the cell cellId.
MFloat * m_lengthOnLevel
MBool ** m_bndCutInfo

◆ checkLBRefinementValidity()

template<MInt nDim>
void GridgenPar< nDim >::checkLBRefinementValidity
protected
Author
Andreas Lintermann
Date
23.11.2017

Definition at line 5668 of file cartesiangridgenpar.cpp.

5668 {
5669 TRACE();
5670
5671 NEW_SUB_TIMER_STATIC(t_checkLBRefinementValidity, "check refinement valdity for LB", m_t_finalizeGrid);
5672 RECORD_TIMER_START(t_checkLBRefinementValidity);
5673
5674 outStream << " + checking mesh validity for LB" << endl;
5675 m_log << " + checking mesh validity for LB" << endl;
5676
5677 // run over all cells on the lowest tree level
5678 // find out if the parent has all children
5679 // if not, check if the parent's neighbor is a leaf cell
5680
5681 set<MInt> lberrcells;
5682
5683
5684 for(MInt i = 0; i < m_noCells; ++i) {
5685 // find leave cells
5686 if(a_noChildren(i) == 0) {
5687 MInt parent = (MInt)a_parentId(i);
5688
5689 // check if the parent has a missing child
5690 if(parent >= 0 && a_noChildren(parent) != m_maxNoChildren) {
5691 MIntScratchSpace nghbrList(27, AT_, "nghbrList");
5692 for(MInt l = 0; l < 27; l++)
5693 nghbrList[l] = -1;
5694
5695 const MInt counter = getAdjacentGridCells(parent, nghbrList.begin());
5696 for(MInt n = 0; n < counter; n++) {
5697 if(nghbrList[n] > -1 && a_noChildren(nghbrList[n]) == 0 && !a_hasProperty(nghbrList[n], 5)) {
5698 lberrcells.insert(parent);
5699 break;
5700 }
5701 }
5702 }
5703 }
5704 }
5705
5706
5707 MInt errorcells = 0;
5708 MInt l_lberrcells = (MInt)lberrcells.size();
5709
5710 MPI_Allreduce(&l_lberrcells, &errorcells, 1, MPI_INT, MPI_SUM, mpiComm(), AT_, "l_lberrcells", "errorcells");
5711
5712 if(errorcells > 0) {
5713 outStream << " * \033[1;31mthere are " << errorcells << " errorneous cells\033[0m" << endl;
5714 outStream
5715 << " - \033[1;31mEXPLANATION: there are cells that will be interface cells in the LB computation and "
5716 "which have missing children\033[0m"
5717 << endl;
5718 outStream << " - \033[1;31mHINTS : try to refine in- and outlets\033[0m" << endl;
5719 outStream
5720 << " \033[1;31mmake sure you chose a good combination of localMinBoundaryThreshold and "
5721 "smoothDistance\033[0m"
5722 << endl;
5723 m_log << " * there are " << errorcells << " errorneous cells" << endl;
5724 m_log << " - EXPLANATION: there are cells that will be interface cells in the LB computation and which "
5725 "have missing children"
5726 << endl;
5727 m_log << " - HINTS : try to refine in- and outlets" << endl;
5728 m_log << " make sure you chose a good combination of localMinBoundaryThreshold and "
5729 "smoothDistance"
5730 << endl;
5731 } else {
5732 outStream << " * mesh is \033[1;32mOK\033[0m" << endl;
5733 m_log << " * mesh is OK" << endl;
5734 }
5735
5736
5737 RECORD_TIMER_STOP(t_checkLBRefinementValidity);
5738}
MInt getAdjacentGridCells(MInt cellId, MInt *adjacentCells)
Retrieves all direct and diagonal neighboring cells of the given cell.
MLong & a_parentId(const MInt cellId)
Returns the parent of the cell cellId.
MInt & a_noChildren(const MInt cellId)
Returns the no. of children of the cell cellId.
MChar & a_hasProperty(const MInt cellId, const MInt p)
Returns property p of the cell cellId.
This class is a ScratchSpace.
Definition: scratch.h:758
int32_t MInt
Definition: maiatypes.h:62
int MPI_Allreduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allreduce

◆ checkLoadBalance()

template<MInt nDim>
void GridgenPar< nDim >::checkLoadBalance ( MInt  in_level)
protected
Author
Jerry Grimmen
Date
02.04.2014

This funtions checks the current state of the grid generation.

  1. Get the overall number of cells in the whole grid.
  2. Calculate the average number of cells and allow a small overhead.
  3. Checks if any domain has more than the average.
  4. If it's the case, do a load balance.

Definition at line 7301 of file cartesiangridgenpar.cpp.

7301 {
7302 TRACE();
7303
7304 // 0. Debug: Use to skip spezified levels.
7305 if(in_level == 42) {
7306 return;
7307 }
7308
7309 // 1. Getting the global number of cells in the grid.
7310 MLong globalNoCells = 0;
7311 MLong localNoCells = (MLong)m_noCells;
7312 MPI_Allreduce(&localNoCells, &globalNoCells, 1, MPI_LONG, MPI_SUM, mpiComm(), AT_, "localNoCells", "globalNoCells");
7313
7314 // 2. Calculate the average number of cells each domain should have and adds a small amount to it.
7315 MLong averageNoCells = globalNoCells / ((MLong)noDomains());
7316 // averageNoCells *= 1.5; // Should be fine tuned!
7317 averageNoCells += (averageNoCells / 2); // Should be fine tuned!
7318
7319 // 3. Looks if any domain has more cells than the average.
7320 MInt needsLoadBalancing = 0;
7321 if(m_noCells > averageNoCells) {
7322 needsLoadBalancing = 1;
7323 }
7324 MPI_Allreduce(MPI_IN_PLACE, &needsLoadBalancing, 1, MPI_INT, MPI_SUM, mpiComm(), AT_, "MPI_IN_PLACE",
7325 "needsLoadBalancing");
7326
7327 // 4. If any domain has more cells than to the load balancing.
7328 if(needsLoadBalancing > 0) {
7329 m_log << "Imbalance found, starting load balancing." << endl;
7331 m_hasBeenLoadBalanced = true;
7332
7333// Debug: Neighborhood complete check activated only in extra debug mode.
7334#ifdef MAIA_EXTRA_DEBUG
7335 for(MInt l = m_minLevel; l < in_level + 1; ++l) {
7336 m_log << "Checking Neighborhood for level " << l << endl;
7337 outStream << "Checking Neighborhood for level " << l << endl;
7341 }
7342#endif
7343
7344 m_log << "****************************************" << endl;
7345 m_log << "* *" << endl;
7346 m_log << "* Finished, the load balancing is *" << endl;
7347 m_log << "* Grid generation, with, we continue *" << endl;
7348 m_log << "* *" << endl;
7349 m_log << "* May the force be with you *" << endl;
7350 m_log << "* *" << endl;
7351 m_log << "****************************************" << endl;
7352
7353 // m_log << "Load balancing finished, continuing with grid generation." << endl;
7354
7355 } else {
7356 m_log << "No imbalance in load was found, continuing with grid generation." << endl;
7357 }
7358
7359 return;
7360}
void checkNeighborhood(MInt level_)
checks if the neighborhood is correct
void checkNeighborhoodDistance(MInt level_)
checks if the distance between neighboring cells is alright
void checkNeighborhoodIntegrity(MInt level_)
checks if the neighborhood relation of the cells is alright
void dynamicLoadBalancing()
Rebalances the grid dynamicaly while grid building.
MBool m_hasBeenLoadBalanced
int64_t MLong
Definition: maiatypes.h:64

◆ checkMemoryAvailability()

template<MInt nDim>
void GridgenPar< nDim >::checkMemoryAvailability ( MInt  stage,
MInt  level_ 
)
protected
Author
Date
16.03.2018
Parameters
[in]celloffsets to run on (maybe not needed)
[in]levelto run the check on
[in]solverto run the check for

Definition at line 1528 of file cartesiangridgenpar.cpp.

1528 {
1529 TRACE();
1530
1531 switch(stage) {
1532 case 0:
1533 // the current level is at the beginning of the collector
1534 if((m_levelOffsets[level_ - 1][0] > m_levelOffsets[level_][0]
1535 && m_levelOffsets[level_][1] > m_levelOffsets[level_ - 1][0])
1536 || (m_levelOffsets[level_ - 1][0] < m_levelOffsets[level_][0]
1537 && m_levelOffsets[level_][0] < m_levelOffsets[level_ - 1][1])) {
1538 stringstream errorMsg;
1539 errorMsg << "Not enough memory - normal cells overlap:\n"
1540 << " - cell offsets current level: " << m_levelOffsets[level_][0] << " " << m_levelOffsets[level_][1]
1541 << "\n"
1542 << " - cell offset last level: " << m_levelOffsets[level_ - 1][0] << " "
1543 << m_levelOffsets[level_ - 1][1] << "\n"
1544 << " - max. no of available cells: " << m_maxNoCells << endl;
1545 m_log << errorMsg.str();
1546 mTerm(1, AT_, errorMsg.str());
1547 }
1548
1549 break;
1550 case 1:
1551 if(noDomains() > 1) {
1552 if(m_levelOffsets[level_][1] > m_haloCellOffsetsLevel[level_][0]) {
1553 stringstream errorMsg;
1554 errorMsg << "Not enough memory - normal and halo cells overlap:\n"
1555 << " - upper normal cell offset: " << m_levelOffsets[level_][1] << "\n"
1556 << " - lower halo cell offset: " << m_haloCellOffsetsLevel[level_][0] << "\n"
1557 << " - max. no of available cells: " << m_maxNoCells << endl;
1558 m_log << errorMsg.str();
1559 mTerm(1, AT_, errorMsg.str());
1560 }
1561 } else {
1562 if(m_levelOffsets[level_][1] > m_maxNoCells - 1) {
1563 stringstream errorMsg;
1564 errorMsg << "Not enough memory:\n"
1565 << " - upper cell offset: " << m_levelOffsets[level_][1] << "\n"
1566 << " - max. no of available cells: " << m_maxNoCells << endl;
1567 m_log << errorMsg.str();
1568 mTerm(1, AT_, errorMsg.str());
1569 }
1570 }
1571
1572 break;
1573 default:
1574 break;
1575 }
1576}
MInt ** m_levelOffsets
MInt ** m_haloCellOffsetsLevel
void mTerm(const MInt errorCode, const MString &location, const MString &message)
Definition: functions.cpp:29

◆ checkNeighborhood()

template<MInt nDim>
void GridgenPar< nDim >::checkNeighborhood ( MInt  level_)
protected
Author
Andreas Lintermann
Date
15.10.2013

Finds minimal and maximal cells and walks in each direction and checks the neighborhood by comparing the coordinates

Parameters
[in]level_the level to apply this algorithm to

Definition at line 10535 of file cartesiangridgenpar.cpp.

10535 {
10536 TRACE();
10537
10538 outStream << " * performing consistency check" << endl;
10539
10540 std::array<MFloat, nDim> min;
10541 std::array<MFloat, nDim> max;
10542 for(MInt d = 0; d < nDim; d++) {
10545 }
10546
10547 // find minimum coordinates
10548 for(MInt i = m_levelOffsets[level_][0]; i < m_levelOffsets[level_][1]; i++) {
10549 MFloat* c = &a_coordinate(i, 0);
10550
10551 for(MInt d = 0; d < nDim; d++) {
10552 if(c[d] < min[d]) min[d] = c[d];
10553 if(c[d] > max[d]) max[d] = c[d];
10554 }
10555 }
10556
10557
10558 vector<vector<MInt>> min_cells;
10559 vector<vector<MInt>> max_cells;
10560 // find all cells
10561 for(MInt d = 0; d < nDim; d++) {
10562 vector<MInt> min_d;
10563 vector<MInt> max_d;
10564 for(MInt i = m_levelOffsets[level_][0]; i < m_levelOffsets[level_][1]; i++) {
10565 MFloat* c = &a_coordinate(i, 0);
10566
10567 if(approx(c[d], min[d], MFloatEps)) min_d.push_back(i);
10568
10569 if(approx(c[d], max[d], MFloatEps)) max_d.push_back(i);
10570 }
10571
10572 min_cells.push_back(min_d);
10573 max_cells.push_back(max_d);
10574 }
10575
10576 MFloat eps = 0.00001;
10577
10578 // do the check
10579 for(MInt d = 0; d < 1; d++) {
10580 outStream << d << endl;
10581 MInt n_dir = 2 * d + 1;
10582 for(MInt i = 0; i < (MInt)min_cells[d].size(); i++) {
10583 MInt start_id = min_cells[d][i];
10584
10585 MFloat* last_c = &a_coordinate(start_id, 0);
10586
10587 outStream << start_id << ": " << last_c[0] << " " << last_c[1] << " " << last_c[2] << endl;
10588
10589 if(a_neighborId(start_id, n_dir) >= 0) {
10590 MInt next_id = a_neighborId(start_id, n_dir);
10591 MFloat* next_c = &a_coordinate(next_id, 0);
10592
10593 while(next_id != start_id) {
10594 if(a_neighborId(next_id, n_dir) >= 0) {
10595 outStream << next_id << ": " << next_c[0] << " " << next_c[1] << " " << next_c[2] << endl;
10596 outStream << a_hasProperty(next_id, 1) << " ";
10597 // test
10598 MInt od1 = (d + 1) % nDim;
10599 MInt od2 = (d + 2) % nDim;
10600
10601 if(!(fabs(last_c[od1] - next_c[od1]) < eps) || !(fabs(last_c[od2] - next_c[od2]) < eps))
10602 outStream << "ERROR1 " << endl;
10603
10604 if(!((fabs(last_c[d] - next_c[d]) - m_lengthOnLevel[level_]) < eps))
10605 outStream << "ERROR2 " << fabs(last_c[d] - next_c[d] - m_lengthOnLevel[level_]) << " "
10606 << m_lengthOnLevel[level_] << endl;
10607
10608 last_c = &a_coordinate(next_id, 0);
10609 next_id = a_neighborId(next_id, n_dir);
10610 next_c = &a_coordinate(next_id, 0);
10611 } else {
10612 break;
10613 }
10614 }
10615 outStream << endl;
10616 }
10617 outStream << endl;
10618 }
10619 }
10620
10621
10622 // do the check
10623 for(MInt d = 0; d < nDim; d++) {
10624 // cout << d << endl;
10625 MInt n_dir = 2 * d;
10626 for(MInt i = 0; i < (MInt)max_cells[d].size(); i++) {
10627 MInt start_id = max_cells[d][i];
10628
10629 MFloat* last_c = &a_coordinate(start_id, 0);
10630
10631 // cout << start_id << ": " << last_c[0] << " " << last_c[1] << " " << last_c[2] << endl;
10632
10633 if(a_neighborId(start_id, n_dir) >= 0) {
10634 MInt next_id = a_neighborId(start_id, n_dir);
10635 MFloat* next_c = &a_coordinate(next_id, 0);
10636
10637 while(next_id != start_id) {
10638 if(a_neighborId(next_id, n_dir) >= 0) {
10639 // cout << next_id << ": " << next_c[0] << " " << next_c[1] << " " << next_c[2] << endl;
10640 // test
10641 MInt od1 = (d + 1) % nDim;
10642 MInt od2 = (d + 2) % nDim;
10643
10644 if(!(fabs(last_c[od1] - next_c[od1]) < eps) || !(fabs(last_c[od2] - next_c[od2]) < eps))
10645 outStream << "ERROR1 " << endl;
10646
10647 if(!((fabs(last_c[d] - next_c[d]) - m_lengthOnLevel[level_]) < eps))
10648 outStream << "ERROR2 " << fabs(last_c[d] - next_c[d] - m_lengthOnLevel[level_]) << " "
10649 << m_lengthOnLevel[level_] << endl;
10650
10651 last_c = &a_coordinate(next_id, 0);
10652 next_id = a_neighborId(next_id, n_dir);
10653 next_c = &a_coordinate(next_id, 0);
10654 } else {
10655 break;
10656 }
10657 }
10658 }
10659 // cout << endl;
10660 }
10661 }
10662}
MFloat * m_centerOfGravity
MFloat * m_geometryExtents
MFloat m_reductionFactor
MLong & a_neighborId(const MInt cellId, const MInt position)
Returns the neighbor id of the cell cellId position.
MBool approx(const T &, const U &, const T)
Definition: functions.h:272
double MFloat
Definition: maiatypes.h:52

◆ checkNeighborhoodDistance()

template<MInt nDim>
void GridgenPar< nDim >::checkNeighborhoodDistance ( MInt  level_)
protected
Author
Andreas Lintermann
Date
02.12.2013
Parameters
[in]level_the level to check

Definition at line 10673 of file cartesiangridgenpar.cpp.

10673 {
10674 TRACE();
10675
10676 for(MInt i = m_levelOffsets[level_][0]; i < m_levelOffsets[level_][1]; i++) {
10677 MLong* neigh = &a_neighborId(i, 0);
10678 for(MInt n = 0; n < m_noNeighbors; n++)
10679 if(neigh[n] >= 0) {
10680 MFloat dist = 0.0;
10681 for(MInt dim = 0; dim < nDim; dim++)
10682 dist += (a_coordinate(neigh[n], dim) - a_coordinate(i, dim))
10683 * (a_coordinate(neigh[n], dim) - a_coordinate(i, dim));
10684
10685 dist = sqrt(dist);
10686 if(!approx(dist, m_lengthOnLevel[level_], MFloatEps)) outStream << dist << endl;
10687 }
10688 }
10689
10690 for(MInt i = m_haloCellOffsetsLevel[level_][0]; i < m_haloCellOffsetsLevel[level_][1]; i++) {
10691 MLong* neigh = &a_neighborId(i, 0);
10692 for(MInt n = 0; n < m_noNeighbors; n++)
10693 if(neigh[n] >= 0) {
10694 MFloat dist = 0.0;
10695 for(MInt dim = 0; dim < nDim; dim++)
10696 dist += (a_coordinate(neigh[n], dim) - a_coordinate(i, dim))
10697 * (a_coordinate(neigh[n], dim) - a_coordinate(i, dim));
10698
10699 dist = sqrt(dist);
10700 if(!approx(dist, m_lengthOnLevel[level_], MFloatEps)) {
10701 outStream << i << " " << n << " " << neigh[n] << " " << dist << " " << m_lengthOnLevel[level_]
10702 << a_coordinate(i, 0) << " " << a_coordinate(i, 1) << " " << a_coordinate(i, 2) << " "
10703 << a_coordinate(neigh[n], 0) << " " << a_coordinate(neigh[n], 1) << " " << a_coordinate(neigh[n], 2)
10704 << " " << a_level(i) << " " << a_level(neigh[n]) << endl;
10705 }
10706 }
10707 }
10708}
MFloat dist(const Point< DIM > &p, const Point< DIM > &q)
Definition: pointbox.h:54

◆ checkNeighborhoodIntegrity()

template<MInt nDim>
void GridgenPar< nDim >::checkNeighborhoodIntegrity ( MInt  level_)
protected
Author
Andreas Lintermann
Date
02.12.2013
Parameters
[in]level_the level to check

Definition at line 10719 of file cartesiangridgenpar.cpp.

10719 {
10720 TRACE();
10721
10722 outStream << "Checking neighborhood integrity for level: " << level_ << endl;
10723 outStream << "Normal:" << endl;
10724 for(MInt i = m_levelOffsets[level_][0]; i < m_levelOffsets[level_][1]; i++) {
10725 MLong* neigh = &a_neighborId(i, 0);
10726 for(MInt n = 0; n < m_noNeighbors; n++)
10727 if(neigh[n] >= 0)
10728 if(a_neighborId(neigh[n], oppositeDirGrid[n]) != i)
10729 // cout << "ERROR: " << i << " is not a neighbor of " << neigh[n] << " " << n << " " << oppositeDirGrid[n]
10730 outStream << "ERROR: " << i << " is not a neighbor of " << neigh[n] << " " << n << " " << oppositeDirGrid[n]
10731 << endl;
10732 }
10733
10734 // cout << "Halos" << endl;
10735 outStream << "Halos" << endl;
10736 for(MInt i = m_haloCellOffsetsLevel[level_][0]; i < m_haloCellOffsetsLevel[level_][1]; i++) {
10737 MLong* neigh = &a_neighborId(i, 0);
10738 for(MInt n = 0; n < m_noNeighbors; n++)
10739 if(neigh[n] >= 0)
10740 if(a_neighborId(neigh[n], oppositeDirGrid[n]) != i)
10741 // cout << "ERROR: " << i << " is not a neighbor of " << neigh[n] << " " << n << " " << oppositeDirGrid[n]
10742 outStream << "ERROR: " << i << " is not a neighbor of " << neigh[n] << " " << n << " " << oppositeDirGrid[n]
10743 << endl;
10744 }
10745}

◆ collectHaloChildren()

template<MInt nDim>
void GridgenPar< nDim >::collectHaloChildren ( MInt  parentId_,
std::vector< MInt > *  cellIdsPerDomain 
)
protected
Author
Andreas Lintermann
Date
20.10.2013

This function calls itself as long as children are avalailable. It traverses the tree starting at given halo node and collects the halos in pre-order depth-first manner in a vector which is passed down as a pointer.

Parameters
[in]parentIdthe id of the current parrent to traverse
[in]cellIdsPerDomainthe collection of the halo cells passed so far

Definition at line 4890 of file cartesiangridgenpar.cpp.

4890 {
4891 TRACE();
4892
4893 for(MInt c = 0; c < m_maxNoChildren; c++) {
4894 if(a_childId(parentId_, c) >= 0 && a_hasProperty((MInt)a_childId(parentId_, c), 4)) {
4895 cellIdsPerDomain->push_back((MInt)a_childId(parentId_, c));
4896 collectHaloChildren((MInt)a_childId(parentId_, c), cellIdsPerDomain);
4897 }
4898 }
4899}
MLong & a_childId(const MInt cellId, const MInt position)
Returns the child id of the cell cellId position.
void collectHaloChildren(MInt parentId, std::vector< MInt > *cellIdsPerDomain)
recursively traverse the tree depth-first and collect halo cells

◆ collectWindowChildren()

template<MInt nDim>
void GridgenPar< nDim >::collectWindowChildren ( MInt  parentId_,
std::vector< MInt > *  cellIdsPerDomain 
)
protected
Author
Andreas Lintermann
Date
23.10.2013

This function calls itself as long as children are avalailable. It traverses the tree starting at given window node and collects the windows in pre-order depth-first manner in a vector which is passed down as a pointer.

Parameters
[in]parentIdthe id of the current parrent to traverse
[in]cellIdsPerDomainthe collection of the window cells passed so far

Definition at line 4915 of file cartesiangridgenpar.cpp.

4915 {
4916 TRACE();
4917
4918 for(MInt c = 0; c < m_maxNoChildren; c++) {
4919 if(a_childId(parentId_, c) >= 0 && a_hasProperty((MInt)a_childId(parentId_, c), 3)) {
4920 cellIdsPerDomain->push_back((MInt)a_childId(parentId_, c));
4921 collectWindowChildren((MInt)a_childId(parentId_, c), cellIdsPerDomain);
4922 }
4923 }
4924}
void collectWindowChildren(MInt parentId, std::vector< MInt > *cellIdsPerDomain)
recursively traverse the tree depth-first and collect window cells

◆ communicateDouble()

template<MInt nDim>
void GridgenPar< nDim >::communicateDouble ( MFloatScratchSpace recvBuffer,
MIntScratchSpace noCellsToReceive,
MFloatScratchSpace sendBuffer,
MIntScratchSpace noCellsToSend 
)
protected
Author
Jerry Grimmen
Date
10.02.2014

The function sends the parts of sendBuffer to the other domains.

  1. Calculate the offsets using the noCellsToSend/Receive arrays.
  2. Loop over all domains. 2.1. If the domain is lower or greater than mine and I need to receive cells, open a MPI_Receive. 2.2. If the domain is my domain, loop over all domains. 2.2.1. If I need to send something to the other domain, open a MPI_Send.

Even through it looks like a complete blocking communication, it is used mostly during the load balancing. At this stage, each domain only communicate with the it's directly neighboring domains. So that most blocking communication takes places in parallel. I.e. while domain 3 is receiving from 4 and 5 and sending to 1 and 2, domain 1223 is receiving from 1224 and 1225 and sending to 1221 and 1222.

Definition at line 9433 of file cartesiangridgenpar.cpp.

9434 {
9435 MPI_Status statusRecv;
9436
9437 MIntScratchSpace sendOffset(noDomains(), AT_, "sendOffset");
9438 MIntScratchSpace recvOffset(noDomains(), AT_, "recvOffset");
9439 sendOffset.fill(0);
9440 recvOffset.fill(0);
9441
9442 for(MInt i = 1; i < noDomains(); ++i) {
9443 sendOffset[i] = sendOffset[i - 1] + noCellsToSend[i - 1];
9444 recvOffset[i] = recvOffset[i - 1] + noCellsToReceive[i - 1];
9445 }
9446
9447 for(MInt dom = 0; dom < noDomains(); ++dom) {
9448 if((dom < globalDomainId()) || (dom > globalDomainId())) {
9449 if(noCellsToReceive[dom] == 0) {
9450 continue;
9451 }
9452
9453 MFloatScratchSpace recvData(noCellsToReceive[dom], AT_, "recvData");
9454 recvData.fill(-2.0);
9455 MPI_Recv(recvData.getPointer(), noCellsToReceive[dom], MPI_DOUBLE, dom, dom, mpiComm(), &statusRecv, AT_,
9456 "recvData.getPointer()");
9457 for(MInt i = 0; i < noCellsToReceive[dom]; ++i) {
9458 recvBuffer[i + recvOffset[dom]] = recvData[i];
9459 }
9460 } // end of : if ( (dom < globalDomainId()) || (dom > globalDomainId()) )
9461
9462 if(dom == globalDomainId()) {
9463 for(MInt toDom = 0; toDom < noDomains(); ++toDom) {
9464 if((noCellsToSend[toDom] == 0) || (globalDomainId() == toDom)) {
9465 continue;
9466 }
9467
9468 MFloatScratchSpace sendData(noCellsToSend[toDom], AT_, "sendData");
9469 sendData.fill(-2.0);
9470 for(MInt i = 0; i < noCellsToSend[toDom]; ++i) {
9471 sendData[i] = sendBuffer[i + sendOffset[toDom]];
9472 }
9473
9474 MPI_Send(sendData.getPointer(), noCellsToSend[toDom], MPI_DOUBLE, toDom, globalDomainId(), mpiComm(), AT_,
9475 "sendData.getPointer()");
9476 } // end of : for (MInt toDom = 0; toDom < noDomains(); ++toDom)
9477 } // end of : if (dom == globalDomainId())
9478
9479 } // end of : for (MInt dom = 0; dom < noDomains(); ++dom)
9480
9481} // end of : void GridgenPar::communicateDouble(MFloatScratchSpace & recvBuffer, MIntScratchSpace &
int MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status, const MString &name, const MString &varname)
same as MPI_Recv
int MPI_Send(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, const MString &name, const MString &varname)
same as MPI_Send

◆ communicateHaloGlobalIds()

template<MInt nDim>
void GridgenPar< nDim >::communicateHaloGlobalIds ( MInt  level)
protected
Author
Jerry Grimmen
Date
26.02.2014

The function communicates the new global ids of the halo cells.

  1. If we are already finished with building the grid, then call reorderGlobalIdsDF
  2. Collect all local halo cell ids into a vector
  3. Get the new global ids of the halo cell. In this part, we send the coordinates of our halo cells to the other domain. The neighbor looks through it's window cell for the right one and sends back the new global id.
  4. Changes the local ids to global ids of internal cells.

The coordinate check is currently the only way i found out to get the right new global id. Sending the level of the halo cell would reduce the amoung of cells to look through, but it will also add another communication.

Definition at line 8876 of file cartesiangridgenpar.cpp.

8876 {
8877 TRACE();
8878
8879 // 1. If we are at the end of the grid creation use reoderGlobalIdsDF
8880 if(level > -1) {
8881 // 1.1. Get the number of cells created on the other domains.
8882 MInt* sndBuf = &m_noCells;
8883 MPI_Allgather(sndBuf, 1, MPI_INT, m_noCellsPerDomain, 1, MPI_INT, mpiComm(), AT_, "sndBuf", "m_noCellsPerDomain");
8884
8885 // 1.2. Determine my own offset.
8886 for(MInt d = 0; d < globalDomainId(); d++)
8888
8889 // 1.3. Reorder the global ids to be sorted depth-first.
8891 }
8892
8893 // 2. Collect all halo cells local ids.
8894 vector<vector<MLong>> winCellIdsPerDomain;
8895 vector<vector<MLong>> haloCellIdsPerDomain;
8896
8897 // 2.1. Create vectors to hold the halo cells local id.
8898 for(MInt dom = 0; dom < m_noNeighborDomains; dom++) {
8899 vector<MLong> w;
8900 winCellIdsPerDomain.push_back(w);
8901
8902 vector<MLong> h;
8903 haloCellIdsPerDomain.push_back(h);
8904
8905 for(MInt i = 0; i < m_noCells; ++i) {
8906 a_hasProperty(i, 3) = 0;
8907 a_hasProperty(i, 4) = 0;
8908 }
8909
8910 // 2.2. Collect the halo cells local ids
8911 for(MInt lev = m_minLevel; lev <= m_maxRfnmntLvl; lev++) {
8912 MInt lev_pos = 2 * (lev - m_minLevel);
8913 for(MInt p = m_haloCellOffsets[dom][lev_pos]; p < m_haloCellOffsets[dom][lev_pos + 1]; p++) {
8914 haloCellIdsPerDomain[dom].push_back(m_cellIdLUT[p]);
8915 }
8916 }
8917 }
8918
8919 // 3. Get the halo cells global ids.
8920 { // extra '{ }' span for communication of the globalId of the halo cells.
8921
8922 // 3.1. Scatter to other domains the number of halo cells we have.
8923 MIntScratchSpace noDataToSend(noDomains() + 1, AT_, "noDataToSend");
8924 MIntScratchSpace noDataToReceive(noDomains() + 1, AT_, "noDataToReceive");
8925 noDataToSend.fill(0);
8926 noDataToReceive.fill(0);
8927
8928 for(MInt i = 0; i < m_noNeighborDomains; ++i) {
8929 noDataToReceive[m_neighborDomains[i]] = (MInt)haloCellIdsPerDomain[i].size();
8930 noDataToReceive[noDomains()] += (MInt)haloCellIdsPerDomain[i].size();
8931 }
8932
8933 for(MInt d = 0; d < noDomains(); ++d) {
8934 MPI_Scatter(noDataToReceive.getPointer(), 1, MPI_INT, &noDataToSend[d], 1, MPI_INT, d, mpiComm(), AT_,
8935 "noDataToReceive.getPointer()", "noDataToSend[d]");
8936 }
8937
8938 for(MInt i = 0; i < noDomains(); ++i) {
8939 noDataToSend[noDomains()] += noDataToSend[i];
8940 }
8941
8942 // 3.2. Prepare an array to hold all halo cells coordinates and level we will receive.
8943 MFloatScratchSpace haloCoordinates(noDataToSend[noDomains()], nDim, AT_, "haloCoordinates");
8944 MIntScratchSpace haloLevel(noDataToSend[noDomains()], AT_, "haloLevel");
8945
8946 { // extra '{}' for sending / receiving halo cells coordinates.
8947 for(MInt dim = 0; dim < nDim; ++dim) {
8948 MFloatScratchSpace sendBuffer(noDataToSend[noDomains()], AT_, "sendBuffer");
8949 MFloatScratchSpace recvBuffer(noDataToReceive[noDomains()], AT_, "recvBuffer");
8950
8951 MInt offset = 0;
8952 for(MInt dom = 0; dom < m_noNeighborDomains; ++dom) {
8953 for(MInt i = 0; i < noDataToReceive[m_neighborDomains[dom]]; ++i) {
8954 recvBuffer(i + offset) = a_coordinate((MInt)haloCellIdsPerDomain[dom][i], dim);
8955 }
8956 offset += noDataToReceive[m_neighborDomains[dom]];
8957 }
8958
8959 communicateDouble(sendBuffer, noDataToSend, recvBuffer, noDataToReceive);
8960
8961 offset = 0;
8962 for(MInt dom = 0; dom < m_noNeighborDomains; ++dom) {
8963 for(MInt i = 0; i < noDataToSend[m_neighborDomains[dom]]; ++i) {
8964 haloCoordinates(i + offset, dim) = sendBuffer(i + offset);
8965 }
8966 offset += noDataToSend[m_neighborDomains[dom]];
8967 }
8968 }
8969 } // end of : extra '{}' for sending / receiving halo cells coordinates.
8970
8971 { // extra '{}' for sending / receiving halo cells level.
8972 MIntScratchSpace sendBuffer(noDataToSend[noDomains()], AT_, "sendBuffer");
8973 MIntScratchSpace recvBuffer(noDataToReceive[noDomains()], AT_, "recvBuffer");
8974
8975 MInt offset = 0;
8976 for(MInt dom = 0; dom < m_noNeighborDomains; ++dom) {
8977 for(MInt i = 0; i < noDataToReceive[m_neighborDomains[dom]]; ++i) {
8978 recvBuffer(i + offset) = a_level((MInt)haloCellIdsPerDomain[dom][i]);
8979 }
8980 offset += noDataToReceive[m_neighborDomains[dom]];
8981 }
8982
8983 communicateInt(sendBuffer, noDataToSend, recvBuffer, noDataToReceive);
8984
8985 offset = 0;
8986 for(MInt dom = 0; dom < m_noNeighborDomains; ++dom) {
8987 for(MInt i = 0; i < noDataToSend[m_neighborDomains[dom]]; ++i) {
8988 haloLevel(i + offset) = sendBuffer(i + offset);
8989 }
8990 offset += noDataToSend[m_neighborDomains[dom]];
8991 }
8992 } // end of : extra '{}' for sending / receiving halo cells level.
8993
8994 // 3.3. Get the correct window cell using coordinate check and add it to the vector.
8995
8996 vector<Point<3>> pts;
8997 for(MInt cellId = 0; cellId < m_noCells; ++cellId) {
8998 IF_CONSTEXPR(nDim == 2) {
8999 Point<3> pt(a_coordinate(cellId, 0), a_coordinate(cellId, 1), 0.0, cellId);
9000 pts.push_back(pt);
9001 }
9002 else {
9003 Point<3> pt(a_coordinate(cellId, 0), a_coordinate(cellId, 1), a_coordinate(cellId, 2), cellId);
9004 pts.push_back(pt);
9005 }
9006 }
9007
9008 KDtree<3> tree(pts);
9009
9010 MInt offset = 0;
9011 for(MInt dom = 0; dom < m_noNeighborDomains; ++dom) {
9012 for(MInt i = 0; i < noDataToSend[m_neighborDomains[dom]]; ++i) {
9013 MInt cellId = -2;
9014 MFloat distance = -2.0;
9015 IF_CONSTEXPR(nDim == 2) {
9016 Point<3> pt(haloCoordinates(i + offset, 0), haloCoordinates(i + offset, 1), 0.0, cellId);
9017 cellId = tree.nearest(pt, distance);
9018 }
9019 else {
9020 Point<3> pt(haloCoordinates(i + offset, 0), haloCoordinates(i + offset, 1), haloCoordinates(i + offset, 2),
9021 cellId);
9022 cellId = tree.nearest(pt, distance);
9023 }
9024
9025 winCellIdsPerDomain[dom].push_back(a_globalId(cellId));
9026
9027 } // end of : for (MInt i = 0; i < noDataToSend[m_neighborDomains[dom]]; ++i)
9028 offset += noDataToSend[m_neighborDomains[dom]];
9029 } // end of : for (MInt dom = 0; dom < m_noNeighborDomains; ++dom)
9030
9031 // 3.4. Send and receive the halo cells global ids.
9032 { // extra '{}' span for sending / receiving halo cells global ids.
9033 MLongScratchSpace sendBuffer(noDataToSend[noDomains()], AT_, "sendBuffer");
9034 MLongScratchSpace recvBuffer(noDataToReceive[noDomains()], AT_, "recvBuffer");
9035 sendBuffer.fill(-2);
9036 recvBuffer.fill(-2);
9037
9038 offset = 0;
9039 for(MInt dom = 0; dom < m_noNeighborDomains; ++dom) {
9040 for(MInt i = 0; i < (signed)winCellIdsPerDomain[dom].size(); ++i) {
9041 sendBuffer(i + offset) = winCellIdsPerDomain[dom][i];
9042 }
9043 offset += (MInt)winCellIdsPerDomain[dom].size();
9044 }
9045
9046 communicateLong(recvBuffer, noDataToReceive, sendBuffer, noDataToSend);
9047
9048 offset = 0;
9049 for(MInt dom = 0; dom < m_noNeighborDomains; ++dom) {
9050 for(MInt i = 0; i < (signed)haloCellIdsPerDomain[dom].size(); ++i) {
9051 a_globalId((MInt)haloCellIdsPerDomain[dom][i]) = recvBuffer(i + offset);
9052 }
9053 offset += (signed)haloCellIdsPerDomain[dom].size();
9054 }
9055
9056 } // end of : extra '{}' span for sending / receiving halo cells global ids.
9057
9058 } // end of : extra '{ }' span for communication of the globalId of the halo cells.
9059
9060 // 4. For all internal cells, change all local ids to global ids.
9061 for(MInt cellId = 0; cellId < m_noCells; ++cellId) {
9062 if(a_parentId(cellId) > -1) {
9063 a_parentId(cellId) = a_globalId((MInt)a_parentId(cellId));
9064 }
9065
9066 for(MInt i = 0; i < m_maxNoChildren; ++i) {
9067 if(a_childId(cellId, i) > -1) {
9068 a_childId(cellId, i) = a_globalId((MInt)a_childId(cellId, i));
9069 }
9070 }
9071
9072 for(MInt i = 0; i < m_noNeighbors; ++i) {
9073 if(a_neighborId(cellId, i) > -1) {
9074 a_neighborId(cellId, i) = a_globalId((MInt)a_neighborId(cellId, i));
9075 }
9076 }
9077 } // end of : for (MInt cellId = 0; cellId < m_noCells; ++cellId)
9078}
void communicateDouble(MFloatScratchSpace &recvBuffer, MIntScratchSpace &noCellsToReceive, MFloatScratchSpace &sendBuffer, MIntScratchSpace &noCellsToSend)
Communicates an array of double values.
void communicateInt(MIntScratchSpace &recvBuffer, MIntScratchSpace &noCellsToReceive, MIntScratchSpace &sendBuffer, MIntScratchSpace &noCellsToSend)
Communicates an array of int values.
void communicateLong(MLongScratchSpace &recvBuffer, MIntScratchSpace &noCellsToReceive, MLongScratchSpace &sendBuffer, MIntScratchSpace &noCellsToSend)
Communicates an array of int values.
MInt ** m_haloCellOffsets
MLong & a_globalId(const MInt cellId)
Returns the globalId of the cell cellId.
MInt * m_neighborDomains
MInt * m_noCellsPerDomain
void reorderGlobalIdsDF()
reorders the globalIds depth-first
std::map< MInt, MInt > m_cellIdLUT
int MPI_Scatter(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Scatter
int MPI_Allgather(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allgather
MFloat distance(const MFloat *a, const MFloat *b)
Definition: maiamath.h:249
Definition: kdtree.h:73
Definition: pointbox.h:20

◆ communicateInt()

template<MInt nDim>
void GridgenPar< nDim >::communicateInt ( MIntScratchSpace recvBuffer,
MIntScratchSpace noCellsToReceive,
MIntScratchSpace sendBuffer,
MIntScratchSpace noCellsToSend 
)
protected
Author
Jerry Grimmen
Date
10.02.2014

The function sends the parts of sendBuffer to the other domains.

  1. Calculate the offsets using the noCellsToSend/Receive arrays.
  2. Loop over all domains. 2.1. If the domain is lower or greater than mine and I need to receive cells, open a MPI_Receive. 2.2. If the domain is my domain, loop over all domains. 2.2.1. If I need to send something to the other domain, open a MPI_Send.

Even through it looks like a complete blocking communication, it is used mostly during the load balancing. At this stage, each domain only communicate with the it's directly neighboring domains. So that most blocking communication takes places in parallel. I.e. while domain 3 is receiving from 4 and 5 and sending to 1 and 2, domain 1223 is receiving from 1224 and 1225 and sending to 1221 and 1222.

Definition at line 9288 of file cartesiangridgenpar.cpp.

9289 {
9290 MPI_Status statusRecv;
9291
9292 MIntScratchSpace sendOffset(noDomains(), AT_, "sendOffset");
9293 MIntScratchSpace recvOffset(noDomains(), AT_, "recvOffset");
9294 sendOffset.fill(0);
9295 recvOffset.fill(0);
9296
9297 for(MInt i = 1; i < noDomains(); ++i) {
9298 sendOffset[i] = sendOffset[i - 1] + noCellsToSend[i - 1];
9299 recvOffset[i] = recvOffset[i - 1] + noCellsToReceive[i - 1];
9300 }
9301
9302 for(MInt dom = 0; dom < noDomains(); ++dom) {
9303 if((dom < globalDomainId()) || (dom > globalDomainId())) {
9304 if(noCellsToReceive[dom] == 0) {
9305 continue;
9306 }
9307
9308 MIntScratchSpace recvData(noCellsToReceive[dom], AT_, "recvData");
9309 recvData.fill(-2);
9310 MPI_Recv(recvData.getPointer(), noCellsToReceive[dom], MPI_INT, dom, dom, mpiComm(), &statusRecv, AT_,
9311 "recvData.getPointer()");
9312 for(MInt i = 0; i < noCellsToReceive[dom]; ++i) {
9313 recvBuffer[i + recvOffset[dom]] = recvData[i];
9314 }
9315 } // end of : if ( (dom < globalDomainId()) || (dom > globalDomainId()) )
9316
9317 if(dom == globalDomainId()) {
9318 for(MInt toDom = 0; toDom < noDomains(); ++toDom) {
9319 if((noCellsToSend[toDom] == 0) || (globalDomainId() == toDom)) {
9320 continue;
9321 }
9322
9323 MIntScratchSpace sendData(noCellsToSend[toDom], AT_, "sendData");
9324 sendData.fill(-2);
9325 for(MInt i = 0; i < noCellsToSend[toDom]; ++i) {
9326 sendData[i] = sendBuffer[i + sendOffset[toDom]];
9327 }
9328
9329 MPI_Send(sendData.getPointer(), noCellsToSend[toDom], MPI_INT, toDom, globalDomainId(), mpiComm(), AT_,
9330 "sendData.getPointer()");
9331 } // end of : for (MInt toDom = 0; toDom < noDomains(); ++toDom)
9332 } // end of : if (dom == globalDomainId())
9333
9334 } // end of : for (MInt dom = 0; dom < noDomains(); ++dom)
9335
9336} // end of : void GridgenPar::communicateInt(MIntScratchSpace & recvBuffer, MIntScratchSpace & noCellsToReceive,

◆ communicateIntToNeighbors()

template<MInt nDim>
void GridgenPar< nDim >::communicateIntToNeighbors ( MIntScratchSpace recvMem,
MIntScratchSpace noCellsToReceive,
MIntScratchSpace sendMem,
MIntScratchSpace noCellsToSend,
MInt  noVar 
)
protected
Author
Thomas Schilden
Date
26.08.2015

a check whether a send-recv mismatch exist is not performed, mpi will tell you

Definition at line 9492 of file cartesiangridgenpar.cpp.

9494 {
9495 MIntScratchSpace sendOffset(m_noNeighborDomains, AT_, "sendOffset");
9496 MIntScratchSpace recvOffset(m_noNeighborDomains, AT_, "recvOffset");
9497 sendOffset.fill(0);
9498 recvOffset.fill(0);
9499
9500 for(MInt i = 1; i < m_noNeighborDomains; i++) {
9501 sendOffset[i] = sendOffset[i - 1] + noCellsToSend[i - 1];
9502 recvOffset[i] = recvOffset[i - 1] + noCellsToReceive[i - 1];
9503 }
9504
9505 MInt noRecv = 0;
9506 for(MInt i = 0; i < m_noNeighborDomains; i++)
9507 if(noCellsToReceive[i] > 0) noRecv++;
9508
9509 ScratchSpace<MPI_Request> request(noRecv, AT_, "request");
9510 ScratchSpace<MPI_Status> status(noRecv, AT_, "status");
9511
9512 for(MInt i = 0, rCnt = 0; i < m_noNeighborDomains; i++)
9513 if(noCellsToReceive[i] > 0) {
9514 MPI_Irecv(recvMem.getPointer() + noVar * recvOffset[i], noVar * noCellsToReceive[i], MPI_INT,
9515 m_neighborDomains[i], 0, MPI_COMM_WORLD, request.getPointer() + rCnt, AT_,
9516 "recvMem.getPointer() + noVar * recvOffset[i]");
9517 rCnt++;
9518 }
9519
9520 for(MInt i = 0; i < m_noNeighborDomains; i++)
9521 if(noCellsToSend[i] > 0) {
9522 MPI_Send(sendMem.getPointer() + noVar * sendOffset[i], noVar * noCellsToSend[i], MPI_INT, m_neighborDomains[i], 0,
9523 MPI_COMM_WORLD, AT_, "sendMem.getPointer() + noVar * sendOffset[i]");
9524 }
9525
9526 MPI_Waitall(noRecv, request.getPointer(), status.getPointer(), AT_);
9527}
T * getPointer() const
Deprecated: use begin() instead!
Definition: scratch.h:316
int MPI_Irecv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Request *request, const MString &name, const MString &varname)
same as MPI_Irecv
int MPI_Waitall(int count, MPI_Request *request, MPI_Status *status, const MString &name)
same as MPI_Waitall

◆ communicateLong()

template<MInt nDim>
void GridgenPar< nDim >::communicateLong ( MLongScratchSpace recvBuffer,
MIntScratchSpace noCellsToReceive,
MLongScratchSpace sendBuffer,
MIntScratchSpace noCellsToSend 
)
protected
Author
Jerry Grimmen
Date
10.02.2014

The function sends the parts of sendBuffer to the other domains.

  1. Calculate the offsets using the noCellsToSend/Receive arrays.
  2. Loop over all domains. 2.1. If the domain is lower or greater than mine and I need to receive cells, open a MPI_Receive. 2.2. If the domain is my domain, loop over all domains. 2.2.1. If I need to send something to the other domain, open a MPI_Send.

Even through it looks like a complete blocking communication, it is used mostly during the load balancing. At this stage, each domain only communicate with the it's directly neighboring domains. So that most blocking communication takes places in parallel. I.e. while domain 3 is receiving from 4 and 5 and sending to 1 and 2, domain 1223 is receiving from 1224 and 1225 and sending to 1221 and 1222.

Definition at line 9360 of file cartesiangridgenpar.cpp.

9361 {
9362 MPI_Status statusRecv;
9363
9364 MIntScratchSpace sendOffset(noDomains(), AT_, "sendOffset");
9365 MIntScratchSpace recvOffset(noDomains(), AT_, "recvOffset");
9366 sendOffset.fill(0);
9367 recvOffset.fill(0);
9368
9369 for(MInt i = 1; i < noDomains(); ++i) {
9370 sendOffset[i] = sendOffset[i - 1] + noCellsToSend[i - 1];
9371 recvOffset[i] = recvOffset[i - 1] + noCellsToReceive[i - 1];
9372 }
9373
9374 for(MInt dom = 0; dom < noDomains(); ++dom) {
9375 if((dom < globalDomainId()) || (dom > globalDomainId())) {
9376 if(noCellsToReceive[dom] == 0) {
9377 continue;
9378 }
9379
9380 MLongScratchSpace recvData(noCellsToReceive[dom], AT_, "recvData");
9381 recvData.fill(-2);
9382 MPI_Recv(recvData.getPointer(), noCellsToReceive[dom], MPI_LONG, dom, dom, mpiComm(), &statusRecv, AT_,
9383 "recvData.getPointer()");
9384 for(MInt i = 0; i < noCellsToReceive[dom]; ++i) {
9385 recvBuffer[i + recvOffset[dom]] = recvData[i];
9386 }
9387 } // end of : if ( (dom < globalDomainId()) || (dom > globalDomainId()) )
9388
9389 if(dom == globalDomainId()) {
9390 for(MInt toDom = 0; toDom < noDomains(); ++toDom) {
9391 if((noCellsToSend[toDom] == 0) || (globalDomainId() == toDom)) {
9392 continue;
9393 }
9394
9395 MLongScratchSpace sendData(noCellsToSend[toDom], AT_, "sendData");
9396 sendData.fill(-2);
9397 for(MInt i = 0; i < noCellsToSend[toDom]; ++i) {
9398 sendData[i] = sendBuffer[i + sendOffset[toDom]];
9399 }
9400
9401 MPI_Send(sendData.getPointer(), noCellsToSend[toDom], MPI_LONG, toDom, globalDomainId(), mpiComm(), AT_,
9402 "sendData.getPointer()");
9403 } // end of : for (MInt toDom = 0; toDom < noDomains(); ++toDom)
9404 } // end of : if (dom == globalDomainId())
9405
9406 } // end of : for (MInt dom = 0; dom < noDomains(); ++dom)
9407
9408} // end of : void GridgenPar::communicateInt(MIntScratchSpace & recvBuffer, MIntScratchSpace & noCellsToReceive,

◆ concludeSolverRefinement()

template<MInt nDim>
void GridgenPar< nDim >::concludeSolverRefinement ( MInt  level_)
protected

Definition at line 1777 of file cartesiangridgenpar.cpp.

1777 {
1778 TRACE();
1779
1780 // reset counts of refined cells
1781 m_rfnCount = 0;
1782 m_rfnCountHalos = 0;
1783 if(noDomains() > 1) {
1784 for(MInt dom = 0; dom < m_noNeighborDomains; dom++) {
1785 m_rfnCountHalosDom[dom] = 0;
1786 }
1787 }
1788
1789 // set internal cells that need to be refined
1790 for(MInt k = m_levelOffsets[gridLvl][0]; k < m_levelOffsets[gridLvl][1]; k++) {
1791 for(MInt solver = 0; solver < m_noSolvers; solver++) {
1792 if(a_isToRefineForSolver(k, solver) || a_noSolidLayer(k, solver) > 0) {
1793 m_rfnCount++;
1794 a_hasProperty(k, 5) = 1;
1795 break;
1796 }
1797 }
1798 }
1799
1800 // set halo cells that need to be refined
1801 if(noDomains() > 1) {
1802 MInt lev_pos = 2 * (gridLvl - m_minLevel);
1803 for(MInt dom = 0; dom < m_noNeighborDomains; dom++) {
1804 for(MInt k = m_haloCellOffsets[dom][lev_pos]; k < m_haloCellOffsets[dom][lev_pos + 1]; k++) {
1805 for(MInt solver = 0; solver < m_noSolvers; solver++) {
1806 if(a_isToRefineForSolver(k, solver)) {
1808 m_rfnCountHalosDom[dom]++;
1809 a_hasProperty(k, 5) = 1;
1810 break;
1811 }
1812 }
1813 }
1814 }
1815 }
1816}
MChar & a_isToRefineForSolver(const MInt cellId, const MInt solver)
Multisolver grid: does a cell belong to a certain solver.
MInt & a_noSolidLayer(const MInt cellId, const MInt solver)
Returns the solid layer of the cell cellId.
MInt * m_rfnCountHalosDom

◆ copyCell()

template<MInt nDim>
void GridgenPar< nDim >::copyCell ( MInt  from,
MInt  to 
)
protected
Author
Andreas Lintermann
Date
11.10.2013

Within this function all the information is copied to the new location.

Parameters
[in]fromthe id of the cell to be moved
[in]tothe id of the cell that should be overwritten

Definition at line 4054 of file cartesiangridgenpar.cpp.

4054 {
4055 TRACE();
4056
4057 // don't copy cells that have been marked moved (messes with neighbors)
4058 ASSERT(a_hasProperty(from, 7) != 1, "" << globalDomainId() << ": Invalid cell " << from << " copied!");
4059
4060 for(MInt i = 0; i < 8; i++) {
4061 a_hasProperty(to, i) = a_hasProperty(from, i);
4062 a_isInSolver(to, i) = a_isInSolver(from, i);
4063 a_isSolverBoundary(to, i) = a_isSolverBoundary(from, i);
4065 }
4066
4067 a_level(to) = a_level(from);
4068 a_noChildren(to) = a_noChildren(from);
4069 a_globalId(to) = a_globalId(from);
4070 a_parentId(to) = a_parentId(from);
4071 for(MInt s = 0; s < 8; s++) {
4072 a_noSolidLayer(to, s) = a_noSolidLayer(from, s);
4073 }
4074
4075 copy(&a_coordinate(from, 0), &a_coordinate(from, nDim), &a_coordinate(to, 0));
4076 copy(&a_neighborId(from, 0), &a_neighborId(from, m_noNeighbors), &a_neighborId(to, 0));
4077 copy(&a_childId(from, 0), &a_childId(from, m_maxNoChildren), &a_childId(to, 0));
4078
4079 // update the neighbors
4080 for(MInt i = 0; i < m_noNeighbors; i++)
4081 if(a_neighborId(to, i) >= 0) a_neighborId((MInt)a_neighborId(to, i), oppositeDirGrid[i]) = (MLong)to;
4082
4083 // update the parent
4084 if(a_parentId(to) >= 0)
4085 for(MInt c = 0; c < m_maxNoChildren; c++)
4086 if(a_childId((MInt)a_parentId(to), c) == (MLong)from) {
4087 a_childId((MInt)a_parentId(to), c) = (MLong)to;
4088 break;
4089 }
4090
4091 // update the children
4092 for(MInt c = 0; c < m_maxNoChildren; c++)
4093 if(a_childId(to, c) >= 0) a_parentId((MInt)a_childId(to, c)) = (MLong)to;
4094}
MChar & a_isInSolver(const MInt cellId, const MInt solver)
Multisolver grid: does a cell belong to a certain solver.
MChar & a_isSolverBoundary(const MInt cellId, const MInt solver)
Multisolver grid: does a cell belong to a certain solver.

◆ createComputationalMultisolverGrid()

template<MInt nDim>
void GridgenPar< nDim >::createComputationalMultisolverGrid
protected
Author
Thomas Schilden
Date
03.04.2018

First, the uniform grid up to the minimal maxUniformRefinementLevel of the solvers is created in createStartGrid. Second, the remaining levels are looped up and the local solver refinement methods are called. They mark cells as to be refined for a specific solver. In concludeSolver refinement, the solver refinement request is concluded to a single property no 5. Then, the offsets are updated and the grid is refined.

Definition at line 1732 of file cartesiangridgenpar.cpp.

1732 {
1733 TRACE();
1734
1735 // could be part of the loop below without any problems
1737
1738 RECORD_TIMER_START(m_t_createComputationalGrid);
1739
1740 m_log << " createComputationalMultisolverGrid" << endl;
1741
1742 // l is the level i want to refine
1744 // let all solvers mark the cells they want to refine
1745 for(MInt solver = 0; solver < m_noSolvers; solver++) {
1746 markLocalSolverRefinement(l, solver);
1747 }
1748
1749 // cells that are marked for refinement by at least one solver will be refined
1751
1752 // update the offsets
1753 updateOffsets(l);
1754
1755 if(noDomains() > 1) {
1757 }
1758
1759 // refine marked cells
1761 }
1762
1763 // deleting useless solid cells
1765 if(noDomains() > 1) {
1766 mTerm(1, AT_, "ERROR: keepOutsideBndryCellChildren in mode 3 is not implemented for parallel usage yet!!!");
1768 } else {
1770 }
1771 }
1772
1773 RECORD_TIMER_STOP(m_t_createComputationalGrid);
1774}
void updateOffsets(MInt gridLevel)
updates the offsets
MInt m_t_createComputationalGrid
void deleteCoarseSolidCellsSerial()
performs deleting solid cells lower than maxRefinementLevel
void refineComputationalGrid(MInt lvl)
refines cells of the computational grid that are marked for refinement
MInt m_maxUniformRefinementLevel
void updateHaloOffsets(MInt l, MInt noHalos, MInt *rfnCountHalosDom)
updates the offsets of the halos
MInt m_keepOutsideBndryCellChildren
void createStartGrid()
creates the start grid
void markLocalSolverRefinement(MInt level_, MInt solver)
void concludeSolverRefinement(MInt level_)
void deleteCoarseSolidCellsParallel()
performs deleting solid cells lower than maxRefinementLevel

◆ createInitialGrid()

template<MInt nDim>
void GridgenPar< nDim >::createInitialGrid
protected
Author
Andreas Lintermann
Date
11.10.2013

4.1 Creates an initial cube around the geometry. 4.2 Refines the initial cube to the initialGeometricalRfnLvl. In each iteration the following is performed: 4.2.1 update the level offsets: this gets rid of the delettion of lower levels by using the following structure. Based on the m_initialGeometricalRfnLevel the first initial cube is located at the beginning or at the end of the collector:

  • m_initialGeometricalRfnLevel is even: locate at the beginning
  • m_initialGeometricalRfnLevel is odd: locate at the end The next following level is always written to the other end of the collector, i.e., if the first cube is located at the end of the collector, the next higher level starts at the beginning of the collector. This method iterates, cells are written to the front back of the collector continuously. This way it is not necessary to delete the lower levels since they are just overwritten by one of the upcoming levels. This way, at the end of the refinement the initial level is located at the beginning of the collector. Before refining and writing to a level at the end of the collector the offsets are determined by estimating the possible number of cells on the upcoming level. 4.2.2 check if there is enough memory 4.2.3 refine the grid one further level 4.2.4 update the neighborhood information on the newly created cells 4.2.5 update solver affiliation and cells outside the geometry or without solver affiliation are deleted 4.3 Remove the link to the parents on the initial level 4.4 Update the number of generated cells and print information 4.5 Reorder cells after Hilbert id 4.6 If the code runs parallel and no further refinement is requested, finish the process otherwise nothing is required at this stage. Finishing calls updateInterRankNeighbors().

Definition at line 1352 of file cartesiangridgenpar.cpp.

1352 {
1353 TRACE();
1354
1355 RECORD_TIMER_START(m_t_createInitialGrid);
1356
1357 m_log << " (4) creating initial grid" << endl;
1358 outStream << " (4) creating initial grid" << endl;
1359
1360 m_log << " + refining from: 0 to " << m_minLevel << endl;
1361 outStream << " + refining from: 0 to " << m_minLevel << endl;
1362
1363 m_log << " + initial cube size: " << m_lengthOnLevel[0] << endl;
1364 outStream << " + initial cube size: " << m_lengthOnLevel[0] << endl;
1365
1366 MInt in_id = m_levelOffsets[0][0];
1367
1368 // 4.1 Create initial cube
1369 for(MInt d = 0; d < nDim; d++)
1370 a_coordinate(in_id, d) = m_centerOfGravity[d];
1371
1372 for(MInt d = 0; d < m_noNeighbors; d++)
1373 a_neighborId(in_id, d) = -1;
1374
1375 for(MInt c = 0; c < m_maxNoChildren; c++)
1376 a_childId(in_id, c) = -1;
1377
1378 a_parentId(in_id) = -1;
1379 a_level(in_id) = 0;
1380 a_globalId(in_id) = (MLong)in_id;
1381 a_noChildren(in_id) = 0;
1382 for(MInt s = 0; s < m_noSolvers; s++) {
1383 a_noSolidLayer(in_id, s) = -1;
1384 }
1385
1386 for(MInt i = 0; i < 8; i++)
1387 a_hasProperty(in_id, i) = 0;
1388
1389 // we need to say that the initial cell has a cut so that the children are checked for a cut
1390 a_hasProperty(in_id, 1) = 1;
1391
1392 // all Solvers are cut and inside and to be refined
1393 for(MInt solver = 0; solver < m_noSolvers; solver++) {
1394 a_isSolverBoundary(in_id, solver) = 1;
1395 a_isInSolver(in_id, solver) = 1;
1396 a_isToRefineForSolver(in_id, solver) = 1;
1397 }
1398
1399 m_noCells = 1;
1400
1401 // 4.2 Refine to the initial refinement level
1402 for(MInt l = 0; l < m_minLevel; l++) {
1403 // 4.2.1 Update the level offsets
1404 if(m_levelOffsets[l][0] == 0) {
1406 m_levelOffsets[l + 1][1] = m_maxNoCells;
1407 } else {
1408 m_levelOffsets[l + 1][0] = 0;
1409 m_levelOffsets[l + 1][1] = (m_levelOffsets[l][1] - m_levelOffsets[l][0]) * m_maxNoChildren;
1410 }
1411
1412 // 4.2.2 check if there is enough memory
1413 checkMemoryAvailability(0, l + 1);
1414
1415 for(MInt solver = 0; solver < m_noSolvers; solver++)
1416 markSolverForRefinement(l, solver);
1417
1418 // 4.2.3 refine
1420
1421 // 4.2.4 update neighbors
1422 m_log << " * finding the neighbors for the new level" << endl;
1423 outStream << " * finding the neighbors for the new level" << endl;
1425
1426 // 4.2.5 delete outside cells
1428 }
1429 // 4.3 remove parent links on base cell level
1430 for(MInt i = m_levelOffsets[m_minLevel][0]; i < m_levelOffsets[m_minLevel][1]; i++)
1431 a_parentId(i) = -1;
1432
1433 // 4.4 update number of cells generated
1435 m_log << " + created " << m_noCells << " cells for level " << m_minLevel << endl;
1436 outStream << " + created " << m_noCells << " cells for level " << m_minLevel << endl;
1437
1438 // 4.5 reorder cells after Hilbert curve
1440
1441 RECORD_TIMER_STOP(m_t_createInitialGrid);
1442}
void findChildLevelNeighbors(MInt **offsets, MInt level_)
updates the children of a given level
void checkMemoryAvailability(MInt stage, MInt level_)
void deleteOutsideCellsSerial(MInt level_)
deletes the cells outside of the geometry
void reorderCellsHilbert()
reorders the cells after Hilbert id
void markSolverForRefinement(MInt level_, MInt solver)
void refineGrid(MInt **offsets, MInt level_, MBool halo)
refines the grid on a given level

◆ createSolidCellLayer()

template<MInt nDim>
void GridgenPar< nDim >::createSolidCellLayer ( MInt  cellId,
MInt  solidLayer,
MInt  finalLayer_ 
)
protected

Definition at line 2842 of file cartesiangridgenpar.cpp.

2842 {
2843 TRACE();
2844
2845 MInt totalNoNeighbors = (nDim == 3) ? 26 : 8;
2846 if(a_noSolidLayer(cellId, solver) > layer) {
2847 a_noSolidLayer(cellId, solver) = layer;
2848 // Definition: We do not refine at final distance!
2849 if(layer < m_noSolidLayer[solver]) {
2850 for(MInt n = 0; n < totalNoNeighbors; n++) {
2851 // for (MInt n = 0; n < m_noNeighbors; n++){
2852 MInt nghborId = cellId;
2853 for(MInt d = 0; d < nDim; d++) {
2854 if(nghborStencil(n, d) == -1) break;
2855 nghborId = (MInt)a_neighborId(nghborId, nghborStencil(n, d));
2856 if(nghborId == -1) break;
2857 }
2858 if(nghborId == -1) continue;
2859 // if (a_neighborId(cellId, n) > -1)
2860 // createSolidCellLayer((MInt)a_neighborId(cellId, n), layer + 1, solver);
2861 createSolidCellLayer(nghborId, layer + 1, solver);
2862 }
2863 }
2864 }
2865}
MInt nghborStencil(MInt, MInt)
void createSolidCellLayer(MInt cellId, MInt solidLayer, MInt finalLayer_)

◆ createStartGrid()

template<MInt nDim>
void GridgenPar< nDim >::createStartGrid
protected
Author
Andreas Lintermann
Date
23.10.2013

The algorithm does the following:

5.1. Check if we are running in parallel, if so parallelize the grid. This calls parallelizeGrid(). 5.2. Run over all levels that are still to be refined and do the following: 5.2.1 Update the m_levelOffsets of the next level. This generates a new offset range for the new level to create under the assumption that all cells on the current level are refined. 5.2.2 Update the halo cell offsets. This call the updateHaloCellOffsets(...) function. 5.2.3 Check memory availability. 5.2.4 Refine the normal cells and the halo cells. This calls refineGrid(...) similar to the serial case. To refine the halo cells the new halo cell offsets are provided. 5.2.5 Update the number of cells on this domain, since it has changed. 5.2.6 Find the neighbors for all newly generated normal and halo cells. This calls findChildLevelNeighbors(...) and provides the offsets for the normal cells and the halo cells of the current level. 5.2.7 Delete all normal outside cells. This has still to be done for the halo cells. 5.3 Again update the number of cells. 5.4 If the code runs parallel and no further refinement is requested, finish the process otherwise nothing is required at this stage. Finishing calls updateInterRankNeighbors().

Definition at line 4180 of file cartesiangridgenpar.cpp.

4180 {
4181 TRACE();
4182
4183 RECORD_TIMER_START(m_t_createStartGrid);
4184
4185 // 5.2. run over all levels that are still to be refined uniformly
4186 for(MInt l = m_minLevel; l < m_maxUniformRefinementLevel; l++) {
4187 // 5.2.1 update the m_levelOffsets of the next level
4188 m_levelOffsets[l + 1][0] = m_noCells;
4190
4191 // 5.2.2 update the halo offset information and size
4192 if(noDomains() > 1) updateHaloOffsets(l, m_noHaloCellsOnLevel[l], nullptr);
4193
4194 for(MInt solver = 0; solver < m_noSolvers; solver++)
4195 markSolverForRefinement(l, solver);
4196
4197 // 5.2.3 check memory availability
4198 checkMemoryAvailability(1, l + 1);
4199
4200 // 5.2.4 refine the normal cells and the halo cells
4202 if(noDomains() > 1) {
4204 }
4205
4206 // 5.2.5 update the number of cells on this domain
4207 m_noCells = m_levelOffsets[l + 1][1];
4208
4209 // 5.2.6 find the neighbors for all newly generated normal and halo cells
4211 if(noDomains() > 1) {
4213 }
4214
4215 // 5.2.7 delete all outside cells
4216 if(noDomains() > 1) {
4218 } else {
4220 }
4221
4222 // 5.3 update the number of cells
4223 m_noCells = m_levelOffsets[l + 1][1];
4224 }
4225
4226 RECORD_TIMER_STOP(m_t_createStartGrid);
4227}
void deleteOutsideCellsParallel(MInt level_)
deletes outside cells in parallel mode
MInt * m_noHaloCellsOnLevel

◆ deleteCellReferences()

template<MInt nDim>
void GridgenPar< nDim >::deleteCellReferences ( MInt  cell,
MInt  pos 
)
protected
Author
Andreas Lintermann
Date
06.11.2013

08.05.2014: Removed pointer references (Jerry Grimmen)

The algorithm does the following:

a. Run over all neighbors of the given cell and delete the reference to this cell. b. Go to the parent, and update the according child-id.

Parameters
[in]cellid of the cell to delete
[in]posthe id of the cell

Definition at line 3141 of file cartesiangridgenpar.cpp.

3141 {
3142 TRACE();
3143
3144 // a. update all directions
3145 for(MInt dir = 0; dir < m_noNeighbors; dir++) {
3146 MInt dirNeighborId = (MInt)a_neighborId(cell, dir);
3147
3148 // if we have a neighbor
3149 if(dirNeighborId >= 0) a_neighborId(dirNeighborId, oppositeDirGrid[dir]) = -1;
3150 }
3151
3152 // b. update parent
3153 if(a_parentId(cell) >= 0) {
3154 MInt parent = (MInt)a_parentId(cell);
3155 for(MInt c = 0; c < m_maxNoChildren; c++)
3156 if((MInt)a_childId((MInt)parent, c) == pos) a_childId((MInt)parent, c) = -1;
3157
3158 a_noChildren((MInt)parent) = a_noChildren((MInt)parent) - 1;
3159 }
3160}

◆ deleteCoarseSolidCellsParallel()

template<MInt nDim>
void GridgenPar< nDim >::deleteCoarseSolidCellsParallel
protected
Author
Jie Ruan, Moritz Waldmann
Date
30.09.2018

The function call when we set ggp_keepOutsideBndryCellChildren = 3 in property file, for creating solid cells. After reaching maxRefinementLevel when need delete all solid cells which lower than maxRfnmntLvl, thus in this function run through maxRefinementLevel-1 to minlevel to delete all solid cells which havw no child.

Definition at line 2556 of file cartesiangridgenpar.cpp.

2556 {
2557 TRACE();
2558
2559 // declare lambda to check for valid neighbors
2560 auto neighborExists = [&](MInt haloCellId) {
2561 for(MInt n = 0; n < m_noNeighbors; n++) {
2562 if(a_neighborId(haloCellId, n) >= 0 && a_neighborId(haloCellId, n) < m_noCells) {
2563 return true;
2564 }
2565 }
2566 return false;
2567 };
2568
2569 for(MInt j = m_minLevel; j <= m_maxRfnmntLvl; j++) {
2570 m_log << " Level: " << j << "- old offsets: " << m_levelOffsets[j][0] << " " << m_levelOffsets[j][1]
2571 << endl;
2572 cout << " Level: " << j << "- old offsets: " << m_levelOffsets[j][0] << " " << m_levelOffsets[j][1] << endl;
2573 }
2574
2575 for(MInt j = m_minLevel; j <= m_maxRfnmntLvl; j++) {
2576 MInt levPos = 2 * (j - m_minLevel);
2577 for(MInt dom = m_noNeighborDomains - 1; dom >= 0; dom--) {
2578 m_log << " Level: " << j << "- old offsets: " << m_haloCellOffsets[dom][levPos + 1] << " "
2579 << m_haloCellOffsets[dom][levPos] << endl;
2580 cout << " Level: " << j << "- old offsets: " << m_haloCellOffsets[dom][levPos + 1] << " "
2581 << m_haloCellOffsets[dom][levPos] << endl;
2582 }
2583 }
2584 m_log << " * detecting coarse solid cells to delete:" << endl;
2585 cout << " * detecting coarse solid cells to delete:" << endl;
2586
2587 MInt noDeletedCellsTotal = 0;
2588 MInt noDeletedHalosTotal = 0;
2589 for(MInt level = m_maxRfnmntLvl - 1; level >= m_minLevel; level--) {
2590 MInt noDeletedCellsPerLevel = 0;
2591
2592 for(MInt cell = m_levelOffsets[level][1] - 1; cell >= m_levelOffsets[level][0]; cell--) {
2593 if(!(a_hasProperty(cell, 0)) && !(a_hasProperty(cell, 1)) && a_noChildren(cell) == 0) {
2594 // update parent
2595 if(a_parentId(cell) > -1) {
2596 for(MInt c = 0; c < m_maxNoChildren; c++)
2597 if(a_childId((MInt)a_parentId(cell), c) == cell) {
2598 a_childId((MInt)a_parentId(cell), c) = -1;
2599 break;
2600 }
2602 }
2603 // update all directions
2604 for(MInt dir = 0; dir < m_noNeighbors; dir++) {
2605 MInt dirNeighborId = (MInt)a_neighborId(cell, dir);
2606 // if we have a neighbor
2607 if(dirNeighborId >= 0) {
2608 // delete direct reference
2609 a_neighborId(dirNeighborId, oppositeDirGrid[dir]) = -1;
2610 }
2611 }
2612 // delete the cell from the collector
2613 if(cell != m_levelOffsets[level][1] - 1) copyCell(m_levelOffsets[level][1] - 1, cell);
2614 m_levelOffsets[level][1]--;
2615 noDeletedCellsPerLevel++;
2616 }
2617 }
2618 noDeletedCellsTotal += noDeletedCellsPerLevel;
2619 for(MInt re = level + 1; re <= m_maxRfnmntLvl; re++) {
2620 for(MInt i = 0; i < noDeletedCellsPerLevel; i++) {
2621 copyCell(m_levelOffsets[re][1] - 1 - i, m_levelOffsets[re][0] - 1 - i);
2622 }
2623 m_levelOffsets[re][0] = m_levelOffsets[re][0] - noDeletedCellsPerLevel;
2624 m_levelOffsets[re][1] = m_levelOffsets[re][1] - noDeletedCellsPerLevel;
2625 }
2626
2627 const MInt levelPos = 2 * (level - m_minLevel);
2628 MInt noDeletedHalosPerLevel = 0;
2629
2630 for(MInt dom = m_noNeighborDomains - 1; dom >= 0; dom--) {
2631 for(MInt haloCellId = m_haloCellOffsets[dom][levelPos + 1] - 1; haloCellId >= m_haloCellOffsets[dom][levelPos];
2632 haloCellId--) {
2633 // if cell hasn't been moved check it
2634 if(!a_hasProperty(haloCellId, 7)) {
2635 // 1. for boundary or inside cells check if neighbors still exist
2636 // 2. if they do skip those cells since they are valid
2637 if(a_hasProperty(haloCellId, 0) || a_hasProperty(haloCellId, 1) || (a_noSolidLayer(haloCellId, 0) > 0)) {
2638 if(neighborExists(haloCellId)) {
2639 continue;
2640 }
2641 }
2642
2643 // delete cell
2644 cout << " x-dir " << a_coordinate(haloCellId, 0) << " y-dir " << a_coordinate(haloCellId, 1) << " z-dir "
2645 << a_coordinate(haloCellId, 2) << endl;
2646 a_hasProperty(haloCellId, 7) = 1;
2647 deleteCellReferences(haloCellId, haloCellId);
2648 noDeletedHalosPerLevel++;
2649 }
2650
2651 // skip cells marked as moved
2652 while(m_haloCellOffsets[dom][levelPos] < haloCellId && a_hasProperty(m_haloCellOffsets[dom][levelPos], 7)) {
2653 m_haloCellOffsets[dom][levelPos]++;
2654 }
2655
2656 // copy last cell to current position
2657 if(haloCellId > m_haloCellOffsets[dom][levelPos]) {
2658 copyCell(m_haloCellOffsets[dom][levelPos], haloCellId);
2659
2660 // mark as moved
2661 a_hasProperty(m_haloCellOffsets[dom][levelPos], 7) = 1;
2662
2663 // check copied cell
2664 haloCellId++;
2665 }
2666
2667 // increase offset since cell has either been copied or was last cell and invalid
2668 m_haloCellOffsets[dom][levelPos]++;
2669 }
2670
2671 // set new offset
2672 if(dom > 0) {
2673 m_haloCellOffsets[dom - 1][levelPos + 1] = m_haloCellOffsets[dom][levelPos];
2674 }
2675 }
2676 noDeletedHalosTotal += noDeletedHalosPerLevel;
2677
2678 for(MInt re = level + 1; re <= m_maxRfnmntLvl; re++) {
2679 const MInt levPos = 2 * (re - m_minLevel);
2680 for(MInt dom = m_noNeighborDomains - 1; dom >= 0; dom--) {
2681 for(MInt i = m_haloCellOffsets[dom][levPos + 1] - 1; i >= m_haloCellOffsets[dom][levPos]; i--) {
2682 copyCell(i, i + noDeletedHalosPerLevel);
2683 }
2684 m_haloCellOffsets[dom][levPos] = m_haloCellOffsets[dom][levPos] + noDeletedCellsPerLevel;
2685 m_haloCellOffsets[dom][levPos + 1] = m_haloCellOffsets[dom][levPos + 1] + noDeletedCellsPerLevel;
2686 }
2687 }
2688 }
2690
2691 m_log << " - coarse solid cells deleted: " << noDeletedCellsTotal << endl;
2692 cout << " - coarse solid cells deleted: " << noDeletedCellsTotal << endl;
2693
2694 for(MInt j = m_minLevel; j <= m_maxRfnmntLvl; j++) {
2695 m_log << " Level: " << j << "- new offsets: " << m_levelOffsets[j][0] << " " << m_levelOffsets[j][1]
2696 << endl;
2697 cout << " Level: " << j << "- new offsets: " << m_levelOffsets[j][0] << " " << m_levelOffsets[j][1] << endl;
2698 }
2699 m_log << " - coarse solid halos deleted: " << noDeletedHalosTotal << endl;
2700 cout << " - coarse solid halos deleted: " << noDeletedHalosTotal << endl;
2701
2702 for(MInt j = m_minLevel; j <= m_maxRfnmntLvl; j++) {
2703 MInt levPos = 2 * (j - m_minLevel);
2704 for(MInt dom = m_noNeighborDomains - 1; dom >= 0; dom--) {
2705 m_log << " Level: " << j << "- new offsets: " << m_haloCellOffsets[dom][levPos + 1] << " "
2706 << m_haloCellOffsets[dom][levPos] << endl;
2707 cout << " Level: " << j << "- new offsets: " << m_haloCellOffsets[dom][levPos + 1] << " "
2708 << m_haloCellOffsets[dom][levPos] << endl;
2709 }
2710 }
2711}
void copyCell(MInt from, MInt to)
moves a cell from one location in the collector to another
void deleteCellReferences(MInt cell, MInt pos)
deletes the references of a given cell

◆ deleteCoarseSolidCellsSerial()

template<MInt nDim>
void GridgenPar< nDim >::deleteCoarseSolidCellsSerial
protected
Author
Jie Ruan, Moritz Waldmann
Date
30.09.2018

The function call when we set ggp_keepOutsideBndryCellChildren = 3 in property file, for creating solid cells. After reaching maxRefinementLevel when need delete all solid cells which lower than maxRfnmntLvl, thus in this function run through maxRefinementLevel-1 to minlevel to delete all solid cells which havw no child.

Definition at line 2484 of file cartesiangridgenpar.cpp.

2484 {
2485 TRACE();
2486
2487 m_log << " * detecting coarse solid cells to delete:" << endl;
2488 cout << " * detecting coarse solid cells to delete:" << endl;
2489
2490 MInt noDeletedCellsTotal = 0;
2491
2492 for(MInt level = m_maxRfnmntLvl - 1; level >= m_minLevel; level--) {
2493 MInt noDeletedCellsPerLevel = 0;
2494 cout << "m_levelOffsets[level][0] " << m_levelOffsets[level][0] << " m_levelOffsets[level][1] "
2495 << m_levelOffsets[level][1] << endl;
2496 for(MInt cell = m_levelOffsets[level][1] - 1; cell >= m_levelOffsets[level][0]; cell--) {
2497 if(!(a_hasProperty(cell, 0)) && !(a_hasProperty(cell, 1)) && a_noChildren(cell) == 0) {
2498 // update parent
2499 if(a_parentId(cell) > -1) {
2500 for(MInt c = 0; c < m_maxNoChildren; c++)
2501 if(a_childId((MInt)a_parentId(cell), c) == cell) {
2502 a_childId((MInt)a_parentId(cell), c) = -1;
2503 break;
2504 }
2506 }
2507 // update all directions
2508 for(MInt dir = 0; dir < m_noNeighbors; dir++) {
2509 MInt dirNeighborId = (MInt)a_neighborId(cell, dir);
2510 // if we have a neighbor
2511 if(dirNeighborId >= 0) {
2512 // delete direct reference
2513 a_neighborId(dirNeighborId, oppositeDirGrid[dir]) = -1;
2514 }
2515 }
2516 // delete the cell from the collector
2517 if(cell != m_levelOffsets[level][1] - 1) copyCell(m_levelOffsets[level][1] - 1, cell);
2518 m_levelOffsets[level][1]--;
2519 noDeletedCellsPerLevel++;
2520 }
2521 }
2522 noDeletedCellsTotal += noDeletedCellsPerLevel;
2523 for(MInt re = level + 1; re <= m_maxRfnmntLvl; re++) {
2524 for(MInt i = 0; i < noDeletedCellsPerLevel; i++) {
2525 copyCell(m_levelOffsets[re][1] - 1 - i, m_levelOffsets[re][0] - 1 - i);
2526 }
2527 m_levelOffsets[re][0] = m_levelOffsets[re][0] - noDeletedCellsPerLevel;
2528 m_levelOffsets[re][1] = m_levelOffsets[re][1] - noDeletedCellsPerLevel;
2529 }
2530 }
2532
2533 m_log << " - coarse solid cells deleted: " << noDeletedCellsTotal << endl;
2534 cout << " - coarse solid cells deleted: " << noDeletedCellsTotal << endl;
2535
2536 for(MInt j = m_minLevel; j <= m_maxRfnmntLvl; j++) {
2537 m_log << " Level: " << j << "- new offsets: " << m_levelOffsets[j][0] << " " << m_levelOffsets[j][1]
2538 << endl;
2539 cout << " Level: " << j << "- new offsets: " << m_levelOffsets[j][0] << " " << m_levelOffsets[j][1] << endl;
2540 }
2541}

◆ deleteOutsideCellsParallel()

template<MInt nDim>
void GridgenPar< nDim >::deleteOutsideCellsParallel ( MInt  level_)
protected
Author
Andreas Lintermann
Date
21.10.2013

Similar to deleteOutsideCellsSerial(...) this function does the following:

a. Mark all inside and outside cells: calls markInsideOutside(...) with the normal cell and halo-cell offsets. b. perform cutOff c. Runs over all cells on the given level and deletes those cells which are marked as outside (b_properties[0] = 0 && b_properties[1] = 0). d. Runs over all halo cells on the given level and deletes those halo cells which are marked as outside (b_properties[0] = 0) or not referenced anymore (non-existing neighborhood). This algorithm runs over all neighbor domains and then over the according halo-cell offsets. e. Generates look-up table to allow access to cells in globalId order, if required ( i.e. important for the exchange in updateInterRankNeighbors()).

Parameters
[in]level_the level to check

Definition at line 3185 of file cartesiangridgenpar.cpp.

3185 {
3186 TRACE();
3187
3188 MInt t_deleteOutsideCellsParallel = 0;
3189 if(level_ <= m_maxUniformRefinementLevel) {
3190 NEW_SUB_TIMER_STATIC(t_delPar, "delete outside cells parallel", m_t_createStartGrid);
3191 t_deleteOutsideCellsParallel = t_delPar;
3192 } else if(level_ <= m_maxRfnmntLvl) {
3193 NEW_SUB_TIMER_STATIC(t_delPar, "delete outside cells parallel", m_t_createComputationalGrid);
3194 t_deleteOutsideCellsParallel = t_delPar;
3195 }
3196
3197
3198 RECORD_TIMER_START(t_deleteOutsideCellsParallel);
3199
3200 m_log << " * detecting outside cells to delete:" << endl;
3201 outStream << " * detecting outside cells to delete:" << endl;
3202
3203 // a. mark all inside and outside cells
3206
3207 // b. perform cut-off
3208 if(m_cutOff && level_ >= m_minLevel) {
3211 }
3212
3213 // mark solver affiliation set cells without solver affiliation as outside
3214 markSolverAffiliation(level_);
3215
3216 // c. delete all outside cells
3217 const MInt levelPos = 2 * (level_ - m_minLevel);
3218 const MInt num = m_levelOffsets[level_][1] - m_levelOffsets[level_][0];
3219 MInt noDeletedCells = 0;
3220
3221 // b.2 keep some of the outside cells
3223
3224 const MInt numHalo = m_haloCellOffsetsLevel[level_][1] - m_haloCellOffsetsLevel[level_][0];
3225
3226 for(MInt cellId = m_levelOffsets[level_][0]; cellId < m_levelOffsets[level_][1]; cellId++) {
3227 MBool anySolver = false;
3228 for(MInt s = 0; s < m_noSolvers; s++) {
3229 if(a_noSolidLayer(cellId, s) > 0) {
3230 anySolver = true;
3231 break;
3232 }
3233 }
3234
3235 // is neither an inside nor boundary cell -> delete
3236 if(!a_hasProperty(cellId, 0) && !a_hasProperty(cellId, 1) && !anySolver) {
3237 // erase entry if not already erased
3238 if(!a_hasProperty(cellId, 7)) {
3239 a_hasProperty(cellId, 7) = 1;
3240 deleteCellReferences(cellId, cellId);
3241 noDeletedCells++;
3242 }
3243
3244 // skip cells marked as moved
3245 do {
3246 m_levelOffsets[level_][1]--;
3247 } while(m_levelOffsets[level_][1] > cellId && a_hasProperty(m_levelOffsets[level_][1], 7));
3248
3249 // copy last cell to empty position
3250 if(cellId < m_levelOffsets[level_][1]) {
3251 copyCell(m_levelOffsets[level_][1], cellId);
3252
3253 // mark as moved
3254 a_hasProperty(m_levelOffsets[level_][1], 7) = 1;
3255
3256 // copied cell needs to be checked
3257 cellId--;
3258 }
3259 }
3260 }
3261 m_noCells -= noDeletedCells;
3262
3263 m_log << " =deleted " << noDeletedCells << " cells" << endl;
3264 outStream << " =deleted " << noDeletedCells << " cells" << endl;
3265
3266 // d. delete outside as well as now unreferenced halocells
3267 m_log << " - halo cell deletion:" << endl;
3268 outStream << " - halo cell deletion:" << endl;
3269 m_log << " = outside halo cells per domain deleted [new offsets]:" << endl;
3270 outStream << " = outside halo cells per domain deleted [new offsets]:" << endl;
3271
3272 MInt noDeletedHalos = 0;
3273
3274 // declare lambda to check for valid neighbors
3275 auto neighborExists = [&](MInt haloCellId) {
3276 for(MInt n = 0; n < m_noNeighbors; n++) {
3277 if(a_neighborId(haloCellId, n) >= 0 && a_neighborId(haloCellId, n) < m_noCells) {
3278 return true;
3279 }
3280 }
3281 return false;
3282 };
3283
3284 for(MInt dom = m_noNeighborDomains - 1; dom >= 0; dom--) {
3285 for(MInt haloCellId = m_haloCellOffsets[dom][levelPos + 1] - 1; haloCellId >= m_haloCellOffsets[dom][levelPos];
3286 haloCellId--) {
3287 // if cell hasn't been moved check it
3288 if(!a_hasProperty(haloCellId, 7)) {
3289 // 1. for boundary or inside cells check if neighbors still exist
3290 // 2. if they do skip those cells since they are valid
3291 if(a_hasProperty(haloCellId, 0) || a_hasProperty(haloCellId, 1) || (a_noSolidLayer(haloCellId, 0) > 0)) {
3292 if(neighborExists(haloCellId)) {
3293 continue;
3294 }
3295 }
3296
3297 // delete cell
3298 a_hasProperty(haloCellId, 7) = 1;
3299 deleteCellReferences(haloCellId, haloCellId);
3300 noDeletedHalos++;
3301 }
3302
3303 // skip cells marked as moved
3304 while(m_haloCellOffsets[dom][levelPos] < haloCellId && a_hasProperty(m_haloCellOffsets[dom][levelPos], 7)) {
3305 m_haloCellOffsets[dom][levelPos]++;
3306 }
3307
3308 // copy last cell to current position
3309 if(haloCellId > m_haloCellOffsets[dom][levelPos]) {
3310 copyCell(m_haloCellOffsets[dom][levelPos], haloCellId);
3311
3312 // mark as moved
3313 a_hasProperty(m_haloCellOffsets[dom][levelPos], 7) = 1;
3314
3315 // check copied cell
3316 haloCellId++;
3317 }
3318
3319 // increase offset since cell has either been copied or was last cell and invalid
3320 m_haloCellOffsets[dom][levelPos]++;
3321 }
3322
3323 // set new offset
3324 if(dom > 0) {
3325 m_haloCellOffsets[dom - 1][levelPos + 1] = m_haloCellOffsets[dom][levelPos];
3326 }
3327
3328 m_log << " . " << m_neighborDomains[dom] << ": "
3329 << " [" << m_haloCellOffsets[dom][levelPos] << " " << m_haloCellOffsets[dom][levelPos + 1] << "]" << endl;
3330 outStream << " . " << m_neighborDomains[dom] << ": "
3331 << " [" << m_haloCellOffsets[dom][levelPos] << " " << m_haloCellOffsets[dom][levelPos + 1] << "]" << endl;
3332 }
3333
3334
3335 m_haloCellOffsetsLevel[level_][0] += noDeletedHalos;
3336 m_noTotalHaloCells -= noDeletedHalos;
3337 m_noHaloCellsOnLevel[level_] -= noDeletedHalos;
3338
3339 // d. generate look-up table
3340
3341 // sort index by globalId
3342 map<MLong, MInt> lut;
3343 for(MInt cellId = m_levelOffsets[level_][0]; cellId < m_levelOffsets[level_][1]; cellId++) {
3344 lut.insert(make_pair(a_globalId(cellId), cellId));
3345 }
3346 for(MInt cellId = m_haloCellOffsets[0][levelPos]; cellId < m_haloCellOffsets[m_noNeighborDomains - 1][levelPos + 1];
3347 cellId++) {
3348 lut.insert(make_pair(a_globalId(cellId), cellId));
3349 }
3350
3351 // generate lookup table
3352 auto lutIt = lut.begin();
3353 for(MInt cellId = m_levelOffsets[level_][0]; cellId < m_levelOffsets[level_][1]; cellId++) {
3354 m_cellIdLUT.insert(make_pair(cellId, lutIt->second));
3355 lutIt++;
3356 }
3357 for(MInt cellId = m_haloCellOffsets[0][levelPos]; cellId < m_haloCellOffsets[m_noNeighborDomains - 1][levelPos + 1];
3358 cellId++) {
3359 m_cellIdLUT.insert(make_pair(cellId, lutIt->second));
3360 lutIt++;
3361 }
3362
3363 m_log << " = outside and unreferenced halo cells deleted [deleted]: "
3364 << numHalo - (m_haloCellOffsetsLevel[level_][1] - m_haloCellOffsetsLevel[level_][0]) << " [" << noDeletedHalos
3365 << "]" << endl;
3366 m_log << " = new halo offsets: " << m_haloCellOffsetsLevel[level_][0] << " "
3367 << m_haloCellOffsetsLevel[level_][1] << endl;
3368 m_log << " = new halo cells per domain on this level " << level_ << ":" << endl;
3369
3370 outStream << " = outside and unreferenced halo cells deleted [deleted]: "
3371 << numHalo - (m_haloCellOffsetsLevel[level_][1] - m_haloCellOffsetsLevel[level_][0]) << " ["
3372 << noDeletedHalos << "]" << endl;
3373 outStream << " = new halo offsets: " << m_haloCellOffsetsLevel[level_][0] << " "
3374 << m_haloCellOffsetsLevel[level_][1] << endl;
3375 outStream << " = new halo cells per domain on this level " << level_ << ":" << endl;
3376
3377 for(MInt dom = 0; dom < m_noNeighborDomains; dom++) {
3378 m_log << " . " << m_neighborDomains[dom] << " "
3379 << m_haloCellOffsets[dom][levelPos + 1] - m_haloCellOffsets[dom][levelPos] << endl;
3380
3381 outStream << " . " << m_neighborDomains[dom] << " "
3382 << m_haloCellOffsets[dom][levelPos + 1] - m_haloCellOffsets[dom][levelPos] << endl;
3383 }
3384
3385 m_log << " - outside cells deleted: " << num - (m_levelOffsets[level_][1] - m_levelOffsets[level_][0])
3386 << endl;
3387 m_log << " = new offsets: " << m_levelOffsets[level_][0] << " " << m_levelOffsets[level_][1] << endl;
3388
3389 outStream << " - outside cells deleted: " << num - (m_levelOffsets[level_][1] - m_levelOffsets[level_][0])
3390 << endl;
3391 outStream << " = new offsets: " << m_levelOffsets[level_][0] << " " << m_levelOffsets[level_][1] << endl;
3392
3393 RECORD_TIMER_STOP(t_deleteOutsideCellsParallel);
3394}
void markInsideOutside(MInt **offsets, MInt level_)
marks inside and outside cells
void markSolverAffiliation(MInt level_)
marks cells without solver affiliation as outside cells
void performCutOff(MInt **offsets, MInt level_, MBool deleteMode=false)
performs a cut-off defined by the properties
void keepOutsideBndryCellChildrenParallel(MInt level_)
bool MBool
Definition: maiatypes.h:58

◆ deleteOutsideCellsSerial()

template<MInt nDim>
void GridgenPar< nDim >::deleteOutsideCellsSerial ( MInt  level_)
protected
Author
Andreas Lintermann
Date
11.10.2013

Outside cells are detected in the following way:

a. Mark all inside and outside cells. This calls markInsideOutside(...). b. perform cutOff c. marks solver affiliation and declares cells for deletion that are inside but without solver affiliation d. keeps some outside cells needed for grid refinement steps along walls in the solver run e. delete all outside cells. These are the cells which were not marked as inside and are not a boundary cell. The deletion is performed from the back of the offsetrange. The deletion moves a cell at the end of the offsetrange to the location of the cell to be deleted. This is done by calling the copy cell function.

All neighbors are updated to have no reference to the deleted cell anymore.
The size of the offsetrange is decremented by 1 upon deletion.
Parameters
[in]level_the level to check outside cells for

Definition at line 2370 of file cartesiangridgenpar.cpp.

2370 {
2371 TRACE();
2372
2373 MInt t_deleteOutsideCellsSerial = 0;
2374 if(level_ <= m_minLevel) {
2375 NEW_SUB_TIMER_STATIC(t_delSer, "delete outside cells serial", m_t_createInitialGrid);
2376 t_deleteOutsideCellsSerial = t_delSer;
2377 } else if(level_ <= m_maxUniformRefinementLevel) {
2378 NEW_SUB_TIMER_STATIC(t_delSer, "delete outside cells serial", m_t_createStartGrid);
2379 t_deleteOutsideCellsSerial = t_delSer;
2380 } else if(level_ <= m_maxRfnmntLvl) {
2381 NEW_SUB_TIMER_STATIC(t_delSer, "delete outside cells serial", m_t_createComputationalGrid);
2382 t_deleteOutsideCellsSerial = t_delSer;
2383 }
2384
2385 RECORD_TIMER_START(t_deleteOutsideCellsSerial);
2386
2387 MInt num = m_levelOffsets[level_][1] - m_levelOffsets[level_][0];
2388
2389 m_log << " * detecting outside cells to delete:" << endl;
2390 outStream << " * detecting outside cells to delete:" << endl;
2391
2392 // a. mark all inside and outside cells
2394
2395 // b. perform cut-off
2396 if(m_cutOff && level_ >= m_minLevel) performCutOff(m_levelOffsets, level_);
2397
2398 // c. mark solver affiliation and set cells without solver affiliation as outside
2399 markSolverAffiliation(level_);
2400
2401 // d keep some of the outside cells
2404 // perform another cut-off and mark cell outside the cutOff so that they are surely
2405 // deleted in the next step!
2406 if(m_keepOutsideBndryCellChildren == 3 && m_cutOff && level_ >= m_minLevel) {
2407 performCutOff(m_levelOffsets, level_, true);
2408 }
2409 }
2410
2411 // e. delete all outside cells
2412 for(MInt i = m_levelOffsets[level_][1] - 1; i >= m_levelOffsets[level_][0]; i--) {
2413 MInt cell = i;
2414
2415 // labels:GRID NOTE: hack to keep all refined cells
2416 // usefull for periodicBoundaries with leveljumps of the different solvers!
2417 // if(level_ > m_minLevel ) {
2418 // a_hasProperty(cell, 0) = true;
2419 // a_isInSolver(cell, 0) = true;
2420 //}
2421
2422 // this is required, it is an outside and not an inside or boundary cell
2423 MBool inSolidLayer = false;
2424 for(MInt s = 0; s < m_noSolvers; s++) {
2425 if(a_noSolidLayer(cell, s) >= 0) {
2426 inSolidLayer = true;
2427 break;
2428 }
2429 }
2430
2431 if(!(a_hasProperty(cell, 0)) && !(a_hasProperty(cell, 1)) && !inSolidLayer) {
2432 // update parent
2433 if(a_parentId(cell) > -1) {
2434 for(MInt c = 0; c < m_maxNoChildren; c++)
2435 if(a_childId((MInt)a_parentId(cell), c) == i) {
2436 a_childId((MInt)a_parentId(cell), c) = -1;
2437 break;
2438 }
2440 }
2441
2442 // update all directions
2443 for(MInt dir = 0; dir < m_noNeighbors; dir++) {
2444 MInt dirNeighborId = (MInt)a_neighborId(cell, dir);
2445
2446 // if we have a neighbor
2447 if(dirNeighborId >= 0) {
2448 // delete direct reference
2449 a_neighborId(dirNeighborId, oppositeDirGrid[dir]) = -1;
2450 }
2451 }
2452
2453 // delete the cell from the collector
2454 if(i != m_levelOffsets[level_][1] - 1) copyCell(m_levelOffsets[level_][1] - 1, i);
2455 m_levelOffsets[level_][1]--;
2456 }
2457 }
2458
2459 m_noCells = m_levelOffsets[level_][1];
2460
2461 m_log << " - outside cells deleted: " << num - (m_levelOffsets[level_][1] - m_levelOffsets[level_][0])
2462 << endl;
2463 m_log << " - new offsets: " << m_levelOffsets[level_][0] << " " << m_levelOffsets[level_][1] << endl;
2464 outStream << " - outside cells deleted: " << num - (m_levelOffsets[level_][1] - m_levelOffsets[level_][0])
2465 << endl;
2466 outStream << " - new offsets: " << m_levelOffsets[level_][0] << " " << m_levelOffsets[level_][1] << endl;
2467
2468 RECORD_TIMER_STOP(t_deleteOutsideCellsSerial);
2469}
void keepOutsideBndryCellChildrenSerial(MInt *offsets, MInt level_)

◆ determineRankOffsets()

template<MInt nDim>
void GridgenPar< nDim >::determineRankOffsets ( MIntScratchSpace offsets)
protected

Definition at line 4593 of file cartesiangridgenpar.cpp.

4593 {
4594 TRACE();
4595
4596 rank_offsets.fill(0);
4597 rank_offsets[noDomains()] = m_noCells;
4599 // calculate the cell weights and the sum of the weights
4600 m_log << " * using further refinement information" << endl;
4601 MInt sumOfWeights = 0;
4602 MIntScratchSpace cellWeights(m_noCells, AT_, "cellWeights");
4603 cellWeights.fill((MInt)pow(IPOW2(m_maxUniformRefinementLevel - m_minLevel), nDim));
4604 for(MInt cId = 0; cId < m_noCells; cId++) {
4605 // solver uniform check
4607 for(MInt solver = 0; solver < m_noSolvers; solver++) {
4608 SolverRefinement* bp = m_solverRefinement + solver;
4609 if(a_isInSolver(cId, solver)) {
4610 MInt tmpWeight = (MInt)pow(IPOW2(bp->maxUniformRefinementLevel - m_minLevel), nDim);
4611 cellWeights[cId] = mMax(cellWeights[cId], tmpWeight);
4612 }
4613 }
4614 }
4615 // Bnd check
4616 if(m_weightBndCells) {
4617 // check cell for cut
4618 if(checkCellForCut(cId)) {
4619 // get the max refinement level of all cuts
4620 MInt maxCutLevel = 0;
4621 for(MInt solver = 0; solver < m_noSolvers; solver++) {
4622 SolverRefinement* bp = m_solverRefinement + solver;
4623 if(bp->noLocalBndRfnLvls) { // only check if boundary refinement is enabled for this solver
4624 for(MInt rfnBndId = 0; rfnBndId < bp->noLocalRfnBoundaryIds; rfnBndId++) {
4625 if(m_bndCutInfo[solver][bp->localRfnBoundaryIds[rfnBndId]]) {
4626 maxCutLevel = mMax(bp->maxBoundaryRfnLvl - bp->localRfnLvlDiff[rfnBndId], maxCutLevel);
4627 }
4628 }
4629 }
4630 }
4631 // calculate weight
4632 MInt cutWeight = (MInt)pow(IPOW2(maxCutLevel - m_minLevel), nDim);
4633 cellWeights[cId] = mMax(cellWeights(cId), cutWeight);
4634 }
4635 }
4636 // Patch check
4637 if(m_weightPatchCells) {
4638 // cell bounding box
4639 MFloat bbox[2 * nDim];
4640 for(MInt dim = 0; dim < nDim; dim++) {
4641 bbox[dim] = a_coordinate(cId, dim) - m_lengthOnLevel[m_minLevel] * 0.5;
4642 bbox[dim + nDim] = a_coordinate(cId, dim) + m_lengthOnLevel[m_minLevel] * 0.5;
4643 }
4644 MInt maxCutLevel = 0;
4645 for(MInt solver = 0; solver < m_noSolvers; solver++) {
4646 if(a_isInSolver(cId, solver)) {
4647 // 1. do the regions overlap?
4648 SolverRefinement* bp = m_solverRefinement + solver;
4649 MInt patchLvl = (bp->noLocalPatchRfnLvls() - 1);
4650 for(; patchLvl >= 0; patchLvl--) { // no patch no enter (patchLvl = -1)
4651 MBool intersect = false;
4652 for(MInt patch = 0; patch < (MInt)bp->noPatchesPerLevel(patchLvl); patch++) {
4653 const MString patchStr = bp->localRfnLevelMethods[patchLvl].substr(patch, 1);
4654 const MInt pos = bp->localRfnLevelPropertiesOffset[patchLvl] + patch;
4655 if(patchStr == "B") {
4656 intersect = maia::geom::doBoxesOverlap<MFloat, nDim>(bbox, bp->localRfnPatchProperties[pos]);
4657 } else if(patchStr == "R") {
4658 intersect = maia::geom::doBoxAndSphereOverlap<nDim>(bbox, bp->localRfnPatchProperties[pos],
4659 bp->localRfnPatchProperties[pos][nDim]);
4660 } else {
4661 m_log << "weighting not implemented for patches other than the BOX and sphere, sorry" << endl;
4662 intersect = false;
4663 }
4664 if(intersect) break;
4665 }
4666 if(intersect) {
4667 patchLvl += bp->maxUniformRefinementLevel;
4668 maxCutLevel = mMax(maxCutLevel, patchLvl);
4669 break;
4670 }
4671 }
4672 }
4673 }
4674 MInt patchWeight = (MInt)pow(IPOW2(maxCutLevel - m_minLevel), nDim);
4675 cellWeights[cId] = mMax(cellWeights(cId), patchWeight);
4676 }
4677 // sum of weights for distribution
4678 sumOfWeights += cellWeights[cId];
4679 }
4680 // set offsets
4681 // average Load
4682 MInt avgLoad = (MInt)ceil(sumOfWeights / noDomains());
4683 MInt tmpLoad = 0;
4684 MInt tmpSumLoad = 0;
4685 MInt dom = 1;
4686 for(MInt cId = 0; cId < m_noCells && dom < noDomains(); cId++) {
4687 if(tmpLoad < avgLoad) {
4688 // still fits
4689 tmpLoad += cellWeights[cId];
4690 } else {
4691 // too much
4692 rank_offsets[dom] = cId;
4693 tmpSumLoad += tmpLoad;
4694 // update average
4695 avgLoad = (MInt)ceil((sumOfWeights - tmpSumLoad) / (noDomains() - dom));
4696 tmpLoad = cellWeights[cId];
4697 dom++;
4698 }
4699 }
4700 } else {
4701 rank_offsets[1] = (MInt)ceil(m_noCells / noDomains());
4702 for(MInt dom = 2; dom < noDomains(); dom++)
4703 rank_offsets[dom] =
4704 rank_offsets[dom - 1] + (MInt)ceil((m_noCells - rank_offsets[dom - 1]) / (noDomains() - dom + 1));
4705 }
4706}
SolverRefinement * m_solverRefinement
MBool m_weightSolverUniformLevel
MBool checkCellForCut(MInt id)
checks if a cell has a cut with the geometry
constexpr T mMax(const T &x, const T &y)
Definition: functions.h:94
constexpr MLong IPOW2(MInt x)
std::basic_string< char > MString
Definition: maiatypes.h:55
MFloat ** localRfnPatchProperties
MInt * localRfnLevelPropertiesOffset
MInt noPatchesPerLevel(MInt addLevel)
std::vector< MString > localRfnLevelMethods

◆ domainId()

template<MInt nDim>
MInt GridgenPar< nDim >::domainId ( ) const
inline

Definition at line 147 of file cartesiangridgenpar.h.

147{ return m_domainId; }

◆ dynamicLoadBalancing()

template<MInt nDim>
void GridgenPar< nDim >::dynamicLoadBalancing
protected
Author
Jerry Grimmen
Date
26.02.2014

This function can be splitted in the following big parts:

  • Gathering informations: – Calculate current offsets. – Calculate new global ids for local cells. – Calculate new offsets. – Calculate the domain to which the local cells will belong. – Calculate the number of cells we will send and receive.
  • Updating halo ids: – Send and receive new halo global ids. – Changes all local ids from local cell to global ids.
  • Sending and receiving new cells: – Send and receive all cell datas into scratchspaces.
  • Recreation of the cell array: – Moves all cells we keep to the end of the cell array. – In domain and level order, add the cells back to the cell array.
  • Regenerate halo cells: – Gather the halo ids of all the parents of the first cell in the domain. – Tags window cells and collect the halo ids. – Communicate halo global ids to the other domains. – Send and receive all halo cell datas into scratchspaces. – Put the new halo cells into the cell array.
  • Global to local: – Create a global to local map. – Add the local cells to the map. – Add the halo cells to the map. – Changes all global ids of all cells to local ids.

Definition at line 7401 of file cartesiangridgenpar.cpp.

7401 {
7402 TRACE();
7403
7404#ifdef MAIA_EXTRA_DEBUG
7405 m_log << "DynamicLoadBalancing Extra Debug: Step 0 - Setting timer" << endl;
7406#endif
7407
7408 // Setting timer
7409 MInt t_dynamicLoadBalancing = 0;
7410 NEW_SUB_TIMER_STATIC(t_dynLoadBal, "dynamic load balancing", m_t_createComputationalGrid);
7411 t_dynamicLoadBalancing = t_dynLoadBal;
7412
7413 MInt t_gatherInformation = 0;
7414 MInt t_updateHaloIds = 0;
7415 MInt t_communicateCells = 0;
7416 MInt t_recreateCells = 0;
7417 MInt t_createHaloCells = 0;
7418 MInt t_globalToLocal = 0;
7419
7420 NEW_SUB_TIMER_STATIC(t_dynLoadBal1, "Gathering informations", t_dynamicLoadBalancing);
7421 NEW_SUB_TIMER_STATIC(t_dynLoadBal2, "Update halo cells ids", t_dynamicLoadBalancing);
7422 NEW_SUB_TIMER_STATIC(t_dynLoadBal3, "Sending and receiving new cells", t_dynamicLoadBalancing);
7423 NEW_SUB_TIMER_STATIC(t_dynLoadBal4, "Recreation of cell array", t_dynamicLoadBalancing);
7424 NEW_SUB_TIMER_STATIC(t_dynLoadBal5, "Regenerate halo cells", t_dynamicLoadBalancing);
7425 NEW_SUB_TIMER_STATIC(t_dynLoadBal6, "Global to local", t_dynamicLoadBalancing);
7426
7427 t_gatherInformation = t_dynLoadBal1;
7428 t_updateHaloIds = t_dynLoadBal2;
7429 t_communicateCells = t_dynLoadBal3;
7430 t_recreateCells = t_dynLoadBal4;
7431 t_createHaloCells = t_dynLoadBal5;
7432 t_globalToLocal = t_dynLoadBal6;
7433
7434 RECORD_TIMER_START(t_dynamicLoadBalancing);
7435
7436 // ==============================
7437 // #=- Gathering informations -=#
7438 // ==============================
7439
7440#ifdef MAIA_EXTRA_DEBUG
7441 m_log << "DynamicLoadBalancing Extra Debug: Step 1 - Gathering informations" << endl;
7442#endif
7443
7444 RECORD_TIMER_START(t_gatherInformation);
7445
7446 // 1. Get current number of cells on each domain.
7447 MLong noCells = (MLong)m_noCells;
7448 MLongScratchSpace globalNoCellsPerDomain(noDomains() + 1, AT_, "globalNoCellsPerDomain");
7449 MPI_Allgather(&noCells, 1, MPI_LONG, globalNoCellsPerDomain.getPointer(), 1, MPI_LONG, mpiComm(), AT_, "noCells",
7450 "globalNoCellsPerDomain.getPointer()");
7451
7452 // 2. Calculate the current offset.
7453 MLongScratchSpace globalOffset(noDomains() + 1, AT_, "globalOffset");
7454 MLong globalNoCells = globalNoCellsPerDomain[0];
7455 globalOffset[0] = 0;
7456
7457 for(MInt i = 1; i < noDomains(); ++i) {
7458 globalOffset[i] = globalOffset[i - 1] + globalNoCellsPerDomain[i - 1];
7459 globalNoCells += globalNoCellsPerDomain[i];
7460 }
7461
7462 /* 3. Now we create an information array localCellInfo.
7463 * [cellId][0] : local id of the cell in its own domain.
7464 * [cellId][1] : number of offsprings of the cell.
7465 * [cellId][2] : global id of the cell.
7466 * [cellId][3] : id of the domain to which the cell will belong.
7467 */
7468
7469 MLongScratchSpace localCellInfo(m_noCells, 4, AT_, "localCellInfo");
7470 MLong currentGlobalId = globalOffset[globalDomainId()] - 1;
7471
7472 // 3.1. Collecting information [0] and [1] (local id and number of offsprings)
7473 MInt currentCellId = 0;
7474
7475 // 3.1.1. Gather all cells which are before the cell at m_levelOffsets[m_minLevel][0] (may happen after load balacing)
7476 MInt noMissingParents = m_noMissingParents;
7477#ifdef MAIA_EXTRA_DEBUG
7478 m_log << "DynamicLoadBalancing Extra Debug: Gathering informations:: m_noMisingParents is " << m_noMissingParents
7479 << endl;
7480#endif
7481
7482 // Short Fix to match the new traverseDFGlobalId
7483 MFloatScratchSpace minWorkloadPerCell(m_noCells, AT_, "minWorkloadPerCell");
7484 minWorkloadPerCell.fill(0.0);
7485 MFloatScratchSpace minWeightList(m_noCells, AT_, "minWeightList");
7486 minWeightList.fill(0.0);
7487 MFloatScratchSpace minWorkloadList(m_noCells, AT_, "minWorkloadList");
7488 minWorkloadList.fill(0.0);
7489 MFloat currentWorkload = 0.0;
7490
7491 while(noMissingParents > 0) {
7492 MInt k = 0;
7493 MInt cellId = m_levelOffsets[m_minLevel + noMissingParents][0];
7494 while((a_hasProperty((MInt)a_parentId(cellId), 4) == 1) && (a_level(cellId) == (m_minLevel + noMissingParents))) {
7495 currentGlobalId++;
7496 a_globalId(cellId) = currentGlobalId;
7497 localCellInfo(currentCellId, 0) = (MLong)cellId;
7498
7499 MInt last = currentCellId;
7500
7501 traverseDFGlobalId(cellId, &currentGlobalId, localCellInfo, minWorkloadPerCell, &currentWorkload, minWeightList,
7502 minWorkloadList, &currentCellId);
7503
7504 MLong noOffsprings = 0;
7505
7506 if(cellId == 0)
7507 noOffsprings = currentGlobalId - globalOffset[globalDomainId()] + 1;
7508 else
7509 noOffsprings = currentGlobalId - a_globalId(cellId);
7510
7511 localCellInfo(last, 1) = noOffsprings;
7512
7513 ++currentCellId;
7514 ++k;
7515 cellId = m_levelOffsets[m_minLevel + noMissingParents][0] + k;
7516
7517 } // end of : while ( (a_hasProperty(a_parentId(cellId), 4) == 1) && (a_level(cellId) == (m_minLevel +
7518 // noMissingParents)) )
7519
7520 --noMissingParents;
7521
7522 } // end of : while ( noMissingParents > 0 )
7523
7524 // 3.1.2. Gather all cells from m_levelOffsets[m_minLevel][0] and after.
7525 for(MInt cellId = m_levelOffsets[m_minLevel][0]; cellId < m_levelOffsets[m_minLevel][1]; cellId++, currentCellId++) {
7526 ++currentGlobalId;
7527 a_globalId(cellId) = currentGlobalId;
7528 localCellInfo(currentCellId, 0) = (MLong)cellId;
7529 MInt lastCellId = currentCellId;
7530
7531 traverseDFGlobalId(cellId, &currentGlobalId, localCellInfo, minWorkloadPerCell, &currentWorkload, minWeightList,
7532 minWorkloadList, &currentCellId);
7533
7534 MLong noOffsprings = 0;
7535 if(cellId == 0) {
7536 noOffsprings = currentGlobalId - globalOffset[globalDomainId()] + 1;
7537 } else {
7538 noOffsprings = currentGlobalId - a_globalId(cellId) + 1;
7539 }
7540
7541 localCellInfo(lastCellId, 1) = noOffsprings;
7542 } // end of : for (MInt cellId = m_levelOffsets[m_minLevel][0]; cellId < m_levelOffsets[m_minLevel][1]; cellId++,
7543 // currentCellId++)
7544
7545 // 3.2. Collecting information [2] (global id)
7546 for(MInt cellId = 0; cellId < m_noCells; ++cellId) {
7547 localCellInfo(cellId, 2) = a_globalId((MInt)localCellInfo(cellId, 0));
7548 }
7549
7550 // 3.3. Calculate new fixed offsets such that on all domains there is no more than 1 cell difference.
7551 globalOffset.fill(-1);
7552 globalNoCellsPerDomain.fill(0);
7553
7554 globalOffset[0] = 0;
7555 for(MLong d = 1; d < noDomains(); ++d) {
7556 globalOffset[d] = globalOffset[d - 1] + ((globalNoCells - globalOffset[d - 1]) / (((MLong)noDomains()) - (d - 1)));
7557 globalNoCellsPerDomain[d - 1] = globalOffset[d] - globalOffset[d - 1];
7558 }
7559 globalNoCellsPerDomain[noDomains() - 1] = globalNoCells - globalOffset[noDomains() - 1];
7560 globalNoCellsPerDomain[noDomains()] = globalNoCells;
7561 globalOffset[noDomains()] = globalNoCells;
7562
7563 // 3.4. Collecting information [3] (id of the new domain the cell will belong)
7564 MInt currentCpu = 0;
7565 for(MInt i = 1; i < (noDomains() + 1); ++i) {
7566 if(globalOffset[i] > localCellInfo(0, 2)) {
7567 currentCpu = i;
7568 break;
7569 }
7570 }
7571
7572 for(MInt i = 0; i < m_noCells; ++i) {
7573 if(localCellInfo(i, 2) < globalOffset[currentCpu]) {
7574 localCellInfo(i, 3) = (MLong)(currentCpu - 1);
7575 continue;
7576 }
7577
7578 if(localCellInfo(i, 2) == globalOffset[currentCpu]) {
7579 localCellInfo(i, 3) = (MLong)currentCpu;
7580 ++currentCpu;
7581 continue;
7582 }
7583
7584 } // end of : for (MInt i = 0; i < m_noCells; ++i)
7585
7586 // 4. Calculating the number of cells to send and to receive.
7587 MIntScratchSpace noCellsToReceive(noDomains() + 1, AT_, "noCellsToReceive");
7588 MIntScratchSpace noCellsToSend(noDomains() + 1, AT_, "noCellsToSend");
7589 noCellsToReceive.fill(0);
7590 noCellsToSend.fill(0);
7591
7592 for(MInt i = 0; i < m_noCells; ++i) {
7593 if(localCellInfo(i, 3) == (MLong)globalDomainId()) {
7594 continue;
7595 }
7596
7597 noCellsToSend[localCellInfo(i, 3)] += 1;
7598 }
7599
7600 for(MInt i = 0; i < noDomains(); ++i) {
7601 MPI_Scatter(noCellsToSend.getPointer(), 1, MPI_INT, &noCellsToReceive[i], 1, MPI_INT, i, mpiComm(), AT_,
7602 "noCellsToSend.getPointer()", "noCellsToReceive[i]");
7603 }
7604
7605 for(MInt i = 0; i < noDomains(); ++i) {
7606 noCellsToSend[noDomains()] += noCellsToSend[i];
7607 noCellsToReceive[noDomains()] += noCellsToReceive[i];
7608#ifdef MAIA_EXTRA_DEBUG
7609 m_log << "DynamicLoadBalancing Debug: To domain " << i << ", we will send " << noCellsToSend[i] << " and receive "
7610 << noCellsToReceive[i] << " cells." << endl;
7611#endif
7612 }
7613
7614#ifdef MAIA_EXTRA_DEBUG
7615 m_log << "DynamicLoadBalancing Debug: Total number of cells, we will send " << noCellsToSend[noDomains()]
7616 << " and receive " << noCellsToReceive[noDomains()] << " cells." << endl;
7617#endif
7618
7619 RECORD_TIMER_STOP(t_gatherInformation);
7620
7621 // ================================
7622 // #=- Updating halo global ids -=#
7623 // ================================
7624
7625#ifdef MAIA_EXTRA_DEBUG
7626 m_log << "DynamicLoadBalancing Extra Debug: Step 2 - Update halo global ids" << endl;
7627#endif
7628
7629 RECORD_TIMER_START(t_updateHaloIds);
7630
7632
7633 RECORD_TIMER_STOP(t_updateHaloIds);
7634
7635 // =======================================
7636 // #=- Sending and receiving new cells -=#
7637 // =======================================
7638
7639#ifdef MAIA_EXTRA_DEBUG
7640 m_log << "DynamicLoadBalancing Extra Debug: Step 3 - Sending and receiving new cells" << endl;
7641#endif
7642
7643 RECORD_TIMER_START(t_communicateCells);
7644
7645 { // extra '{}' span for sending / receiving the new cells.
7646 MLongScratchSpace newParentId(noCellsToReceive[noDomains()], AT_, "newParentId");
7647 MLongScratchSpace newGlobalId(noCellsToReceive[noDomains()], AT_, "newGlobalId");
7648 MIntScratchSpace newLevel(noCellsToReceive[noDomains()], AT_, "newLevel");
7649 MIntScratchSpace newNoChildren(noCellsToReceive[noDomains()], AT_, "newNoChildren");
7650
7651 MLongScratchSpace newChildId(noCellsToReceive[noDomains()], m_maxNoChildren, AT_, "newChildId");
7652 MLongScratchSpace newNeighborId(noCellsToReceive[noDomains()], m_noNeighbors, AT_, "newNeighborId");
7653 MIntScratchSpace newProperty(noCellsToReceive[noDomains()], 8, AT_, "newProperty");
7654 MIntScratchSpace newIsInSolver(noCellsToReceive[noDomains()], m_noSolvers, AT_, "newIsInSolver");
7655 MIntScratchSpace newIsSolverBoundary(noCellsToReceive[noDomains()], m_noSolvers, AT_, "newIsSolverBoundary");
7656 MIntScratchSpace newIsToRefineForSolver(noCellsToReceive[noDomains()], m_noSolvers, AT_, "newIsToRefineForSolver");
7657 MFloatScratchSpace newCoordinate(noCellsToReceive[noDomains()], nDim, AT_, "newCoordinate");
7658
7659 newParentId.fill(-1);
7660 newGlobalId.fill(-1);
7661 newLevel.fill(-1);
7662 newNoChildren.fill(-1);
7663 newChildId.fill(-1);
7664 newNeighborId.fill(-1);
7665 newProperty.fill(-1);
7666 newCoordinate.fill(-1.0);
7667
7668 { // sending / receiving parentId
7669 MLongScratchSpace sendBuffer(noCellsToSend[noDomains()], AT_, "sendBuffer");
7670
7671 MInt currentId = 0;
7672 for(MInt dom = 0; dom < noDomains(); ++dom) {
7673 if(noCellsToSend[dom] == 0) {
7674 continue;
7675 }
7676
7677 for(MInt i = 0; i < m_noCells; ++i) {
7678 if(localCellInfo(i, 3) == dom) {
7679 sendBuffer(currentId) = a_parentId((MInt)localCellInfo(i, 0));
7680 ++currentId;
7681 }
7682 }
7683 }
7684
7685 communicateLong(newParentId, noCellsToReceive, sendBuffer, noCellsToSend);
7686 } // end of : sending / receiving parentId
7687
7688 { // sending / receiving globalId
7689 MLongScratchSpace sendBuffer(noCellsToSend[noDomains()], AT_, "sendBuffer");
7690
7691 MInt currentId = 0;
7692 for(MInt dom = 0; dom < noDomains(); ++dom) {
7693 if(noCellsToSend[dom] == 0) {
7694 continue;
7695 }
7696
7697 for(MInt i = 0; i < m_noCells; ++i) {
7698 if(localCellInfo(i, 3) == dom) {
7699 sendBuffer(currentId) = a_globalId((MInt)localCellInfo(i, 0));
7700 ++currentId;
7701 }
7702 }
7703 }
7704
7705 communicateLong(newGlobalId, noCellsToReceive, sendBuffer, noCellsToSend);
7706 } // end of : sending / receiving globalId
7707
7708 { // sending / receiving level
7709 MIntScratchSpace sendBuffer(noCellsToSend[noDomains()], AT_, "sendBuffer");
7710
7711 MInt currentId = 0;
7712 for(MInt dom = 0; dom < noDomains(); ++dom) {
7713 if(noCellsToSend[dom] == 0) {
7714 continue;
7715 }
7716
7717 for(MInt i = 0; i < m_noCells; ++i) {
7718 if(localCellInfo(i, 3) == dom) {
7719 sendBuffer(currentId) = a_level((MInt)localCellInfo(i, 0));
7720 ++currentId;
7721 }
7722 }
7723 }
7724
7725 communicateInt(newLevel, noCellsToReceive, sendBuffer, noCellsToSend);
7726 } // end of : sending / receiving level
7727
7728 { // sending / receiving noChildren
7729 MIntScratchSpace sendBuffer(noCellsToSend[noDomains()], AT_, "sendBuffer");
7730
7731 MInt currentId = 0;
7732 for(MInt dom = 0; dom < noDomains(); ++dom) {
7733 if(noCellsToSend[dom] == 0) {
7734 continue;
7735 }
7736
7737 for(MInt i = 0; i < m_noCells; ++i) {
7738 if(localCellInfo(i, 3) == dom) {
7739 sendBuffer(currentId) = a_noChildren((MInt)localCellInfo(i, 0));
7740 ++currentId;
7741 }
7742 }
7743 }
7744
7745 communicateInt(newNoChildren, noCellsToReceive, sendBuffer, noCellsToSend);
7746 } // end of : sending / receiving noChildren
7747
7748 // sending / receiving childId
7749 for(MInt childId = 0; childId < m_maxNoChildren; ++childId) {
7750 MLongScratchSpace sendBuffer(noCellsToSend[noDomains()], AT_, "sendBuffer");
7751 MLongScratchSpace recvBuffer(noCellsToReceive[noDomains()], AT_, "recvBuffer");
7752
7753 MInt currentId = 0;
7754 for(MInt dom = 0; dom < noDomains(); ++dom) {
7755 if(noCellsToSend[dom] == 0) {
7756 continue;
7757 }
7758
7759 for(MInt i = 0; i < m_noCells; ++i) {
7760 if(localCellInfo(i, 3) == dom) {
7761 sendBuffer(currentId) = a_childId((MInt)localCellInfo(i, 0), childId);
7762 ++currentId;
7763 }
7764 }
7765 }
7766
7767 communicateLong(recvBuffer, noCellsToReceive, sendBuffer, noCellsToSend);
7768
7769 for(MInt i = 0; i < noCellsToReceive[noDomains()]; ++i) {
7770 newChildId(i, childId) = recvBuffer(i);
7771 }
7772
7773 } // end of : sending / receiving childId
7774
7775 // sending / receiving neighborId
7776 for(MInt neighborId = 0; neighborId < m_noNeighbors; ++neighborId) {
7777 MLongScratchSpace sendBuffer(noCellsToSend[noDomains()], AT_, "sendBuffer");
7778 MLongScratchSpace recvBuffer(noCellsToReceive[noDomains()], AT_, "recvBuffer");
7779
7780 MInt currentId = 0;
7781 for(MInt dom = 0; dom < noDomains(); ++dom) {
7782 if(noCellsToSend[dom] == 0) {
7783 continue;
7784 }
7785
7786 for(MInt i = 0; i < m_noCells; ++i) {
7787 if(localCellInfo(i, 3) == dom) {
7788 sendBuffer(currentId) = a_neighborId((MInt)localCellInfo(i, 0), neighborId);
7789 ++currentId;
7790 }
7791 }
7792 }
7793
7794 communicateLong(recvBuffer, noCellsToReceive, sendBuffer, noCellsToSend);
7795
7796 for(MInt i = 0; i < noCellsToReceive[noDomains()]; ++i) {
7797 newNeighborId(i, neighborId) = recvBuffer(i);
7798 }
7799
7800 } // end of : sending / receiving neighborId
7801
7802 // sending / receiving property
7803 for(MInt property = 0; property < 8; ++property) {
7804 MIntScratchSpace sendBuffer(noCellsToSend[noDomains()], AT_, "sendBuffer");
7805 MIntScratchSpace recvBuffer(noCellsToReceive[noDomains()], AT_, "recvBuffer");
7806
7807 MInt currentId = 0;
7808 for(MInt dom = 0; dom < noDomains(); ++dom) {
7809 if(noCellsToSend[dom] == 0) {
7810 continue;
7811 }
7812
7813 for(MInt i = 0; i < m_noCells; ++i) {
7814 if(localCellInfo(i, 3) == dom) {
7815 sendBuffer(currentId) = a_hasProperty((MInt)localCellInfo(i, 0), property);
7816 ++currentId;
7817 }
7818 }
7819 }
7820
7821 communicateInt(recvBuffer, noCellsToReceive, sendBuffer, noCellsToSend);
7822
7823 for(MInt i = 0; i < noCellsToReceive[noDomains()]; ++i) {
7824 newProperty(i, property) = recvBuffer(i);
7825 }
7826
7827 } // end of : sending / receiving property
7828
7829 // sending / receiving solver affiliation
7830 for(MInt solver = 0; solver < m_noSolvers; solver++) {
7831 MIntScratchSpace sendBuffer(noCellsToSend[noDomains()], AT_, "sendBuffer");
7832 MIntScratchSpace recvBuffer(noCellsToReceive[noDomains()], AT_, "recvBuffer");
7833
7834 MInt currentId = 0;
7835 for(MInt dom = 0; dom < noDomains(); ++dom) {
7836 if(noCellsToSend[dom] == 0) {
7837 continue;
7838 }
7839
7840 for(MInt i = 0; i < m_noCells; ++i) {
7841 if(localCellInfo(i, 3) == dom) {
7842 sendBuffer(currentId) = a_isInSolver((MInt)localCellInfo(i, 0), solver);
7843 ++currentId;
7844 }
7845 }
7846 }
7847
7848 communicateInt(recvBuffer, noCellsToReceive, sendBuffer, noCellsToSend);
7849
7850 for(MInt i = 0; i < noCellsToReceive[noDomains()]; ++i) {
7851 newIsInSolver(i, solver) = recvBuffer(i);
7852 }
7853 }
7854
7855 // sending / receiving solver boundary
7856 for(MInt solver = 0; solver < m_noSolvers; solver++) {
7857 MIntScratchSpace sendBuffer(noCellsToSend[noDomains()], AT_, "sendBuffer");
7858 MIntScratchSpace recvBuffer(noCellsToReceive[noDomains()], AT_, "recvBuffer");
7859
7860 MInt currentId = 0;
7861 for(MInt dom = 0; dom < noDomains(); ++dom) {
7862 if(noCellsToSend[dom] == 0) {
7863 continue;
7864 }
7865
7866 for(MInt i = 0; i < m_noCells; ++i) {
7867 if(localCellInfo(i, 3) == dom) {
7868 sendBuffer(currentId) = a_isSolverBoundary((MInt)localCellInfo(i, 0), solver);
7869 ++currentId;
7870 }
7871 }
7872 }
7873
7874 communicateInt(recvBuffer, noCellsToReceive, sendBuffer, noCellsToSend);
7875
7876 for(MInt i = 0; i < noCellsToReceive[noDomains()]; ++i) {
7877 newIsSolverBoundary(i, solver) = recvBuffer(i);
7878 }
7879 }
7880
7881 // sending / receiving solver is to refine
7882 for(MInt solver = 0; solver < m_noSolvers; solver++) {
7883 MIntScratchSpace sendBuffer(noCellsToSend[noDomains()], AT_, "sendBuffer");
7884 MIntScratchSpace recvBuffer(noCellsToReceive[noDomains()], AT_, "recvBuffer");
7885
7886 MInt currentId = 0;
7887 for(MInt dom = 0; dom < noDomains(); ++dom) {
7888 if(noCellsToSend[dom] == 0) {
7889 continue;
7890 }
7891
7892 for(MInt i = 0; i < m_noCells; ++i) {
7893 if(localCellInfo(i, 3) == dom) {
7894 sendBuffer(currentId) = a_isToRefineForSolver((MInt)localCellInfo(i, 0), solver);
7895 ++currentId;
7896 }
7897 }
7898 }
7899
7900 communicateInt(recvBuffer, noCellsToReceive, sendBuffer, noCellsToSend);
7901
7902 for(MInt i = 0; i < noCellsToReceive[noDomains()]; ++i) {
7903 newIsToRefineForSolver(i, solver) = recvBuffer(i);
7904 }
7905 }
7906
7907 // sending / receiving coordinate
7908 for(MInt dim = 0; dim < nDim; ++dim) {
7909 MFloatScratchSpace sendBuffer(noCellsToSend[noDomains()], AT_, "sendBuffer");
7910 MFloatScratchSpace recvBuffer(noCellsToReceive[noDomains()], AT_, "recvBuffer");
7911
7912 MInt currentId = 0;
7913 for(MInt dom = 0; dom < noDomains(); ++dom) {
7914 if(noCellsToSend[dom] == 0) {
7915 continue;
7916 }
7917
7918 for(MInt i = 0; i < m_noCells; ++i) {
7919 if(localCellInfo(i, 3) == dom) {
7920 sendBuffer(currentId) = a_coordinate((MInt)localCellInfo(i, 0), dim);
7921 ++currentId;
7922 }
7923 }
7924 }
7925
7926 communicateDouble(recvBuffer, noCellsToReceive, sendBuffer, noCellsToSend);
7927
7928 for(MInt i = 0; i < noCellsToReceive[noDomains()]; ++i) {
7929 newCoordinate(i, dim) = recvBuffer(i);
7930 }
7931
7932 } // end of : sending / receiving coordinate
7933
7934 RECORD_TIMER_STOP(t_communicateCells);
7935
7936 // ====================================
7937 // #=- Recreation of the cell array -=#
7938 // ====================================
7939
7940#ifdef MAIA_EXTRA_DEBUG
7941 m_log << "DynamicLoadBalancing Extra Debug: Step 4 - Recreation of the cell array" << endl;
7942#endif
7943
7944 RECORD_TIMER_START(t_recreateCells);
7945
7946 // 1. Move own cells out of the way (moves the cells that we will keep to the end of the cell array)
7947 currentCellId = m_maxNoCells - 2;
7948 for(MInt i = m_noCells - 1; i > -1; --i) {
7949 if(localCellInfo(i, 3) == globalDomainId()) {
7950 a_parentId(currentCellId) = a_parentId((MInt)localCellInfo(i, 0));
7951 a_globalId(currentCellId) = a_globalId((MInt)localCellInfo(i, 0));
7952 a_noChildren(currentCellId) = a_noChildren((MInt)localCellInfo(i, 0));
7953 a_level(currentCellId) = a_level((MInt)localCellInfo(i, 0));
7954
7955 for(MInt child = 0; child < m_maxNoChildren; ++child) {
7956 a_childId(currentCellId, child) = a_childId((MInt)localCellInfo(i, 0), child);
7957 }
7958
7959 for(MInt ngh = 0; ngh < m_noNeighbors; ++ngh) {
7960 a_neighborId(currentCellId, ngh) = a_neighborId((MInt)localCellInfo(i, 0), ngh);
7961 }
7962
7963 for(MInt dim = 0; dim < nDim; ++dim) {
7964 a_coordinate(currentCellId, dim) = a_coordinate((MInt)localCellInfo(i, 0), dim);
7965 }
7966
7967 for(MInt property = 0; property < 8; ++property) {
7968 a_hasProperty(currentCellId, property) = a_hasProperty((MInt)localCellInfo(i, 0), property);
7969 }
7970
7971 for(MInt solver = 0; solver < 8; solver++) {
7972 a_isInSolver(currentCellId, solver) = a_isInSolver((MInt)localCellInfo(i, 0), solver);
7973 a_isSolverBoundary(currentCellId, solver) = a_isSolverBoundary((MInt)localCellInfo(i, 0), solver);
7974 a_isToRefineForSolver(currentCellId, solver) = a_isToRefineForSolver((MInt)localCellInfo(i, 0), solver);
7975 // not working in parallel yet anyway
7976 a_noSolidLayer(currentCellId, solver) = -1;
7977 }
7978
7979 localCellInfo(i, 0) = currentCellId;
7980 --currentCellId;
7981 } // end of : if (localCellInfo(i, 3) == globalDomainId())
7982 } // end of : for (MInt i = m_noCells - 1; i > -1; --i)
7983
7984 // 2. Copy all the cells in the right order in the cell array.
7985 MInt currentLocalCellId = 0;
7986 for(MInt level = m_minLevel; level <= m_maxRfnmntLvl; ++level) {
7987 m_levelOffsets[level][0] = currentLocalCellId;
7988 currentCellId = 0;
7989 for(MInt dom = 0; dom < noDomains(); ++dom) {
7990 if(dom == globalDomainId()) {
7991 for(MInt cellId = 0; cellId < m_noCells; ++cellId) {
7992 if((a_level((MInt)localCellInfo(cellId, 0)) == level) && (localCellInfo(cellId, 3) == globalDomainId())) {
7993 a_parentId(currentLocalCellId) = a_parentId((MInt)localCellInfo(cellId, 0));
7994 a_globalId(currentLocalCellId) = a_globalId((MInt)localCellInfo(cellId, 0));
7995 a_noChildren(currentLocalCellId) = a_noChildren((MInt)localCellInfo(cellId, 0));
7996 a_level(currentLocalCellId) = a_level((MInt)localCellInfo(cellId, 0));
7997
7998 for(MInt child = 0; child < m_maxNoChildren; ++child) {
7999 a_childId(currentLocalCellId, child) = a_childId((MInt)localCellInfo(cellId, 0), child);
8000 }
8001
8002 for(MInt ngh = 0; ngh < m_noNeighbors; ++ngh) {
8003 a_neighborId(currentLocalCellId, ngh) = a_neighborId((MInt)localCellInfo(cellId, 0), ngh);
8004 }
8005
8006 for(MInt dim = 0; dim < nDim; ++dim) {
8007 a_coordinate(currentLocalCellId, dim) = a_coordinate((MInt)localCellInfo(cellId, 0), dim);
8008 }
8009
8010 for(MInt property = 0; property < 8; ++property) {
8011 a_hasProperty(currentLocalCellId, property) = a_hasProperty((MInt)localCellInfo(cellId, 0), property);
8012 }
8013
8014 for(MInt solver = 0; solver < 8; solver++) {
8015 a_isInSolver(currentLocalCellId, solver) = a_isInSolver((MInt)localCellInfo(cellId, 0), solver);
8016 a_isSolverBoundary(currentLocalCellId, solver) =
8017 a_isSolverBoundary((MInt)localCellInfo(cellId, 0), solver);
8018 a_isToRefineForSolver(currentLocalCellId, solver) =
8019 a_isToRefineForSolver((MInt)localCellInfo(cellId, 0), solver);
8020 // not working in parallel yet anyway
8021 a_noSolidLayer(currentLocalCellId, solver) = -1;
8022 }
8023
8024 ++currentLocalCellId;
8025
8026 } // end of : if ( (a_level((MInt)localCellInfo(cellId, 0)) == level) && (localCellInfo(cellId, 3) ==
8027 // globalDomainId()) )
8028
8029 } // end of : for (MInt cellId = 0; cellId < m_noCells; ++cellId)
8030 continue;
8031
8032 } // end of : if (dom == globalDomainId())
8033
8034 if(noCellsToReceive[dom] == 0) {
8035 continue;
8036 } // end of : if (noCellsToReceive[dom] == 0)
8037
8038 if(noCellsToReceive[dom] > 0) {
8039 for(MInt cellId = currentCellId; cellId < (currentCellId + noCellsToReceive[dom]); ++cellId) {
8040 if(newLevel(cellId) == level) {
8041 a_parentId(currentLocalCellId) = newParentId(cellId);
8042 a_globalId(currentLocalCellId) = newGlobalId(cellId);
8043 a_noChildren(currentLocalCellId) = newNoChildren(cellId);
8044 a_level(currentLocalCellId) = newLevel(cellId);
8045
8046 for(MInt child = 0; child < m_maxNoChildren; ++child) {
8047 a_childId(currentLocalCellId, child) = newChildId(cellId, child);
8048 }
8049
8050 for(MInt ngh = 0; ngh < m_noNeighbors; ++ngh) {
8051 a_neighborId(currentLocalCellId, ngh) = newNeighborId(cellId, ngh);
8052 }
8053
8054 for(MInt dim = 0; dim < nDim; ++dim) {
8055 a_coordinate(currentLocalCellId, dim) = newCoordinate(cellId, dim);
8056 }
8057
8058 for(MInt property = 0; property < 8; ++property) {
8059 a_hasProperty(currentLocalCellId, property) = (MBool)newProperty(cellId, property);
8060 }
8061
8062 for(MInt solver = 0; solver < m_noSolvers; solver++) {
8063 a_isInSolver(currentLocalCellId, solver) = (MBool)newIsInSolver(cellId, solver);
8064 a_isSolverBoundary(currentLocalCellId, solver) = (MBool)newIsSolverBoundary(cellId, solver);
8065 a_isToRefineForSolver(currentLocalCellId, solver) = (MBool)newIsToRefineForSolver(cellId, solver);
8066 // solid-data is not communicated as its not working for
8067 // multiple-ranks yet!
8068 a_noSolidLayer(currentLocalCellId, solver) = -1;
8069 }
8070
8071 // who knows what is there
8072 for(MInt solver = m_noSolvers; solver < 8; solver++) {
8073 a_isInSolver(currentLocalCellId, solver) = 0;
8074 a_isSolverBoundary(currentLocalCellId, solver) = 0;
8075 a_isToRefineForSolver(currentLocalCellId, solver) = 0;
8076 a_noSolidLayer(currentLocalCellId, solver) = -1;
8077 }
8078
8079 ++currentLocalCellId;
8080 } // end of : if (cells->a[cellId].m_level[0] == level)
8081 } // end of : for (MInt cellId = currentCellId; cellId < (currentCellId + cellToReceive[dom]); ++cellId)
8082 currentCellId += noCellsToReceive[dom];
8083 } // end of : if (cellToReceive[dom] > 0)
8084
8085
8086 } // end of : for (MInt dom = 0; dom < noDomains(); ++dom)
8087 m_levelOffsets[level][1] = currentLocalCellId;
8088 } // end of : for (MInt level = m_minLevel; level <= m_maxRfnmntLvl; ++level)
8089
8090 m_noCells = currentLocalCellId;
8091
8092 } // end of : extra '{}' span for sending / receiving the new cells.
8093
8094 RECORD_TIMER_STOP(t_recreateCells);
8095
8096 // =============================
8097 // #=- Regenerate halo cells -=#
8098 // =============================
8099
8100#ifdef MAIA_EXTRA_DEBUG
8101 m_log << "DynamicLoadBalancing Extra Debug: Step 5 - Regenerate halo cells" << endl;
8102#endif
8103
8104 RECORD_TIMER_START(t_createHaloCells);
8105
8106 // Resetting neighborDomainInformation.
8110 noCellsToReceive.fill(0);
8111
8112 // Map to collect all missing halo cells
8113 map<MLong, MInt> haloCellsMap;
8114
8115 // 1. Get the number of missing parents up to the m_minLevel
8116 MInt parentDepth = 0;
8117 MLong parentId = -1;
8118 for(MInt level = m_minLevel; level <= m_maxRfnmntLvl; ++level) {
8119 if(globalOffset[globalDomainId()] == a_globalId(m_levelOffsets[level][0])) {
8120 parentDepth = a_level(m_levelOffsets[level][0]) - m_minLevel;
8121 parentId = a_parentId(m_levelOffsets[level][0]);
8122 break;
8123 }
8124 }
8125
8126 m_noMissingParents = parentDepth;
8127 MInt currentId = 0;
8128
8129 // 2. Add the first missing parent to the map.
8130 if(parentId > -1) {
8131 haloCellsMap.insert(make_pair(parentId, currentId));
8132 ++currentId;
8133 --parentDepth;
8134 }
8135
8136 // 3. Look for more parents.
8137 MBool stillLookingForParents = true;
8138 while(stillLookingForParents) {
8139 // 3.1. Gather from all domains, the number of parents currently missing.
8140 MIntScratchSpace parentDepthGathered(noDomains(), AT_, "parentDepthGathered");
8141 parentDepthGathered.fill(0);
8142 MPI_Allgather(&parentDepth, 1, MPI_INT, parentDepthGathered.getPointer(), 1, MPI_INT, mpiComm(), AT_, "parentDepth",
8143 "parentDepthGathered.getPointer()");
8144
8145 MLong parentIdToLookFor = -1;
8146 MPI_Status status;
8147
8148 // 3.2. Calculate the domain to which our current missing parent belongs.
8149 MInt parentDomain = -1;
8150 for(MInt i = 0; i < noDomains(); ++i) {
8151 if(parentId < globalOffset[i]) {
8152 parentDomain = i - 1;
8153 break;
8154 }
8155 }
8156
8157 // 3.3. Gather from all domains, which domain will send us a parent.
8158 MIntScratchSpace parentDomainGathered(noDomains(), AT_, "parentDomainGathered");
8159 parentDomainGathered.fill(-1);
8160 MPI_Allgather(&parentDomain, 1, MPI_INT, parentDomainGathered.getPointer(), 1, MPI_INT, mpiComm(), AT_,
8161 "parentDomain", "parentDomainGathered.getPointer()");
8162
8163
8164 // 3.4. Communication...
8165 for(MInt dom = 0; dom < noDomains(); ++dom) {
8166 // 3.4.a) If its our turn:
8167 if((dom == globalDomainId()) && (parentDepthGathered[globalDomainId()] > 0)) {
8168 // Send the parent id we have.
8169 MPI_Send(&parentId, 1, MPI_LONG, parentDomain, parentDomain, mpiComm(), AT_, "parentId");
8170 // Wait for the parent of the parent.
8171 MPI_Recv(&parentId, 1, MPI_LONG, parentDomain, parentDomain, mpiComm(), &status, AT_, "parentId");
8172 // Add the new halo parent to the map.
8173 // #ifdef MAIA_EXTRA_DEBUG
8174 // m_log << "DynamicLoadBalancing Debug: Adding halo partition level ancestor with parentId " <<
8175 // parentId << " to the haloCellsMap." << endl;
8176 // #endif
8177 haloCellsMap.insert(make_pair(parentId, currentId));
8178 ++currentId;
8179 } // end of : if ( (dom == globalDomainId()) && (parentDepthGathered[globalDomainId()] > 0) )
8180
8181 // 3.5.b) If it's not our turn and the other domain sends us a parent:
8182 if((parentDomainGathered[dom] == globalDomainId()) && (parentDepthGathered[dom] > 0)) {
8183 // Receive the parent.
8184 MPI_Recv(&parentIdToLookFor, 1, MPI_LONG, dom, globalDomainId(), mpiComm(), &status, AT_, "parentIdToLookFor");
8185 // Search for it and save the parent of the parent.
8186 for(MInt i = 0; i < m_noCells; ++i) {
8187 if(a_globalId(i) == parentIdToLookFor) {
8188 parentIdToLookFor = a_parentId(i);
8189 break;
8190 }
8191 }
8192 // Sends back the parent of the parent.
8193 MPI_Send(&parentIdToLookFor, 1, MPI_LONG, dom, globalDomainId(), mpiComm(), AT_, "parentIdToLookFor");
8194 } // end of : if ( (parentDomainGathered[dom] == globalDomainId()) && (parentDepthGathered[dom] > 0) )
8195
8196 } // end of : for (MInt dom = 0; dom < noDomains(); ++dom)
8197
8198 // 3.5. Decrease the number of parents we need to find.
8199 if(parentDepth > 0) {
8200 --parentDepth;
8201 }
8202
8203 // 3.6. Look if any domain still search for more parents.
8204 MInt continueSearch = 0;
8205 MPI_Allreduce(&parentDepth, &continueSearch, 1, MPI_INT, MPI_SUM, mpiComm(), AT_, "parentDepth", "continueSearch");
8206
8207 if(continueSearch == 0) {
8208 stillLookingForParents = false;
8209 }
8210
8211 } // end of : while (stillLookingForParents)
8212
8213 // 4. Taging window cells and adding halo cells to the map.
8214 for(MInt i = 0; i < m_noCells; ++i) {
8215 a_hasProperty(i, 3) = 0;
8216 a_hasProperty(i, 4) = 0;
8217
8218 // 4.1. Looks for halo neighbors.
8219 for(MInt ngh = 0; ngh < m_noNeighbors; ++ngh) {
8220 if(a_neighborId(i, ngh) == -1) {
8221 continue;
8222 }
8223 if((a_neighborId(i, ngh) < globalOffset[globalDomainId()])
8224 || (a_neighborId(i, ngh) >= globalOffset[globalDomainId()] + m_noCells)) {
8225 if(haloCellsMap.count(a_neighborId(i, ngh)) == 0) {
8226 // #ifdef MAIA_EXTRA_DEBUG
8227 // m_log << "DynamicLoadBalancing Debug: Adding halo neighborId " << a_neighborId(i, ngh) << "
8228 // to the haloCellsMap." << endl;
8229 // #endif
8230 haloCellsMap.insert(make_pair(a_neighborId(i, ngh), currentId));
8231 ++currentId;
8232 }
8233 a_hasProperty(i, 3) = 1;
8234 }
8235 } // end of : for (MInt ngh = 0; ngh < m_noNeighbors; ++ngh)
8236
8237 // 4.2. Looks for halo childs.
8238 for(MInt child = 0; child < m_maxNoChildren; ++child) {
8239 if(a_childId(i, child) == -1) {
8240 continue;
8241 }
8242
8243 if((a_childId(i, child) < globalOffset[globalDomainId()])
8244 || (a_childId(i, child) >= globalOffset[globalDomainId()] + m_noCells)) {
8245 if(haloCellsMap.count(a_childId(i, child)) == 0) {
8246 // #ifdef MAIA_EXTRA_DEBUG
8247 // m_log << "DynamicLoadBalancing Debug: Adding halo childId " << a_childId(i, child) << " to
8248 // the haloCellsMap." << endl;
8249 // #endif
8250 haloCellsMap.insert(make_pair(a_childId(i, child), currentId));
8251 ++currentId;
8252 }
8253 a_hasProperty(i, 3) = 1;
8254 }
8255 } // end of : for (MInt child = 0; child < m_maxNoChildren; ++child)
8256
8257 // 4.3. Looks for halo parents.
8258 if((a_parentId(i) < globalOffset[globalDomainId()])
8259 || (a_parentId(i) >= globalOffset[globalDomainId()] + m_noCells)) {
8260 if(a_parentId(i) == -1) {
8261 continue;
8262 }
8263
8264 if(haloCellsMap.count(a_parentId(i)) == 0) {
8265 // #ifdef MAIA_EXTRA_DEBUG
8266 // m_log << "DynamicLoadBalancing Debug: Adding halo parentId " << a_parentId(i) << " to the
8267 // haloCellsMap." << endl;
8268 // #endif
8269 haloCellsMap.insert(make_pair(a_parentId(i), currentId));
8270 ++currentId;
8271 }
8272 a_hasProperty(i, 3) = 1;
8273 } // end of : if ( (a_parentId(i) < globalOffset[globalDomainId()]) || (a_parentId(i) >=
8274 // globalOffset[globalDomainId()] + m_noCells) )
8275
8276 } // end of : for (MInt i = 0; i < m_noCells; ++i)
8277
8278 // 5. Creating haloInformation which holds:
8279 // - [0] == An identifier
8280 // - [1] == The global id of the halo cell.
8281 // - [2] == The domain to which the corresponding window cell belongs.
8282 MLongScratchSpace haloInformation((MInt)haloCellsMap.size(), 3, AT_, "haloInformation");
8283 haloInformation.fill(-2);
8284
8285 // 5.1. Looks for the domain id of the halo cells
8286 currentId = 0;
8287 // #ifdef MAIA_EXTRA_DEBUG
8288 // m_log << "DynamicLoadBalancing Extra Debug: Creating haloInformation array... " << endl;
8289 // #endif
8290 for(map<MLong, MInt>::iterator i = haloCellsMap.begin(); i != haloCellsMap.end(); ++i) {
8291 for(MLong dom = 0; dom < (MLong)noDomains(); ++dom) {
8292 if((globalOffset[dom] <= i->first) && (globalOffset[dom + 1] > i->first)) {
8293 haloInformation(currentId, 0) = (MInt)i->second;
8294 haloInformation(currentId, 1) = i->first;
8295 haloInformation(currentId, 2) = dom;
8296 // #ifdef MAIA_EXTRA_DEBUG
8297 // m_log << "haloInformation(currentId, 0) is " << haloInformation(currentId, 0) << " ";
8298 // m_log << "haloInformation(currentId, 1) is " << haloInformation(currentId, 1) << " ";
8299 // m_log << "haloInformation(currentId, 2) is " << haloInformation(currentId, 2) << endl;
8300 // #endif
8301 ++currentId;
8302 ++noCellsToReceive[dom];
8303 break;
8304 } // end of : if ( (globalOffset[dom] <= i->first) && (globalOffset[dom+1] > i->first) )
8305 } // end of : for (MInt dom = 0; dom < noDomains(); ++dom)
8306
8307 } // end of : for (map<MInt, MInt>::iterator i = haloCellsMap.begin(); i != haloCellsMap.end(); ++i)
8308
8309 // 6. Communicating the whole informations of the halo cells.
8310 // 6.1. Preparation...
8311 for(MInt i = 0; i < noDomains(); ++i) {
8312 if(noCellsToReceive[i] > 0) {
8313 noCellsToReceive[noDomains()] += noCellsToReceive[i];
8314 }
8315 }
8316
8317 noCellsToSend.fill(0);
8318 for(MInt i = 0; i < noDomains(); ++i) {
8319 MPI_Scatter(noCellsToReceive.getPointer(), 1, MPI_INT, &noCellsToSend[i], 1, MPI_INT, i, mpiComm(), AT_,
8320 "noCellsToReceive.getPointer()", "noCellsToSend[i]");
8321 }
8322
8323 for(MInt i = 0; i < noDomains(); ++i) {
8324 if(noCellsToSend[i] > 0) {
8325 noCellsToSend[noDomains()] += noCellsToSend[i];
8326 }
8327 }
8328
8329 for(MInt i = 0; i < noDomains(); ++i) {
8330 if((noCellsToSend[i] > 0) || (noCellsToReceive[i] > 0)) {
8332 }
8333 }
8334
8335 mAlloc(m_neighborDomains, m_noNeighborDomains, "m_neighborDomains", -1, AT_);
8336 mAlloc(m_rfnCountHalosDom, m_noNeighborDomains, "m_rfnCountHalosDom", 0, AT_);
8337
8338 currentId = 0;
8339 for(MInt i = 0; i < noDomains(); ++i) {
8340 if((noCellsToSend[i] > 0) || (noCellsToReceive[i] > 0)) {
8341 m_neighborDomains[currentId] = i;
8342 ++currentId;
8343 }
8344 }
8345
8346 // 6.2. Sending first which halo cells are needed to the other domain.
8347 MLongScratchSpace cellsToSendGlobalId(noCellsToSend[noDomains()], AT_, "cellsToSendGlobalId");
8348
8349 { // extra '{}' span for communicating globalIds of the window cell we need to receive
8350 MLongScratchSpace dataToSend(noCellsToReceive[noDomains()], AT_, "dataToSend");
8351 MLongScratchSpace dataToReceive(noCellsToSend[noDomains()], AT_, "dataToReceive");
8352
8353 MInt offset = 0;
8354 for(MInt dom = 0; dom < m_noNeighborDomains; ++dom) {
8355 currentId = 0;
8356 for(MInt i = 0; i < (signed)haloCellsMap.size(); ++i) {
8357 if(haloInformation(i, 2) == m_neighborDomains[dom]) {
8358 dataToSend(currentId + offset) = haloInformation(i, 1);
8359 ++currentId;
8360 }
8361 }
8362 offset += currentId;
8363 } // end of : for (MInt dom = 0; dom < m_noNeighborDomains; ++dom)
8364
8365 communicateLong(dataToReceive, noCellsToSend, dataToSend, noCellsToReceive);
8366
8367 offset = 0;
8368 for(MInt dom = 0; dom < m_noNeighborDomains; ++dom) {
8369 for(MInt i = 0; i < noCellsToSend[m_neighborDomains[dom]]; ++i) {
8370 // m_log << "Receiving from Domain " << m_neighborDomains[dom] << " globalId " << dataToReceive(i +
8371 // offset) << endl;
8372 cellsToSendGlobalId(i + offset) = dataToReceive(i + offset);
8373 // m_log << "Saved value is " << cellsToSendGlobalId(i + offset) << endl;
8374 }
8375 offset += noCellsToSend[m_neighborDomains[dom]];
8376 } // end of : for (MInt dom = 0; dom < m_noNeighborDomains; ++dom)
8377 } // end of : extra '{}' span for communicating globalIds of the window cell we need to receive
8378
8379 // 6.3. Send / Receive the new halo cells.
8380 { // extra '{}' span for sending / receiving the new halo cells.
8381
8382 MLongScratchSpace newParentId((MInt)haloCellsMap.size(), AT_, "newParentId");
8383 MLongScratchSpace newGlobalId((MInt)haloCellsMap.size(), AT_, "newGlobalId");
8384 MIntScratchSpace newLevel((MInt)haloCellsMap.size(), AT_, "newLevel");
8385 MIntScratchSpace newNoChildren((MInt)haloCellsMap.size(), AT_, "newNoChildren");
8386
8387 MLongScratchSpace newChildId((MInt)haloCellsMap.size(), m_maxNoChildren, AT_, "newChildId");
8388 MLongScratchSpace newNeighborId((MInt)haloCellsMap.size(), m_noNeighbors, AT_, "newNeighborId");
8389 MIntScratchSpace newProperty((MInt)haloCellsMap.size(), 8, AT_, "newProperty");
8390 MIntScratchSpace newIsInSolver((MInt)haloCellsMap.size(), m_noSolvers, AT_, "newIsInSolver");
8391 MIntScratchSpace newIsSolverBoundary((MInt)haloCellsMap.size(), m_noSolvers, AT_, "newIsSolverBoundary");
8392 MIntScratchSpace newIsToRefineForSolver((MInt)haloCellsMap.size(), m_noSolvers, AT_, "newIsToRefineForSolver");
8393 MFloatScratchSpace newCoordinate((MInt)haloCellsMap.size(), nDim, AT_, "newCoordinate");
8394
8395 MIntScratchSpace windowCellLocalId(noCellsToSend[noDomains()], AT_, "windowCellLocalId");
8396 MIntScratchSpace windowCellLocalIdOffset(m_noNeighborDomains, AT_, "windowCellLocalIdOffset");
8397
8398 // 6.3.1. Getting window cell local ids.
8399 currentId = 0;
8400 MInt offset = 0;
8401 for(MInt dom = 0; dom < m_noNeighborDomains; ++dom) {
8402 MInt domain = m_neighborDomains[dom];
8403
8404 windowCellLocalIdOffset[dom] = currentId;
8405 // m_log << "domain is " << domain << endl;
8406 // m_log << "noCellsToSend[" << domain<< "] is " << noCellsToSend[domain] << endl;
8407 // m_log << "offset is " << offset << endl;
8408
8409 for(MInt cellId = 0; cellId < m_noCells; ++cellId) {
8410 for(MInt i = 0; i < noCellsToSend[domain]; ++i) {
8411 if(cellsToSendGlobalId(i + offset) == a_globalId(cellId)) {
8412 // m_log << "Both are Equal!!! ";
8413 // m_log << "noCells left to find are " << noCellsToSend[domain] - currentId + offset << endl;
8414 // m_log << cellsToSendGlobalId(i + offset) << " == " << a_globalId(cellId) << endl;
8415 windowCellLocalId[currentId] = cellId;
8416 ++currentId;
8417 break;
8418 } // end of : if (cellsToSendGlobalId(i + offset) == m_cells->a[cellId].m_globalId[0])
8419 } // end of : for (MInt i = 0; i < noCellsToSend[domain]; ++i)
8420
8421 } // end of : for (MInt cellId = 0; cellId < m_noCells; ++cellId)
8422 offset += noCellsToSend[domain];
8423
8424 } // end of : for (MInt dom = 0; dom < m_noNeighborDomains; ++dom)
8425
8426 MIntScratchSpace haloOffset(m_noNeighborDomains, AT_, "haloOffset");
8427 if(m_noNeighborDomains > 0) {
8428 haloOffset[0] = 0;
8429 }
8430
8431 for(MInt dom = 1; dom < m_noNeighborDomains; ++dom) {
8432 haloOffset[dom] = haloOffset[dom - 1] + noCellsToReceive[m_neighborDomains[dom - 1]];
8433 }
8434
8435 // 6.3.2. Communicate halo/window data...
8436 { // sending / receiving parentId
8437 MLongScratchSpace sendBuffer(noCellsToSend[noDomains()], AT_, "sendBuffer");
8438
8439 currentId = 0;
8440 for(MInt dom = 0; dom < m_noNeighborDomains; ++dom) {
8441 MInt domain = m_neighborDomains[dom];
8442
8443 for(MInt i = windowCellLocalIdOffset[dom]; i < (windowCellLocalIdOffset[dom] + noCellsToSend[domain]); ++i) {
8444 sendBuffer(currentId) = a_parentId(windowCellLocalId(i));
8445 ++currentId;
8446 }
8447 }
8448
8449 communicateLong(newParentId, noCellsToReceive, sendBuffer, noCellsToSend);
8450 } // end of : sending / receiving parentId
8451
8452 { // sending / receiving globalId
8453 MLongScratchSpace sendBuffer(noCellsToSend[noDomains()], AT_, "sendBuffer");
8454
8455 currentId = 0;
8456 for(MInt dom = 0; dom < m_noNeighborDomains; ++dom) {
8457 MInt domain = m_neighborDomains[dom];
8458
8459 for(MInt i = windowCellLocalIdOffset[dom]; i < (windowCellLocalIdOffset[dom] + noCellsToSend[domain]); ++i) {
8460 sendBuffer(currentId) = a_globalId(windowCellLocalId(i));
8461 ++currentId;
8462 }
8463 }
8464
8465 communicateLong(newGlobalId, noCellsToReceive, sendBuffer, noCellsToSend);
8466 } // end of : sending / receiving GlobalId
8467
8468 { // sending / receiving level
8469 MIntScratchSpace sendBuffer(noCellsToSend[noDomains()], AT_, "sendBuffer");
8470
8471 currentId = 0;
8472 for(MInt dom = 0; dom < m_noNeighborDomains; ++dom) {
8473 MInt domain = m_neighborDomains[dom];
8474
8475 for(MInt i = windowCellLocalIdOffset[dom]; i < (windowCellLocalIdOffset[dom] + noCellsToSend[domain]); ++i) {
8476 sendBuffer(currentId) = a_level(windowCellLocalId(i));
8477 ++currentId;
8478 }
8479 }
8480
8481 communicateInt(newLevel, noCellsToReceive, sendBuffer, noCellsToSend);
8482 } // end of : sending / receiving level
8483
8484 { // sending / receiving noChildren
8485 MIntScratchSpace sendBuffer(noCellsToSend[noDomains()], AT_, "sendBuffer");
8486
8487 currentId = 0;
8488 for(MInt dom = 0; dom < m_noNeighborDomains; ++dom) {
8489 MInt domain = m_neighborDomains[dom];
8490
8491 for(MInt i = windowCellLocalIdOffset[dom]; i < (windowCellLocalIdOffset[dom] + noCellsToSend[domain]); ++i) {
8492 sendBuffer(currentId) = a_noChildren(windowCellLocalId(i));
8493 ++currentId;
8494 }
8495 }
8496
8497 communicateInt(newNoChildren, noCellsToReceive, sendBuffer, noCellsToSend);
8498 } // end of : sending / receiving noChildren
8499
8500 for(MInt childId = 0; childId < m_maxNoChildren; ++childId) { // sending / receiving childId
8501 MLongScratchSpace sendBuffer(noCellsToSend[noDomains()], AT_, "sendBuffer");
8502 MLongScratchSpace recvBuffer(noCellsToReceive[noDomains()], AT_, "recvBuffer");
8503
8504 currentId = 0;
8505 for(MInt dom = 0; dom < m_noNeighborDomains; ++dom) {
8506 MInt domain = m_neighborDomains[dom];
8507
8508 for(MInt i = windowCellLocalIdOffset[dom]; i < (windowCellLocalIdOffset[dom] + noCellsToSend[domain]); ++i) {
8509 sendBuffer(currentId) = a_childId(windowCellLocalId(i), childId);
8510 ++currentId;
8511 }
8512 }
8513
8514 communicateLong(recvBuffer, noCellsToReceive, sendBuffer, noCellsToSend);
8515
8516 for(MInt i = 0; i < noCellsToReceive[noDomains()]; ++i) {
8517 newChildId(i, childId) = recvBuffer(i);
8518 }
8519
8520 } // end of : sending / receiving childId
8521
8522 for(MInt neighborId = 0; neighborId < m_noNeighbors; ++neighborId) { // sending / receiving neighborId
8523 MLongScratchSpace sendBuffer(noCellsToSend[noDomains()], AT_, "sendBuffer");
8524 MLongScratchSpace recvBuffer(noCellsToReceive[noDomains()], AT_, "recvBuffer");
8525
8526 currentId = 0;
8527 for(MInt dom = 0; dom < m_noNeighborDomains; ++dom) {
8528 MInt domain = m_neighborDomains[dom];
8529
8530 for(MInt i = windowCellLocalIdOffset[dom]; i < (windowCellLocalIdOffset[dom] + noCellsToSend[domain]); ++i) {
8531 sendBuffer(currentId) = a_neighborId(windowCellLocalId(i), neighborId);
8532 ++currentId;
8533 }
8534 }
8535
8536 communicateLong(recvBuffer, noCellsToReceive, sendBuffer, noCellsToSend);
8537
8538 for(MInt i = 0; i < noCellsToReceive[noDomains()]; ++i) {
8539 newNeighborId(i, neighborId) = recvBuffer(i);
8540 }
8541
8542 } // end of : sending / receiving neighborId
8543
8544 for(MInt property = 0; property < 8; ++property) { // sending / receiving property
8545 MIntScratchSpace sendBuffer(noCellsToSend[noDomains()], AT_, "sendBuffer");
8546 MIntScratchSpace recvBuffer(noCellsToReceive[noDomains()], AT_, "recvBuffer");
8547
8548 currentId = 0;
8549 for(MInt dom = 0; dom < m_noNeighborDomains; ++dom) {
8550 MInt domain = m_neighborDomains[dom];
8551
8552 for(MInt i = windowCellLocalIdOffset[dom]; i < (windowCellLocalIdOffset[dom] + noCellsToSend[domain]); ++i) {
8553 sendBuffer(currentId) = a_hasProperty(windowCellLocalId(i), property);
8554 ++currentId;
8555 }
8556 }
8557
8558 communicateInt(recvBuffer, noCellsToReceive, sendBuffer, noCellsToSend);
8559
8560 for(MInt i = 0; i < noCellsToReceive[noDomains()]; ++i) {
8561 newProperty(i, property) = recvBuffer(i);
8562 }
8563
8564 } // end of : sending / receiving property
8565
8566 for(MInt solver = 0; solver < m_noSolvers; solver++) { // sending / receiving of solver affiliation
8567 MIntScratchSpace sendBuffer(noCellsToSend[noDomains()], AT_, "sendBuffer");
8568 MIntScratchSpace recvBuffer(noCellsToReceive[noDomains()], AT_, "recvBuffer");
8569
8570 currentId = 0;
8571 for(MInt dom = 0; dom < m_noNeighborDomains; ++dom) {
8572 MInt domain = m_neighborDomains[dom];
8573
8574 for(MInt i = windowCellLocalIdOffset[dom]; i < (windowCellLocalIdOffset[dom] + noCellsToSend[domain]); ++i) {
8575 sendBuffer(currentId) = a_isInSolver(windowCellLocalId(i), solver);
8576 ++currentId;
8577 }
8578 }
8579
8580 communicateInt(recvBuffer, noCellsToReceive, sendBuffer, noCellsToSend);
8581
8582 for(MInt i = 0; i < noCellsToReceive[noDomains()]; ++i) {
8583 newIsInSolver(i, solver) = recvBuffer(i);
8584 }
8585 }
8586
8587 for(MInt solver = 0; solver < m_noSolvers; solver++) { // sending / receiving of solver boundary
8588 MIntScratchSpace sendBuffer(noCellsToSend[noDomains()], AT_, "sendBuffer");
8589 MIntScratchSpace recvBuffer(noCellsToReceive[noDomains()], AT_, "recvBuffer");
8590
8591 currentId = 0;
8592 for(MInt dom = 0; dom < m_noNeighborDomains; ++dom) {
8593 MInt domain = m_neighborDomains[dom];
8594
8595 for(MInt i = windowCellLocalIdOffset[dom]; i < (windowCellLocalIdOffset[dom] + noCellsToSend[domain]); ++i) {
8596 sendBuffer(currentId) = a_isSolverBoundary(windowCellLocalId(i), solver);
8597 ++currentId;
8598 }
8599 }
8600
8601 communicateInt(recvBuffer, noCellsToReceive, sendBuffer, noCellsToSend);
8602
8603 for(MInt i = 0; i < noCellsToReceive[noDomains()]; ++i) {
8604 newIsSolverBoundary(i, solver) = recvBuffer(i);
8605 }
8606 }
8607
8608 for(MInt solver = 0; solver < m_noSolvers; solver++) { // sending / receiving of solver boundary
8609 MIntScratchSpace sendBuffer(noCellsToSend[noDomains()], AT_, "sendBuffer");
8610 MIntScratchSpace recvBuffer(noCellsToReceive[noDomains()], AT_, "recvBuffer");
8611
8612 currentId = 0;
8613 for(MInt dom = 0; dom < m_noNeighborDomains; ++dom) {
8614 MInt domain = m_neighborDomains[dom];
8615
8616 for(MInt i = windowCellLocalIdOffset[dom]; i < (windowCellLocalIdOffset[dom] + noCellsToSend[domain]); ++i) {
8617 sendBuffer(currentId) = a_isSolverBoundary(windowCellLocalId(i), solver);
8618 ++currentId;
8619 }
8620 }
8621
8622 communicateInt(recvBuffer, noCellsToReceive, sendBuffer, noCellsToSend);
8623
8624 for(MInt i = 0; i < noCellsToReceive[noDomains()]; ++i) {
8625 newIsToRefineForSolver(i, solver) = recvBuffer(i);
8626 }
8627 }
8628
8629 for(MInt dim = 0; dim < nDim; ++dim) { // sending / receiving coordinate
8630 MFloatScratchSpace sendBuffer(noCellsToSend[noDomains()], AT_, "sendBuffer");
8631 MFloatScratchSpace recvBuffer(noCellsToReceive[noDomains()], AT_, "recvBuffer");
8632
8633 currentId = 0;
8634 for(MInt dom = 0; dom < m_noNeighborDomains; ++dom) {
8635 MInt domain = m_neighborDomains[dom];
8636
8637 for(MInt i = windowCellLocalIdOffset[dom]; i < (windowCellLocalIdOffset[dom] + noCellsToSend[domain]); ++i) {
8638 sendBuffer(currentId) = a_coordinate(windowCellLocalId(i), dim);
8639 ++currentId;
8640 }
8641 }
8642
8643 communicateDouble(recvBuffer, noCellsToReceive, sendBuffer, noCellsToSend);
8644
8645 for(MInt i = 0; i < noCellsToReceive[noDomains()]; ++i) {
8646 newCoordinate(i, dim) = recvBuffer(i);
8647 }
8648
8649 } // end of : sending / receiving coordinate
8650
8651 for(MInt dom = 0; dom < m_noNeighborDomains; ++dom) {
8652 for(MInt i = haloOffset[dom]; i < (haloOffset[dom] + noCellsToReceive[m_neighborDomains[dom]]); ++i) {
8653 newProperty(i, 3) = 0;
8654 newProperty(i, 4) = 1;
8655 }
8656 }
8657
8658 // 7. Recreate halo cells from the communication data.
8660 mAlloc(m_haloCellOffsets, m_noNeighborDomains, 2 * (m_maxRfnmntLvl - m_minLevel + 1), "m_haloCellOffsets", 0, AT_);
8662
8663 MInt currentLocalCellId = m_maxNoCells - 2;
8664 for(MInt level = m_minLevel; level <= m_maxRfnmntLvl; ++level) {
8665 m_haloCellOffsetsLevel[level][1] = currentLocalCellId + 1;
8666
8667 for(MInt dom = m_noNeighborDomains - 1; dom > -1; --dom) {
8668 m_haloCellOffsets[dom][(2 * (level - m_minLevel)) + 1] = currentLocalCellId + 1;
8669
8670 for(MInt cellId = (haloOffset[dom] + noCellsToReceive[m_neighborDomains[dom]]) - 1; cellId >= haloOffset[dom];
8671 --cellId) {
8672 if(newLevel(cellId) == level) {
8673 a_parentId(currentLocalCellId) = newParentId(cellId);
8674 a_globalId(currentLocalCellId) = newGlobalId(cellId);
8675 a_noChildren(currentLocalCellId) = newNoChildren(cellId);
8676 a_level(currentLocalCellId) = level;
8677
8678 for(MInt child = 0; child < m_maxNoChildren; ++child) {
8679 a_childId(currentLocalCellId, child) = newChildId(cellId, child);
8680 }
8681
8682 for(MInt ngh = 0; ngh < m_noNeighbors; ++ngh) {
8683 a_neighborId(currentLocalCellId, ngh) = newNeighborId(cellId, ngh);
8684 }
8685
8686 for(MInt dim = 0; dim < nDim; ++dim) {
8687 a_coordinate(currentLocalCellId, dim) = newCoordinate(cellId, dim);
8688 }
8689
8690 for(MInt property = 0; property < 8; ++property) {
8691 a_hasProperty(currentLocalCellId, property) = (MBool)newProperty(cellId, property);
8692 }
8693
8694 for(MInt solver = 0; solver < m_noSolvers; solver++) {
8695 a_isInSolver(currentLocalCellId, solver) = (MBool)newIsInSolver(cellId, solver);
8696 a_isSolverBoundary(currentLocalCellId, solver) = (MBool)newIsSolverBoundary(cellId, solver);
8697 a_isToRefineForSolver(currentLocalCellId, solver) = (MBool)newIsToRefineForSolver(cellId, solver);
8698 // not working in parallel yet anyway
8699 a_noSolidLayer(currentLocalCellId, solver) = -1;
8700 }
8701
8702 for(MInt solver = m_noSolvers; solver < 8; solver++) {
8703 a_isInSolver(currentLocalCellId, solver) = 0;
8704 a_isSolverBoundary(currentLocalCellId, solver) = 0;
8705 a_isToRefineForSolver(currentLocalCellId, solver) = 0;
8706 a_noSolidLayer(currentLocalCellId, solver) = -1;
8707 }
8708 --currentLocalCellId;
8709 } // end of : if (cells->a[cellId].m_level[0] == level)
8710
8711 } // end of : for (MInt i = (haloOffset[dom] + noCellsToReceive[m_neighborDomains[dom]]) - 1; i >=
8712 // haloOffset[dom]; --i)
8713
8714 m_haloCellOffsets[dom][(2 * (level - m_minLevel))] = currentLocalCellId + 1;
8715
8716 } // end of : for (MInt dom = 0; dom < m_noNeighborDomains; ++dom)
8717
8718 m_haloCellOffsetsLevel[level][0] = currentLocalCellId + 1;
8721 } // end of : for (MInt level = m_minLevel; level <= m_maxRfnmntLvl; ++level)
8722
8723 } // end of : extra '{}' span for sending / receiving the new halo cells.
8724
8725 RECORD_TIMER_STOP(t_createHaloCells);
8726
8727 // =======================
8728 // #=- Global to local -=#
8729 // =======================
8730
8731#ifdef MAIA_EXTRA_DEBUG
8732 m_log << "DynamicLoadBalancing Extra Debug: Step 6 - Global to local" << endl;
8733#endif
8734
8735 RECORD_TIMER_START(t_globalToLocal);
8736
8737 map<MLong, MInt> globalToLocal;
8738
8739 // 1. Add local cells to the map
8740 for(MInt i = 0; i < m_noCells; ++i) {
8741 globalToLocal.insert(make_pair(a_globalId(i), i));
8742 }
8743
8744 // 2. Add halo cells to the map
8745 for(MInt level = m_minLevel; level <= m_maxRfnmntLvl; ++level) {
8746 if(m_noHaloCellsOnLevel[level] > 0) {
8747 for(MInt i = m_haloCellOffsetsLevel[level][0]; i < m_haloCellOffsetsLevel[level][1]; ++i) {
8748 globalToLocal.insert(make_pair(a_globalId(i), i));
8749 }
8750 }
8751 }
8752
8753 // 3. Convert local cells
8754 for(MInt i = 0; i < m_noCells; ++i) {
8755 if(globalToLocal.count(a_parentId(i)) == 0) {
8756#ifdef MAIA_EXTRA_DEBUG
8757 if(a_parentId(i) > -1) {
8758 m_log << "DynamicLoadBalancing Debug: global parenId " << a_parentId(i) << " does not exist" << endl;
8759 }
8760#endif
8761 a_parentId(i) = -1;
8762 } else {
8763 a_parentId(i) = globalToLocal[a_parentId(i)];
8764 }
8765
8766 for(MInt ngh = 0; ngh < m_noNeighbors; ++ngh) {
8767 if(globalToLocal.count(a_neighborId(i, ngh)) == 0) {
8768#ifdef MAIA_EXTRA_DEBUG
8769 if(a_neighborId(i, ngh) > -1) {
8770 m_log << "DynamicLoadBalancing Debug: global nghbrId " << a_neighborId(i, ngh) << " does not exist" << endl;
8771 }
8772#endif
8773 a_neighborId(i, ngh) = -1;
8774 } else {
8775 a_neighborId(i, ngh) = globalToLocal[a_neighborId(i, ngh)];
8776 }
8777 }
8778
8780 for(MInt child = 0; child < m_maxNoChildren; ++child) {
8781 if(globalToLocal.count(a_childId(i, child)) == 0) {
8782#ifdef MAIA_EXTRA_DEBUG
8783 if(a_childId(i, child) > -1) {
8784 m_log << "DynamicLoadBalancing Debug: global childId " << a_childId(i, child) << " does not exist" << endl;
8785 }
8786#endif
8787 a_childId(i, child) = -1;
8788 --a_noChildren(i);
8789 } else {
8790 a_childId(i, child) = globalToLocal[a_childId(i, child)];
8791 }
8792 }
8793
8794 } // end of : for (MInt i = 0; i < m_noCells; ++i)
8795
8796 // 4. Convert halo cells
8797 for(MInt level = m_minLevel; level <= m_maxRfnmntLvl; ++level) {
8798 if(m_noHaloCellsOnLevel[level] > 0) {
8799 for(MInt i = m_haloCellOffsetsLevel[level][0]; i < m_haloCellOffsetsLevel[level][1]; ++i) {
8800 if(globalToLocal.count(a_parentId(i)) == 0) {
8801 a_parentId(i) = -1;
8802 } else {
8803 a_parentId(i) = globalToLocal[a_parentId(i)];
8804 }
8805
8806 for(MInt ngh = 0; ngh < m_noNeighbors; ++ngh) {
8807 if(globalToLocal.count(a_neighborId(i, ngh)) == 0) {
8808 a_neighborId(i, ngh) = -1;
8809 } else {
8810 a_neighborId(i, ngh) = globalToLocal[a_neighborId(i, ngh)];
8811 }
8812 }
8813
8814 a_noChildren(i) = 0;
8815 for(MInt child = 0; child < m_maxNoChildren; ++child) {
8816 if(globalToLocal.count(a_childId(i, child)) == 0) {
8817 a_childId(i, child) = -1;
8818 } else {
8819 a_childId(i, child) = globalToLocal[a_childId(i, child)];
8820 ++a_noChildren(i);
8821 }
8822 }
8823
8824 } // end of : for (MInt i = m_haloCellOffsetsLevel[level][0]; i < m_haloCellOffsetsLevel[level][1]; ++i)
8825
8826 } // end of : if (m_noHaloCellsOnLevel[level] > 0)
8827
8828 } // end of : for (MInt level = m_minLevel; level <= m_maxRfnmntLvl; ++level)
8829
8830 RECORD_TIMER_STOP(t_globalToLocal);
8831
8832 // ==========================
8833 // #=- Reset lookup table -=#
8834 // ==========================
8835
8836#ifdef MAIA_EXTRA_DEBUG
8837 m_log << "DynamicLoadBalancing Extra Debug: Step 6 - Reset lookup table" << endl;
8838#endif
8839
8840 m_cellIdLUT.clear();
8841
8842 for(MInt level = m_minLevel; level <= m_maxRfnmntLvl; ++level) {
8843 for(MInt cellId = m_levelOffsets[level][0]; cellId < m_levelOffsets[level][1]; cellId++) {
8844 m_cellIdLUT.insert(m_cellIdLUT.end(), make_pair(cellId, cellId));
8845 }
8846
8847 for(MInt cellId = m_haloCellOffsetsLevel[level][0]; cellId < m_haloCellOffsetsLevel[level][1]; cellId++) {
8848 m_cellIdLUT.insert(m_cellIdLUT.end(), make_pair(cellId, cellId));
8849 }
8850 }
8851
8852 RECORD_TIMER_STOP(t_dynamicLoadBalancing);
8853 return;
8854} // end of : void GridgenPar::dynamicLoadBalancing()
void mAlloc(T *&a, const MLong N, const MString &objectName, MString function)
allocates memory for one-dimensional array 'a' of size N
Definition: alloc.h:173
MBool mDeallocate(T *&a)
deallocates the memory previously allocated for element 'a'
Definition: alloc.h:544
void traverseDFGlobalId(MInt parentId, MLong *globalId_, MLongScratchSpace &partitionCellList, MFloatScratchSpace &workloadPerCell, MFloat *currentWorkload, MFloatScratchSpace &weight, MFloatScratchSpace &workload, MInt *j)
recursively traverses the octree
void communicateHaloGlobalIds(MInt level)
communicate the global ids of the halo cells.

◆ excludeInsideOutside()

template<MInt nDim>
void GridgenPar< nDim >::excludeInsideOutside ( MInt **  offsets,
MInt  level_,
MInt  solver 
)
protected
Author
Thomas Schilden
Date
03.04.2018

Before the inside outside check of a specific solver is performed, cells not belonging to the solver are marked as visited, that reduces the number of cells to flood in the following step: markInsideOutside( , ,solver) While doing so, the visited property is reset for cells that might be inside

Parameters
[in]level_the level to check
[in]solverspecific solver

Definition at line 1459 of file cartesiangridgenpar.cpp.

1459 {
1460 TRACE();
1461
1462 // reset "visited" property
1463 for(MInt i = offsets[level_][1] - 1; i >= offsets[level_][0]; i--) {
1464 if(a_isInSolver(i, solver)) {
1465 a_hasProperty(i, 6) = 0;
1466 } else {
1467 a_hasProperty(i, 6) = 1;
1468 }
1469 }
1470}

◆ finalizeGrid()

template<MInt nDim>
void GridgenPar< nDim >::finalizeGrid
protected

Definition at line 2000 of file cartesiangridgenpar.cpp.

2000 {
2001 TRACE();
2002
2003 RECORD_TIMER_START(m_t_finalizeGrid);
2004
2005 // 6.3 Check the refinement validity for LB.
2006 // Note: can be skipped via property for non-LB grids since this may take a really long time for large grids
2009 } else {
2010 outStream << " + NOTE: Skipping mesh validity check for LB" << endl;
2011 m_log << " + NOTE: Skipping mesh validity check for LB" << endl;
2012 }
2013
2014 // 6.4 we are finished, run the final setup, TODO labels:GRIDGEN,totest check the level, what is it needed for
2015 if(noDomains() > 1) {
2018 } else {
2020 }
2021
2022 m_noTotalCells = 0;
2023 for(MInt d = 0; d < noDomains(); d++) {
2025 }
2026 } else {
2030 }
2031
2032 RECORD_TIMER_STOP(m_t_finalizeGrid);
2033}
MBool m_checkGridLbValidity
void updateGlobalIdsReferences()
updates the references of all cells to use the global-ids
void checkLBRefinementValidity()
checks if this is a valid mesh also for LB computations
void updateInterRankNeighbors()
updates the neighbors on the neighboring ranks

◆ findChildLevelNeighbors()

template<MInt nDim>
void GridgenPar< nDim >::findChildLevelNeighbors ( MInt **  offsets,
MInt  level_ 
)
protected
Author
Andreas Lintermann
Date
11.10.2013

This algorithm runs over all children of a given level and updates the neighborhood. This is simply be done by checking if a missing connection is considered to be an inside or an outside connection:

  • inside connection: the neighbor is one of my siblings
  • outside connection: the neighbor is one of the sibling of a neighboring parent

The reconstruction is based on hardcoded neighboring connections, i.e., it is known for a given direction which internal sibling is a neighbor due to the relative position of a child beneath a parent. This is also given across neighboring parents. Therefore an outside neighbor can be found by going to the parent and then to the neighboring parent in the desired direction and then inspecting a certain child of this cell.

Parameters
[in]levelthe level of the parent, for which the neighborhood of the children need to be updated

Definition at line 2177 of file cartesiangridgenpar.cpp.

2177 {
2178 TRACE();
2179
2180 MInt t_refineGrid = 0;
2181 if(level_ < m_minLevel) {
2182 NEW_SUB_TIMER_STATIC(t_rfnGrid, "find new neighborhood", m_t_createInitialGrid);
2183 t_refineGrid = t_rfnGrid;
2184 } else if(level_ < m_maxUniformRefinementLevel) {
2185 NEW_SUB_TIMER_STATIC(t_rfnGrid, "find new neighborhood", m_t_createStartGrid);
2186 t_refineGrid = t_rfnGrid;
2187 } else if(level_ < m_maxRfnmntLvl) {
2188 NEW_SUB_TIMER_STATIC(t_rfnGrid, "find new neighborhood", m_t_createComputationalGrid);
2189 t_refineGrid = t_rfnGrid;
2190 }
2191
2192 RECORD_TIMER_START(t_refineGrid);
2193
2194 // loop over all parents
2195 for(MInt i = offsets[level_][0]; i < offsets[level_][1]; i++) {
2196 MInt parent = i;
2197 MLong* childIds = &a_childId(parent, 0);
2198
2199 // loop over all children
2200 for(MInt c = 0; c < m_maxNoChildren; c++) {
2201 if(childIds[c] < 0) continue;
2202
2203 MInt child = (MInt)childIds[c];
2204 // loop over all directions of a child
2205 for(MInt dir = 0; dir < m_noNeighbors; dir++) {
2206 if(a_neighborId(child, dir) == -1) {
2207 // this is an inner connection (nghInside3D is a 3D search array but should also work for 2D)
2208 if(nghInside3D[c][dir] >= 0) {
2209 a_neighborId(child, dir) = childIds[nghInside3D[c][dir]];
2210 } else { // this is an outside connection
2211 // 2D/3D Switch for nghAcrossCell
2212 const MInt chdir = (nDim == 3) ? nghAcrossCell3D[c][dir] : nghAcrossCell2D[c][dir];
2213
2214 if(a_neighborId(parent, dir) >= 0 && a_childId((MInt)a_neighborId(parent, dir), chdir) >= 0)
2215 a_neighborId(child, dir) = a_childId((MInt)a_neighborId(parent, dir), chdir);
2216 }
2217 }
2218 }
2219 }
2220 }
2221
2222 RECORD_TIMER_STOP(t_refineGrid);
2223}

◆ findHaloAndWindowCells()

template<MInt nDim>
void GridgenPar< nDim >::findHaloAndWindowCells ( std::vector< std::vector< MInt > > &  winCellIdsPerDomain,
std::vector< std::vector< MInt > > &  haloCellIdsPerDomain 
)
protected
Author
Thomas Schilden
Date
3.2.2016
Parameters
[in]winCellIdsPerDomain: vector of window cells to be filled
[in]haloCellIdsPerDomainvector of halo cells to be filled

Definition at line 9090 of file cartesiangridgenpar.cpp.

9091 {
9092 TRACE();
9093
9094 for(MInt dom = 0; dom < m_noNeighborDomains; dom++) {
9095 for(MInt i = 0; i < m_noCells; i++) {
9096 a_hasProperty(i, 3) = 0;
9097 }
9098
9099 // collect the halo cells and mark the window cells
9100 for(MInt lev = m_minLevel; lev <= m_maxRfnmntLvl; lev++) {
9101 MInt cnt = 0;
9102 MInt lev_pos = 2 * (lev - m_minLevel);
9103 for(MInt p = m_haloCellOffsets[dom][lev_pos]; p < m_haloCellOffsets[dom][lev_pos + 1]; p++) {
9104 const MInt cellId = m_cellIdLUT[p];
9105 haloCellIdsPerDomain[dom].push_back(cellId);
9106 for(MInt n = 0; n < m_noNeighbors; n++) {
9107 if(a_neighborId(cellId, n) < m_noCells && a_neighborId(cellId, n) > -1) {
9108 a_hasProperty((MInt)a_neighborId(cellId, n), 3) = 1;
9109 }
9110 }
9111 cnt++;
9112 }
9113 }
9114
9115 // collect the window cells
9116 for(MInt lev = m_minLevel; lev <= m_maxRfnmntLvl; lev++) {
9117 MInt cnt = 0;
9118 for(MInt i = m_levelOffsets[lev][0]; i < m_levelOffsets[lev][1]; i++) {
9119 if(a_hasProperty(m_cellIdLUT[i], 3)) {
9120 winCellIdsPerDomain[dom].push_back(m_cellIdLUT[i]);
9121 cnt++;
9122 }
9123 }
9124 }
9125 }
9126}

◆ findHaloAndWindowCellsKD()

template<MInt nDim>
void GridgenPar< nDim >::findHaloAndWindowCellsKD ( std::vector< std::vector< MInt > > &  winCellIdsPerDomain,
std::vector< std::vector< MInt > > &  haloCellIdsPerDomain 
)
protected
Author
Thomas Schilden
Date
25.08.2015

does the same as findHaloAndWindowCells

Jerry: The coordinate check is currently the only way i found out to get the right ids. Sending the level of the halo cell reduces the amoung of cells to look through, but it will also add another communication.

Definition at line 9142 of file cartesiangridgenpar.cpp.

9143 {
9144 TRACE();
9145 // 1. fill vectors that hold the halo cells local id.
9146 for(MInt dom = 0; dom < m_noNeighborDomains; dom++) {
9147 for(MInt i = 0; i < m_noCells; ++i) {
9148 a_hasProperty(i, 3) = 0;
9149 a_hasProperty(i, 4) = 0;
9150 }
9151
9152 for(MInt lev = m_minLevel; lev <= m_maxRfnmntLvl; lev++) {
9153 MInt lev_pos = 2 * (lev - m_minLevel);
9154 for(MInt p = m_haloCellOffsets[dom][lev_pos]; p < m_haloCellOffsets[dom][lev_pos + 1]; p++) {
9155 haloCellIdsPerDomain[dom].push_back(m_cellIdLUT[p]);
9156 }
9157 }
9158 }
9159
9160 // 2. Scatter the number of halo cells between the domains
9161 MIntScratchSpace noDataToSend(noDomains() + 1, AT_, "noDataToSend");
9162 MIntScratchSpace noDataToReceive(noDomains() + 1, AT_, "noDataToReceive");
9163 noDataToSend.fill(0);
9164 noDataToReceive.fill(0);
9165
9166 for(MInt i = 0; i < m_noNeighborDomains; ++i) {
9167 noDataToReceive[m_neighborDomains[i]] = (MInt)haloCellIdsPerDomain[i].size();
9168 noDataToReceive[noDomains()] += (MInt)haloCellIdsPerDomain[i].size();
9169 }
9170
9171 MPI_Alltoall(noDataToReceive.getPointer(), 1, MPI_INT, noDataToSend.getPointer(), 1, MPI_INT, mpiComm(), AT_,
9172 "noDataToReceive.getPointer()", "noDataToSend.getPointer()");
9173
9174 for(MInt i = 0; i < noDomains(); ++i) {
9175 noDataToSend[noDomains()] += noDataToSend[i];
9176 }
9177
9178 // 3. distribute the halo cells coordinates among the domains that have to communicate
9179 MFloatScratchSpace haloCoordinates(noDataToSend[noDomains()], nDim, AT_, "haloCoordinates");
9180 for(MInt dim = 0; dim < nDim; ++dim) {
9181 MFloatScratchSpace sendBuffer(noDataToSend[noDomains()], AT_, "sendBuffer");
9182 MFloatScratchSpace recvBuffer(noDataToReceive[noDomains()], AT_, "recvBuffer");
9183
9184 MInt offset = 0;
9185 for(MInt dom = 0; dom < m_noNeighborDomains; ++dom) {
9186 for(MInt i = 0; i < noDataToReceive[m_neighborDomains[dom]]; ++i) {
9187 recvBuffer(i + offset) = a_coordinate(haloCellIdsPerDomain[dom][i], dim);
9188 }
9189 offset += noDataToReceive[m_neighborDomains[dom]];
9190 }
9191
9192 communicateDouble(sendBuffer, noDataToSend, recvBuffer, noDataToReceive);
9193
9194 offset = 0;
9195 for(MInt dom = 0; dom < m_noNeighborDomains; ++dom) {
9196 for(MInt i = 0; i < noDataToSend[m_neighborDomains[dom]]; ++i) {
9197 haloCoordinates(i + offset, dim) = sendBuffer(i + offset);
9198 }
9199 offset += noDataToSend[m_neighborDomains[dom]];
9200 }
9201 }
9202
9203 // 4. distribute the halo cell levels among the domains that have to communicate
9204 MIntScratchSpace haloLevel(noDataToSend[noDomains()], AT_, "haloLevel");
9205 { // extra '{}' for sending / receiving halo cells level.
9206 MIntScratchSpace sendBuffer(noDataToSend[noDomains()], AT_, "sendBuffer");
9207 MIntScratchSpace recvBuffer(noDataToReceive[noDomains()], AT_, "recvBuffer");
9208
9209 MInt offset = 0;
9210 for(MInt dom = 0; dom < m_noNeighborDomains; ++dom) {
9211 for(MInt i = 0; i < noDataToReceive[m_neighborDomains[dom]]; ++i) {
9212 recvBuffer(i + offset) = a_level(haloCellIdsPerDomain[dom][i]);
9213 }
9214 offset += noDataToReceive[m_neighborDomains[dom]];
9215 }
9216
9217 communicateInt(sendBuffer, noDataToSend, recvBuffer, noDataToReceive);
9218
9219 offset = 0;
9220 for(MInt dom = 0; dom < m_noNeighborDomains; ++dom) {
9221 for(MInt i = 0; i < noDataToSend[m_neighborDomains[dom]]; ++i) {
9222 haloLevel(i + offset) = sendBuffer(i + offset);
9223 }
9224 offset += noDataToSend[m_neighborDomains[dom]];
9225 }
9226 } // end of : extra '{}' for sending / receiving halo cells level.
9227
9228 // 5. Get the correct window cell using coordinate check and add it to the vector.
9229 vector<Point<3>> pts;
9230 for(MInt cellId = 0; cellId < m_noCells; ++cellId) {
9231 IF_CONSTEXPR(nDim == 2) {
9232 Point<3> pt(a_coordinate(cellId, 0), a_coordinate(cellId, 1), 0.0, cellId);
9233 pts.push_back(pt);
9234 }
9235 else {
9236 Point<3> pt(a_coordinate(cellId, 0), a_coordinate(cellId, 1), a_coordinate(cellId, 2), cellId);
9237 pts.push_back(pt);
9238 }
9239 }
9240
9241 KDtree<3> tree(pts);
9242
9243 MInt offset = 0;
9244 for(MInt dom = 0; dom < m_noNeighborDomains; ++dom) {
9245 for(MInt i = 0; i < noDataToSend[m_neighborDomains[dom]]; ++i) {
9246 MInt cellId = -2;
9247 MFloat distance = -2.0;
9248 IF_CONSTEXPR(nDim == 2) {
9249 Point<3> pt(haloCoordinates(i + offset, 0), haloCoordinates(i + offset, 1), 0.0, cellId);
9250 cellId = tree.nearest(pt, distance);
9251 }
9252 else {
9253 Point<3> pt(haloCoordinates(i + offset, 0), haloCoordinates(i + offset, 1), haloCoordinates(i + offset, 2),
9254 cellId);
9255 cellId = tree.nearest(pt, distance);
9256 }
9257
9258 // contains the global Id of the cell that i have to send
9259 winCellIdsPerDomain[dom].push_back(cellId);
9260
9261 } // end of : for (MInt i = 0; i < noDataToSend[m_neighborDomains[dom]]; ++i)
9262 offset += noDataToSend[m_neighborDomains[dom]];
9263 } // end of : for (MInt dom = 0; dom < m_noNeighborDomains; ++dom)
9264}
int MPI_Alltoall(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Alltoall

◆ floodCells() [1/2]

template<MInt nDim>
void GridgenPar< nDim >::floodCells ( std::stack< MInt > *  fillStack,
MChar  marker 
)
protected
Author
Andreas Lintermann
Date
22.10.2013

Having found a cell do a flooding on the inside cells by checking the neighborhood recursively by making use of the stack. Only add cells that are not boundary cells.

Parameters
[in]fillStackthe stack carrying the initial cells
[in]markermarks if the cells are marked inside (1) or outside (0)

Definition at line 2293 of file cartesiangridgenpar.cpp.

2293 {
2294 TRACE();
2295
2296 while(!fillStack->empty()) {
2297 MInt currentId = fillStack->top();
2298 fillStack->pop();
2299
2300 for(MInt n = 0; n < m_noNeighbors; n++)
2301 if(a_neighborId(currentId, n) >= 0) {
2302 MInt nghbr = (MInt)a_neighborId(currentId, n);
2303
2304 // cell is not visited and is not a boundary cell
2305 if(!(a_hasProperty(nghbr, 6))) {
2306 if(!(a_hasProperty(nghbr, 1))) {
2307 fillStack->push(nghbr);
2308 a_hasProperty(nghbr, 0) = marker;
2309 a_hasProperty(nghbr, 6) = 1;
2310 } else {
2311 a_hasProperty(nghbr, 0) = 1;
2312 a_hasProperty(nghbr, 6) = 1;
2313 }
2314 }
2315 }
2316 }
2317}

◆ floodCells() [2/2]

template<MInt nDim>
void GridgenPar< nDim >::floodCells ( std::stack< MInt > *  fillStack,
MChar  marker,
MInt  solver 
)
protected

Definition at line 2320 of file cartesiangridgenpar.cpp.

2320 {
2321 TRACE();
2322
2323 while(!fillStack->empty()) {
2324 MInt currentId = fillStack->top();
2325 fillStack->pop();
2326
2327 for(MInt n = 0; n < m_noNeighbors; n++)
2328 if(a_neighborId(currentId, n) >= 0) {
2329 MInt nghbr = (MInt)a_neighborId(currentId, n);
2330
2331 // cell is not visited and is not a boundary cell
2332 if(!(a_hasProperty(nghbr, 6))) {
2333 if(!(a_isSolverBoundary(nghbr, solver))) {
2334 fillStack->push(nghbr);
2335 a_isInSolver(nghbr, solver) = marker;
2336 a_hasProperty(nghbr, 6) = 1;
2337 } else {
2338 a_isInSolver(nghbr, solver) = 1;
2339 a_hasProperty(nghbr, 6) = 1;
2340 }
2341 }
2342 }
2343 }
2344}

◆ getAdjacentGridCells()

template<MInt nDim>
MInt GridgenPar< nDim >::getAdjacentGridCells ( MInt  cellId,
MInt adjacentCells 
)
protected
Author
Lennart Schneiders, Andreas Lintermann
Date
27.11.2017
Parameters
[in]cellIdthe id of the cell to return the neighbors from
[in]adjacentCellspointer to an array that will be filled with the results

Definition at line 5625 of file cartesiangridgenpar.cpp.

5625 {
5626 MInt cnt = 0;
5627 set<MLong> nghbrs;
5628 for(MInt dir0 = 0; dir0 < 2 * nDim; dir0++) {
5629 MLong nghbrId0 = -1;
5630 if(a_neighborId(cellId, dir0) > -1) nghbrId0 = a_neighborId(cellId, dir0);
5631 if(nghbrId0 < 0) continue;
5632 nghbrs.insert(nghbrId0);
5633 for(MInt dir1 = 0; dir1 < 2 * nDim; dir1++) {
5634 if((dir1 / 2) == (dir0 / 2)) continue;
5635 MLong nghbrId1 = -1;
5636 if(a_neighborId((MInt)nghbrId0, dir1) > -1) nghbrId1 = a_neighborId((MInt)nghbrId0, dir1);
5637 if(nghbrId1 < 0) continue;
5638 nghbrs.insert(nghbrId1);
5639 IF_CONSTEXPR(nDim == 3) {
5640 for(MInt dir2 = 0; dir2 < 2 * nDim; dir2++) {
5641 if(((dir2 / 2) == (dir0 / 2)) || ((dir2 / 2) == (dir1 / 2))) continue;
5642 MLong nghbrId2 = -1;
5643 if(a_neighborId((MInt)nghbrId1, dir2) > -1) nghbrId2 = a_neighborId((MInt)nghbrId1, dir2);
5644 if(nghbrId2 < 0) continue;
5645 nghbrs.insert(nghbrId2);
5646 }
5647 }
5648 }
5649 }
5650 set<MLong>::iterator it = nghbrs.begin();
5651 for(it = nghbrs.begin(); it != nghbrs.end(); it++) {
5652 ASSERT(cnt < 27, "");
5653 adjacentCells[cnt] = (MInt)*it;
5654 cnt++;
5655 }
5656 return cnt;
5657}

◆ getLastNonWindowCell()

template<MInt nDim>
MInt GridgenPar< nDim >::getLastNonWindowCell ( MInt  no_consider,
MInt  last 
)
protected

◆ gridAlignCutOff()

template<MInt nDim>
void GridgenPar< nDim >::gridAlignCutOff
protected
Author
Thomas schilden
Date
20.02.2016

aligns the cutOffCoordinates of boxes with the grid on the m_minLevel this is necessary for cutOffs at levels higher than m_minLevel

Definition at line 1294 of file cartesiangridgenpar.cpp.

1294 {
1295 MFloat cellLength = m_lengthOnLevel[m_minLevel];
1296 for(MInt solver = 0; solver < m_noSolvers; solver++) {
1297 SolverRefinement* bp = m_solverRefinement + solver;
1298 for(MInt c = 0; c < (signed)bp->cutOffMethods.size(); c++) {
1299 if(!(bp->cutOffMethods[c] == "B" || bp->cutOffMethods[c] == "iB")) continue;
1300 for(MInt dim = 0; dim < nDim; dim++) {
1301 for(MInt dir = 0; dir < 2; dir++) {
1302 MFloat relCoord = bp->cutOffCoordinates[c][dim + dir * nDim] - m_centerOfGravity[dim];
1303 MInt n = -1;
1304 if(bp->cutOffMethods[c] == "B") {
1305 n = (MInt)floor(relCoord / cellLength + 0.5);
1306 } else if(bp->cutOffMethods[c] == "iB") {
1307 n = (MInt)ceil(relCoord / cellLength + 0.5);
1308 }
1309 bp->cutOffCoordinates[c][dim + dir * nDim] = n * cellLength + m_centerOfGravity[dim];
1310 }
1311 }
1312 }
1313 }
1314}
std::vector< MString > cutOffMethods

◆ initGeometry()

template<MInt nDim>
void GridgenPar< nDim >::initGeometry
protected
Author
Andreas Lintermann
Date
11.10.2013
  • Creates a new Geometry-object depending on the dimensionality of the problem.
  • Prints out further information about the geometry

Definition at line 1203 of file cartesiangridgenpar.cpp.

1203 {
1204 TRACE();
1205
1206 RECORD_TIMER_START(m_t_initGeometry);
1207
1208 m_log << " (3) initializing geometry" << endl;
1209 outStream << " (3) initializing geometry" << endl;
1210
1212
1213 mAlloc(m_noBndIdsPerSolver, m_geometry->noNodes(), AT_, 0, "noBndIds");
1214 for(MInt solver = 0; solver < m_geometry->noNodes(); solver++) {
1216 }
1217 mAlloc(m_bndCutInfo, m_geometry->noNodes(), m_noBndIdsPerSolver, AT_, "bndCutInfo");
1218
1220
1221
1222 // Use the given multisolver bounding box as bounding box for the grid generation (and not only for
1223 // sorting by a different Hilbert curve if the given min-levels are different)
1225 m_log << "Using multisolver bounding box information from property file" << std::endl;
1226 for(MInt i = 0; i < nDim; i++) {
1227 TERMM_IF_COND(m_boundingBox[i] < m_multiSolverBoundingBox[i],
1228 "Multisolver bounding box error (dim: " + std::to_string(i) + "): "
1229 + std::to_string(m_boundingBox[i]) + " < " + std::to_string(m_multiSolverBoundingBox[i]));
1230 TERMM_IF_COND(m_boundingBox[nDim + i] > m_multiSolverBoundingBox[nDim + i],
1231 "Multisolver bounding box error (dim: " + std::to_string(i)
1232 + "): " + std::to_string(m_boundingBox[nDim + i]) + " > "
1233 + std::to_string(m_multiSolverBoundingBox[nDim + i]));
1235 m_boundingBox[nDim + i] = m_multiSolverBoundingBox[nDim + i];
1236 }
1237 }
1238
1239
1240 for(MInt dir = 0; dir < nDim; dir++) {
1241 m_geometryExtents[dir] = m_boundingBox[dir + nDim] - m_boundingBox[dir];
1243 m_centerOfGravity[dir] = m_boundingBox[dir] + 0.5 * (m_boundingBox[dir + nDim] - m_boundingBox[dir]);
1244 }
1245
1247 for(MInt l = 1; l < m_maxLevels; l++)
1248 m_lengthOnLevel[l] = m_lengthOnLevel[l - 1] * 0.5;
1249
1250 m_log << " + center of gravity: ";
1251 for(MInt dir = 0; dir < nDim; dir++)
1252 m_log << m_centerOfGravity[dir] << " ";
1253 m_log << "\n";
1254 m_log << " + decisive direction: " << m_decisiveDirection << "\n";
1255 m_log << " + geometry extents: ";
1256 for(MInt dir = 0; dir < nDim; dir++)
1257 m_log << m_geometryExtents[dir] << " ";
1258 m_log << "\n";
1259 m_log << " + bounding box: ";
1260 for(MInt dir = 0; dir < m_noNeighbors; dir++)
1261 m_log << m_boundingBox[dir] << " ";
1262 m_log << endl;
1263
1264 outStream << " + center of gravity: ";
1265 for(MInt dir = 0; dir < nDim; dir++)
1266 outStream << m_centerOfGravity[dir] << " ";
1267 outStream << "\n";
1268 outStream << " + decisive direction: " << m_decisiveDirection << "\n";
1269 outStream << " + geometry extents: ";
1270 for(MInt dir = 0; dir < nDim; dir++)
1271 outStream << m_geometryExtents[dir] << " ";
1272 outStream << "\n";
1273 outStream << " + bounding box: ";
1274 for(MInt dir = 0; dir < m_noNeighbors; dir++)
1275 outStream << m_boundingBox[dir] << " ";
1276 outStream << endl;
1277
1278 RECORD_TIMER_STOP(m_t_initGeometry);
1279}
MInt noNodes()
Definition: geometryroot.h:143
void boundingBox(MFloat *const bBox)
MInt noSegmentsOfNode(const MInt node)
std::vector< MFloat > m_multiSolverBoundingBox
MInt * m_noBndIdsPerSolver
MFloat * m_boundingBox
MBool m_hasMultiSolverBoundingBox
constexpr MFloat FPOW2(MInt x)

◆ initMembers()

template<MInt nDim>
void GridgenPar< nDim >::initMembers
protected
Author
Andreas Lintermann
Date
11.10.2013

Definition at line 1122 of file cartesiangridgenpar.cpp.

1122 {
1123 TRACE();
1124
1125 RECORD_TIMER_START(m_t_initMembers);
1126
1127 m_log << " (2) initializing member variables" << endl;
1128 outStream << " (2) initializing member variables" << endl;
1129
1130 mAlloc(m_boundingBox, 2 * nDim, "m_boundingBox", AT_);
1131 mAlloc(m_geometryExtents, nDim, "m_geometryExtents", AT_);
1132 mAlloc(m_centerOfGravity, nDim, "m_centerOfGravity", AT_);
1133
1134 mAlloc(m_cells, m_maxNoCells, nDim, 0, "m_cells", AT_);
1135 m_pCells = m_cells->a;
1136
1137 m_noCells = -1;
1138 m_noTotalCells = -1;
1139 m_noPartitionCells = -1;
1141 m_noTotalHaloCells = -1;
1144 m_maxNoChildren = IPOW2(nDim);
1145 m_maxLevels = 31;
1146 m_noNeighbors = 2 * nDim;
1147 m_cellOffsetPar = 0;
1148
1149 // the offsets of the levels
1150 mAlloc(m_levelOffsets, m_maxRfnmntLvl + 1, 2, "m_levelOffsets", -1, AT_);
1151 mAlloc(m_haloCellOffsetsLevel, m_maxRfnmntLvl + 1, 2, "m_haloCellOffsetsLevel", -1, AT_);
1152 mAlloc(m_noHaloCellsOnLevel, m_maxRfnmntLvl + 1, "m_noHaloCellsOnLevel", 0, AT_);
1153 mAlloc(m_noCellsPerDomain, noDomains(), "m_noCellsPerDomain", 0, AT_);
1154
1155 // the lengths on the different levels
1156 mAlloc(m_lengthOnLevel, m_maxLevels, "m_lengthOnLevel", 0.0, AT_);
1157
1158 if(m_minLevel % 2 == 0) {
1159 m_levelOffsets[0][0] = 0;
1160 m_levelOffsets[0][1] = 1;
1163 } else {
1164 m_levelOffsets[0][0] = m_maxNoCells - 1;
1166 m_levelOffsets[1][0] = 0;
1168 }
1169
1170 // dynamic load balancing
1172 m_hasBeenLoadBalanced = false;
1173
1174 RECORD_TIMER_STOP(m_t_initMembers);
1175}
Collector< GridgenCell< nDim > > * m_cells
MLong m_noTotalPartitionCells

◆ initTimers()

template<MInt nDim>
void GridgenPar< nDim >::initTimers
protected

Definition at line 198 of file cartesiangridgenpar.cpp.

198 {
199 TRACE();
200
201 NEW_TIMER_GROUP(tgrp_GG, "Parallel grid generation");
202 NEW_TIMER(t_comp_GG, "complete grid generation", tgrp_GG);
203 NEW_SUB_TIMER(t_readProperties, "(1) read properties", t_comp_GG);
204 NEW_SUB_TIMER(t_initMembers, "(2) init members", t_comp_GG);
205 NEW_SUB_TIMER(t_initGeometry, "(3) init geometry", t_comp_GG);
206 NEW_SUB_TIMER(t_createInitialGrid, "(4) create initial grid", t_comp_GG);
207 NEW_SUB_TIMER(t_parallelizeGrid, "(5) distribute grid among processes", t_comp_GG);
208 NEW_SUB_TIMER(t_createStartGrid, "(6) create start grid", t_comp_GG);
209 NEW_SUB_TIMER(t_createComputationalGrid, "(7) create computational grid", t_comp_GG);
210 NEW_SUB_TIMER(t_finalizeGrid, "(8) prepare grid for IO", t_comp_GG);
211 NEW_SUB_TIMER(t_saveGrid, "(9) parallel grid I/O", t_comp_GG);
212
213 m_t_comp_GG = t_comp_GG;
214 m_t_readProperties = t_readProperties;
215 m_t_initMembers = t_initMembers;
216 m_t_initGeometry = t_initGeometry;
217 m_t_createInitialGrid = t_createInitialGrid;
218 m_t_parallelizeGrid = t_parallelizeGrid;
219 m_t_createStartGrid = t_createStartGrid;
220 m_t_createComputationalGrid = t_createComputationalGrid;
221 m_t_finalizeGrid = t_finalizeGrid;
222 m_t_saveGrid = t_saveGrid;
223}

◆ isInsideCylinder()

template<MInt nDim>
MBool GridgenPar< nDim >::isInsideCylinder ( const MFloat *const  pointCoord,
const MFloat *const  leftCoord,
const MFloat *const  rightCoord,
const MFloat *const  normalDiffAB,
const MFloat *const  normalDiffBA,
const MFloat  radius,
const MFloat  innerRadius 
)
protected
Author
Andreas Lintermann
Date
04.12.2013
Parameters
[in]pointCoordcell coordinate
[in](left/right)Coordcoordinates of the left and right circles
[in]normalDiff(AB/BA)cylinder axis
[in]radiusradius of the cylinder
[in]innerRadiusinner radius of the cylinder (tube)

Definition at line 6267 of file cartesiangridgenpar.cpp.

6270 {
6271 TRACE();
6272
6273 std::array<MFloat, nDim> diffA;
6274 std::array<MFloat, nDim> diffB;
6275
6276 MFloat s1 = 0.0;
6277 MFloat s2 = 0.0;
6278 for(MInt d = 0; d < nDim; d++) {
6279 diffA[d] = pointCoord[d] - leftCoord[d];
6280 diffB[d] = pointCoord[d] - rightCoord[d];
6281 s1 += diffA[d] * normalDiffAB[d];
6282 s2 += diffB[d] * normalDiffBA[d];
6283 }
6284
6285 std::array<MFloat, nDim> cross;
6286 MFloat distance = 0.0;
6287 for(MInt d = 0; d < nDim; d++) {
6288 MInt p1 = (d + 1) % (nDim);
6289 MInt p2 = (d + 2) % (nDim);
6290
6291 cross[d] = diffA[p1] * normalDiffAB[p2] - normalDiffAB[p1] * diffA[p2];
6292 distance += cross[d] * cross[d];
6293 }
6294 distance = sqrt(distance);
6295
6296 if(distance <= radius && distance >= innerRadius && s1 >= 0.0 && s2 >= 0.0) {
6297 return 1;
6298 }
6299 return 0;
6300}
void cross(const T *const u, const T *const v, T *const c)
Definition: maiamath.h:101

◆ isInsideSlicedCone()

template<MInt nDim>
MBool GridgenPar< nDim >::isInsideSlicedCone ( const MFloat *const  pointCoord,
const MFloat *const  leftCoord,
const MFloat *const  rightCoord,
const MFloat *const  leftNormal,
const MFloat *const  rightNormal,
const MFloat *const  normalDifforigAB,
const MFloat  leftR,
const MFloat  rightR 
)
protected
Author
Rodrigo Miguez (rodrigo) rodri.nosp@m.go.m.nosp@m.iguez.nosp@m.@rwt.nosp@m.h-aac.nosp@m.hen..nosp@m.de
Date
25.05.2022

This algorithm does the following:

a. For any given point we find the perpendicular projection of vector p (the point we are testing): lambda = \frac{(\vec{p} - \vec{a}) \cdot (\vec{b} - \vec{a})} {(\vec{b} - \vec{a}) \cdot (\vec{b} - \vec{a})} where, \vec{a} and/or \vec{b}: are the center points of the circles that form the sliced cone

b. Calculate the point of projection of p on the line: \vec{r_p} = \vec{a} + lambda * (\vec{b} - \vec{a})

c. Calculate the distance of the point to its projection on the line: lenght = |\vec{p} - \vec{r_p}|

d. Check if point is inside the sliced cone radius: length <= Ra + lambda * (Rb - Ra), where Ra/Rb: are the radius of the circles that form the sliced cone

e. Finally, check if the point lies between the circles that form the sliced cone by calculating the normals of the circles and comparing if the point is in the opposite direction of both normals

Parameters
[in]pointCoordcell coordinate
[in](left/right)Coordcoordinates of the left and right circles
[in](left/right)Normalnormals of the left and right circles
[in]normalDifforigABsliced cone axis
[in](left/right)Rradius of the left and right circles

Definition at line 6945 of file cartesiangridgenpar.cpp.

6948 {
6949 TRACE();
6950
6951 // Calculate lambda
6952 MFloat lambda = 0.0;
6953 MFloat temp0 = 0.0;
6954 MFloat temp1 = 0.0;
6955 // dot product
6956 for(MInt d = 0; d < nDim; d++) {
6957 temp0 += (pointCoord[d] - leftCoord[d]) * normalDifforigAB[d];
6958 temp1 += normalDifforigAB[d] * normalDifforigAB[d];
6959 }
6960 lambda = temp0 / temp1;
6961
6962 // Store the length between pointCoord and projectionCoord
6963 MFloat lengthPP = 0.0;
6964
6965 std::array<MFloat, nDim> projectionCoord;
6966
6967 for(MInt d = 0; d < nDim; d++) {
6968 projectionCoord[d] = leftCoord[d] + lambda * normalDifforigAB[d];
6969 lengthPP += pow(pointCoord[d] - projectionCoord[d], 2);
6970 }
6971 lengthPP = sqrt(lengthPP);
6972 if(lengthPP <= (leftR + lambda * (rightR - leftR))) {
6973 MFloat isPointDirLeftNormal = 0.0;
6974 MFloat isPointDirRightNormal = 0.0;
6975 // dot product
6976 for(MInt d = 0; d < nDim; d++) {
6977 isPointDirLeftNormal += leftNormal[d] * (pointCoord[d] - leftCoord[d]);
6978 isPointDirRightNormal += rightNormal[d] * (pointCoord[d] - rightCoord[d]);
6979 }
6980 // Only mark if pointCoord is in the oposite direction of both circle normals
6981 if(isPointDirLeftNormal <= 0.0 && isPointDirRightNormal <= 0.0) {
6982 return true;
6983 }
6984 }
6985
6986 return false;
6987}

◆ keepOutsideBndryCellChildrenParallel()

template<MInt nDim>
void GridgenPar< nDim >::keepOutsideBndryCellChildrenParallel ( MInt  level_)
protected

Definition at line 3458 of file cartesiangridgenpar.cpp.

3458 {
3459 // parallel part
3462
3463 const MInt levelPos = 2 * (level_ - m_minLevel);
3464
3465 // declare lambda to check for valid neighbors
3466 auto neighborExists = [&](MInt haloCellId) {
3467 for(MInt n = 0; n < m_noNeighbors; n++) {
3468 if(a_neighborId(haloCellId, n) >= 0 && a_neighborId(haloCellId, n) < m_noCells) {
3469 return true;
3470 }
3471 }
3472 return false;
3473 };
3474
3475 // delete unreferenced halo cells
3476 MInt noDeletedHalos = 0;
3477
3478 for(MInt dom = m_noNeighborDomains - 1; dom >= 0; dom--) {
3479 for(MInt haloCellId = m_haloCellOffsets[dom][levelPos + 1] - 1; haloCellId >= m_haloCellOffsets[dom][levelPos];
3480 haloCellId--) {
3481 // if cell hasn't been moved check it
3482 if(!a_hasProperty(haloCellId, 7)) {
3483 // find dereferenced cells
3484 if(neighborExists(haloCellId)) {
3485 continue;
3486 }
3487
3488 // delete cell
3489 a_hasProperty(haloCellId, 7) = 1;
3490 deleteCellReferences(haloCellId, haloCellId);
3491 noDeletedHalos++;
3492 }
3493
3494 // skip cells marked as moved
3495 while(m_haloCellOffsets[dom][levelPos] < haloCellId && a_hasProperty(m_haloCellOffsets[dom][levelPos], 7)) {
3496 m_haloCellOffsets[dom][levelPos]++;
3497 }
3498
3499 // copy last cell to current position
3500 if(haloCellId > m_haloCellOffsets[dom][levelPos]) {
3501 copyCell(m_haloCellOffsets[dom][levelPos], haloCellId);
3502
3503 // mark as moved
3504 a_hasProperty(m_haloCellOffsets[dom][levelPos], 7) = 1;
3505
3506 // check copied cell
3507 haloCellId++;
3508 }
3509
3510 // increase offset since cell has either been copied or was last cell and invalid
3511 m_haloCellOffsets[dom][levelPos]++;
3512 }
3513
3514 // set new offset
3515 if(dom > 0) {
3516 m_haloCellOffsets[dom - 1][levelPos + 1] = m_haloCellOffsets[dom][levelPos];
3517 }
3518 }
3519
3520 // update halo offsets
3521 m_haloCellOffsetsLevel[level_][0] += noDeletedHalos;
3522 m_noTotalHaloCells -= noDeletedHalos;
3523 m_noHaloCellsOnLevel[level_] -= noDeletedHalos;
3524
3525 // create a small LUT for the halos
3526 map<MInt, MInt> lut;
3527 map<MInt, MInt> LUT;
3528 for(MInt cellId = m_haloCellOffsets[0][levelPos]; cellId < m_haloCellOffsets[m_noNeighborDomains - 1][levelPos + 1];
3529 cellId++) {
3530 lut.insert(make_pair(static_cast<MInt>(a_globalId(cellId)), cellId));
3531 }
3532 auto lutIt = lut.begin();
3533 for(MInt cellId = m_haloCellOffsets[0][levelPos]; cellId < m_haloCellOffsets[m_noNeighborDomains - 1][levelPos + 1];
3534 cellId++) {
3535 LUT.insert(make_pair(cellId, lutIt->second));
3536 lutIt++;
3537 }
3538
3539 // identify window cells: we dont use the m_ Look Up Table, so we duplicate some code
3540 vector<vector<MInt>> winCellIdsPerDomain(m_noNeighborDomains, vector<MInt>(0));
3541 vector<vector<MInt>> haloCellIdsPerDomain(m_noNeighborDomains, vector<MInt>(0));
3542
3543 for(MInt dom = 0; dom < m_noNeighborDomains; dom++) {
3544 for(MInt i = m_levelOffsets[level_][0]; i < m_levelOffsets[level_][1]; i++) {
3545 a_hasProperty(i, 3) = 0;
3546 }
3547
3548 for(MInt p = m_haloCellOffsets[dom][levelPos]; p < m_haloCellOffsets[dom][levelPos + 1]; p++) {
3549 const MInt cellId = LUT[p];
3550 haloCellIdsPerDomain[dom].push_back(cellId);
3551 for(MInt n = 0; n < m_noNeighbors; n++) {
3552 if(a_neighborId(cellId, n) < m_noCells && a_neighborId(cellId, n) > -1) {
3553 a_hasProperty((MInt)a_neighborId(cellId, n), 3) = 1;
3554 }
3555 }
3556 }
3557 for(MInt i = m_levelOffsets[level_][0]; i < m_levelOffsets[level_][1]; i++) {
3558 if(a_hasProperty(i, 3)) {
3559 winCellIdsPerDomain[dom].push_back(i);
3560 }
3561 }
3562 }
3563
3564 // prepare communication
3565 MIntScratchSpace noSendWindowPerDomain(m_noNeighborDomains, AT_, "noSendWindowPerDomain");
3566 MIntScratchSpace noReceiveHaloPerDomain(m_noNeighborDomains, AT_, "noReceiveHaloPerDomain");
3567 MInt allSend = 0;
3568 MInt allReceive = 0;
3569
3570 for(MInt d = 0; d < m_noNeighborDomains; ++d) {
3571 noReceiveHaloPerDomain[d] = (MInt)haloCellIdsPerDomain[d].size();
3572 allReceive += noReceiveHaloPerDomain[d];
3573 noSendWindowPerDomain[d] = (MInt)winCellIdsPerDomain[d].size();
3574 allSend += noSendWindowPerDomain[d];
3575 }
3576
3577 MIntScratchSpace myWindowInt(allSend, AT_, "myWindowInt");
3578 MIntScratchSpace myHaloInt(allReceive, AT_, "myHaloInt");
3579
3580 MInt offset = 0;
3581 for(MInt d = 0; d < m_noNeighborDomains; ++d) {
3582 for(MInt c = 0; c < noSendWindowPerDomain[d]; c++)
3583 myWindowInt(offset + c) = a_hasProperty(winCellIdsPerDomain[d][c], 0);
3584 offset += noSendWindowPerDomain[d];
3585 }
3586
3587 communicateIntToNeighbors(myHaloInt, noReceiveHaloPerDomain, myWindowInt, noSendWindowPerDomain, 1);
3588
3589 // distribute inside/outside to halo cells
3590 offset = 0;
3591 for(MInt d = 0; d < m_noNeighborDomains; d++) {
3592 for(MInt c = 0; c < noReceiveHaloPerDomain[d]; c++) {
3593 a_hasProperty(haloCellIdsPerDomain[d][c], 0) = (MBool)myHaloInt(offset + c);
3594 }
3595 offset += noReceiveHaloPerDomain[d];
3596 }
3597
3598 // reset the "moved" property
3599 for(MInt dom = 0; dom < m_noNeighborDomains; dom++)
3600 for(MInt p = m_haloCellOffsets[dom][levelPos]; p < m_haloCellOffsets[dom][levelPos + 1]; p++)
3601 a_hasProperty(p, 7) = 0;
3602 } else if(m_keepOutsideBndryCellChildren == 2) {
3605 } else if(m_keepOutsideBndryCellChildren == 3) {
3606 mTerm(1, AT_, "ERROR: keepOutsideBndryCellChildren in mode 3 is not implemented for parallel usage yet!!!");
3607
3608 MInt SOLID0 = 0;
3609 MInt SOLID1 = 0;
3610 MInt FLUID = 0;
3611 MInt DELETE = 0;
3612
3613 // loop over all solvers!
3614 for(MInt s = 0; s < m_noSolvers; s++) {
3615 // initialize all cells; fluid cells have a_noSolidLayer=-1: other cells get a hugh value
3616 for(MInt cellId = m_levelOffsets[level_][0]; cellId < m_levelOffsets[level_][1]; cellId++) {
3617 // skip cell outside the solver and also cells outside the cutOff!
3618 if(a_isInSolver(cellId, s) == 0) continue;
3619 if(a_hasProperty(cellId, 0) && !a_hasProperty(cellId, 1)) {
3620 a_noSolidLayer(cellId, s) = -1;
3621 FLUID++;
3622 }
3623 if(a_hasProperty(cellId, 1)) {
3624 a_noSolidLayer(cellId, s) = m_noSolidLayer[s] * 2;
3625 SOLID0++;
3626 }
3627 if(!a_hasProperty(cellId, 0) && !a_hasProperty(cellId, 1)) {
3628 a_noSolidLayer(cellId, s) = m_noSolidLayer[s] * 2;
3629 SOLID1++;
3630 }
3631 }
3632 cout << "## FLUID " << FLUID << " SOLID0 " << SOLID0 << " SOLID1 " << SOLID1 << " TODELETE " << DELETE << endl;
3633
3634 // initialize all halos; fluid cells have a_noSolidLayer=-1: other cells get a hugh value
3635 const MInt lev_pos = 2 * (level_ - m_minLevel);
3636 for(MInt dom = 0; dom < m_noNeighborDomains; dom++) {
3637 for(MInt i = m_haloCellOffsets[dom][lev_pos]; i < m_haloCellOffsets[dom][lev_pos + 1]; i++) {
3638 if(a_hasProperty(i, 0)) a_noSolidLayer(i, s) = -1;
3639 if(a_hasProperty(i, 1)) a_noSolidLayer(i, s) = m_noSolidLayer[s] * 2;
3640 if(!a_hasProperty(i, 0) && !a_hasProperty(i, 1)) a_noSolidLayer(i, s) = m_noSolidLayer[s] * 2;
3641 }
3642 }
3643
3644 // propagate the solid layers starting from the boundary cells do this
3645 // only for normal cells, halos will be updated later
3646 for(MInt cellId = m_levelOffsets[level_][0]; cellId < m_levelOffsets[level_][1]; cellId++) {
3647 if(a_isInSolver(cellId, s) == 0) continue;
3648 if(!a_hasProperty(cellId, 1)) continue;
3649 createSolidCellLayer(cellId, 0, m_noSolidLayer[s]);
3650 }
3651
3652 //############################################################################
3653 // PREPARE COMMUNICATION
3654 //############################################################################
3655
3656 // create a small LUT for the halos
3657 map<MInt, MInt> lut;
3658 map<MInt, MInt> LUT;
3659 for(MInt cellId = m_haloCellOffsets[0][lev_pos]; cellId < m_haloCellOffsets[m_noNeighborDomains - 1][lev_pos + 1];
3660 cellId++) {
3661 lut.insert(make_pair(static_cast<MInt>(a_globalId(cellId)), cellId));
3662 }
3663 auto lutIt = lut.begin();
3664 for(MInt cellId = m_haloCellOffsets[0][lev_pos]; cellId < m_haloCellOffsets[m_noNeighborDomains - 1][lev_pos + 1];
3665 cellId++) {
3666 LUT.insert(make_pair(cellId, lutIt->second));
3667 lutIt++;
3668 }
3669
3670 // create lists of window and halo cells
3671 vector<vector<MInt>> winCellIdsPerDomain(m_noNeighborDomains, vector<MInt>(0));
3672 vector<vector<MInt>> haloCellIdsPerDomain(m_noNeighborDomains, vector<MInt>(0));
3673
3674
3675 for(MInt dom = 0; dom < m_noNeighborDomains; dom++) {
3676 for(MInt i = m_levelOffsets[level_][0]; i < m_levelOffsets[level_][1]; i++) {
3677 a_hasProperty(i, 3) = 0;
3678 }
3679
3680 for(MInt p = m_haloCellOffsets[dom][lev_pos]; p < m_haloCellOffsets[dom][lev_pos + 1]; p++) {
3681 const MInt cellId = LUT[p];
3682 haloCellIdsPerDomain[dom].push_back(cellId);
3683 for(MInt n = 0; n < m_noNeighbors; n++) {
3684 if(a_neighborId(cellId, n) < m_noCells && a_neighborId(cellId, n) > -1) {
3685 a_hasProperty((MInt)a_neighborId(cellId, n), 3) = 1;
3686 }
3687 }
3688 }
3689 for(MInt i = m_levelOffsets[level_][0]; i < m_levelOffsets[level_][1]; i++) {
3690 if(a_hasProperty(i, 3)) {
3691 winCellIdsPerDomain[dom].push_back(i);
3692 }
3693 }
3694 }
3695
3696 // d. prepare the communication
3697 MIntScratchSpace noSendWindowPerDomain(m_noNeighborDomains, AT_, "noSendWindowPerDomain");
3698 MIntScratchSpace noReceiveHaloPerDomain(m_noNeighborDomains, AT_, "noReceiveHaloPerDomain");
3699
3700 m_log << " - process " << domainId() << " needs to transfer to domain [no. cells to transfer]: ";
3701 cout << " - process " << domainId() << " needs to transfer to domain [no. cells to transfer]: ";
3702 for(MInt d = 0; d < m_noNeighborDomains; d++) {
3703 noSendWindowPerDomain[d] = (MInt)winCellIdsPerDomain[d].size();
3704 m_log << m_neighborDomains[d] << " [" << noSendWindowPerDomain[d] << "] ";
3705 cout << m_neighborDomains[d] << " [" << noSendWindowPerDomain[d] << "] ";
3706 }
3707 m_log << endl;
3708 cout << endl;
3709
3710 m_log << " - process " << domainId() << " needs to receive from domain [no. cells to receive]: ";
3711 cout << " - process " << domainId() << " needs to receive from domain [no. cells to receive]: ";
3712 for(MInt d = 0; d < m_noNeighborDomains; d++) {
3713 noReceiveHaloPerDomain[d] = (MInt)haloCellIdsPerDomain[d].size();
3714 m_log << m_neighborDomains[d] << " [" << noReceiveHaloPerDomain[d] << "] ";
3715 cout << m_neighborDomains[d] << " [" << noReceiveHaloPerDomain[d] << "] ";
3716 }
3717 m_log << endl;
3718 cout << endl;
3719
3720 MInt allSend = 0;
3721 MInt allReceive = 0;
3722 vector<MInt> offsetsSend;
3723 vector<MInt> offsetsReceive;
3724 for(MInt dom = 0; dom < m_noNeighborDomains; dom++) {
3725 offsetsSend.push_back(allSend);
3726 offsetsReceive.push_back(allReceive);
3727 allSend += noSendWindowPerDomain[dom];
3728 allReceive += noReceiveHaloPerDomain[dom];
3729 }
3730
3731 MIntScratchSpace sndBufWin(allSend, AT_, "sndBufWin");
3732 MIntScratchSpace rcvBufHalo(allReceive, AT_, "rcvBufHalo");
3733
3734 MUshort finished = 0;
3735
3736 // e. determine whether we have changes by comparing a_refinementDistance
3737 // on halo and window cells
3738 // this has to be repeated until we are finished, exchange information as long
3739 // as we have local changes
3740 MInt rounds = 0;
3741 while(!finished) {
3742 finished = 1;
3743
3744 MPI_Request* mpi_request_;
3745 mAlloc(mpi_request_, m_noNeighborDomains, "mpi_request_", AT_);
3746 for(MInt d = 0; d < m_noNeighborDomains; d++) {
3747 for(MInt c = 0; c < noSendWindowPerDomain[d]; c++) {
3748 sndBufWin[offsetsSend[d] + c] = a_noSolidLayer(winCellIdsPerDomain[d][c], 0);
3749 }
3750 MPI_Issend(&(sndBufWin[offsetsSend[d]]), noSendWindowPerDomain[d], MPI_INT, m_neighborDomains[d], 0,
3751 mpiComm(), &mpi_request_[d], AT_, "(sndBufWin[offsetsSend[d]])");
3752 }
3753
3754 MPI_Status status_;
3755 for(MInt d = 0; d < m_noNeighborDomains; d++)
3756 MPI_Recv(&(rcvBufHalo[offsetsReceive[d]]), noReceiveHaloPerDomain[d], MPI_INT, m_neighborDomains[d], 0,
3757 mpiComm(), &status_, AT_, "(rcvBufHalo[offsetsReceive[d]])");
3758
3759 for(MInt d = 0; d < m_noNeighborDomains; d++)
3760 MPI_Wait(&mpi_request_[d], &status_, AT_);
3761
3762 for(MInt d = 0; d < m_noNeighborDomains; d++) {
3763 for(MInt c = 0; c < noReceiveHaloPerDomain[d]; c++) {
3764 const MInt halo = haloCellIdsPerDomain[d][c];
3765 if(a_isInSolver(halo, s) == 0) continue;
3766 if(a_noSolidLayer(halo, 0) == -1) {
3767 for(MInt n = 0; n < m_noNeighbors; n++) {
3768 MInt nghborId = (MInt)a_neighborId(halo, n);
3769 if((nghborId < 0) || (nghborId > m_noCells)) continue;
3770 if((a_noSolidLayer(nghborId, 0) > (rcvBufHalo[c + offsetsReceive[d]] + 1))
3771 && (rcvBufHalo[c + offsetsReceive[d]] > -1)) {
3772 if(rcvBufHalo[c + offsetsReceive[d]] < m_noSolidLayer[s]) {
3773 createSolidCellLayer(nghborId, (rcvBufHalo[c + offsetsReceive[d]] + 1), m_noSolidLayer[s]);
3774 finished = 0;
3775 }
3776 }
3777 }
3778 }
3779 }
3780 }
3781 MPI_Allreduce(MPI_IN_PLACE, &finished, 1, MPI_UNSIGNED_SHORT, MPI_MIN, mpiComm(), AT_, "MPI_IN_PLACE",
3782 "finished");
3783
3784 rounds++;
3785 }
3786 cout << " - communication rounds required: " << rounds << endl;
3787 }
3788
3789 // loop over all solvers:
3790 for(MInt s = 0; s < m_noSolvers; s++) {
3791 SOLID0 = 0;
3792 SOLID1 = 0;
3793 FLUID = 0;
3794 DELETE = 0;
3795 // only outside cells with a_noSolidLayer = -1 will be deleted so reset all cells which
3796 // have a_noSolidLayer > m_noSolidLayer
3797 for(MInt cellId = m_levelOffsets[level_][0]; cellId < m_levelOffsets[level_][1]; cellId++) {
3798 if(a_isInSolver(cellId, s) == 0) continue;
3799 if(a_noSolidLayer(cellId, s) == -1) FLUID++;
3800
3801 if(a_noSolidLayer(cellId, s) > m_noSolidLayer[s]) {
3802 a_noSolidLayer(cellId, s) = -1;
3803 DELETE++;
3804 }
3805
3806 if(a_noSolidLayer(cellId, s) == 0) SOLID0++;
3807
3808 if(a_noSolidLayer(cellId, s) == 1) SOLID1++;
3809 }
3810
3811 cout << " FLUID " << FLUID << " SOLID0 " << SOLID0 << " SOLID1 " << SOLID1 << " TODELETE " << DELETE << endl;
3812 const MInt lev_pos = 2 * (level_ - m_minLevel);
3813 for(MInt dom = 0; dom < m_noNeighborDomains; dom++) {
3814 for(MInt i = m_haloCellOffsets[dom][lev_pos]; i < m_haloCellOffsets[dom][lev_pos + 1]; i++) {
3815 if(a_noSolidLayer(i, s) > m_noSolidLayer[s]) a_noSolidLayer(i, s) = -1;
3816 }
3817 }
3818 }
3819
3820 for(MInt cellId = m_levelOffsets[level_][0]; cellId < m_levelOffsets[level_][1]; cellId++) {
3821 for(MInt s = 0; s < m_noSolvers; s++) {
3822 if(a_noSolidLayer(cellId, s) >= 0) {
3823 a_isToRefineForSolver(cellId, s) = 1;
3824 a_isInSolver(cellId, s) = 1;
3825 }
3826 }
3827 }
3828
3829 // for (MInt dom = 0; dom < m_noNeighborDomains; dom++){
3830 // for (MInt i = m_haloCellOffsets[dom][lev_pos]; i < m_haloCellOffsets[dom][lev_pos + 1]; i++) {
3831 // if(a_noSolidLayer(i) >= 0){
3832 // for(MInt block = 0; block < m_noSolvers; block++){
3833 // a_isToRefineForSolver(i, block) = 1;
3834 // a_isInSolver(i, block) = 1;
3835 // }
3836 // }
3837 // }
3838 // }
3839 } else {
3840 mTerm(1, AT_, "unknown keepOutsideBndryCellChildren option");
3841 }
3842}
void communicateIntToNeighbors(MIntScratchSpace &recvMem, MIntScratchSpace &noCellsToReceive, MIntScratchSpace &sendMem, MIntScratchSpace &noCellsToSend, MInt noVar)
Communicates Int values, with a variable nmbr of variables to the Neighbors.
uint_least16_t MUshort
Definition: maiatypes.h:61
int MPI_Issend(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request, const MString &name, const MString &varname)
same as MPI_Issend
int MPI_Wait(MPI_Request *request, MPI_Status *status, const MString &name)
same as MPI_Wait

◆ keepOutsideBndryCellChildrenSerial()

template<MInt nDim>
void GridgenPar< nDim >::keepOutsideBndryCellChildrenSerial ( MInt offsets,
MInt  level_ 
)
protected

Definition at line 2715 of file cartesiangridgenpar.cpp.

2715 {
2717 // check for refinement along a curved wall: if the outside-cell's parent
2718 // has a boundary-cell-neighbor without children, then the cell is kept
2719 for(MInt cellId = offsets[0]; cellId < offsets[1]; cellId++) {
2720 MInt pId = (MInt)a_parentId(cellId);
2721 for(MInt n = 0; n < m_noNeighbors; n++) {
2722 MInt nId = (MInt)a_neighborId(pId, n);
2723 if(nId < 0) continue;
2724 if(!(a_hasProperty(nId, 1))) continue;
2725 if(a_noChildren(nId) > 0) continue;
2726 a_hasProperty(cellId, 0) = 1;
2727 break;
2728 }
2729 }
2730 } else if(m_keepOutsideBndryCellChildren == 2) {
2731 // check for refinement along a curved wall: if the outside-cell's parent
2732 // is a boundary-cell, then the cell is kept
2733 for(MInt cellId = offsets[0]; cellId < offsets[1]; cellId++) {
2734 MInt pId = (MInt)a_parentId(cellId);
2735 if(a_hasProperty(pId, 1)) a_hasProperty(cellId, 0) = 1;
2736 }
2737 } else if(m_keepOutsideBndryCellChildren == 3) {
2738#ifdef MAIA_EXTRA_DEBUG
2739 MInt SOLID0;
2740 MInt SOLID1;
2741 MInt FLUID;
2742 MInt DELETE;
2743#endif
2744
2745 // loop over all solvers:
2746 for(MInt s = 0; s < m_noSolvers; s++) {
2747#ifdef MAIA_EXTRA_DEBUG
2748 FLUID = 0;
2749 SOLID1 = 0;
2750 SOLID0 = 0;
2751#endif
2752 // initialize all cells;
2753 // fluid cells have a_noSolidLayer=-1: other cells get a hugh value
2754 for(MInt cellId = offsets[0]; cellId < offsets[1]; cellId++) {
2755 if(a_hasProperty(cellId, 0) && !a_hasProperty(cellId, 1)) {
2756 a_noSolidLayer(cellId, s) = -1;
2757#ifdef MAIA_EXTRA_DEBUG
2758 FLUID++;
2759#endif
2760 }
2761 if(a_hasProperty(cellId, 1)) {
2762 a_noSolidLayer(cellId, s) = m_noSolidLayer[s] * 2;
2763#ifdef MAIA_EXTRA_DEBUG
2764 SOLID0++;
2765#endif
2766 }
2767 if(!a_hasProperty(cellId, 0) && !a_hasProperty(cellId, 1)) {
2768 a_noSolidLayer(cellId, s) = m_noSolidLayer[s] * 2;
2769#ifdef MAIA_EXTRA_DEBUG
2770 SOLID1++;
2771#endif
2772 }
2773 }
2774#ifdef MAIA_EXTRA_DEBUG
2775 cout << s << " FLUID " << FLUID << " bndry " << SOLID0 << " outside " << SOLID1 << endl;
2776#endif
2777 // propagate the solid layers starting from the boundary cells
2778 for(MInt cellId = offsets[0]; cellId < offsets[1]; cellId++) {
2779 if(!a_hasProperty(cellId, 1)) continue;
2780 createSolidCellLayer(cellId, 0, s);
2781 }
2782 }
2783
2784 // loop over all solvers:
2785 for(MInt s = 0; s < m_noSolvers; s++) {
2786#ifdef MAIA_EXTRA_DEBUG
2787 SOLID0 = 0;
2788 SOLID1 = 0;
2789 FLUID = 0;
2790 DELETE = 0;
2791#endif
2792 // only outside cells with a_noSolidLayer = -1 will be deleted
2793 // so reset all cells which
2794 // have a_noSolidLayer > m_noSolidLayer[s]
2795 for(MInt cellId = offsets[0]; cellId < offsets[1]; cellId++) {
2796 if(a_noSolidLayer(cellId, s) > m_noSolidLayer[s]) {
2797 a_noSolidLayer(cellId, s) = -1;
2798 }
2799
2800#ifdef MAIA_EXTRA_DEBUG
2801 if(a_noSolidLayer(cellId, s) > m_noSolidLayer[s]) DELETE++;
2802 if(a_noSolidLayer(cellId, s) == -1) FLUID++;
2803 if(a_noSolidLayer(cellId, s) == 0) SOLID0++;
2804 if(a_noSolidLayer(cellId, s) == 1) SOLID1++;
2805#endif
2806 }
2807#ifdef MAIA_EXTRA_DEBUG
2808 cout << s << " FLUID " << FLUID << " bndry " << SOLID0 << " SOLID1 " << SOLID1 << " TODELETE " << DELETE << endl;
2809#endif
2810 }
2811 for(MInt cellId = m_levelOffsets[level_][0]; cellId < m_levelOffsets[level_][1]; cellId++) {
2812 for(MInt s = 0; s < m_noSolvers; s++) {
2813 if(a_noSolidLayer(cellId, s) >= 0) {
2814 a_isToRefineForSolver(cellId, s) = 1;
2815 a_isInSolver(cellId, s) = 1;
2816 }
2817 }
2818 }
2819 } else {
2820 mTerm(1, AT_, "unknown keepOutsideBndryCellChildren option");
2821 }
2822}

◆ markBndDistance()

template<MInt nDim>
void GridgenPar< nDim >::markBndDistance ( MInt  level_,
MInt  solver 
)
protected
Author
Andreas Lintermann
Date
02.06.2014
Parameters
[in]level_the level to run over
[in]diststhe distances to use

Definition at line 7264 of file cartesiangridgenpar.cpp.

7264 {
7265 TRACE();
7266
7267 for(MInt i = m_levelOffsets[level_][0]; i < m_levelOffsets[level_][1]; i++) {
7268 if(a_refinementDistance(i) < numeric_limits<MInt>::max()) {
7269 a_isToRefineForSolver(i, solver) = 1;
7270 }
7271 }
7272
7273 // parallel part
7274 if(noDomains() > 1) {
7275 // 6.2b.2.3 dry run for the halo cells, how many new cells will we generate?
7276 MInt lev_pos = 2 * (level_ - m_minLevel);
7277 for(MInt dom = 0; dom < m_noNeighborDomains; dom++) {
7278 for(MInt i = m_haloCellOffsets[dom][lev_pos]; i < m_haloCellOffsets[dom][lev_pos + 1]; i++) {
7279 if(a_refinementDistance(i) < numeric_limits<MInt>::max()) {
7280 a_isToRefineForSolver(i, solver) = 1;
7281 }
7282 }
7283 }
7284 }
7285}
MInt & a_refinementDistance(const MInt cellId)
Returns rfnDistance of the cell cellId position.

◆ markBndForSolverRefinement()

template<MInt nDim>
void GridgenPar< nDim >::markBndForSolverRefinement ( MInt  level_,
MInt  solver 
)
protected

Definition at line 1866 of file cartesiangridgenpar.cpp.

1866 {
1867 TRACE();
1868
1869 SolverRefinement* bp = m_solverRefinement + solver;
1870
1871 MInt refLevel = level_ - bp->maxUniformRefinementLevel;
1872
1873 m_log << " + running boundary refinement for solver " << solver << endl;
1874
1875 // 6.2b.1 initialize the distances of all levels
1876 MIntScratchSpace dists(bp->noLocalBndRfnLvls, bp->noLocalRfnBoundaryIds, AT_, "dists");
1877 dists.fill(0);
1878
1879 switch(bp->localBndRfnMethod) {
1880 case 0: {
1881 for(MInt i = 0; i < bp->noLocalRfnBoundaryIds; i++)
1882 dists(bp->noLocalBndRfnLvls - bp->localRfnLvlDiff[i] - 1, i) = bp->localMinBoundaryThreshold[i];
1883
1884 for(MInt i = 0; i < bp->noLocalRfnBoundaryIds; i++)
1885 for(MInt lvl = bp->noLocalBndRfnLvls - bp->localRfnLvlDiff[i] - 2; lvl >= 0; lvl--)
1886 dists(lvl, i) = dists(lvl + 1, i) + bp->smoothDistance[i];
1887
1888 for(MInt i = 0; i < bp->noLocalRfnBoundaryIds; i++)
1889 for(MInt lvl = bp->noLocalBndRfnLvls - bp->localRfnLvlDiff[i] - 1; lvl >= 0; lvl--)
1890 dists(lvl, i) = ((MInt)pow(2, refLevel)) * dists(lvl, i);
1891 } break;
1892 case 1: {
1893 MFloatScratchSpace fists(bp->noLocalBndRfnLvls, bp->noLocalRfnBoundaryIds, AT_, "fists");
1894 fists.fill(F0);
1895
1896 for(MInt i = 0; i < bp->noLocalRfnBoundaryIds; i++)
1897 fists(bp->noLocalBndRfnLvls - bp->localRfnLvlDiff[i] - 1, i) =
1899
1900 for(MInt i = 0; i < bp->noLocalRfnBoundaryIds; i++)
1901 for(MInt lvl = bp->noLocalBndRfnLvls - bp->localRfnLvlDiff[i] - 2; lvl >= 0; lvl--)
1902 fists(lvl, i) =
1903 fists(lvl + 1, i) + bp->smoothDistance[i] * m_lengthOnLevel[bp->maxUniformRefinementLevel + lvl + 1];
1904
1905 for(MInt i = 0; i < bp->noLocalRfnBoundaryIds; i++)
1906 for(MInt lvl = bp->noLocalBndRfnLvls - bp->localRfnLvlDiff[i] - 1; lvl >= 0; lvl--)
1907 dists(lvl, i) = (MInt)(fists(lvl, i) / m_lengthOnLevel[bp->maxUniformRefinementLevel + lvl] + 0.5);
1908 } break;
1909 case 2: {
1910 // notes: - localBndRfnDistance : distance in stl units for first layer to be refined
1911 MFloatScratchSpace distsStlUnits(bp->noLocalBndRfnLvls, bp->noLocalRfnBoundaryIds, AT_, "distsStlUnits");
1912 distsStlUnits.fill(F0);
1913
1914 for(MInt i = 0; i < bp->noLocalRfnBoundaryIds; i++)
1915 distsStlUnits(bp->noLocalBndRfnLvls - bp->localRfnLvlDiff[i] - 1, i) = bp->localBndRfnDistance[i];
1916
1917 for(MInt i = 0; i < bp->noLocalRfnBoundaryIds; i++) {
1918 const MInt localRfnMaxLvl = bp->noLocalBndRfnLvls - bp->localRfnLvlDiff[i] - 1;
1919 const MInt localRfnMinLvl = bp->noLocalBndRfnLvls - bp->localBndRfnMinLvlDiff[i] - 1;
1920 for(MInt lvl = localRfnMaxLvl - 1; lvl >= localRfnMinLvl; lvl--) {
1921 distsStlUnits(lvl, i) = distsStlUnits(lvl + 1, i)
1923 }
1924 // ensure a default SmoothDistance to always have a valid grid, even in case of non-meaningful user input
1925 constexpr MInt defaultSmoothDistance = 2;
1926 for(MInt lvl = localRfnMinLvl - 1; lvl > -1; lvl--) {
1927 distsStlUnits(lvl, i) = distsStlUnits(lvl + 1, i)
1928 + defaultSmoothDistance * m_lengthOnLevel[bp->maxUniformRefinementLevel + lvl + 1];
1929 }
1930 }
1931
1932 for(MInt i = 0; i < bp->noLocalRfnBoundaryIds; i++) {
1933 const MInt localRfnMaxLvl = bp->noLocalBndRfnLvls - bp->localRfnLvlDiff[i] - 1;
1934 for(MInt lvl = localRfnMaxLvl; lvl >= 0; lvl--)
1935 dists(lvl, i) = (MInt)(distsStlUnits(lvl, i) / m_lengthOnLevel[bp->maxUniformRefinementLevel + lvl] + 0.5);
1936 }
1937 } break;
1938 default:
1939 mTerm(1, "no valid localBndRfnMethod");
1940 }
1941
1942 // group the Ids with the same distance
1943 set<MInt> rfnBoundaryGroupDist;
1944 for(MInt bId = 0; bId < bp->noLocalRfnBoundaryIds; bId++)
1945 rfnBoundaryGroupDist.insert(dists(refLevel, bId));
1946
1947 vector<vector<MInt>> rfnBoundaryGroupMemberIds(rfnBoundaryGroupDist.size(), vector<MInt>(0));
1948
1949 for(MInt bId = 0; bId < bp->noLocalRfnBoundaryIds; bId++) {
1950 set<MInt>::iterator setIt = rfnBoundaryGroupDist.find(dists(refLevel, bId));
1951 rfnBoundaryGroupMemberIds[distance(rfnBoundaryGroupDist.begin(), setIt)].push_back(bp->localRfnBoundaryIds[bId]);
1952 }
1953
1954 m_log << " * refinement groups (distance: Ids)" << endl;
1955
1956 for(MInt gId = 0; gId < (MInt)rfnBoundaryGroupDist.size(); gId++) {
1957 set<MInt>::iterator setIt = rfnBoundaryGroupDist.begin();
1958 advance(setIt, gId);
1959 if(*setIt == 0) continue;
1960
1961 m_log << " - group " << *setIt << " :";
1962 for(MInt mId = 0; mId < (MInt)rfnBoundaryGroupMemberIds[gId].size(); mId++) {
1963 m_log << " " << rfnBoundaryGroupMemberIds[gId][mId];
1964 }
1965 m_log << endl;
1966
1967 // 6.2b.3.1 do the boundary propagation
1968 // * we propagate untill we reach cell (*setIt - 1). So this will be the farest marked distance
1969 propagateDistance(level_, *setIt, rfnBoundaryGroupMemberIds[gId], solver);
1970
1971 // 6.2b.3.2 mark the according cells
1972 // * we refine cells with a distance < *setIt, therefore all marked cells
1973 markBndDistance(level_, solver);
1974 }
1975}
void propagateDistance(MInt level_, MInt distance, std::vector< MInt > &rfnBoundaryGroup, MInt solver)
propagates the distance away from the boundary
void markBndDistance(MInt level_, MInt solver)
marks cells that lie in a certain distance to the boundary

◆ markInsideOutside() [1/2]

template<MInt nDim>
void GridgenPar< nDim >::markInsideOutside ( MInt **  offsets,
MInt  level_ 
)
protected
Author
Andreas Lintermann
Date
29.10.2013

This algorithm runs over all cells in the provided offset range and checks for each cell if it has beend marked (b_properties[6]). If not, this cell is checked if is a boundary cell (b_properties[1]). If not, this cell is checked for its position (inside or outside). If it is inside a inside-flooding is performed by calling floodCells with the argument "1" for inside determination. Otherwise an outside-flooding is performed, which call floodCells with the argument "0" for outside determination.

Parameters
[in]offsetsa pointer to the offsets array, i.e., the normal cells or the halo cells
[in]level_the level to check

Definition at line 2244 of file cartesiangridgenpar.cpp.

2244 {
2245 TRACE();
2246
2247 // reset "visited" property, added since markInsideOutsideSolver also uses it
2248 for(MInt i = offsets[level_][1] - 1; i >= offsets[level_][0]; i--)
2249 a_hasProperty(i, 6) = 0;
2250
2251 for(MInt i = offsets[level_][1] - 1; i >= offsets[level_][0]; i--) {
2252 // this cell was already visited, skip
2253 if(a_hasProperty(i, 6)) continue;
2254
2255 // this is a boundary cell, skip
2256 if(a_hasProperty(i, 1)) {
2257 a_hasProperty(i, 0) = 1;
2258 a_hasProperty(i, 6) = 1;
2259 continue;
2260 }
2261
2262 // cell is inside, do inside-flooding
2263 if(pointIsInside(&a_coordinate(i, 0)) && !(a_hasProperty(i, 1))) {
2264 stack<MInt> fillStack;
2265 a_hasProperty(i, 0) = 1;
2266 a_hasProperty(i, 6) = 1;
2267 fillStack.push(i);
2268 floodCells(&fillStack, 1);
2269 } // cell is outside, do outside-flooding
2270 else {
2271 stack<MInt> fillStack;
2272 a_hasProperty(i, 0) = 0;
2273 a_hasProperty(i, 6) = 1;
2274 fillStack.push(i);
2275 floodCells(&fillStack, 0);
2276 }
2277 }
2278}
MBool pointIsInside(MFloat *coordinates)
checks if a given point is inside the geometry
void floodCells(std::stack< MInt > *fillStack, MChar marker)
floods cells

◆ markInsideOutside() [2/2]

template<MInt nDim>
void GridgenPar< nDim >::markInsideOutside ( MInt **  offsets,
MInt  level_,
MInt  solver 
)
protected
Author
Thomas Schilden
Date
03.04.2018

similar to markInsideOutside(,) but runs only for a specific solver

Parameters
[in]offsetsthe range of cells to run on
[in]level_the level to check
[in]solverspecific solver

Definition at line 1485 of file cartesiangridgenpar.cpp.

1485 {
1486 TRACE();
1487
1488 for(MInt i = offsets[level_][1] - 1; i >= offsets[level_][0]; i--) {
1489 // this cell was already visited, skip
1490 if(a_hasProperty(i, 6)) continue;
1491
1492 // this is a solver boundary cell, skip
1493 if(a_isSolverBoundary(i, solver)) {
1494 a_isInSolver(i, solver) = 1;
1495 a_hasProperty(i, 6) = 1;
1496 continue;
1497 }
1498
1499 // cell is inside solver, do inside-solver-flooding
1500 if(pointIsInsideSolver(&a_coordinate(i, 0), solver)) {
1501 stack<MInt> fillStack;
1502 a_isInSolver(i, solver) = 1;
1503 a_hasProperty(i, 6) = 1;
1504 fillStack.push(i);
1505 floodCells(&fillStack, 1, solver);
1506 } // cell is outside, do outside-flooding
1507 else {
1508 stack<MInt> fillStack;
1509 a_isInSolver(i, solver) = 0;
1510 a_hasProperty(i, 6) = 1;
1511 fillStack.push(i);
1512 floodCells(&fillStack, 0, solver);
1513 }
1514 }
1515}
MBool pointIsInsideSolver(MFloat *coordinates, MInt solver)

◆ markLocalBox()

template<MInt nDim>
void GridgenPar< nDim >::markLocalBox ( MInt  compRfnLvl,
MInt  patch,
MInt  solver 
)
protected
Author
Andreas Lintermann
Date
04.12.2013

This algorithm does the following:

a. It performs a dry run of the refinement, i.e., runs over alls cells on the current level, counts the number of cells to refine (the cells which are inside a given box) and marks these cells (b_properties[5] = 1). b. the same is done for the halo cells if we run in parallel mode

Parameters
[in]level_the level to run over

Definition at line 6033 of file cartesiangridgenpar.cpp.

6033 {
6034 TRACE();
6035
6036 SolverRefinement* bp = m_solverRefinement + solver;
6037
6038 // a. do a dry run so that we know how many cells we can expect,
6039 // also mark these cells
6040 const MInt pos = bp->localRfnLevelPropertiesOffset[compRfnLvl] + patch;
6041 const MInt gridLvl = compRfnLvl + bp->maxUniformRefinementLevel;
6042
6043 m_log << " * marking local box for solver " << solver << endl;
6044 m_log << " - corner1: ";
6045 for(MInt d = 0; d < nDim; d++) {
6046 m_log << bp->localRfnPatchProperties[pos][d] << " ";
6047 }
6048 m_log << endl << " - corner2: ";
6049 for(MInt d = nDim; d < 2 * nDim; d++) {
6050 m_log << bp->localRfnPatchProperties[pos][d] << " ";
6051 }
6052 m_log << endl;
6053
6054 for(MInt k = m_levelOffsets[gridLvl][0]; k < m_levelOffsets[gridLvl][1]; k++) {
6055 if(a_isInSolver(k, solver)) {
6056 if(maia::geom::isPointInsideBox<MFloat, nDim>(&a_coordinate(k, 0), bp->localRfnPatchProperties[pos])) {
6057 a_isToRefineForSolver(k, solver) = 1;
6058 }
6059 }
6060 }
6061
6062 // b. do the same for the halos
6063 if(noDomains() > 1) {
6064 MInt lev_pos = 2 * (gridLvl - m_minLevel);
6065 for(MInt dom = 0; dom < m_noNeighborDomains; dom++) {
6066 for(MInt k = m_haloCellOffsets[dom][lev_pos]; k < m_haloCellOffsets[dom][lev_pos + 1]; k++) {
6067 if(a_isInSolver(k, solver)) {
6068 if(maia::geom::isPointInsideBox<MFloat, nDim>(&a_coordinate(k, 0), bp->localRfnPatchProperties[pos])) {
6069 a_isToRefineForSolver(k, solver) = 1;
6070 }
6071 }
6072 }
6073 }
6074 }
6075}

◆ markLocalCartesianWedge()

template<MInt nDim>
void GridgenPar< nDim >::markLocalCartesianWedge ( MInt  level_,
MInt  patch,
MInt  solver 
)
protected

Definition at line 6303 of file cartesiangridgenpar.cpp.

6303 {
6304 TRACE();
6305
6306 SolverRefinement* bp = m_solverRefinement + solver;
6307
6308 const MInt pos = bp->localRfnLevelPropertiesOffset[compRfnLvl] + patch;
6309 const MInt gridLvl = compRfnLvl + bp->maxUniformRefinementLevel;
6310
6311 m_log << " * marking local cylinder for solver " << solver << endl;
6312 m_log << " - min center: ";
6313 for(MInt d = 0; d < nDim; d++) {
6314 m_log << bp->localRfnPatchProperties[pos][d] << " ";
6315 }
6316 m_log << endl;
6317 m_log << " - radius: " << bp->localRfnPatchProperties[pos][nDim] << endl;
6318 m_log << " - length: " << bp->localRfnPatchProperties[pos][nDim + 1] << endl;
6319 m_log << " - axis: " << bp->localRfnPatchProperties[pos][nDim + 2] << endl;
6320 m_log << " - start angle: " << bp->localRfnPatchProperties[pos][nDim + 3] << endl;
6321 m_log << " - end angle: " << bp->localRfnPatchProperties[pos][nDim + 4] << endl;
6322
6323 MFloat length = bp->localRfnPatchProperties[pos][nDim + 1];
6324 MInt axis = (MInt)(bp->localRfnPatchProperties[pos][nDim + 2]);
6325
6326 if(axis >= nDim) mTerm(1, AT_, "cylinder wedge refinement: axis out of bounds! Must be < nDim");
6327
6328 for(MInt k = m_levelOffsets[gridLvl][0]; k < m_levelOffsets[gridLvl][1]; k++) {
6329 if(a_isInSolver(k, solver)) {
6330 MFloat* coords = &a_coordinate(k, 0);
6331
6332 // check if cell is within cylinder axis range
6333 if(coords[axis] < bp->localRfnPatchProperties[pos][axis]
6334 || coords[axis] > bp->localRfnPatchProperties[pos][axis] + length)
6335 continue;
6336
6337 // check if cell is within radius
6338 std::array<MFloat, nDim> normalVector;
6339 MFloat distance = 0.0;
6340 for(MInt d = 0; d < nDim; d++) {
6341 if(d == axis)
6342 normalVector[d] = 0.0;
6343 else
6344 normalVector[d] = coords[d] - bp->localRfnPatchProperties[pos][d];
6345 distance += normalVector[d] * normalVector[d];
6346 }
6347 distance = sqrt(distance);
6348 if(distance > bp->localRfnPatchProperties[pos][nDim]) continue;
6349
6350 // determine angle
6351 // MInt relativeDirection = (axis + 1) % nDim;
6352 // MFloat angle = asin(normalVector[relativeDirection])*180.0/PI;
6353 MFloat angle = atan2(normalVector[(axis + 2) % nDim], normalVector[(axis + 1) % nDim]) * 180.0 / PI;
6354
6355 if(angle < bp->localRfnPatchProperties[pos][nDim + 3] || angle > bp->localRfnPatchProperties[pos][nDim + 4])
6356 continue;
6357
6358 a_isToRefineForSolver(k, solver) = 1;
6359 }
6360 }
6361
6362 if(noDomains() > 1) {
6363 MInt lev_pos = 2 * (gridLvl - m_minLevel);
6364 for(MInt dom = 0; dom < m_noNeighborDomains; dom++) {
6365 for(MInt k = m_haloCellOffsets[dom][lev_pos]; k < m_haloCellOffsets[dom][lev_pos + 1]; k++) {
6366 if(a_isInSolver(k, solver)) {
6367 MFloat* coords = &a_coordinate(k, 0);
6368
6369 if(coords[axis] < bp->localRfnPatchProperties[pos][axis]
6370 || coords[axis] > bp->localRfnPatchProperties[pos][axis] + length)
6371 continue; // outside of cylinder length
6372
6373 std::array<MFloat, nDim> normalVector;
6374 MFloat distance = 0.0;
6375 for(MInt d = 0; d < nDim; d++) {
6376 if(d == axis)
6377 normalVector[d] = 0.0;
6378 else
6379 normalVector[d] = coords[d] - bp->localRfnPatchProperties[pos][d];
6380 distance += normalVector[d] * normalVector[d];
6381 }
6382 distance = sqrt(distance);
6383 if(distance > bp->localRfnPatchProperties[pos][nDim]) continue; // outside of radius
6384
6385 // MInt relativeDirection = (axis + 1) % nDim;
6386 // MFloat angle = asin(normalVector[relativeDirection])*180.0/PI;
6387 MFloat angle = atan2(normalVector[(axis + 2) % nDim], normalVector[(axis + 1) % nDim]) * 180.0 / PI;
6388
6389 if(angle < bp->localRfnPatchProperties[pos][nDim + 3] || angle > bp->localRfnPatchProperties[pos][nDim + 4])
6390 continue; // outside of angular section
6391
6392 a_isToRefineForSolver(k, solver) = 1;
6393 }
6394 }
6395 }
6396 }
6397}

◆ markLocalCone()

template<MInt nDim>
void GridgenPar< nDim >::markLocalCone ( MInt  compRfnLvl,
MInt  patch,
MInt  solver 
)
protected
Author
Andreas Lintermann
Date
12.12.2013

This algorithm does the following:

a. It performs a dry run of the refinement, i.e., runs over alls cells on the current level, counts the number of cells to refine (the cells which are inside a given cone and sphere) and marks these cells (b_properties[5] = 1). First the center of the sphere and the new center point of the cone are calculated. Then, the distance of a coordinates of a given cell is calculated to obatain the enclosed angle between this the vector of the coordinates and the first provided point. In case the angle is larger than the one provided in the properties, this cell is marked as outside, otherwise as inside. The distance of the coordinates to the line is calculated as described in markLocalCylinder. b. The same is done for the halo cells if we run in parallel mode

Parameters
[in]levelthe level to run over

Definition at line 6588 of file cartesiangridgenpar.cpp.

6588 {
6589 TRACE();
6590
6591 SolverRefinement* bp = m_solverRefinement + solver;
6592
6593 const MInt pos = bp->localRfnLevelPropertiesOffset[compRfnLvl] + patch;
6594 const MInt gridLvl = compRfnLvl + bp->maxUniformRefinementLevel;
6595
6596 m_log << " * marking local rounded cone for solver " << solver << endl;
6597 m_log << " - left point: ";
6598 for(MInt d = 0; d < nDim; d++) {
6599 m_log << bp->localRfnPatchProperties[pos][d] << " ";
6600 }
6601 m_log << " - right point: ";
6602 for(MInt d = nDim; d < 2 * nDim; d++) {
6603 m_log << bp->localRfnPatchProperties[pos][d] << " ";
6604 }
6605 m_log << endl;
6606 m_log << " - opening angle: " << bp->localRfnPatchProperties[pos][2 * nDim] << endl;
6607 m_log << " - radius: " << bp->localRfnPatchProperties[pos][2 * nDim + 1] << endl;
6608
6609 // a. precalculate the required vector
6610
6611 MFloat Radius = bp->localRfnPatchProperties[pos][2 * nDim + 1];
6612 MFloat angle = bp->localRfnPatchProperties[pos][2 * nDim];
6613 MFloat angle_rad = angle * PI / 180.0;
6614 // MFloat angle_rad90 = (90.0-angle) * PI / 180.0;
6615 MFloat radius = Radius * cos(angle_rad);
6616
6617 std::array<MFloat, nDim> normalDifforigAB;
6618 MFloat length = 0.0;
6619 for(MInt d = 0; d < nDim; d++) {
6620 normalDifforigAB[d] = bp->localRfnPatchProperties[pos][d + nDim] - bp->localRfnPatchProperties[pos][d];
6621 length += normalDifforigAB[d] * normalDifforigAB[d];
6622 }
6623
6624 length = sqrt(length);
6625
6626 for(MInt d = 0; d < nDim; d++)
6627 normalDifforigAB[d] /= length;
6628
6629 // calucate the new position of A
6630 std::array<MFloat, nDim> newPosA;
6631 std::array<MFloat, nDim> sphereCenter;
6632 std::array<MFloat, nDim> normalDiffAB;
6633 std::array<MFloat, nDim> normalDiffBA;
6634 MFloat lengthAB = 0.0;
6635 for(MInt d = 0; d < nDim; d++) {
6636 newPosA[d] = bp->localRfnPatchProperties[pos][d] + radius / tan(angle_rad) * normalDifforigAB[d];
6637 sphereCenter[d] =
6638 bp->localRfnPatchProperties[pos][d] + radius * (1.0 / tan(angle_rad) + tan(angle_rad)) * normalDifforigAB[d];
6639
6640 normalDiffAB[d] = bp->localRfnPatchProperties[pos][d + nDim] - newPosA[d];
6641 normalDiffBA[d] = newPosA[d] - bp->localRfnPatchProperties[pos][d + nDim];
6642
6643 lengthAB += normalDiffAB[d] * normalDiffAB[d];
6644 }
6645
6646 lengthAB = sqrt(lengthAB);
6647
6648 for(MInt d = 0; d < nDim; d++) {
6649 normalDiffAB[d] /= lengthAB;
6650 }
6651
6652 // b. do a dry run so that we know how many cells we can expect,
6653 // also mark these cells
6654 for(MInt k = m_levelOffsets[gridLvl][0]; k < m_levelOffsets[gridLvl][1]; k++) {
6655 if(a_isInSolver(k, solver)) {
6656 MFloat* coords = &a_coordinate(k, 0);
6657
6658 std::array<MFloat, nDim> diffA;
6659 std::array<MFloat, nDim> difforigA;
6660 std::array<MFloat, nDim> diffB;
6661 std::array<MFloat, nDim> diffCenter;
6662
6663 MFloat s1 = 0.0;
6664 MFloat s2 = 0.0;
6665 MFloat len_diffOrig = 0.0;
6666 MFloat len_diffCenter = 0.0;
6667 for(MInt d = 0; d < nDim; d++) {
6668 diffA[d] = coords[d] - newPosA[d];
6669 diffB[d] = coords[d] - bp->localRfnPatchProperties[pos][d + nDim];
6670 difforigA[d] = coords[d] - bp->localRfnPatchProperties[pos][d];
6671 diffCenter[d] = coords[d] - sphereCenter[d];
6672
6673 s1 += diffA[d] * normalDiffAB[d];
6674 s2 += diffB[d] * normalDiffBA[d];
6675 len_diffOrig += difforigA[d] * difforigA[d];
6676 len_diffCenter += diffCenter[d] * diffCenter[d];
6677 }
6678
6679 len_diffOrig = sqrt(len_diffOrig);
6680 len_diffCenter = sqrt(len_diffCenter);
6681
6682 std::array<MFloat, nDim> cross;
6683 MFloat distance = 0.0;
6684 for(MInt d = 0; d < nDim; d++) {
6685 MInt p1 = (d + 1) % (nDim);
6686 MInt p2 = (d + 2) % (nDim);
6687
6688 cross[d] = diffA[p1] * normalDiffAB[p2] - normalDiffAB[p1] * diffA[p2];
6689 distance += cross[d] * cross[d];
6690 }
6691
6692 distance = sqrt(distance);
6693
6694 MFloat ang = asin(distance / len_diffOrig) * 180 / PI;
6695
6696 if((ang <= angle && s1 >= 0.0 && s2 >= 0.0) || len_diffCenter <= Radius) {
6697 a_isToRefineForSolver(k, solver) = 1;
6698 }
6699 }
6700 }
6701
6702 // b. do the same for the halos
6703 if(noDomains() > 1) {
6704 MInt lev_pos = 2 * (gridLvl - m_minLevel);
6705
6706 for(MInt dom = 0; dom < m_noNeighborDomains; dom++) {
6707 for(MInt k = m_haloCellOffsets[dom][lev_pos]; k < m_haloCellOffsets[dom][lev_pos + 1]; k++) {
6708 if(a_isInSolver(k, solver)) {
6709 MFloat* coords = &a_coordinate(k, 0);
6710
6711 std::array<MFloat, nDim> diffA;
6712 std::array<MFloat, nDim> difforigA;
6713 std::array<MFloat, nDim> diffB;
6714 std::array<MFloat, nDim> diffCenter;
6715
6716 MFloat s1 = 0.0;
6717 MFloat s2 = 0.0;
6718 MFloat len_diffOrig = 0.0;
6719 MFloat len_diffCenter = 0.0;
6720 for(MInt d = 0; d < nDim; d++) {
6721 diffA[d] = coords[d] - newPosA[d];
6722 diffB[d] = coords[d] - bp->localRfnPatchProperties[pos][d + nDim];
6723 difforigA[d] = coords[d] - bp->localRfnPatchProperties[pos][d];
6724 diffCenter[d] = coords[d] - sphereCenter[d];
6725
6726 s1 += diffA[d] * normalDiffAB[d];
6727 s2 += diffB[d] * normalDiffBA[d];
6728 len_diffOrig += difforigA[d] * difforigA[d];
6729 len_diffCenter += diffCenter[d] * diffCenter[d];
6730 }
6731
6732 len_diffOrig = sqrt(len_diffOrig);
6733 len_diffCenter = sqrt(len_diffCenter);
6734
6735 std::array<MFloat, nDim> cross;
6736 MFloat distance = 0.0;
6737 for(MInt d = 0; d < nDim; d++) {
6738 MInt p1 = (d + 1) % (nDim);
6739 MInt p2 = (d + 2) % (nDim);
6740
6741 cross[d] = diffA[p1] * normalDiffAB[p2] - normalDiffAB[p1] * diffA[p2];
6742 distance += cross[d] * cross[d];
6743 }
6744
6745 distance = sqrt(distance);
6746
6747 MFloat ang = asin(distance / len_diffOrig) * 180 / PI;
6748
6749 if((ang <= angle && s1 >= 0.0 && s2 >= 0.0) || len_diffCenter <= Radius) {
6750 a_isToRefineForSolver(k, solver) = 1;
6751 }
6752 }
6753 }
6754 }
6755 }
6756}
T cos(const T a, const T b, const T x)
Cosine slope filter.
Definition: filter.h:125

◆ markLocalCylinder()

template<MInt nDim>
void GridgenPar< nDim >::markLocalCylinder ( MInt  compRfnLvl,
MInt  patch,
MInt  solver,
MString  patchStr 
)
protected
Author
Andreas Lintermann
Date
04.12.2013

This algorithm does the following:

a. It performs a dry run of the refinement, i.e., runs over alls cells on the current level, counts the number of cells to refine (the cells which are inside a given cylinder) and marks these cells (b_properties[5] = 1). The according formula for the calculation of the distance \(d\) of a given point \(\vec{p}\) (cell coordinates) is given by

\[d = \left|\left(\vec{p}-\vec{o}_1\right)\times\vec{r}\right|,\]

where \(\vec{o}_1\) is the first center-point provided in the property, \(\vec{r}\) is the normalized vector between \(\vec{o}_1\) and \(\vec{o}_2\) (as provieded in thr property file).

b. The same is done for the halo cells if we run in parallel mode

Parameters
[in]levelthe level to run over

Definition at line 6166 of file cartesiangridgenpar.cpp.

6166 {
6167 TRACE();
6168
6169 if(patchStr != "C" && patchStr != "T") {
6170 TERMM(1, "This function doesn't support the selected patch type!");
6171 }
6172
6173 const MBool isTube = (patchStr == "T") ? true : false;
6174
6175 SolverRefinement* bp = m_solverRefinement + solver;
6176
6177 const MInt pos = bp->localRfnLevelPropertiesOffset[compRfnLvl] + patch;
6178 const MInt gridLvl = compRfnLvl + bp->maxUniformRefinementLevel;
6179
6180 if(isTube) {
6181 m_log << " * marking local tube for solver " << solver << endl;
6182 } else {
6183 m_log << " * marking local cylinder for solver " << solver << endl;
6184 }
6185
6186 // Get coordinates
6187 std::array<MFloat, nDim> leftCoord;
6188 std::array<MFloat, nDim> rightCoord;
6189 for(MInt d = 0; d < nDim; d++) {
6190 leftCoord[d] = bp->localRfnPatchProperties[pos][d];
6191 rightCoord[d] = bp->localRfnPatchProperties[pos][d + nDim];
6192 }
6193
6194 m_log << " - left center: ";
6195 for(MInt d = 0; d < nDim; d++) {
6196 m_log << leftCoord[d] << " ";
6197 }
6198 m_log << " - right center: ";
6199 for(MInt d = 0; d < nDim; d++) {
6200 m_log << rightCoord[d] << " ";
6201 }
6202 m_log << endl;
6203 MFloat radius = bp->localRfnPatchProperties[pos][2 * nDim];
6204 m_log << " - radius: " << radius << endl;
6205 MFloat innerRadius = -1.0; // for cylinder, distance is always > innerRadius
6206 if(isTube) {
6207 m_log << " - inner radius: " << bp->localRfnPatchProperties[pos][2 * nDim + 1] << endl;
6208 innerRadius = bp->localRfnPatchProperties[pos][2 * nDim + 1];
6209 }
6210
6211 // a. precalculate the required vector
6212 std::array<MFloat, nDim> normalDiffAB;
6213 std::array<MFloat, nDim> normalDiffBA;
6214 MFloat length = 0.0;
6215 for(MInt d = 0; d < nDim; d++) {
6216 normalDiffAB[d] = rightCoord[d] - leftCoord[d];
6217 normalDiffBA[d] = leftCoord[d] - rightCoord[d];
6218 length += normalDiffAB[d] * normalDiffAB[d];
6219 }
6220 length = sqrt(length);
6221
6222 for(MInt d = 0; d < nDim; d++) {
6223 normalDiffAB[d] /= length;
6224 }
6225
6226 // b. do a dry run so that we know how many cells we can expect,
6227 // also mark these cells
6228 for(MInt k = m_levelOffsets[gridLvl][0]; k < m_levelOffsets[gridLvl][1]; k++) {
6229 if(a_isInSolver(k, solver)) {
6230 if(isInsideCylinder(&a_coordinate(k, 0), leftCoord.data(), rightCoord.data(), normalDiffAB.data(),
6231 normalDiffBA.data(), radius, innerRadius)) {
6232 a_isToRefineForSolver(k, solver) = 1;
6233 }
6234 }
6235 }
6236
6237 // c. do the same for the halos
6238 if(noDomains() > 1) {
6239 MInt lev_pos = 2 * (gridLvl - m_minLevel);
6240 for(MInt dom = 0; dom < m_noNeighborDomains; dom++) {
6241 for(MInt k = m_haloCellOffsets[dom][lev_pos]; k < m_haloCellOffsets[dom][lev_pos + 1]; k++) {
6242 if(a_isInSolver(k, solver)) {
6243 if(isInsideCylinder(&a_coordinate(k, 0), leftCoord.data(), rightCoord.data(), normalDiffAB.data(),
6244 normalDiffBA.data(), radius, innerRadius)) {
6245 a_isToRefineForSolver(k, solver) = 1;
6246 }
6247 }
6248 }
6249 }
6250 }
6251}
MBool isInsideCylinder(const MFloat *const pointCoord, const MFloat *const leftCoord, const MFloat *const rightCoord, const MFloat *const normalDiffAB, const MFloat *const normalDiffBA, const MFloat radius, const MFloat innerRadius)
checks if point (cell) is inside a cylinder

◆ markLocalFlatCone()

template<MInt nDim>
void GridgenPar< nDim >::markLocalFlatCone ( MInt  level_,
MInt  patch,
MInt  solver 
)
protected

◆ markLocalHat()

template<MInt nDim>
void GridgenPar< nDim >::markLocalHat ( MInt  compRfnLvl,
MInt  patch,
MInt  solver 
)
protected
Author
Andreas Lintermann
Date
12.12.2013

This algorithm does the following:

a. It performs a dry run of the refinement, i.e., runs over alls cells on the current level, counts the number of cells to refine (the cells which are inside a given cone and sphere) and marks these cells (b_properties[5] = 1). First the center of the sphere and the new center point of the cone are calculated. Then, the distance of a coordinates of a given cell is calculated to obtain the enclosed angle between this the vector of the coordinates and the first provided point. In case the angle is larger than the one provided in the properties, this cell is marked as outside, otherwise as inside. The distance of the coordinates to the line is calculated as described in markLocalCylinder. b. The same is done for the halo cells if we run in parallel mode

Parameters
[in]levelthe level to run over

Definition at line 7015 of file cartesiangridgenpar.cpp.

7015 {
7016 TRACE();
7017
7018 SolverRefinement* bp = m_solverRefinement + solver;
7019
7020 const MInt pos = bp->localRfnLevelPropertiesOffset[compRfnLvl] + patch;
7021 const MInt gridLvl = compRfnLvl + bp->maxUniformRefinementLevel;
7022
7023 m_log << " * marking local hat for solver " << solver << endl;
7024 m_log << " - left point: ";
7025 for(MInt d = 0; d < nDim; d++) {
7026 m_log << bp->localRfnPatchProperties[pos][d] << " ";
7027 }
7028 m_log << " - right point: ";
7029 for(MInt d = nDim; d < 2 * nDim; d++) {
7030 m_log << bp->localRfnPatchProperties[pos][d] << " ";
7031 }
7032 m_log << endl;
7033 m_log << " - opening angle: " << bp->localRfnPatchProperties[pos][2 * nDim] << endl;
7034 m_log << " - radius: " << bp->localRfnPatchProperties[pos][2 * nDim + 1] << endl;
7035 m_log << " - thickness: " << bp->localRfnPatchProperties[pos][2 * nDim + 2] << endl;
7036
7037
7038 // SolverRefinement* bp = m_solverRefinement + 0;
7039
7040 MFloat Radius = bp->localRfnPatchProperties[pos][2 * nDim + 1];
7041 MFloat thickness = bp->localRfnPatchProperties[pos][2 * nDim + 2];
7042 MFloat angle = bp->localRfnPatchProperties[pos][2 * nDim];
7043 MFloat angle_rad = angle * PI / 180.0;
7044 MFloat deltaA = thickness / (F2 * sin(angle_rad));
7045 // original property
7046 std::array<MFloat, nDim> normalDifforigAB;
7047 MFloat length = 0.0;
7048 for(MInt d = 0; d < nDim; d++) {
7049 normalDifforigAB[d] = bp->localRfnPatchProperties[pos][d + nDim] - bp->localRfnPatchProperties[pos][d];
7050 length += normalDifforigAB[d] * normalDifforigAB[d];
7051 }
7052
7053 length = sqrt(length);
7054
7055 for(MInt d = 0; d < nDim; d++) {
7056 normalDifforigAB[d] /= length;
7057 }
7058
7059 std::array<MFloat, nDim> newPosA;
7060 std::array<MFloat, nDim> sphereCenter;
7061 std::array<MFloat, nDim> normalDiffAB;
7062 std::array<MFloat, nDim> normalDiffBA;
7063 MBoolScratchSpace insideLargerCone((m_levelOffsets[gridLvl][1] - m_levelOffsets[gridLvl][0]), AT_,
7064 "insideLargerCone");
7065
7066 for(MInt k = m_levelOffsets[gridLvl][0]; k < m_levelOffsets[gridLvl][1]; k++) {
7067 insideLargerCone(k - m_levelOffsets[gridLvl][0]) = false;
7068 }
7069
7070 for(MInt dir = 1; dir > -2; dir = dir - 2) {
7071 // a. precalculate the required vector for the inner/outer cone
7072 MFloat radius = (Radius + dir * thickness / F2) * cos(angle_rad);
7073 // calucate the new position of A
7074 MFloat lengthAB = 0.0;
7075 for(MInt d = 0; d < nDim; d++) {
7076 // splitpoint between cone and sphere
7077 newPosA[d] = (bp->localRfnPatchProperties[pos][d] - dir * deltaA * normalDifforigAB[d])
7078 + radius / tan(angle_rad) * normalDifforigAB[d];
7079
7080 sphereCenter[d] = (bp->localRfnPatchProperties[pos][d] - dir * deltaA * normalDifforigAB[d])
7081 + radius * (1.0 / tan(angle_rad) + tan(angle_rad)) * normalDifforigAB[d];
7082
7083 normalDiffAB[d] = bp->localRfnPatchProperties[pos][d + nDim] - newPosA[d];
7084 normalDiffBA[d] = newPosA[d] - bp->localRfnPatchProperties[pos][d + nDim];
7085
7086 lengthAB += normalDiffAB[d] * normalDiffAB[d];
7087 }
7088
7089 lengthAB = sqrt(lengthAB);
7090
7091
7092 for(MInt d = 0; d < nDim; d++) {
7093 normalDiffAB[d] /= lengthAB;
7094 }
7095
7096 // b. do a dry run so that we know how many cells we can expect,
7097 // also mark these cells
7098 // MInt rfnCount = 0;
7099 for(MInt k = m_levelOffsets[gridLvl][0]; k < m_levelOffsets[gridLvl][1]; k++) {
7100 if(a_isInSolver(k, solver)) {
7101 MFloat* coords = &a_coordinate(k, 0);
7102
7103 std::array<MFloat, nDim> diffA;
7104 std::array<MFloat, nDim> difforigA;
7105 std::array<MFloat, nDim> diffB;
7106 std::array<MFloat, nDim> diffCenter;
7107
7108 MFloat s1 = 0.0;
7109 MFloat s2 = 0.0;
7110 MFloat len_diffOrig = 0.0;
7111 MFloat len_diffCenter = 0.0;
7112 for(MInt d = 0; d < nDim; d++) {
7113 diffA[d] = coords[d] - newPosA[d];
7114 diffB[d] = coords[d] - bp->localRfnPatchProperties[pos][d + nDim];
7115 difforigA[d] = coords[d] - (bp->localRfnPatchProperties[pos][d] - dir * deltaA * normalDifforigAB[d]);
7116 diffCenter[d] = coords[d] - sphereCenter[d];
7117
7118 s1 += diffA[d] * normalDiffAB[d];
7119 s2 += diffB[d] * normalDiffBA[d];
7120 len_diffOrig += difforigA[d] * difforigA[d];
7121 len_diffCenter += diffCenter[d] * diffCenter[d];
7122 }
7123
7124 len_diffOrig = sqrt(len_diffOrig);
7125 len_diffCenter = sqrt(len_diffCenter);
7126
7127 std::array<MFloat, nDim> cross;
7128 MFloat distance = 0.0;
7129 for(MInt d = 0; d < nDim; d++) {
7130 MInt p1 = (d + 1) % (nDim);
7131 MInt p2 = (d + 2) % (nDim);
7132
7133 cross[d] = diffA[p1] * normalDiffAB[p2] - normalDiffAB[p1] * diffA[p2];
7134 distance += cross[d] * cross[d];
7135 }
7136
7137 distance = sqrt(distance);
7138
7139 MFloat ang = asin(distance / len_diffOrig) * 180 / PI;
7140
7141 if((ang <= angle && s1 >= 0.0 && s2 >= 0.0) || len_diffCenter <= Radius + dir * thickness / F2) {
7142 insideLargerCone(k - m_levelOffsets[gridLvl][0]) = true;
7143 if(dir == -1) {
7144 insideLargerCone(k - m_levelOffsets[gridLvl][0]) = false;
7145 }
7146 }
7147 }
7148 }
7149 }
7150
7151 for(MInt k = m_levelOffsets[gridLvl][0]; k < m_levelOffsets[gridLvl][1]; k++) {
7152 if(insideLargerCone(k - m_levelOffsets[gridLvl][0])) {
7153 a_isToRefineForSolver(k, solver) = 1;
7154 }
7155 }
7156
7157
7158 // b. do the same for the halos
7159 if(noDomains() > 1) {
7160 MInt lev_pos = 2 * (gridLvl - m_minLevel);
7161 MBoolScratchSpace insideLargerConeHalo(
7162 (m_haloCellOffsets[m_noNeighborDomains - 1][lev_pos + 1] - m_haloCellOffsets[0][lev_pos]), AT_,
7163 "insideLargerCone");
7164 for(MInt k = m_haloCellOffsets[0][lev_pos]; k < m_haloCellOffsets[m_noNeighborDomains - 1][lev_pos + 1]; k++) {
7165 insideLargerConeHalo(k - m_haloCellOffsets[0][lev_pos]) = false;
7166 }
7167
7168 for(MInt dir = 1; dir > -2; dir = dir - 2) {
7169 // a. precalculate the required vector for the inner/outer cone
7170 MFloat radius = (Radius + dir * thickness / F2) * cos(angle_rad);
7171 // calucate the new position of A
7172 MFloat lengthAB = 0.0;
7173 for(MInt d = 0; d < nDim; d++) {
7174 // splitpoint between cone and sphere
7175 newPosA[d] = (bp->localRfnPatchProperties[pos][d] - dir * deltaA * normalDifforigAB[d])
7176 + radius / tan(angle_rad) * normalDifforigAB[d];
7177 sphereCenter[d] = (bp->localRfnPatchProperties[pos][d] - dir * deltaA * normalDifforigAB[d])
7178 + radius * (1.0 / tan(angle_rad) + tan(angle_rad)) * normalDifforigAB[d];
7179 normalDiffAB[d] = bp->localRfnPatchProperties[pos][d + nDim] - newPosA[d];
7180 normalDiffBA[d] = newPosA[d] - bp->localRfnPatchProperties[pos][d + nDim];
7181
7182 lengthAB += normalDiffAB[d] * normalDiffAB[d];
7183 }
7184
7185 lengthAB = sqrt(lengthAB);
7186
7187
7188 for(MInt d = 0; d < nDim; d++)
7189 normalDiffAB[d] /= lengthAB;
7190
7191 for(MInt dom = 0; dom < m_noNeighborDomains; dom++) {
7192 for(MInt k = m_haloCellOffsets[dom][lev_pos]; k < m_haloCellOffsets[dom][lev_pos + 1]; k++) {
7193 if(a_isInSolver(k, solver)) {
7194 MFloat* coords = &a_coordinate(k, 0);
7195
7196 std::array<MFloat, nDim> diffA;
7197 std::array<MFloat, nDim> difforigA;
7198 std::array<MFloat, nDim> diffB;
7199 std::array<MFloat, nDim> diffCenter;
7200
7201 MFloat s1 = 0.0;
7202 MFloat s2 = 0.0;
7203 MFloat len_diffOrig = 0.0;
7204 MFloat len_diffCenter = 0.0;
7205 for(MInt d = 0; d < nDim; d++) {
7206 diffA[d] = coords[d] - newPosA[d];
7207 diffB[d] = coords[d] - bp->localRfnPatchProperties[pos][d + nDim];
7208 difforigA[d] = coords[d] - (bp->localRfnPatchProperties[pos][d] - dir * deltaA * normalDifforigAB[d]);
7209 diffCenter[d] = coords[d] - sphereCenter[d];
7210
7211 s1 += diffA[d] * normalDiffAB[d];
7212 s2 += diffB[d] * normalDiffBA[d];
7213 len_diffOrig += difforigA[d] * difforigA[d];
7214 len_diffCenter += diffCenter[d] * diffCenter[d];
7215 }
7216
7217 len_diffOrig = sqrt(len_diffOrig);
7218 len_diffCenter = sqrt(len_diffCenter);
7219
7220 std::array<MFloat, nDim> cross;
7221 MFloat distance = 0.0;
7222 for(MInt d = 0; d < nDim; d++) {
7223 MInt p1 = (d + 1) % (nDim);
7224 MInt p2 = (d + 2) % (nDim);
7225
7226 cross[d] = diffA[p1] * normalDiffAB[p2] - normalDiffAB[p1] * diffA[p2];
7227 distance += cross[d] * cross[d];
7228 }
7229
7230 distance = sqrt(distance);
7231
7232 MFloat ang = asin(distance / len_diffOrig) * 180 / PI;
7233
7234 if((ang <= angle && s1 >= 0.0 && s2 >= 0.0) || len_diffCenter <= Radius + dir * thickness / F2) {
7235 insideLargerConeHalo(k - m_haloCellOffsets[0][lev_pos]) = true;
7236 if(dir == -1) {
7237 insideLargerConeHalo(k - m_haloCellOffsets[0][lev_pos]) = false;
7238 }
7239 }
7240 }
7241 }
7242 } // for dom k
7243 } // for dir
7244
7245 for(MInt dom = 0; dom < m_noNeighborDomains; dom++) {
7246 for(MInt k = m_haloCellOffsets[dom][lev_pos]; k < m_haloCellOffsets[dom][lev_pos + 1]; k++) {
7247 if(insideLargerConeHalo(k - m_haloCellOffsets[0][lev_pos])) {
7248 a_isToRefineForSolver(k, solver) = 1;
7249 }
7250 }
7251 }
7252 } // if domain id
7253}

◆ markLocalRadius()

template<MInt nDim>
void GridgenPar< nDim >::markLocalRadius ( MInt  compRfnLvl,
MInt  patch,
MInt  solver 
)
protected
Author
Andreas Lintermann
Date
04.12.2013

This algorithm does the following:

a. It performs a dry run of the refinement, i.e., runs over all cells on the current level, counts the number of cells to refine (the cells which are inside a given sphere) and marks these cells (b_properties[5] = 1). b. the same is done for the halo cells if we run in parallel mode

Parameters
[in]levelthe level to run over

Definition at line 6094 of file cartesiangridgenpar.cpp.

6094 {
6095 TRACE();
6096
6097 SolverRefinement* bp = m_solverRefinement + solver;
6098
6099 // a. do a dry run so that we know how many cells we can expect,
6100 // also mark these cells
6101 const MInt pos = bp->localRfnLevelPropertiesOffset[compRfnLvl] + patch;
6102 const MInt gridLvl = compRfnLvl + bp->maxUniformRefinementLevel;
6103
6104 // Get coordinates
6105 const MFloat* sphereCoord = bp->localRfnPatchProperties[pos];
6106
6107 // Get radius
6108 const MFloat radius = bp->localRfnPatchProperties[pos][nDim];
6109
6110 m_log << " * marking local sphere for solver " << solver << endl;
6111 m_log << " - center: ";
6112 for(MInt d = 0; d < nDim; d++) {
6113 m_log << sphereCoord[d] << " ";
6114 }
6115 m_log << endl << " - radius: " << radius << endl;
6116
6117 for(MInt k = m_levelOffsets[gridLvl][0]; k < m_levelOffsets[gridLvl][1]; k++) {
6118 if(a_isInSolver(k, solver)) {
6119 if(maia::geom::isPointInsideSphere<nDim>(&a_coordinate(k, 0), sphereCoord, radius)) {
6120 a_isToRefineForSolver(k, solver) = 1;
6121 }
6122 }
6123 }
6124
6125 // b. do the same for the halos
6126 if(noDomains() > 1) {
6127 MInt lev_pos = 2 * (gridLvl - m_minLevel);
6128 for(MInt dom = 0; dom < m_noNeighborDomains; dom++) {
6129 for(MInt k = m_haloCellOffsets[dom][lev_pos]; k < m_haloCellOffsets[dom][lev_pos + 1]; k++) {
6130 if(a_isInSolver(k, solver)) {
6131 if(maia::geom::isPointInsideSphere<nDim>(&a_coordinate(k, 0), sphereCoord, radius)) {
6132 a_isToRefineForSolver(k, solver) = 1;
6133 }
6134 }
6135 }
6136 }
6137 }
6138}

◆ markLocalRectangleAngled()

template<MInt nDim>
void GridgenPar< nDim >::markLocalRectangleAngled ( MInt  compRfnLvl,
MInt  patch,
MInt  solver 
)
protected
  • This algorithm does the following:

    a. It performs a dry run of the refinement, i.e., runs over alls cells on the current level, counts the number of cells to refine (the cells which are inside a given cylinder) and marks these cells (b_properties[5] = 1). The according formula for the calculation of the distance \(d\) of a given point \(\vec{p}\) (cell coordinates) is given by

    \[d = \left|\left(\vec{p}-\vec{o}_1\right)\times\vec{r}\right|,\]

    where \(\vec{o}_1\) is the first center-point provided in the property, \(\vec{r}\) is the normalized vector between \(\vec{o}_1\) and \(\vec{o}_2\) (as provieded in thr property file).

    b. The same is done for the halo cells if we run in parallel mode

Parameters
[in]levelthe level to run over

Definition at line 6423 of file cartesiangridgenpar.cpp.

6423 {
6424 TRACE();
6425
6426 SolverRefinement* bp = m_solverRefinement + solver;
6427
6428 const MInt pos = bp->localRfnLevelPropertiesOffset[compRfnLvl] + patch;
6429 const MInt gridLvl = compRfnLvl + bp->maxUniformRefinementLevel;
6430
6431 m_log << " * marking local angled rectangle for solver " << solver << endl;
6432 m_log << " - left center: ";
6433 for(MInt d = 0; d < nDim; d++) {
6434 m_log << bp->localRfnPatchProperties[pos][d] << " ";
6435 }
6436 m_log << " - right center: ";
6437 for(MInt d = nDim; d < 2 * nDim; d++) {
6438 m_log << bp->localRfnPatchProperties[pos][d] << " ";
6439 }
6440 m_log << endl;
6441 m_log << " - height: " << bp->localRfnPatchProperties[pos][2 * nDim] << endl;
6442 m_log << " - width: " << bp->localRfnPatchProperties[pos][2 * nDim + 1] << endl;
6443
6444
6445 // a. precalculate the required vector
6446
6447 std::array<MFloat, nDim> normalDiffAB;
6448 std::array<MFloat, nDim> normalDiffBA;
6449 MFloat length = 0.0;
6450 for(MInt d = 0; d < nDim; d++) {
6451 normalDiffAB[d] = bp->localRfnPatchProperties[pos][d + nDim] - bp->localRfnPatchProperties[pos][d];
6452 normalDiffBA[d] = bp->localRfnPatchProperties[pos][d] - bp->localRfnPatchProperties[pos][d + nDim];
6453 length += normalDiffAB[d] * normalDiffAB[d];
6454 }
6455
6456 length = sqrt(length);
6457
6458 for(MInt d = 0; d < nDim; d++) {
6459 normalDiffAB[d] /= length;
6460 }
6461
6462 // b. do a dry run so that we know how many cells we can expect,
6463 // also mark these cells
6464 for(MInt k = m_levelOffsets[gridLvl][0]; k < m_levelOffsets[gridLvl][1]; k++) {
6465 if(a_isInSolver(k, solver)) {
6466 MFloat* coords = &a_coordinate(k, 0);
6467
6468 std::array<MFloat, nDim> diffA;
6469 std::array<MFloat, nDim> diffB;
6470
6471 MFloat s1 = 0.0;
6472 MFloat s2 = 0.0;
6473 for(MInt d = 0; d < nDim; d++) {
6474 diffA[d] = coords[d] - bp->localRfnPatchProperties[pos][d];
6475 diffB[d] = coords[d] - bp->localRfnPatchProperties[pos][d + nDim];
6476 s1 += diffA[d] * normalDiffAB[d];
6477 s2 += diffB[d] * normalDiffBA[d];
6478 }
6479
6480 std::array<MFloat, nDim> cross;
6481 MFloat distanceH = 0.0;
6482 MFloat distanceW = 0.0;
6483
6484
6485 for(MInt d = 0; d < nDim; d++) {
6486 MInt p1 = (d + 1) % (nDim);
6487 MInt p2 = (d + 2) % (nDim);
6488
6489 cross[d] = diffA[p1] * normalDiffAB[p2] - normalDiffAB[p1] * diffA[p2];
6490 if(d == 0) {
6491 distanceH += cross[d] * cross[d];
6492 }
6493 if(d == 1) {
6494 distanceH += cross[d] * cross[d];
6495 }
6496 if(d == 2) {
6497 distanceW += cross[d] * cross[d];
6498 }
6499 }
6500 distanceH = sqrt(distanceH);
6501 distanceW = sqrt(distanceW);
6502
6503 if(distanceH <= bp->localRfnPatchProperties[pos][2 * nDim]
6504 && distanceW <= bp->localRfnPatchProperties[pos][2 * nDim + 1] && s1 >= 0.0 && s2 >= 0.0) {
6505 a_isToRefineForSolver(k, solver) = 1;
6506 }
6507 }
6508 }
6509
6510 // c. do the same for the halos
6511 if(noDomains() > 1) {
6512 MInt lev_pos = 2 * (gridLvl - m_minLevel);
6513 for(MInt dom = 0; dom < m_noNeighborDomains; dom++) {
6514 for(MInt k = m_haloCellOffsets[dom][lev_pos]; k < m_haloCellOffsets[dom][lev_pos + 1]; k++) {
6515 if(a_isInSolver(k, solver)) {
6516 MFloat* coords = &a_coordinate(k, 0);
6517
6518 std::array<MFloat, nDim> diffA;
6519 std::array<MFloat, nDim> diffB;
6520
6521 MFloat s1 = 0.0;
6522 MFloat s2 = 0.0;
6523 for(MInt d = 0; d < nDim; d++) {
6524 diffA[d] = coords[d] - bp->localRfnPatchProperties[pos][d];
6525 diffB[d] = coords[d] - bp->localRfnPatchProperties[pos][d + nDim];
6526 s1 += diffA[d] * normalDiffAB[d];
6527 s2 += diffB[d] * normalDiffBA[d];
6528 }
6529
6530 std::array<MFloat, nDim> cross;
6531 MFloat distanceH = 0.0;
6532 MFloat distanceW = 0.0;
6533
6534
6535 for(MInt d = 0; d < nDim; d++) {
6536 MInt p1 = (d + 1) % (nDim);
6537 MInt p2 = (d + 2) % (nDim);
6538
6539 cross[d] = diffA[p1] * normalDiffAB[p2] - normalDiffAB[p1] * diffA[p2];
6540 if(d == 0) {
6541 distanceH += cross[d] * cross[d];
6542 }
6543 if(d == 1) {
6544 distanceH += cross[d] * cross[d];
6545 }
6546 if(d == 2) {
6547 distanceW += cross[d] * cross[d];
6548 }
6549 }
6550 distanceH = sqrt(distanceH);
6551 distanceW = sqrt(distanceW);
6552
6553 if(distanceH <= bp->localRfnPatchProperties[pos][2 * nDim]
6554 && distanceW <= bp->localRfnPatchProperties[pos][2 * nDim + 1] && s1 >= 0.0 && s2 >= 0.0) {
6555 a_isToRefineForSolver(k, solver) = 1;
6556 }
6557 }
6558 }
6559 }
6560 }
6561}

◆ markLocalSlicedCone()

template<MInt nDim>
void GridgenPar< nDim >::markLocalSlicedCone ( MInt  compRfnLvl,
MInt  patch,
MInt  solver,
MString  patchStr 
)
protected
Author
Rodrigo Miguez (rodrigo) rodri.nosp@m.go.m.nosp@m.iguez.nosp@m.@rwt.nosp@m.h-aac.nosp@m.hen..nosp@m.de
Date
12.05.2022

This algorithm does the following:

a. Precalculate the required values such as the sliced cone axis, circle normals according to the type of frustum cone being used (aligned or not aligned circle normals). For the non-aligned case, a check of the provided normal vectors is done.

b. A dry-run is performed to mark the cells that must be refined in the current level and the same is done for the halo cells if we run in parallel mode.

Parameters
[in]levelthe level to run over
[in]patchStrthe type of frustum cone patch being used

Definition at line 6778 of file cartesiangridgenpar.cpp.

6778 {
6779 TRACE();
6780
6781 if(patchStr != "A" && patchStr != "N") {
6782 TERMM(1, "This function doesn't support the selected patch type!");
6783 }
6784
6785 const MBool isAligned = (patchStr == "A") ? true : false;
6786
6787 SolverRefinement* bp = m_solverRefinement + solver;
6788
6789 const MInt pos = bp->localRfnLevelPropertiesOffset[compRfnLvl] + patch;
6790 const MInt gridLvl = compRfnLvl + bp->maxUniformRefinementLevel;
6791
6792 m_log << " * marking local sliced cone for solver " << solver << endl;
6793 // Get coordinates
6794 std::array<MFloat, nDim> leftCoord;
6795 std::array<MFloat, nDim> rightCoord;
6796 for(MInt d = 0; d < nDim; d++) {
6797 leftCoord[d] = bp->localRfnPatchProperties[pos][d];
6798 rightCoord[d] = bp->localRfnPatchProperties[pos][d + nDim];
6799 }
6800
6801 m_log << " - left coord: ";
6802 for(MInt d = 0; d < nDim; d++) {
6803 m_log << leftCoord[d] << " ";
6804 }
6805 m_log << endl << " - right coord: ";
6806 for(MInt d = 0; d < nDim; d++) {
6807 m_log << rightCoord[d] << " ";
6808 }
6809
6810 // Get radius
6811 const MInt col = (isAligned) ? 2 : 4;
6812 const MFloat leftR = bp->localRfnPatchProperties[pos][col * nDim];
6813 const MFloat rightR = bp->localRfnPatchProperties[pos][col * nDim + 1];
6814
6815 m_log << endl << " - left radius: " << leftR << endl;
6816 m_log << " - right radius: " << rightR << endl;
6817
6818 // a. precalculate the required values
6819 std::array<MFloat, nDim> normalDifforigAB;
6820 MFloat length = 0.0;
6821 for(MInt d = 0; d < nDim; d++) {
6822 normalDifforigAB[d] = rightCoord[d] - leftCoord[d];
6823 length += normalDifforigAB[d] * normalDifforigAB[d];
6824 }
6825 length = sqrt(length);
6826
6827 // Get unit normals
6828 std::array<MFloat, nDim> leftNormal;
6829 std::array<MFloat, nDim> rightNormal;
6830 for(MInt d = 0, i = 0; d < nDim; d++, i++) {
6831 if(isAligned) {
6832 rightNormal[d] = normalDifforigAB[d] / length;
6833 leftNormal[d] = -rightNormal[d];
6834 } else {
6835 leftNormal[d] = bp->localRfnPatchProperties[pos][2 * nDim + d];
6836 rightNormal[d] = bp->localRfnPatchProperties[pos][2 * nDim + d + nDim];
6837 }
6838 }
6839
6840 m_log << " - left normal: ";
6841 for(MInt d = 0; d < nDim; d++) {
6842 m_log << leftNormal[d] << " ";
6843 }
6844 m_log << endl << " - right normal: ";
6845 for(MInt d = 0; d < nDim; d++) {
6846 m_log << rightNormal[d] << " ";
6847 }
6848 m_log << endl;
6849
6850 // Check if the direction of the circle normals are valid (only necessary when using non
6851 // axis-aligned normals)
6852 if(!isAligned) {
6853 MFloat leftNormalDir = 0.0;
6854 MFloat rightNormalDir = 0.0;
6855 MBool isAborting = false;
6856 stringstream ss;
6857 for(MInt d = 0; d < nDim; d++) {
6858 leftNormalDir += (rightCoord[d] - leftCoord[d]) * leftNormal[d];
6859 rightNormalDir += (leftCoord[d] - rightCoord[d]) * rightNormal[d];
6860 // Normals are at a plane not crossed by the cone axis
6861 if(approx(normalDifforigAB[d], 0.0, MFloatEps) && !approx(leftNormal[d], 0.0, MFloatEps)) {
6862 ss << "Warning: Normal values for the left circle are not valid at dir = " << d << "!" << endl;
6863 isAborting = true;
6864 } else if(approx(normalDifforigAB[d], 0.0, MFloatEps) && !approx(rightNormal[d], 0.0, MFloatEps)) {
6865 ss << "Warning: Normal values for the right circle are not valid at dir = " << d << "!" << endl;
6866 isAborting = true;
6867 }
6868 // Normals are pointing in the same direction
6869 if((d == nDim - 1) && leftNormalDir >= 0.0 && rightNormalDir >= 0.0) {
6870 ss << "Warning: Normals are not consistent!" << endl;
6871 isAborting = true;
6872 }
6873 }
6874 if(isAborting) {
6875 cerr << ss.str() << "Aborting...";
6876 m_log << ss.str() << "Aborting...";
6877 TERMM(1, ss.str() + "Aborting...");
6878 }
6879 }
6880
6881 // b. do a dry run so that we know how many cells we can expect,
6882 // also mark these cells
6883 for(MInt k = m_levelOffsets[gridLvl][0]; k < m_levelOffsets[gridLvl][1]; k++) {
6884 if(a_isInSolver(k, solver)) {
6885 if(isInsideSlicedCone(&a_coordinate(k, 0), leftCoord.data(), rightCoord.data(), leftNormal.data(),
6886 rightNormal.data(), normalDifforigAB.data(), leftR, rightR)) {
6887 a_isToRefineForSolver(k, solver) = 1;
6888 }
6889 }
6890 }
6891
6892 // b. do the same for the halos
6893 if(noDomains() > 1) {
6894 MInt lev_pos = 2 * (gridLvl - m_minLevel);
6895
6896 for(MInt dom = 0; dom < m_noNeighborDomains; dom++) {
6897 for(MInt k = m_haloCellOffsets[dom][lev_pos]; k < m_haloCellOffsets[dom][lev_pos + 1]; k++) {
6898 if(a_isInSolver(k, solver)) {
6899 if(isInsideSlicedCone(&a_coordinate(k, 0), leftCoord.data(), rightCoord.data(), leftNormal.data(),
6900 rightNormal.data(), normalDifforigAB.data(), leftR, rightR)) {
6901 a_isToRefineForSolver(k, solver) = 1;
6902 }
6903 }
6904 }
6905 }
6906 }
6907}
MBool isInsideSlicedCone(const MFloat *const pointCoord, const MFloat *const leftCoord, const MFloat *const rightCoord, const MFloat *const leftNormal, const MFloat *const rightNormal, const MFloat *const normalDifforigAB, const MFloat leftR, const MFloat rightR)
checks if point (cell) is inside a sliced cone

◆ markLocalSolverRefinement()

template<MInt nDim>
void GridgenPar< nDim >::markLocalSolverRefinement ( MInt  level_,
MInt  solver 
)
protected

Definition at line 1819 of file cartesiangridgenpar.cpp.

1819 {
1820 TRACE();
1821
1822 SolverRefinement* bp = m_solverRefinement + solver;
1823
1824 if(level_ < bp->maxUniformRefinementLevel) {
1825 markSolverForRefinement(level_, solver);
1826 } else {
1827 MInt refLevel = level_ - bp->maxUniformRefinementLevel;
1828 if(refLevel < bp->noLocalPatchRfnLvls()) markPatchForSolverRefinement(level_, solver);
1829 if(refLevel < bp->noLocalBndRfnLvls) markBndForSolverRefinement(level_, solver);
1830 }
1831}
void markBndForSolverRefinement(MInt level_, MInt solver)
void markPatchForSolverRefinement(MInt level_, MInt solver)

◆ markPatchForSolverRefinement()

template<MInt nDim>
void GridgenPar< nDim >::markPatchForSolverRefinement ( MInt  level_,
MInt  solver 
)
protected

Definition at line 1834 of file cartesiangridgenpar.cpp.

1834 {
1835 TRACE();
1836
1837 SolverRefinement* bp = m_solverRefinement + solver;
1838
1839 MInt refLevel = level_ - bp->maxUniformRefinementLevel;
1840
1841 for(MInt patch = 0; patch < bp->noPatchesPerLevel(refLevel); patch++) {
1842 MString patchStr = bp->localRfnLevelMethods[refLevel].substr(patch, 1);
1843 if(patchStr == "B") {
1844 markLocalBox(refLevel, patch, solver);
1845 } else if(patchStr == "R") {
1846 markLocalRadius(refLevel, patch, solver);
1847 } else if(patchStr == "C" || patchStr == "T") {
1848 markLocalCylinder(refLevel, patch, solver, patchStr);
1849 } else if(patchStr == "O") {
1850 markLocalCone(refLevel, patch, solver);
1851 } else if(patchStr == "H") {
1852 markLocalHat(refLevel, patch, solver);
1853 } else if(patchStr == "S") {
1854 markLocalRectangleAngled(refLevel, patch, solver);
1855 } else if(patchStr == "W") {
1856 markLocalCartesianWedge(refLevel, patch, solver);
1857 } else if(patchStr == "A" || patchStr == "N") {
1858 markLocalSlicedCone(refLevel, patch, solver, patchStr);
1859 } else {
1860 TERMM(1, "Unknown patch type: '" + patchStr + "'");
1861 }
1862 }
1863}
void markLocalCylinder(MInt level_, MInt patch, MInt solver, MString patchStr)
marks cells that lie in a cylinder-type patch
void markLocalBox(MInt level_, MInt patch, MInt solver)
marks cells that lie in a box-type patch
void markLocalRectangleAngled(MInt level_, MInt patch, MInt solver)
marks cells that lie in a rectangular-angled-type patch
void markLocalRadius(MInt level_, MInt patch, MInt solver)
marks cells that lie in a sphere-type patch
void markLocalCartesianWedge(MInt level_, MInt patch, MInt solver)
void markLocalCone(MInt level_, MInt patch, MInt solver)
marks cells that lie in a cone-type patch with a smooth hat
void markLocalHat(MInt level_, MInt patch, MInt solver)
marks cells that lie in a cone-type patch with a smooth hat
void markLocalSlicedCone(MInt level_, MInt patch, MInt solver, MString patchStr)
marks cells that lie in a sliced cone-type patch

◆ markSolverAffiliation()

template<MInt nDim>
void GridgenPar< nDim >::markSolverAffiliation ( MInt  level_)
protected
Author
Thomas Schilden
Date
03.04.2018

In multisolver grids, a refined grid might contain cells that are inside the set of solver geometries but are not affiliated to a solver. Furthermore, these cells might be cut by any geometry, i.e., they are boundary cells. Cells without a solver are marked outside and lose their boundary cell status to be deleted.

Parameters
[in]level_the level to check

Definition at line 3410 of file cartesiangridgenpar.cpp.

3410 {
3411 for(MInt solver = 0; solver < m_noSolvers; solver++) {
3412 excludeInsideOutside(m_levelOffsets, level_, solver);
3413 if(noDomains() > 1) {
3415 }
3416 markInsideOutside(m_levelOffsets, level_, solver);
3417 if(noDomains() > 1) {
3419 }
3420 }
3421
3422 for(MInt i = m_levelOffsets[level_][0]; i < m_levelOffsets[level_][1]; i++) {
3423 MChar inside = 0;
3424 for(MInt solver = 0; solver < m_noSolvers; solver++) {
3425 if(a_isInSolver(i, solver)) {
3426 inside = 1;
3427 break;
3428 }
3429 }
3430 if(!inside) {
3431 a_hasProperty(i, 0) = 0;
3432 a_hasProperty(i, 1) = 0; // they also lose their status as boundary cells to be deleted
3433 }
3434 }
3435
3436 if(noDomains() > 1) { // might be irrelevant since m_noNeighborDomains = 0
3437 MInt lev_pos = 2 * (level_ - m_minLevel);
3438
3439 for(MInt dom = 0; dom < m_noNeighborDomains; dom++) {
3440 for(MInt i = m_haloCellOffsets[dom][lev_pos]; i < m_haloCellOffsets[dom][lev_pos + 1]; i++) {
3441 MChar inside = 0;
3442 for(MInt solver = 0; solver < m_noSolvers; solver++) {
3443 if(a_isInSolver(i, solver)) {
3444 inside = 1;
3445 break;
3446 }
3447 }
3448 if(!inside) {
3449 a_hasProperty(i, 0) = 0;
3450 a_hasProperty(i, 1) = 0;
3451 }
3452 }
3453 }
3454 }
3455}
void excludeInsideOutside(MInt **offsets, MInt level_, MInt solver)
excludes obvious non solver affiliated cells from the inside outside flooding
char MChar
Definition: maiatypes.h:56

◆ markSolverForRefinement()

template<MInt nDim>
void GridgenPar< nDim >::markSolverForRefinement ( MInt  level_,
MInt  solver 
)
protected

Definition at line 1978 of file cartesiangridgenpar.cpp.

1978 {
1979 TRACE();
1980
1981 for(MInt k = m_levelOffsets[level_][0]; k < m_levelOffsets[level_][1]; k++) {
1982 if(a_isInSolver(k, solver)) {
1983 a_isToRefineForSolver(k, solver) = 1;
1984 }
1985 }
1986
1987 if(noDomains() > 1) {
1988 MInt lev_pos = 2 * (level_ - m_minLevel);
1989 for(MInt dom = 0; dom < m_noNeighborDomains; dom++) {
1990 for(MInt k = m_haloCellOffsets[dom][lev_pos]; k < m_haloCellOffsets[dom][lev_pos + 1]; k++) {
1991 if(a_isInSolver(k, solver)) {
1992 a_isToRefineForSolver(k, solver) = 1;
1993 }
1994 }
1995 }
1996 }
1997}

◆ mpiComm()

template<MInt nDim>
MPI_Comm GridgenPar< nDim >::mpiComm ( ) const
inline

Definition at line 146 of file cartesiangridgenpar.h.

146{ return m_mpiComm; }

◆ nghborStencil()

template<MInt nDim>
MInt GridgenPar< nDim >::nghborStencil ( MInt  neighbor,
MInt  dir 
)
protected

Definition at line 2825 of file cartesiangridgenpar.cpp.

2825 {
2826 static constexpr MInt nghborStencil3d[26][3] = {
2827 {0, -1, -1}, {1, -1, -1}, {2, -1, -1}, {3, -1, -1}, {4, -1, -1}, {5, -1, -1}, {0, 2, -1}, {0, 3, -1}, {0, 4, -1},
2828 {0, 5, -1}, {1, 2, -1}, {1, 3, -1}, {1, 4, -1}, {1, 5, -1}, {2, 4, -1}, {2, 5, -1}, {3, 4, -1}, {3, 5, -1},
2829 {0, 2, 4}, {0, 2, 5}, {0, 3, 4}, {0, 3, 5}, {1, 2, 4}, {1, 2, 5}, {1, 3, 4}, {1, 3, 5}};
2830
2831 static constexpr MInt nghborStencil2d[26][3] = {
2832 {0, -1, -1}, {1, -1, -1}, {2, -1, -1}, {3, -1, -1}, {0, 2, -1}, {1, 3, -1}, {2, 1, -1},
2833 {3, 0, -1}, {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1},
2834 {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1},
2835 {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1}, {-1, -1, -1}};
2836
2837 IF_CONSTEXPR(nDim == 3) return nghborStencil3d[neighbor][dir];
2838 return nghborStencil2d[neighbor][dir];
2839}

◆ noDomains()

template<MInt nDim>
MInt GridgenPar< nDim >::noDomains ( ) const
inline

Definition at line 148 of file cartesiangridgenpar.h.

148{ return m_noDomains; }

◆ parallelizeGrid()

template<MInt nDim>
void GridgenPar< nDim >::parallelizeGrid
protected
Author
Andreas Lintermann
Date
17.10.2013

This function parallelizes the grid with the following algorithm:

a. Generate the rank offsets in the current list of all cells. This continuously devides the number of the remaining cells by the number of the remaining ranks. b. Identify the neighbor domains. This runs over the offset for my domain and checks if a neighbor belongs to another offset. If so, a list of neighboring domains is updated by the index of the offset in which the neighbor is located. The number of halo cells for this domain is then incremented. The cell in my domain offset is marked as window cell, while the neighbor on the other domain is marked as halo cell. c. Find halo cells in other domains and move them to the end of the collector. This runs over the offsets of the domains found as a neighbor in the previous step and moves the cells to the end od the collector. Therefore the offsets for the halo cells at the end of the collector is calculated per neighboring domain. The movement also updates the neighbors which are in my domain and deletes the neighbors which are outside my domain. The update of local neighbors already includes the shift performed in the next step. d. Shift all cells to the beginning of the collector. This completely moves the solver of my local cells to the beginning of the collector. Then all neighbor ids are simply updated by shifting the neighbor id by the size of the shift. e. Update number of cells and the level offsets. This finally removes the knowledge about any other cell which does not belong to my domain.

Parameters
[in]level_indicator for the timers

Definition at line 4372 of file cartesiangridgenpar.cpp.

4372 {
4373 TRACE();
4374
4375 RECORD_TIMER_START(m_t_parallelizeGrid);
4376
4377 m_log << " + parallelizing grid" << endl;
4378 outStream << " + parallelizing grid" << endl;
4379
4380 // a. Generate the rank offsets in the current list of all cells
4381 m_log << " * calculating rank offsets" << endl;
4382 outStream << " * calculating rank offsets" << endl;
4383 MIntScratchSpace rank_offsets(noDomains() + 1, AT_, "rank_offsets");
4384
4385 determineRankOffsets(rank_offsets);
4386
4387 m_log << " - rank offsets are : ";
4388 outStream << " - rank offsets are : ";
4389 for(MInt dom = 0; dom < noDomains() + 1; dom++) {
4390 m_log << rank_offsets[dom] << " ";
4391 outStream << rank_offsets[dom] << " ";
4392 }
4393 m_log << endl;
4394 outStream << endl;
4395
4396
4397 // b. Identify the neighbor domains
4398 m_log << " * finding communication partners" << endl;
4399 outStream << " * finding communication partners" << endl;
4400
4401 const MInt my_lower_off = rank_offsets[globalDomainId()];
4402 const MInt my_upper_off = rank_offsets[globalDomainId() + 1];
4403
4404 // set to save neighbor domains
4405 set<MInt> neighbor_domains_set;
4406
4407 // space for saving number of halo cells per domain
4408 MIntScratchSpace no_haloPerDomain(noDomains(), AT_, "no_haloPerDomain");
4409 no_haloPerDomain.fill(0);
4410
4411 // iterate over all assigned cells
4412 for(MInt i = my_lower_off; i < my_upper_off; i++) {
4413 for(MInt dir = 0; dir < m_noNeighbors; dir++) {
4414 const MInt nghbrId = (MInt)a_neighborId(i, dir);
4415
4416 // check if neighbor exists and is not on own domain
4417 if(nghbrId >= 0 && (nghbrId < my_lower_off || nghbrId >= my_upper_off)) {
4418 // mark as window cell
4419 a_hasProperty(i, 3) = 1;
4420
4421 // determine to which domain neighbor cell has been assigned
4422 MInt l = 0;
4423 while(nghbrId >= rank_offsets[l + 1]) {
4424 l++;
4425 }
4426
4427 neighbor_domains_set.insert(l);
4428
4429 // mark as halo cell
4430 if(!a_hasProperty(nghbrId, 4)) {
4431 no_haloPerDomain[l]++;
4432 a_hasProperty(nghbrId, 4) = 1;
4433 }
4434 }
4435 }
4436 }
4437
4438 m_noNeighborDomains = (MInt)neighbor_domains_set.size();
4439 mAlloc(m_neighborDomains, m_noNeighborDomains, "m_neighborDomains", -1, AT_);
4440 mAlloc(m_rfnCountHalosDom, m_noNeighborDomains, "m_rfnCountHalosDom", 0, AT_);
4441
4442 m_log << " - domain " << globalDomainId() << " has " << m_noNeighborDomains
4443 << " neighbor(s) [number of halos]: ";
4444 outStream << " - domain " << globalDomainId() << " has " << m_noNeighborDomains
4445 << " neighbor(s) [number of halos]: ";
4446 set<MInt>::iterator it = neighbor_domains_set.begin();
4447 for(MInt j = 0; j < m_noNeighborDomains; j++) {
4448 m_neighborDomains[j] = *it;
4449 it++;
4450
4451 m_log << m_neighborDomains[j] << " [" << no_haloPerDomain[m_neighborDomains[j]] << "] ";
4452 outStream << m_neighborDomains[j] << " [" << no_haloPerDomain[m_neighborDomains[j]] << "] ";
4453 }
4454 m_log << endl;
4455 outStream << endl;
4456
4457
4458 // c. find halo cells in other domains and move them to the end of the collector
4459 m_log << " * finding and moving halo cells that we want to keep" << endl;
4460 outStream << " * finding and moving halo cells that we want to keep" << endl;
4461
4462 // new ordering, remember the offsets for each domains and for each level
4463 mAlloc(m_haloCellOffsets, m_noNeighborDomains, 2 * (m_maxRfnmntLvl - m_minLevel + 1), "m_haloCellOffsets", 0, AT_);
4464 const MInt lastNeighborDomPos = m_noNeighborDomains - 1;
4465 const MInt lastNeighborDomId = m_neighborDomains[lastNeighborDomPos];
4466
4467 m_haloCellOffsets[lastNeighborDomPos][1] = m_maxNoCells - 1;
4468 m_haloCellOffsets[lastNeighborDomPos][0] =
4469 m_haloCellOffsets[lastNeighborDomPos][1] - no_haloPerDomain[lastNeighborDomId];
4470
4471 for(MInt j = m_noNeighborDomains - 2; j >= 0; j--) {
4472 m_haloCellOffsets[j][1] = m_haloCellOffsets[j + 1][0];
4473 m_haloCellOffsets[j][0] = m_haloCellOffsets[j][1] - no_haloPerDomain[m_neighborDomains[j]];
4474 }
4475
4476 m_log << " - haloCellOffsets on this level for processes [offsets]: " << endl;
4477 outStream << " - haloCellOffsets on this level for processes [offsets]: " << endl;
4478 for(MInt j = 0; j < m_noNeighborDomains; j++) {
4479 m_log << " = " << m_neighborDomains[j] << ": " << m_haloCellOffsets[j][1] - m_haloCellOffsets[j][0]
4480 << " [" << m_haloCellOffsets[j][0] << " " << m_haloCellOffsets[j][1] << "]" << endl;
4481 outStream << " = " << m_neighborDomains[j] << ": " << m_haloCellOffsets[j][1] - m_haloCellOffsets[j][0]
4482 << " [" << m_haloCellOffsets[j][0] << " " << m_haloCellOffsets[j][1] << "]" << endl;
4483 }
4484
4485 MInt shift = my_lower_off;
4486
4487 // copy halo cells to the end of the collector
4488 for(MInt dom = 0; dom < m_noNeighborDomains; dom++) {
4489 MInt domain = m_neighborDomains[dom];
4490 MInt haloPos = m_haloCellOffsets[dom][0];
4491
4492 // run over all cells of my neighbor domain
4493 for(MInt i = rank_offsets[domain]; i < rank_offsets[domain + 1]; i++) {
4494 // if we found a halo cell that we want to keep
4495 if(a_hasProperty(i, 4)) {
4496 copyCell(i, haloPos);
4497 haloPos++;
4498 }
4499 }
4500 }
4501
4502 // update the number of halo cells and their offsets
4505
4508
4509
4510 // update the halo cell such that it only points to cells that are on my domain
4512 MLong* neigh = &a_neighborId(h, 0);
4513 for(MInt n = 0; n < m_noNeighbors; n++) {
4514 if(neigh[n] < my_lower_off || (neigh[n] >= my_upper_off && neigh[n] < m_haloCellOffsetsLevel[m_minLevel][0])) {
4515 neigh[n] = -1;
4516 } else if(neigh[n] >= my_lower_off && neigh[n] < my_upper_off) {
4517 neigh[n] -= shift;
4518 }
4519 }
4520 }
4521
4522 // d. shift all cells to the beginning of the collector
4523 MInt noCellsInMyDomain = my_upper_off - my_lower_off;
4524
4525 m_log << " * shifting my cell array of size " << noCellsInMyDomain << " by " << my_lower_off << " units"
4526 << endl;
4527 outStream << " * shifting my cell array of size " << noCellsInMyDomain << " by " << my_lower_off << " units"
4528 << endl;
4529
4530 m_log << " - moving memory for pointers in cells" << endl;
4531 outStream << " - moving memory for pointers in cells" << endl;
4532
4533 // perform the cell shift by the shift variable, why not use copyCell(...) to help future us's
4534 copy(&a_parentId(my_lower_off), &a_parentId(my_lower_off + noCellsInMyDomain), &a_parentId(0));
4535 copy(&a_globalId(my_lower_off), &a_globalId(my_lower_off + noCellsInMyDomain), &a_globalId(0));
4536 copy(&a_level(my_lower_off), &a_level(my_lower_off + noCellsInMyDomain), &a_level(0));
4537 copy(&a_noChildren(my_lower_off), &a_noChildren(my_lower_off + noCellsInMyDomain), &a_noChildren(0));
4538 copy(&a_neighborId(my_lower_off, 0), &a_neighborId(my_lower_off + noCellsInMyDomain, m_noNeighbors),
4539 &a_neighborId(0, 0));
4540 copy(&a_childId(my_lower_off, 0), &a_childId(my_lower_off + noCellsInMyDomain, m_maxNoChildren), &a_childId(0, 0));
4541 copy(&a_coordinate(my_lower_off, 0), &a_coordinate(my_lower_off + noCellsInMyDomain, nDim), &a_coordinate(0, 0));
4542
4543 m_log << " - moving bitsets and updating the neighbors" << endl;
4544 outStream << " - moving bitsets and updating the neighbors" << endl;
4545
4546 // update bitsets and shift the neighbors
4547 for(MInt i = 0; i < noCellsInMyDomain; i++) {
4548 MInt cell = i;
4549 MInt former_cell = i + my_lower_off;
4550 for(MInt b = 0; b < 8; b++) {
4551 a_hasProperty(cell, b) = a_hasProperty(former_cell, b);
4552 a_isInSolver(cell, b) = a_isInSolver(former_cell, b);
4553 a_isSolverBoundary(cell, b) = a_isSolverBoundary(former_cell, b);
4554 a_isToRefineForSolver(cell, b) = a_isToRefineForSolver(former_cell, b);
4555 }
4556 for(MInt s = 0; s < m_noSolvers; s++) {
4557 a_noSolidLayer(cell, s) = a_noSolidLayer(former_cell, s);
4558 }
4559
4560
4561 MLong* neigh = &a_neighborId(cell, 0);
4562 for(MInt n = 0; n < m_noNeighbors; n++)
4563 if(neigh[n] >= 0 && neigh[n] < m_haloCellOffsets[0][0]) neigh[n] -= shift;
4564 }
4565
4566 // e. update number of cells and the level offsets
4568 m_noCells = noCellsInMyDomain;
4569
4570 for(MInt l = 0; l < m_minLevel; l++) {
4571 m_levelOffsets[l][0] = -1;
4572 m_levelOffsets[l][1] = -1;
4573 }
4574
4575 m_levelOffsets[m_minLevel][0] = 0;
4577
4578 // f. initialize the LUT, needed for updateInterRankNeighbors, (findHaloWindowCells within)
4579 // add initial halo cells to LUT
4580 for(MInt cellId = m_haloCellOffsets[0][0]; cellId < m_haloCellOffsets[m_noNeighborDomains - 1][1]; cellId++) {
4581 m_cellIdLUT.insert(make_pair(cellId, cellId));
4582 }
4583
4584 // add intial cells to LUT
4585 for(MInt cellId = 0; cellId < m_levelOffsets[m_minLevel][1]; cellId++) {
4586 m_cellIdLUT.insert(make_pair(cellId, cellId));
4587 }
4588
4589 RECORD_TIMER_STOP(m_t_parallelizeGrid);
4590}
void determineRankOffsets(MIntScratchSpace &offsets)

◆ performCutOff()

template<MInt nDim>
void GridgenPar< nDim >::performCutOff ( MInt **  offsets,
MInt  level_,
MBool  deleteMode = false 
)
protected
Author
Andreas Lintermann
Date
13.12.2013

Runs over all cells and checks if cut-offs appear:

  • B: a box is used, all inside are kept
  • P: a plane is used, all cells that have a positive scalar product with the normal are kept
Parameters
[in]level_the level to check

Definition at line 2882 of file cartesiangridgenpar.cpp.

2882 {
2883 TRACE();
2884
2885 m_log << " - performing cut-off on level " << level_ << " with the following options: " << endl;
2886
2887 for(MInt solver = 0; solver < m_noSolvers; solver++) {
2888 SolverRefinement* bp = m_solverRefinement + solver;
2889 if(((bp->cutOff == 1) && (level_ == m_minLevel)) || ((bp->cutOff == 2) && (level_ <= m_minLevel))
2890 || ((bp->cutOff == 3) && (level_ >= m_minLevel)) || (bp->cutOff == 4)) {
2891 m_log << " - solver " << solver << endl;
2892
2893 for(MInt c = 0; c < (signed)bp->cutOffMethods.size(); c++) {
2894 m_log << " . type: " << bp->cutOffMethods[c] << endl;
2895 if(bp->cutOffMethods[c] == "P") {
2896 m_log << " : plane point: ";
2897 for(MInt d = 0; d < nDim; d++) {
2898 m_log << bp->cutOffCoordinates[c][d] << " ";
2899 }
2900 m_log << endl;
2901 m_log << " : normal: ";
2902 for(MInt d = 0; d < nDim; d++) {
2903 m_log << bp->cutOffCoordinates[c][d + nDim] << " ";
2904 }
2905 m_log << endl;
2906 m_log << " : layers: ";
2907 m_log << bp->cutOffNmbrLayers[c][0] << " ";
2908 m_log << endl;
2909 } else if(bp->cutOffMethods[c] == "B") {
2910 m_log << " : minimal point: ";
2911 for(MInt d = 0; d < nDim; d++) {
2912 m_log << bp->cutOffCoordinates[c][d] << " ";
2913 }
2914 m_log << endl;
2915 m_log << " : layers: ";
2916 for(MInt d = 0; d < nDim; d++) {
2917 m_log << bp->cutOffNmbrLayers[c][d] << " ";
2918 }
2919 m_log << endl;
2920 m_log << " : maximal point: ";
2921 for(MInt d = 0; d < nDim; d++) {
2922 m_log << bp->cutOffCoordinates[c][d + nDim] << " ";
2923 }
2924 m_log << endl;
2925 m_log << " : layers: ";
2926 for(MInt d = 0; d < nDim; d++) {
2927 m_log << bp->cutOffNmbrLayers[c][d + nDim] << " ";
2928 }
2929 m_log << endl;
2930 } else if(bp->cutOffMethods[c] == "iB") {
2931 m_log << " : minimal point: ";
2932 for(MInt d = 0; d < nDim; d++) {
2933 m_log << bp->cutOffCoordinates[c][d] << " ";
2934 }
2935 m_log << endl;
2936 m_log << " : layers: ";
2937 for(MInt d = 0; d < nDim; d++) {
2938 m_log << bp->cutOffNmbrLayers[c][d] << " ";
2939 }
2940 m_log << endl;
2941 m_log << " : maximal point: ";
2942 for(MInt d = 0; d < nDim; d++) {
2943 m_log << bp->cutOffCoordinates[c][d + nDim] << " ";
2944 }
2945 m_log << endl;
2946 m_log << " : layers: ";
2947 for(MInt d = 0; d < nDim; d++) {
2948 m_log << bp->cutOffNmbrLayers[c][d + nDim] << " ";
2949 }
2950 m_log << endl;
2951 } else if(bp->cutOffMethods[c] == "C") {
2952 m_log << " : rot axis: ";
2953 for(MInt d = 0; d < 2; d++) {
2954 m_log << bp->cutOffCoordinates[c][d] << " ";
2955 }
2956 m_log << endl;
2957 m_log << " : rot angle: ";
2958 m_log << bp->cutOffCoordinates[c][2] << " ";
2959 m_log << endl;
2960 m_log << " : rot axis case: ";
2961 m_log << bp->cutOffCoordinates[c][3] << " ";
2962 m_log << endl;
2963 m_log << " : layers: ";
2964 m_log << bp->cutOffNmbrLayers[c][0] << " ";
2965 m_log << endl;
2966 }
2967 }
2968
2969 // check the cut-offs
2970 for(MInt i = offsets[level_][0]; i < offsets[level_][1]; i++) {
2971 // skip if the cell is not in the solver
2972 if(!a_isInSolver(i, solver)) continue;
2973 // skip if cell is already outside
2974 // only skip outside cells in the first round!
2975 if(!deleteMode && a_hasProperty(i, 0) == 0) continue;
2976
2977 MInt preCut = 0;
2978 MFloat* coords = &a_coordinate(i, 0);
2979 if(level_ > m_minLevel) coords = &a_coordinate((MInt)a_parentId(i), 0);
2980 if(level_ < m_minLevel) preCut = 1;
2981
2982 MBool keep = true;
2983 for(MInt c = 0; c < (signed)bp->cutOffMethods.size(); c++) {
2984 if(bp->cutOffMethods[c] == "P") {
2985 // scalar product between the difference vector of the plane point and the normal
2986 MFloat s = 0.0;
2987 MFloat n = 0.0;
2988 for(MInt d = 0; d < nDim; d++) {
2989 s += (coords[d] - bp->cutOffCoordinates[c][d]) * bp->cutOffCoordinates[c][d + nDim];
2990 n += POW2(bp->cutOffCoordinates[c][d + nDim]);
2991 }
2992
2993 if((s / sqrt(n)) < -(bp->cutOffNmbrLayers[c][0] + preCut) * m_lengthOnLevel[level_]) {
2994 keep = keep && false;
2995 break;
2996 }
2997 } else if(bp->cutOffMethods[c] == "B") {
2998 for(MInt d = 0; d < nDim; d++)
2999 if(coords[d]
3000 < bp->cutOffCoordinates[c][d] - m_lengthOnLevel[level_] * (bp->cutOffNmbrLayers[c][d] + preCut)
3001 || coords[d] > bp->cutOffCoordinates[c][d + nDim]
3002 + m_lengthOnLevel[level_] * (bp->cutOffNmbrLayers[c][d + nDim] + preCut))
3003 keep = keep && false;
3004 } else if(bp->cutOffMethods[c] == "iB") {
3005 if(nDim == 2) {
3006 if(coords[0]
3007 >= bp->cutOffCoordinates[c][0] - m_lengthOnLevel[level_] * (bp->cutOffNmbrLayers[c][0] + preCut)
3008 && coords[0] <= bp->cutOffCoordinates[c][0 + nDim]
3009 + m_lengthOnLevel[level_] * (bp->cutOffNmbrLayers[c][0 + nDim] + preCut)
3010 && coords[1]
3011 >= bp->cutOffCoordinates[c][1] - m_lengthOnLevel[level_] * (bp->cutOffNmbrLayers[c][1] + preCut)
3012 && coords[1] <= bp->cutOffCoordinates[c][1 + nDim]
3013 + m_lengthOnLevel[level_] * (bp->cutOffNmbrLayers[c][1 + nDim] + preCut)) {
3014 keep = keep && false;
3015 }
3016 } else if(nDim == 3) {
3017 if(coords[0]
3018 >= bp->cutOffCoordinates[c][0] - m_lengthOnLevel[level_] * (bp->cutOffNmbrLayers[c][0] + preCut)
3019 && coords[0] <= bp->cutOffCoordinates[c][0 + nDim]
3020 + m_lengthOnLevel[level_] * (bp->cutOffNmbrLayers[c][0 + nDim] + preCut)
3021 && coords[1]
3022 >= bp->cutOffCoordinates[c][1] - m_lengthOnLevel[level_] * (bp->cutOffNmbrLayers[c][1] + preCut)
3023 && coords[1] <= bp->cutOffCoordinates[c][1 + nDim]
3024 + m_lengthOnLevel[level_] * (bp->cutOffNmbrLayers[c][1 + nDim] + preCut)
3025 && coords[2]
3026 >= bp->cutOffCoordinates[c][2] - m_lengthOnLevel[level_] * (bp->cutOffNmbrLayers[c][2] + preCut)
3027 && coords[2] <= bp->cutOffCoordinates[c][2 + nDim]
3028 + m_lengthOnLevel[level_] * (bp->cutOffNmbrLayers[c][2 + nDim] + preCut)) {
3029 keep = keep && false;
3030 }
3031 }
3032 } else if(bp->cutOffMethods[c] == "C") {
3033 MFloat cornerStencil[8][3] = {{1, 1, 1}, {1, -1, 1}, {-1, 1, 1}, {-1, -1, 1},
3034 {1, 1, -1}, {1, -1, -1}, {-1, 1, -1}, {-1, -1, -1}};
3035
3036 MFloat cellLength = m_lengthOnLevel[level_ + 1];
3037 if(level_ > m_minLevel) continue;
3038
3039 MFloat center[3];
3040 center[0] = coords[0];
3041 center[1] = bp->cutOffCoordinates[c][0];
3042 center[2] = bp->cutOffCoordinates[c][1];
3043 MFloat dAlpha = (PI / 180.0) * bp->cutOffCoordinates[c][2];
3044
3045 MFloat phi = (PI / 180.0) * bp->cutOffCoordinates[c][3];
3046
3047 MFloat normal[3];
3048 normal[0] = F0;
3049 normal[1] = sin(phi);
3050 normal[2] = cos(phi);
3051 MFloat s = 0.0;
3052 MFloat n = 0.0;
3053 for(MInt d = 0; d < nDim; d++) {
3054 s += (coords[d] - center[d]) * normal[d];
3055 n += POW2(normal[d]);
3056 }
3057 // Cells on opposite site of rot axis
3058 if(s / sqrt(n) < -(bp->cutOffNmbrLayers[c][0] + preCut) * m_lengthOnLevel[level_]) {
3059 keep = keep && false;
3060 }
3061 if(keep == false) break;
3062
3063
3064 // Cells outside of cut-offs
3065 MFloat sgn[2] = {-1.0, 1.0};
3066 for(MInt p = 0; p < 2; p++) {
3067 MFloat angle = phi + (sgn[p] * dAlpha / 2.0);
3068 if(angle < F0) angle = 2 * PI + angle;
3069 if(angle > 2 * PI) angle = angle - (2 * PI);
3070
3071 normal[1] = -F1 * sgn[p] * cos(angle);
3072 normal[2] = sgn[p] * sin(angle);
3073
3074 MInt cnt = 0;
3075 for(MInt corn = 0; corn < IPOW2(nDim); corn++) {
3076 MFloat dummyCoords[3];
3077 for(MInt d = 0; d < nDim; d++) {
3078 dummyCoords[d] = coords[d] + cornerStencil[corn][d] * cellLength;
3079 }
3080 s = 0.0;
3081 n = 0.0;
3082 for(MInt d = 0; d < nDim; d++) {
3083 s += (dummyCoords[d] - center[d]) * normal[d];
3084 n += POW2(normal[d]);
3085 }
3086 if((s / sqrt(n)) < -(bp->cutOffNmbrLayers[c][0] + preCut) * m_lengthOnLevel[level_]) {
3087 cnt++;
3088 }
3089 }
3090 if(cnt >= IPOW2(nDim)) {
3091 keep = keep && false;
3092 break;
3093 }
3094 }
3095 }
3096 }
3097
3098 if(!keep) {
3099 a_isInSolver(i, solver) = 0;
3100 if(deleteMode) {
3101 a_noSolidLayer(i, solver) = -1;
3102 // if the last solver: check if removed from all others as well
3103 if(solver == m_noSolvers - 1) {
3104 MBool del = true;
3105 for(MInt s = 0; s < m_noSolvers; s++) {
3106 if(a_noSolidLayer(i, s) > 0) {
3107 del = false;
3108 break;
3109 }
3110 }
3111 if(del) {
3112 a_hasProperty(i, 0) = false;
3113 a_hasProperty(i, 1) = false;
3114 }
3115 }
3116 }
3117 }
3118 }
3119 }
3120 }
3121}
constexpr Real POW2(const Real x)
Definition: functions.h:119
MInt sgn(T val)
Definition: maiamath.h:495

◆ pointIsInside()

template<MInt nDim>
MBool GridgenPar< nDim >::pointIsInside ( MFloat coordinates)
protected
Author
Andreas Lintermann
Date
11.10.2013

For each direction a ray is created from the given point towards the outer geometry extent. This ray is then used for a cut-test using the getLineIntersectionElements function of Geometry. Two cases can appear:

  • the number of cuts is even for the rays: the point is outside
  • the number of cuts is odd for the rays: the point is inside
Parameters
[in]coordinatesthe coordinates to check
Returns
if the point is inside or not

Definition at line 4137 of file cartesiangridgenpar.cpp.

4137 {
4138 TRACE();
4139 return m_geometry->isPointInside(coordinates);
4140}
MBool isPointInside(const MFloat *const point)

◆ pointIsInsideSolver()

template<MInt nDim>
MBool GridgenPar< nDim >::pointIsInsideSolver ( MFloat coordinates,
MInt  solver 
)
protected

Definition at line 4143 of file cartesiangridgenpar.cpp.

4143 {
4144 TRACE();
4145 return m_geometry->isPointInsideNode(coordinates, solver);
4146}
MBool isPointInsideNode(const MFloat *const point, const MInt node)

◆ propagateDistance()

template<MInt nDim>
void GridgenPar< nDim >::propagateDistance ( MInt  level_,
MInt  distance,
std::vector< MInt > &  rfnBoundaryGroup,
MInt  solver 
)
protected
Author
Andreas Lintermann
Date
06.11.2013

This function propagates distance information starting at the boundaries and stores them in the local variable m_rfnDistance:

a. Start by collecting all boundary cells. Unfortunately, we have to do an intersection test again, since we probably want to refine only certain boundaries (defined by the property localRfnBoundaryIds). The collected cells are stored in the vector boundaryCells. b. Now start to recursivley mark the cells by their distance. This calls progagationStep(...), which recursively runs over all cells and checks for new unmarked cells. For the serial case, the algorithm is finished at this point. c. Otherwise, if we have a parallel calculation, we need to check if we have to cross a domain boundary with our propagation. d. Exchange information as long as we have local changes. determine whether we have changes by comparing a_refinementDistance on halo and window cells this has to be repeated until we are finished, exchange information as long as we have local changes

Parameters
[in]level_,thelevel to run the propagation on
[in]distance,thefinal distance for this level
[in]rfnBoundaryGroup,groupof boundaries to refine
[in]solver,thesolver to check for refinement

Definition at line 5825 of file cartesiangridgenpar.cpp.

5825 {
5826 TRACE();
5827
5828 NEW_SUB_TIMER_STATIC(t_boundaryPropagation, "boundary propagation", m_t_createComputationalGrid);
5829 RECORD_TIMER_START(t_boundaryPropagation);
5830
5831 m_log << " marking boundary cells: ";
5832
5833 // a. collect all boundary cells on this domain an init the refinementDistance
5834 vector<MInt> boundaryCells;
5835 for(MInt i = m_levelOffsets[level_][0]; i < m_levelOffsets[level_][1]; i++) {
5836 a_refinementDistance(i) = numeric_limits<MInt>::max();
5837 if(a_isSolverBoundary(i, solver)) {
5838 checkCellForCut(i);
5839
5840 for(MInt b = 0; b < (MInt)rfnBoundaryGroup.size(); b++) {
5841 if(m_bndCutInfo[solver][rfnBoundaryGroup[b]]) {
5842 boundaryCells.push_back(i);
5843 break;
5844 }
5845 }
5846 }
5847 }
5848
5849 if(noDomains() > 1) { // i do not really need this, infos would propagate from other domains
5850 MInt lev_pos = 2 * (level_ - m_minLevel);
5851 for(MInt dom = 0; dom < m_noNeighborDomains; dom++) {
5852 for(MInt i = m_haloCellOffsets[dom][lev_pos]; i < m_haloCellOffsets[dom][lev_pos + 1]; i++) {
5853 a_refinementDistance(i) = numeric_limits<MInt>::max();
5854 if(a_isSolverBoundary(i, solver)) {
5855 checkCellForCut(i);
5856
5857 for(MInt b = 0; b < (MInt)rfnBoundaryGroup.size(); b++) {
5858 if(m_bndCutInfo[solver][rfnBoundaryGroup[b]]) {
5859 boundaryCells.push_back(i);
5860 break;
5861 }
5862 }
5863 }
5864 }
5865 }
5866 }
5867
5868 // b. do the recursive marking
5869 for(MInt i = 0; i < (MInt)boundaryCells.size(); i++)
5870 propagationStep(boundaryCells[i], 0, distance, solver);
5871
5872 // if we are parallel, we have to transmit information
5873 if(noDomains() > 1) { // TODO labels:GRIDGEN the communication setup should be done once per level or only account for
5874 // solver window/halos
5875
5876 // c. create lists of window and halo cells
5877 vector<vector<MInt>> winCellIdsPerDomain(m_noNeighborDomains, vector<MInt>(0));
5878 vector<vector<MInt>> haloCellIdsPerDomain(m_noNeighborDomains, vector<MInt>(0));
5879
5881 findHaloAndWindowCellsKD(winCellIdsPerDomain, haloCellIdsPerDomain);
5882 else
5883 findHaloAndWindowCells(winCellIdsPerDomain, haloCellIdsPerDomain);
5884
5885 // d. prepare the communication
5886 MIntScratchSpace noSendWindowPerDomain(m_noNeighborDomains, AT_, "noSendWindowPerDomain");
5887 MIntScratchSpace noReceiveHaloPerDomain(m_noNeighborDomains, AT_, "noReceiveHaloPerDomain");
5888
5889 m_log << " - we need to transfer to domain [no. cells to transfer]: ";
5890 outStream << " - we need to transfer to domain [no. cells to transfer]: ";
5891 for(MInt d = 0; d < m_noNeighborDomains; d++) {
5892 noSendWindowPerDomain[d] = (MInt)winCellIdsPerDomain[d].size();
5893 m_log << m_neighborDomains[d] << " [" << noSendWindowPerDomain[d] << "] ";
5894 outStream << m_neighborDomains[d] << " [" << noSendWindowPerDomain[d] << "] ";
5895 }
5896 m_log << endl;
5897 outStream << endl;
5898
5899 m_log << " - we need to receive from domain [no. cells to receive]: ";
5900 outStream << " - we need to receive from domain [no. cells to receive]: ";
5901 for(MInt d = 0; d < m_noNeighborDomains; d++) {
5902 noReceiveHaloPerDomain[d] = (MInt)haloCellIdsPerDomain[d].size();
5903 m_log << m_neighborDomains[d] << " [" << noReceiveHaloPerDomain[d] << "] ";
5904 outStream << m_neighborDomains[d] << " [" << noReceiveHaloPerDomain[d] << "] ";
5905 }
5906 m_log << endl;
5907 outStream << endl;
5908
5909 MInt allSend = 0;
5910 MInt allReceive = 0;
5911 vector<MInt> offsetsSend;
5912 vector<MInt> offsetsReceive;
5913 for(MInt dom = 0; dom < m_noNeighborDomains; dom++) {
5914 offsetsSend.push_back(allSend);
5915 offsetsReceive.push_back(allReceive);
5916 allSend += noSendWindowPerDomain[dom];
5917 allReceive += noReceiveHaloPerDomain[dom];
5918 }
5919
5920 MIntScratchSpace sndBufWin(allSend, AT_, "sndBufWin");
5921 MIntScratchSpace rcvBufHalo(allReceive, AT_, "rcvBufHalo");
5922
5923 MUshort finished = 0;
5924
5925 // e. determine whether we have changes by comparing a_refinementDistance
5926 // on halo and window cells
5927 // this has to be repeated until we are finished, exchange information as long
5928 // as we have local changes
5929 MInt rounds = 0;
5930 while(!finished) {
5931 finished = 1;
5932
5933 MPI_Request* mpi_request_ = nullptr;
5934 mAlloc(mpi_request_, m_noNeighborDomains, "mpi_request_", AT_);
5935 for(MInt d = 0; d < m_noNeighborDomains; d++) {
5936 for(MInt c = 0; c < noSendWindowPerDomain[d]; c++) {
5937 sndBufWin[offsetsSend[d] + c] = a_refinementDistance(winCellIdsPerDomain[d][c]);
5938 }
5939 MPI_Issend(&(sndBufWin[offsetsSend[d]]), noSendWindowPerDomain[d], MPI_INT, m_neighborDomains[d], 0, mpiComm(),
5940 &mpi_request_[d], AT_, "(sndBufWin[offsetsSend[d]])");
5941 }
5942
5943 MPI_Status status_;
5944 for(MInt d = 0; d < m_noNeighborDomains; d++)
5945 MPI_Recv(&(rcvBufHalo[offsetsReceive[d]]), noReceiveHaloPerDomain[d], MPI_INT, m_neighborDomains[d], 0,
5946 mpiComm(), &status_, AT_, "(rcvBufHalo[offsetsReceive[d]])");
5947
5948 for(MInt d = 0; d < m_noNeighborDomains; d++)
5949 MPI_Wait(&mpi_request_[d], &status_, AT_);
5950
5951 for(MInt d = 0; d < m_noNeighborDomains; d++) {
5952 for(MInt c = 0; c < noReceiveHaloPerDomain[d]; c++) {
5953 const MInt halo = haloCellIdsPerDomain[d][c];
5954 if(rcvBufHalo[c + offsetsReceive[d]] < a_refinementDistance(halo)) {
5955 propagationStep(halo, rcvBufHalo[c + offsetsReceive[d]], distance, solver);
5956 finished = 0;
5957 }
5958 }
5959 }
5960
5961 MPI_Allreduce(MPI_IN_PLACE, &finished, 1, MPI_UNSIGNED_SHORT, MPI_MIN, mpiComm(), AT_, "MPI_IN_PLACE",
5962 "finished");
5963
5964 rounds++;
5965 }
5966 m_log << " - communication rounds required: " << rounds << endl;
5967 }
5968
5969 RECORD_TIMER_STOP(t_boundaryPropagation);
5970}
void propagationStep(MInt cellId, MInt rfnDistance, MInt finalDistance, MInt solver)
recursivley marks the cells with a distance
void findHaloAndWindowCells(std::vector< std::vector< MInt > > &winCellIdsPerDomain, std::vector< std::vector< MInt > > &haloCellIdsPerDomain)
find window cells using the known halo cells
void findHaloAndWindowCellsKD(std::vector< std::vector< MInt > > &winCellIdsPerDomain, std::vector< std::vector< MInt > > &haloCellIdsPerDomain)
finds halo and window cells using a kd tree

◆ propagationStep()

template<MInt nDim>
void GridgenPar< nDim >::propagationStep ( MInt  cellId,
MInt  rfnDistance,
MInt  finalDistance,
MInt  solver 
)
protected
Author
Andreas Lintermann
Date
01.11.2013

This is a recursive function, which is initially called with a boundary cell-id. For this cell, the neighborhood is then recursivley investigated. If a neighbor cell has not been visited, yet (m_rfnDistance < 0) it is traversed and set to an incremental distance. If a neighbor has a distance smaller than the incremented distance it is not traversed.

Parameters
[in]cellIdthe current cell-id to check
[in]rfnDistancethe current distance to use
[in]finalDistancethe final distance to use

Definition at line 5989 of file cartesiangridgenpar.cpp.

5989 {
5990 TRACE();
5991
5992 NEW_SUB_TIMER_STATIC(t_markRfnDistance, "mark refinement distance", m_t_createComputationalGrid);
5993 if(rfnDistance == 0) {
5994 RECORD_TIMER_START(t_markRfnDistance);
5995 }
5996
5997 if(a_refinementDistance(cellId) > rfnDistance) {
5998 a_refinementDistance(cellId) = rfnDistance;
5999 // Definition: We do not refine at final distance!
6000 if(rfnDistance < (finalDistance - 1)) {
6001 for(MInt n = 0; n < m_noNeighbors; n++) {
6002 if(a_neighborId(cellId, n) > -1) {
6003 if(a_isInSolver((MInt)a_neighborId(cellId, n), solver)) {
6004 propagationStep((MInt)a_neighborId(cellId, n), rfnDistance + 1, finalDistance, solver);
6005 }
6006 }
6007 }
6008 }
6009 }
6010
6011 if(rfnDistance == 0) {
6012 RECORD_TIMER_STOP(t_markRfnDistance);
6013 }
6014}

◆ quickSort()

template<MInt nDim>
template<class T >
void GridgenPar< nDim >::quickSort ( T *  globalIdArray,
MInt lookup,
MInt  startIndex,
MInt  endIndex 
)
static
Author
Andreas Lintermann
Date
16.10.2013

This function uses the well known quick-sort algorithm. In addition a second array can be provided to be used as a lookup table. This function is for example to sort the array of Hilbert ids. Additionally, a second array containing a linear increase of cell ids starting from cell 0 is provided. In case the order of the ids is changed in the array to sort the second array is changed accordingly. This can then be used to do a pre-sorting of the Hilbert ids and the second array is incorporated into the swapping of the memory.

Template Parameters

in] T Data type of array to sort.

Parameters
[in]globalIdArraythe array to sort
[in]lookupthe lookup table to be swapped according to the changes in the globalIdArray
[in]startIndexthe index of the beginning of the fraction to sort
[in]endIndexthe index of the end of the fraction to sort

Definition at line 4009 of file cartesiangridgenpar.cpp.

4009 {
4010 TRACE();
4011
4012 T pivot = globalIdArray[startIndex];
4013 MInt splitPoint = 0;
4014
4015 if(endIndex > startIndex) {
4016 MInt leftBoundary = startIndex;
4017 MInt rightBoundary = endIndex;
4018
4019 while(leftBoundary < rightBoundary) {
4020 while(pivot < globalIdArray[rightBoundary] && rightBoundary > leftBoundary)
4021 rightBoundary--;
4022
4023 swap(globalIdArray[leftBoundary], globalIdArray[rightBoundary]);
4024 swap(lookup[leftBoundary], lookup[rightBoundary]);
4025
4026 while(pivot >= globalIdArray[leftBoundary] && leftBoundary < rightBoundary)
4027 leftBoundary++;
4028
4029 swap(globalIdArray[rightBoundary], globalIdArray[leftBoundary]);
4030 swap(lookup[rightBoundary], lookup[leftBoundary]);
4031 }
4032
4033 splitPoint = leftBoundary;
4034
4035 globalIdArray[splitPoint] = pivot;
4036
4037 quickSort(globalIdArray, lookup, startIndex, splitPoint - 1);
4038 quickSort(globalIdArray, lookup, splitPoint + 1, endIndex);
4039 }
4040}
static void quickSort(T *globalIdArray, MInt *lookup, MInt startindex, MInt endindex)
sorts a list of integers and updates a second one
void swap(Tensor< TT > &a, Tensor< TT > &b)
Non-member swap exchanges the contents of two Tensors.
Definition: tensor.h:752

◆ readProperties()

template<MInt nDim>
void GridgenPar< nDim >::readProperties ( )
protected
Author
Andreas Lintermann
Date
11.10.2013

◆ readSolverProperties()

template<MInt nDim>
void GridgenPar< nDim >::readSolverProperties ( MInt  solver)
protected

◆ refineCell()

template<MInt nDim>
void GridgenPar< nDim >::refineCell ( MInt  id,
MInt currentChildId 
)
protected
Author
Andreas Lintermann
Date
11.10.2013

Refines a single cell by the following algorithm: For 8 child cells do: a. Create coordinates b. Init child c. Check if parent has a cut with the geometry, if so check this cell for a cut as well (this calls checkCellForCut(...)) d. Update the parent

Parameters
[in]idthe id of the cell to refine
[in]currentChildIdthe id, where the first child will be written to

Definition at line 2054 of file cartesiangridgenpar.cpp.

2054 {
2055 TRACE();
2056
2057 MInt level_ = a_level(id);
2058 const MInt childLevel = level_ + 1;
2059 const MFloat childCellLength = m_lengthOnLevel[childLevel];
2060
2061 static const MFloat signStencil[8][3] = {{-F1, -F1, -F1}, {F1, -F1, -F1}, {-F1, F1, -F1}, {F1, F1, -F1},
2062 {-F1, -F1, F1}, {F1, -F1, F1}, {-F1, F1, F1}, {F1, F1, F1}};
2063
2064 a_noChildren(id) = 0;
2065
2066 for(MInt c = 0; c < m_maxNoChildren; c++) {
2067 // a. Create coordinates
2068 for(MInt i = 0; i < nDim; i++) {
2069 a_coordinate(*currentChildId, i) = a_coordinate(id, i) + F1B2 * signStencil[c][i] * childCellLength;
2070 }
2071
2072 // b. Init child
2073 a_level(*currentChildId) = childLevel;
2074 a_parentId(*currentChildId) = (MLong)id;
2075 a_noChildren(*currentChildId) = 0;
2076 a_globalId(*currentChildId) = (MLong)(*currentChildId);
2077 for(MInt s = 0; s < m_noSolvers; s++) {
2078 a_noSolidLayer(*currentChildId, s) = -1;
2079 }
2080
2081 // cell is considered outside upon creation and non-boundary
2082 for(MInt i = 0; i < 8; i++)
2083 a_hasProperty(*currentChildId, i) = 0;
2084
2085 for(MInt solver = 0; solver < m_noSolvers; solver++)
2086 a_isSolverBoundary(*currentChildId, solver) = 0;
2087
2088 for(MInt solver = 0; solver < m_noSolvers; solver++)
2089 a_isToRefineForSolver(*currentChildId, solver) = 0;
2090
2091 // The affiliation is taken from the parent,
2092 // because there are solver-outside cells that are refined
2093 // at this stage a_isInSolver = 1 is more a "isMaybeInSolver"
2094 // a_isInSolver = 0 is isNotInSolver
2095 for(MInt solver = 0; solver < m_noSolvers; solver++)
2096 a_isInSolver(*currentChildId, solver) = a_isToRefineForSolver(id, solver) ? 1 : 0;
2097
2098 // init childs childIds
2099 for(MInt k = 0; k < m_maxNoChildren; k++)
2100 a_childId(*currentChildId, k) = -1;
2101
2102 // init childs neighborIds
2103 for(MInt i = 0; i < nDim; i++) {
2104 a_neighborId(*currentChildId, i) = -1;
2105 a_neighborId(*currentChildId, i + nDim) = -1;
2106 }
2107
2108 // c. Check if parent has a cut with the geometry, if so check this cell for a cut as well
2109 if(a_hasProperty(id, 1)) {
2110 a_hasProperty(*currentChildId, 1) = checkCellForCut(*currentChildId);
2111 if(a_hasProperty(*currentChildId, 1)) {
2112 for(MInt solver = 0; solver < m_noSolvers; solver++) {
2113 if(!a_isToRefineForSolver(id, solver)) continue;
2114 for(MInt srfc = 0; srfc < m_noBndIdsPerSolver[solver]; srfc++) {
2115 if(m_bndCutInfo[solver][srfc]) {
2116 a_isSolverBoundary(*currentChildId, solver) = 1;
2117 break;
2118 }
2119 }
2120 }
2121 }
2122 }
2123
2124 // d. Update parent
2125 a_childId(id, c) = *currentChildId;
2126 a_noChildren(id) = a_noChildren(id) + 1;
2127
2128
2129 (*currentChildId)++;
2130 }
2131}

◆ refineComputationalGrid()

template<MInt nDim>
void GridgenPar< nDim >::refineComputationalGrid ( MInt  compRfnLvl)
protected
Author
Andreas Lintermann
Date
6.5.2014
6.2a.2.2 check memory availability
6.2a.2.3 Refine the cells that have previously been marked. This calls the function
         refineGridPatch(...) which only refines cells that have previously been
         marked. If we run in parallel mode, do this also for the halo cells.
6.2b.2.4 Update the number of cells.
6.2b.2.5 Find the neighbors for the new cells. Calls findChildLevelNeighbors(...).
         If we run in parallel mode, this is also done for the halo cells.
6.2b.2.6 Delete all outside cells, do this in serial or in parallel. This calls
         either deleteOutsideCellsSerial(...) or deleteOutsideCellsParallel(...).

Definition at line 5757 of file cartesiangridgenpar.cpp.

5757 {
5758 TRACE();
5759
5760 // 6.2a.2.2 check memory availability
5761 checkMemoryAvailability(1, compRfnLvl + 1);
5762
5763 // 6.2a.2.3 refine the cells and the halo cells if we are parallel
5764 refineGridPatch(m_levelOffsets, compRfnLvl, 0);
5765 if(noDomains() > 1) {
5767 }
5768
5769 // 6.2a.2.4 update the number of cells
5770 m_noCells = m_levelOffsets[compRfnLvl + 1][1];
5771
5772 // 6.2a.2.5 find the neighbors on this level, do this also for the halos if we run in parallel
5774 if(noDomains() > 1) {
5776 }
5777
5778 // 6.2a.2.6 delete all outside cells, do this in serial or in parallel
5779 if(noDomains() > 1) {
5780 deleteOutsideCellsParallel(compRfnLvl + 1);
5781 } else {
5782 deleteOutsideCellsSerial(compRfnLvl + 1);
5783 }
5784
5785 // update number of cells
5786 m_noCells = m_levelOffsets[compRfnLvl + 1][1];
5787
5788 // 6.2a.2.9 in parallel, check if there is a load imbalance in the grid before continuing
5789 if((noDomains() > 1) && (g_dynamicLoadBalancing)) { // TODO labels:GRIDGEN,DLB skip for last level?
5790 checkLoadBalance(compRfnLvl);
5791 }
5792}
void refineGridPatch(MInt **offsets, MInt level_, MBool halo)
refines the grid on a given level for a provided patch
void checkLoadBalance(MInt in_level)
checks if a dynamic load balancing is needed.
MBool g_dynamicLoadBalancing

◆ refineGrid()

template<MInt nDim>
void GridgenPar< nDim >::refineGrid ( MInt **  offsets,
MInt  level_,
MBool  halo 
)
protected
Author
Andreas Lintermann
Date
11.10.2013

Refines the grid on the level provided by the parameter by running over all cells of the current level. The ids of the cells to be considered are obtained from the arrays m_levelOffsets[level]. Also checks during the run if enough memory is still available. Calls refineCell and provides the id of the cell to refine and the first id to write the newly created cells to.

Parameters
[in]offsetsthe offsets to use in the array of the cells
[in]level_the level to be refined
[in]halois this a halo refinement?

Definition at line 1597 of file cartesiangridgenpar.cpp.

1597 {
1598 TRACE();
1599
1600 MInt t_refineGrid = 0;
1601 if(level_ < m_minLevel) {
1602 NEW_SUB_TIMER_STATIC(t_rfnGrid, "refine Grid", m_t_createInitialGrid);
1603 t_refineGrid = t_rfnGrid;
1604 } else if(level_ < m_maxUniformRefinementLevel) {
1605 NEW_SUB_TIMER_STATIC(t_rfnGrid, "refine Grid", m_t_createStartGrid);
1606 t_refineGrid = t_rfnGrid;
1607 }
1608
1609 RECORD_TIMER_START(t_refineGrid);
1610
1611 if(halo) {
1612 m_log << " + refining halo grid on level " << level_ << ": " << endl;
1613 outStream << " + refining halo grid on level " << level_ << ": " << endl;
1614 } else {
1615 m_log << " + refining grid on level " << level_ << ": " << endl;
1616 outStream << " + refining grid on level " << level_ << ": " << endl;
1617 }
1618 outStream.flush();
1619
1620 // this is the start where we want to start writing from
1621 MInt offsetLevelStart = offsets[level_ + 1][0];
1622
1623 MInt diff = offsets[level_][1] - offsets[level_][0];
1624
1625 // Refine each cell on the given level
1626 for(MInt i = offsets[level_][0]; i < offsets[level_][1]; i++) {
1627 MInt current = i - offsets[level_][0];
1628
1629 // display progress
1630 if(diff > 100 && current % (diff / 100) == 0) {
1631 if(100 * current / diff < 11)
1632 outStream << "\b\b\b" << 100 * current / diff << "% ";
1633 else
1634 outStream << "\b\b\b\b" << 100 * current / diff << "% ";
1635 outStream.flush();
1636 }
1637
1638 // refine cell
1639 if(level_ > m_minLevel && noDomains() > 1) {
1640 refineCell(m_cellIdLUT[i], &offsetLevelStart);
1641 } else {
1642 refineCell(i, &offsetLevelStart);
1643 }
1644 }
1645
1646 outStream << "\b\b\b\b\b 100% done." << endl;
1647
1648 RECORD_TIMER_STOP(t_refineGrid);
1649}
void refineCell(MInt id, MInt *currentChildId)
refines a single cell

◆ refineGridPatch()

template<MInt nDim>
void GridgenPar< nDim >::refineGridPatch ( MInt **  offsets,
MInt  level_,
MBool  halo 
)
protected
Author
Andreas Lintermann
Date
23.10.2013

Does the same as refineGrid(...) except that only those cells are refined that apply to the patch constraints (b_properties[5] = 1).

Parameters
[in]offsetsthe offsets to use in the array of the cells
[in]levelthe level to be refined
[in]halois this a halo refinement?

Definition at line 1665 of file cartesiangridgenpar.cpp.

1665 {
1666 TRACE();
1667
1668 NEW_SUB_TIMER_STATIC(t_refineGridPatch, "refine Grid", m_t_createComputationalGrid);
1669 RECORD_TIMER_START(t_refineGridPatch);
1670
1671 if(halo) {
1672 m_log << " + refining halo grid on level " << level_ << ": ";
1673 outStream << " + refining halo grid on level " << level_ << ": ";
1674 } else {
1675 m_log << " + refining grid on level " << level_ << ": ";
1676 outStream << " + refining grid on level " << level_ << ": ";
1677 }
1678 outStream.flush();
1679
1680 // this is the start where we want to start writing from
1681 MInt startchildId = offsets[level_ + 1][0];
1682
1683 size_t diff = offsets[level_][1] - offsets[level_][0];
1684
1685 // Refine each cell on the given level
1686 for(MInt i = offsets[level_][0]; i < offsets[level_][1]; i++) {
1687 MInt cellId = i;
1688 if(level_ > m_minLevel && noDomains() > 1) {
1689 cellId = m_cellIdLUT[i];
1690 }
1691 MInt current = i - offsets[level_][0];
1692 if(diff > 100 && current % (diff / 100) == 0) {
1693 if(100 * (size_t)current / diff < 11)
1694 outStream << "\b\b\b" << 100 * (size_t)current / diff << "% ";
1695 else
1696 outStream << "\b\b\b\b" << 100 * (size_t)current / diff << "% ";
1697 outStream.flush();
1698 }
1699
1700 if(a_hasProperty(cellId, 5)) {
1701 MInt currentNoCells = (offsets[level_][1] - offsets[level_][0]) + m_maxNoChildren;
1702 if(currentNoCells > m_maxNoCells) {
1703 stringstream errorMsg;
1704 errorMsg << "Max. no. cells reached: " << m_maxNoCells << endl;
1705 m_log << errorMsg.str();
1706 mTerm(1, AT_, errorMsg.str());
1707 }
1708 // refine cell
1709 refineCell(cellId, &startchildId);
1710 }
1711 }
1712
1713 outStream << "\b\b\b\b\b 100% done." << endl;
1714
1715 RECORD_TIMER_STOP(t_refineGridPatch);
1716}

◆ reorderCellsHilbert()

template<MInt nDim>
void GridgenPar< nDim >::reorderCellsHilbert
protected
Author
Andreas Lintermann, Jerry Grimmen
Date
16.10.2013, 15.04.2014 (2D Update)

Reorders the cells after the Hilbert curve by the following algorithm

a. Find Hilbert ids of all cells. This changes the local coordinates to be in the unit cube, then calls Hilbert index method to obtain the Hilbert id. This is only done on a temporary array. b. The temporary array containing the Hilbert ids is sorted. Additionally a second array used for lookup is sorted in the same way. c. The cells are swaped according to the sorting of the Hilbert curve. d. The global ids of the cells are updated.

Definition at line 3862 of file cartesiangridgenpar.cpp.

3862 {
3863 TRACE();
3864
3865 NEW_SUB_TIMER(t_reorderCellsHilbert, "reordering cells after Hilbert id", m_t_createInitialGrid);
3866 RECORD_TIMER_START(t_reorderCellsHilbert);
3867
3868 m_log << " + creating Hilbert curve" << endl;
3869 outStream << " + creating Hilbert curve" << endl;
3870
3871 // Store center of gravity, length level-0, and Hilbert level locally
3872 std::array<MFloat, MAX_SPACE_DIMENSIONS> centerOfGravity;
3873 copy_n(m_centerOfGravity, nDim, &centerOfGravity[0]);
3874 MFloat lengthLevel0 = m_lengthOnLevel[0];
3875 MInt hilbertLevel = m_minLevel;
3876
3877 // Load center of gravity, length level-0, and Hilbert level from target grid
3878 // file if such a file was specified
3879 if(m_targetGridFileName != "") {
3880 TERMM(1, "deprecated");
3881 m_log << " * reading grid information from target grid (" << m_targetGridFileName << ")" << endl;
3882 outStream << " * reading grid information from target grid (" << m_targetGridFileName << ")" << endl;
3883
3884 // Read information from target grid file
3885 using namespace maia::parallel_io;
3886 ParallelIo file(m_targetGridFileName, PIO_READ, mpiComm());
3887 file.getAttribute(&centerOfGravity[0], "centerOfGravity", nDim);
3888 file.getAttribute(&lengthLevel0, "lengthLevel0");
3889 file.getAttribute(&hilbertLevel, "minLevel");
3890 } else if(m_multiSolverMinLevel > -1) {
3891 hilbertLevel = m_multiSolverMinLevel;
3892
3893 // Determine center of gravity and length level-0 from the given multisolver bounding box
3894 lengthLevel0 = 0.0;
3895 for(MInt i = 0; i < nDim; i++) {
3896 centerOfGravity[i] = 0.5 * (m_multiSolverBoundingBox[nDim + i] + m_multiSolverBoundingBox[i]);
3897 // Note: computed similar to m_lengthOnLevel
3898 const MFloat dist =
3899 (F1 + F1 / FPOW2(30)) * fabs(m_multiSolverBoundingBox[nDim + i] - m_multiSolverBoundingBox[i]);
3900 lengthLevel0 = std::max(lengthLevel0, dist);
3901 }
3902
3903 // Store for later use
3904 m_multiSolverLengthLevel0 = lengthLevel0;
3905 m_multiSolverCenterOfGravity.resize(nDim);
3906 std::copy_n(&centerOfGravity[0], nDim, &m_multiSolverCenterOfGravity[0]);
3907
3908 // Perform sanity checks to ensure min-level cells match and the same Hilbert order is obtained
3909 checkMultiSolverGridExtents(nDim, &m_centerOfGravity[0], m_lengthOnLevel[0], m_minLevel, &centerOfGravity[0],
3910 lengthLevel0, m_multiSolverMinLevel);
3911
3912 stringstream msg;
3913 msg << " * using multisolver grid information from property file:" << endl
3914 << " - minLevel = " << hilbertLevel << endl
3915 << " - boundingBox = ";
3916 for(MInt i = 0; i < nDim; i++) {
3917 msg << "[" << m_multiSolverBoundingBox[i] << ", " << m_multiSolverBoundingBox[nDim + i] << "]";
3918 if(i < nDim - 1) {
3919 msg << " x ";
3920 }
3921 }
3922 msg << endl << " - centerOfGravity = [";
3923 for(MInt i = 0; i < nDim; i++) {
3924 msg << centerOfGravity[i];
3925 if(i < nDim - 1) {
3926 msg << ", ";
3927 }
3928 }
3929 msg << "]" << endl << " - lengthLevel0 = " << lengthLevel0 << endl;
3930
3931 m_log << msg.str();
3932 if(domainId() == 0) {
3933 outStream << msg.str();
3934 }
3935 }
3936
3937 ScratchSpace<MLong> hilbertIds(m_noCells, AT_, "hilbertIds");
3938 MIntScratchSpace hilbert_lookup(m_noCells, AT_, "hilbert_lookup");
3939 MIntScratchSpace posTracker(m_noCells, AT_, "posTracker");
3940 MIntScratchSpace revPosTracker(m_noCells, AT_, "posTracker");
3941 // a. find Hilbert ids of all cells
3942 for(MInt i = 0; i < m_noCells; ++i) {
3943 MFloat* c = &a_coordinate(i, 0);
3944
3945 // Normalize to unit cube
3946 array<MFloat, 3> x;
3947 x[0] = (c[0] - centerOfGravity[0] + lengthLevel0 * 0.5) / lengthLevel0;
3948 x[1] = (c[1] - centerOfGravity[1] + lengthLevel0 * 0.5) / lengthLevel0;
3949 IF_CONSTEXPR(nDim == 3) { x[2] = (c[2] - centerOfGravity[2] + lengthLevel0 * 0.5) / lengthLevel0; }
3950
3951 IF_CONSTEXPR(nDim == 2) { hilbertIds[i] = maia::grid::hilbert::index<2>(&x[0], static_cast<MLong>(hilbertLevel)); }
3952 else IF_CONSTEXPR(nDim == 3) {
3953 hilbertIds[i] = maia::grid::hilbert::index<3>(&x[0], static_cast<MLong>(hilbertLevel));
3954 }
3955 else {
3956 TERMM(1, "Bad number of dimensions: " + to_string(nDim));
3957 }
3958
3959 hilbert_lookup[i] = i;
3960 posTracker[i] = i;
3961 revPosTracker[i] = i;
3962 }
3963
3964 m_log << " * resorting cells after Hilbert id" << endl;
3965 outStream << " * resorting cells after Hilbert id" << endl;
3966
3967 // b. sort temp. array after Hilbert id
3968 quickSort(hilbertIds.getPointer(), hilbert_lookup.getPointer(), 0, m_noCells - 1);
3969
3970 // c. swap cells in collector so that the cells are soreted by the Hilbert Id
3971 for(MInt i = 0; i < m_noCells; ++i) {
3972 if(i != hilbert_lookup[i]) {
3973 if(i != posTracker[hilbert_lookup[i]]) swapCells(i, posTracker[hilbert_lookup[i]]);
3974 MInt iTmp = revPosTracker[i];
3975 revPosTracker[posTracker[hilbert_lookup[i]]] = iTmp;
3976 posTracker[iTmp] = posTracker[hilbert_lookup[i]];
3977 }
3978 }
3979
3980 // d. Reset global ids after reordering
3981 for(MInt i = 0; i < m_noCells; ++i) {
3982 a_globalId(i) = i;
3983 }
3984 RECORD_TIMER_STOP(t_reorderCellsHilbert);
3985}
MString m_targetGridFileName
void swapCells(MInt cellId1, MInt cellId2)
swaps two cells in memory
std::vector< MFloat > m_multiSolverCenterOfGravity
MFloat m_multiSolverLengthLevel0
void checkMultiSolverGridExtents(const MInt nDim, const MFloat *centerOfGravity, const MFloat lengthLevel0, const MInt minLevel, const MFloat *targetGridCenterOfGravity, const MFloat targetGridLengthLevel0, const MInt targetGridMinLevel)
Checks if the given grid extents and cell sizes match when creating a multisolver grid and correspond...
Definition: functions.cpp:112
PARALLELIO_DEFAULT_BACKEND ParallelIo
Definition: parallelio.h:292

◆ reorderGlobalIdsDF()

template<MInt nDim>
void GridgenPar< nDim >::reorderGlobalIdsDF
protected
Author
Andreas Lintermann
Date
11.12.2013

Takes the cells on the coarsest level and traverses them by calling traverseDFGlobalId(...). The code does the following:

a. Traverse the cells by running over the cells on the coarsest level and descending in depth-first order. While doing so update the global ids and store all the ids and the according offsprings in the 2D scratch partitionCellList. b. Since in the last step all cells were inserted, pick only those, which are really min-cells, i.e., those cells that have a less or equal number of offspring than m_partitionCellOffspringThreshold. c. Update the number of min-cells.

Parameters
[in]level_indicator for the timers

Definition at line 5096 of file cartesiangridgenpar.cpp.

5096 {
5097 TRACE();
5098
5099 NEW_SUB_TIMER_STATIC(t_ro, "reorder global ids DF", m_t_finalizeGrid);
5100 RECORD_TIMER_START(t_ro);
5101
5102 m_log << " + reordering global ids" << endl;
5103 outStream << " + reordering global ids" << endl;
5104
5105
5106 m_log << " * traversing all cells depth-first" << endl;
5107 outStream << " * traversing all cells depth-first" << endl;
5108
5109 MLong currentGlobalId = m_cellOffsetPar - 1;
5110
5111 // partitionCellList(ids,0) -> localIds
5112 // partitionCellList(ids,1) -> noOffsprings of cells
5113 MLongScratchSpace partitionCellList(m_noCells, 2, AT_, "partitionCellList");
5114 // workload of cells
5115 MFloatScratchSpace workloadPerCell(m_noCells, 1, AT_, "workloadPerCell");
5116 // total work load for recursively determine the workload of each cell (=partitionCellList(ids,2))
5117 MFloatScratchSpace workload(m_noCells, AT_, "workload");
5118 // set weights if necessary
5119 MFloatScratchSpace weight(m_noCells, AT_, "weight");
5120
5121 if(m_weightMethod > 0)
5122 setCellWeights(weight);
5123 else
5124 weight.fill(1);
5125
5126 // a. traverse
5127 MInt j = 0;
5128
5129 // After load balancing, it is possible that some domains have so called partition level shift.
5130 // This means we have at least one cell which has a halo cell as parent.
5131 // The real first cell is always the one at m_levelOffsets[m_minLevel + m_noMissingParents][0].
5132 // The next cell is then either m_levelOffsets[m_minLevel + m_noMissingParents][0] + 1 (The cell 'beside' the first
5133 // one) Or m_levelOffsets[m_minLevel + m_noMissingParents - 1][0] (The cell 'one level up' the first one) If we got up
5134 // in level such that we are back on m_minLevel, we continue like always.
5135
5136 MInt noMissingParents = m_noMissingParents;
5137 while(noMissingParents > 0) {
5138 MInt k = 0;
5139 MInt cellId = m_levelOffsets[m_minLevel + noMissingParents][0];
5140 while((a_hasProperty((MInt)a_parentId(cellId), 4) == 1) && (a_level(cellId) == (m_minLevel + noMissingParents))) {
5141 currentGlobalId++;
5142 a_globalId(cellId) = currentGlobalId;
5143 partitionCellList(j, 0) = cellId;
5144 // save the current weight of the initial level cells
5145 MFloat currentWorkload = weight(cellId);
5146
5147 // save last pos
5148 MInt last = j;
5149
5150 traverseDFGlobalId(cellId, &currentGlobalId, partitionCellList, workloadPerCell, &currentWorkload, weight,
5151 workload, &j);
5152
5153 MLong noOffsprings = 0;
5154 if(cellId == 0)
5155 noOffsprings = currentGlobalId - m_cellOffsetPar;
5156 else
5157 noOffsprings = currentGlobalId - a_globalId(cellId);
5158
5159 // update
5160 partitionCellList(last, 1) = noOffsprings;
5161 workloadPerCell(last) = currentWorkload;
5162
5163 ++j;
5164 ++k;
5165 cellId = m_levelOffsets[m_minLevel + noMissingParents][0] + k;
5166
5167 } // end of : while ( (a_hasProperty(a_parentId(cellId), 4) == 1) && (a_level(cellId) == (m_minLevel +
5168 // noMissingParents)) )
5169
5170 --noMissingParents;
5171
5172 } // end of : while ( noMissingParents > 0 )
5173
5174 for(MInt i = m_levelOffsets[m_minLevel][0]; i < m_levelOffsets[m_minLevel][1]; i++, j++) {
5175 currentGlobalId++;
5176 a_globalId(i) = currentGlobalId;
5177 partitionCellList(j, 0) = i;
5178 // save the current weight of the initial level cells
5179 MFloat currentWorkload = weight(i);
5180
5181 // save last pos
5182 MInt last = j;
5183
5184 traverseDFGlobalId(i, &currentGlobalId, partitionCellList, workloadPerCell, &currentWorkload, weight, workload, &j);
5185
5186 MLong noOffsprings = 0;
5187 if((i == 0) && (0 == m_noMissingParents))
5188 noOffsprings = currentGlobalId - m_cellOffsetPar;
5189 else
5190 noOffsprings = currentGlobalId - a_globalId(i);
5191
5192 // update
5193 partitionCellList(last, 1) = noOffsprings;
5194 workloadPerCell(last) = currentWorkload;
5195 }
5196
5197 m_log << " * finding partition cells" << endl;
5198 outStream << " * finding partition cells" << endl;
5199
5200 // b. use only those elements that are min-cells
5201 for(MInt i = 0; i < m_noCells; i++) {
5202 MLong noOffsprings = partitionCellList(i, 1);
5203
5204 // Added by Jerry for load balanced grid. Skipping cells with halo childs.
5205 MBool hasHaloChilds = false;
5206 for(MInt child = 0; child < m_maxNoChildren; ++child) {
5207 MInt t_child = (MInt)a_childId(i, child);
5208 if(t_child == -1) {
5209 continue;
5210 }
5211 if(a_hasProperty(t_child, 4) == 1) {
5212 hasHaloChilds = true;
5213 break;
5214 }
5215 }
5216
5217 if(hasHaloChilds && g_dynamicLoadBalancing) {
5218 continue;
5219 }
5220
5221 const MFloat work = workloadPerCell(i);
5222
5223 MBool isSolverLeafCell = false;
5224 // Multisolver grid: assert that child cells of a cell that is a leaf cell for one solver are
5225 // not selected as partition cells to keep the entire subtree of the grid starting at that
5226 // solver-leaf-cell on one domain for coupling reasons
5227 if(m_noSolvers > 1) {
5228 const MLong tmpCellId = partitionCellList(i, 0);
5229 for(MInt solver = 0; solver < m_noSolvers; solver++) {
5230 if(!a_isInSolver((MInt)tmpCellId, solver)) { // Cell not relevant for solver
5231 continue;
5232 }
5233
5234 // Check if there are child cells for this solver
5235 MBool hasSolverChild = false;
5236 for(MInt child = 0; child < m_maxNoChildren; ++child) {
5237 const MInt t_child = (MInt)a_childId((MInt)tmpCellId, child);
5238 if(t_child == -1) {
5239 continue;
5240 }
5241 if(a_isInSolver(t_child, solver)) {
5242 hasSolverChild = true;
5243 break;
5244 }
5245 }
5246 // If there is no child cell for this solver the cell is a solver leaf cell and is added to
5247 // the list of partition cells below
5248 if(!hasSolverChild) {
5249 m_log << "found solver leaf cell " << i << " id" << tmpCellId << " b" << solver << " l" << a_level(i) << " l"
5250 << a_level((MInt)tmpCellId) << std::endl;
5251 isSolverLeafCell = true;
5252 break;
5253 }
5254 }
5255 }
5256
5258 || isSolverLeafCell) {
5259 if(isSolverLeafCell) {
5260 m_log << "partition solver leaf cell " << i << " " << partitionCellList(i, 0) << " l" << a_level(i) << " o"
5261 << noOffsprings << std::endl;
5262 }
5263 m_partitionCellList.push_back(make_tuple(partitionCellList(i, 0), noOffsprings, work));
5264 i += (MInt)noOffsprings;
5265 }
5266 }
5267
5268 // c. update number of min-cells
5270
5271 m_log << " - found " << m_noPartitionCells << endl;
5272 outStream << " - found " << m_noPartitionCells << endl;
5273
5274 RECORD_TIMER_STOP(t_ro);
5275}
MFloat m_partitionCellWorkloadThreshold
MLong m_partitionCellOffspringThreshold
std::vector< std::tuple< MInt, MLong, MFloat > > m_partitionCellList
void setCellWeights(MFloatScratchSpace &weight)
sets the cell weights according to the box system

◆ saveGrid()

template<MInt nDim>
void GridgenPar< nDim >::saveGrid
protected
Author
Lennart Schneiders
Date
July 2017

Definition at line 9543 of file cartesiangridgenpar.cpp.

9543 {
9544 TRACE();
9545
9546 RECORD_TIMER_START(m_t_saveGrid);
9547
9548 m_log << " (7) writing grid to file" << endl;
9549 outStream << " (7) writing grid to file" << endl;
9550
9551 if(m_noTotalCells > numeric_limits<MInt>::max()) {
9552 outStream << "Exceeding 32bit boundary." << endl;
9553 }
9554
9556
9557 // a. file creation and preprocessing
9558 using namespace maia::parallel_io;
9559 MString filename = m_outputDir;
9560 filename.append(m_gridOutputFileName);
9561
9562 MInt maxLevel = 0;
9563 MInt minLevel = m_maxLevels;
9564 for(MInt j = 0; j < m_noCells; ++j) {
9565 maxLevel = mMax(a_level(j), maxLevel);
9566 minLevel = mMin(a_level(j), minLevel);
9567 }
9568
9570 MPI_Allreduce(MPI_IN_PLACE, &maxNoCells, 1, type_traits<MLong>::mpiType(), MPI_MAX, mpiComm(), AT_, "MPI_IN_PLACE",
9571 "maxNoCells");
9572 m_log << "Save grid: maximum number of cells per rank: " << maxNoCells << std::endl;
9573
9574 MLong maxNoHalos = m_noTotalHaloCells;
9575 MPI_Allreduce(MPI_IN_PLACE, &maxNoHalos, 1, type_traits<MLong>::mpiType(), MPI_MAX, mpiComm(), AT_, "MPI_IN_PLACE",
9576 "maxNoHalos");
9577 m_log << "Save grid: maximum number of halo cells per rank: " << maxNoHalos << std::endl;
9578
9579 MPI_Allreduce(MPI_IN_PLACE, &maxLevel, 1, MPI_INT, MPI_MAX, mpiComm(), AT_, "MPI_IN_PLACE", "maxLevel");
9580 MPI_Allreduce(MPI_IN_PLACE, &minLevel, 1, MPI_INT, MPI_MIN, mpiComm(), AT_, "MPI_IN_PLACE", "minLevel");
9581
9582 MFloat totalWorkload = F0;
9583 for(MInt i = 0; i < m_noPartitionCells; ++i) {
9584 totalWorkload += get<2>(m_partitionCellList[i]);
9585 }
9586 MPI_Allreduce(MPI_IN_PLACE, &totalWorkload, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_, "MPI_IN_PLACE", "totalWorkload");
9587
9588 // e. determine maxNoCPUs
9589 MLong maxNoOffsprings = 0;
9590 MFloat maxWorkload = F0;
9591 for(MInt i = 0; i < m_noPartitionCells; ++i) {
9592 if(get<1>(m_partitionCellList[i]) + 1 > maxNoOffsprings) maxNoOffsprings = get<1>(m_partitionCellList[i]) + 1;
9593 maxWorkload = mMax(maxWorkload, get<2>(m_partitionCellList[i]));
9594 }
9595 MPI_Allreduce(MPI_IN_PLACE, &maxNoOffsprings, 1, MPI_LONG, MPI_MAX, mpiComm(), AT_, "MPI_IN_PLACE",
9596 "maxNoOffsprings");
9597 MPI_Allreduce(MPI_IN_PLACE, &maxWorkload, 1, MPI_DOUBLE, MPI_MAX, mpiComm(), AT_, "MPI_IN_PLACE", "maxWorkload");
9598 // MFloat maxNoCPUs = 0.2 * (MFloat) m_noTotalCells / (MFloat) maxNoOffsprings;
9599 // m_log << " + maximum number of possible CPUs with an average deviation of max. 20%: " << maxNoCPUs << endl;
9600 // cout << " + maximum number of possible CPUs with an average deviation of max. 20%: " << maxNoCPUs << endl;
9601 // m_log << " * obtainable average number of cells: " << m_noTotalCells / (MLong)mMax(F1,maxNoCPUs) << "\n
9602 // (tunable by reducing the property partitionCellOffspringThreshold)" << endl; cout << " * obtainable average
9603 // number of cells: " << m_noTotalCells / (MLong)mMax(F1,maxNoCPUs) << "\n (tunable by reducing the
9604 // property partitionCellOffspringThreshold)" << endl;
9605 MFloat maxNoCPUs = totalWorkload / maxWorkload;
9606
9607 MLong noTotalMinLevelCells = 0;
9608 MLong minLevelCellOffset = 0;
9609 MLong partitionCellOffset = 0;
9610 MLong noLeafCells = 0;
9611 MInt maxPartitionLevelShift = 0;
9612 MInt noMinLevelCells = 0;
9613 vector<pair<MLong, MInt>> minLevelCells;
9614 MIntScratchSpace isMinLevelCell(m_noCells, AT_, "isMinLevelCell");
9615 isMinLevelCell.fill(0);
9616 for(MInt i = 0; i < m_noCells; ++i) {
9617 if(a_level(i) == minLevel) {
9618 minLevelCells.push_back(make_pair(a_globalId(i), i));
9619 isMinLevelCell(i) = 1;
9620 noMinLevelCells++;
9621 }
9622 if(a_noChildren(i) == 0) noLeafCells++;
9623 }
9624 MPI_Allreduce(MPI_IN_PLACE, &noLeafCells, 1, MPI_LONG, MPI_SUM, mpiComm(), AT_, "MPI_IN_PLACE", "noLeafCells");
9625 sort(minLevelCells.begin(), minLevelCells.end());
9626
9627 if(noDomains() == 1) {
9630 noTotalMinLevelCells = (MLong)noMinLevelCells;
9631 } else {
9632 mAlloc(m_noPartitionCellsPerDomain, noDomains(), "m_noPartitionCellsPerDomain", AT_);
9633 MIntScratchSpace noMinLevelCellsPerDomain(noDomains(), AT_, "noMinLevelCellsPerDomain");
9634 MPI_Allgather(&m_noPartitionCells, 1, MPI_INT, m_noPartitionCellsPerDomain, 1, MPI_INT, mpiComm(), AT_,
9635 "m_noPartitionCells", "m_noPartitionCellsPerDomain");
9636 MPI_Allgather(&noMinLevelCells, 1, MPI_INT, noMinLevelCellsPerDomain.getPointer(), 1, MPI_INT, mpiComm(), AT_,
9637 "noMinLevelCells", "noMinLevelCellsPerDomain.getPointer()");
9638
9639 for(MInt d = 0; d < globalDomainId(); d++) {
9640 partitionCellOffset += (MLong)m_noPartitionCellsPerDomain[d];
9641 minLevelCellOffset += (MLong)noMinLevelCellsPerDomain[d];
9642 }
9643
9645 noTotalMinLevelCells = 0;
9646 for(MInt d = 0; d < noDomains(); d++) {
9648 noTotalMinLevelCells += (MLong)noMinLevelCellsPerDomain[d];
9649 }
9650 }
9651 MFloat avgWorkload = totalWorkload / ((MFloat)m_noTotalPartitionCells);
9653
9654 map<MLong, MInt> globalToLocal;
9655 for(MInt i = 0; i < m_noCells; ++i) {
9656 globalToLocal.insert(pair<MLong, MInt>(a_globalId(i), i));
9657 }
9658
9659 set<MLong> partitionLevelAncestorIds;
9660 MInt partitionLevelShift = 0;
9661 for(MInt i = 0; i < m_noPartitionCells; ++i) {
9662 MInt levelDiff = a_level(get<0>(m_partitionCellList[i])) - m_minLevel;
9663 partitionLevelShift = mMax(levelDiff, partitionLevelShift);
9664 }
9665 if(partitionLevelShift) {
9666 for(MInt i = 0; i < m_noPartitionCells; ++i) {
9667 MInt cellId = get<0>(m_partitionCellList[i]);
9668 // if ( a_parentId( globalToLocal[a_globalId(cellId)] ) < 0 ) continue;
9669 MLong parentId = a_parentId(globalToLocal[a_globalId(cellId)]);
9670 // MLong parentId = a_globalId(cellId);
9671 while(parentId > -1) {
9672 if(parentId >= m_cellOffsetPar && parentId < m_cellOffsetPar + m_noCells) {
9673 partitionLevelAncestorIds.insert(parentId);
9674 parentId = a_parentId(globalToLocal[parentId]);
9675 } else {
9676 parentId = -1;
9677 }
9678 }
9679 }
9680 }
9681
9682 MLong totalNoPartitionLevelAncestors = 0;
9683 MLong localPartitionLevelAncestorCount = (signed)partitionLevelAncestorIds.size();
9684 MPI_Allreduce(&localPartitionLevelAncestorCount, &totalNoPartitionLevelAncestors, 1, MPI_LONG, MPI_SUM, mpiComm(),
9685 AT_, "localPartitionLevelAncestorCount", "totalNoPartitionLevelAncestors");
9686 MPI_Allreduce(&partitionLevelShift, &maxPartitionLevelShift, 1, MPI_INT, MPI_MAX, mpiComm(), AT_,
9687 "partitionLevelShift", "maxPartitionLevelShift");
9688
9689 ParallelIo grid(filename, PIO_REPLACE, mpiComm());
9690
9691 grid.defineArray(PIO_LONG, "partitionCellsGlobalId", m_noTotalPartitionCells);
9692 grid.defineArray(PIO_FLOAT, "partitionCellsWorkload", m_noTotalPartitionCells);
9693
9694 grid.defineArray(PIO_LONG, "minLevelCellsTreeId", noTotalMinLevelCells);
9695 grid.defineArray(PIO_LONG, "minLevelCellsNghbrIds", 2 * nDim * noTotalMinLevelCells);
9696
9697 grid.defineArray(PIO_UCHAR, "cellInfo", m_noTotalCells);
9698
9699 if(m_noSolvers > 1 || g_multiSolverGrid) grid.defineArray(PIO_UCHAR, "solver", m_noTotalCells);
9700
9702 m_log << "NOTE: writing coordinates to grid file" << std::endl;
9703 for(MInt i = 0; i < nDim; i++) {
9704 grid.defineArray(PIO_FLOAT, "coordinates_" + std::to_string(i), m_noTotalCells);
9705 }
9706 }
9707
9708 // c. prepare I/O
9709
9710 MPI_Offset start = -1;
9711 MPI_Offset startMinLevelCells = -1;
9712 MPI_Offset startPartitionCells = -1;
9713 MPI_Offset count = -1;
9714 MPI_Offset countMinLevelCells = -1;
9715 MPI_Offset countPartitionCells = -1;
9716
9717 MInt nodims = nDim;
9718 MInt tstep = 0;
9719
9720 outStream << "g_multiSolverGrid: " << g_multiSolverGrid << endl;
9721 if(g_multiSolverGrid) {
9722 for(MInt b = 0; b < m_noSolvers; b++) {
9723 MLong solverCount = 0;
9724 // for (MInt i=0;i<m_noTotalCells; i++){
9725 for(MInt i = 0; i < m_noCells; i++) {
9726 if(a_isInSolver(i, b) == true) {
9727 solverCount++;
9728 }
9729 }
9730 cerr << "counted: " << solverCount << " for solver: " << b << endl;
9731 stringstream attributeName;
9732 attributeName << "noCells_" << b;
9733
9734 MPI_Allreduce(MPI_IN_PLACE, &solverCount, 1, MPI_LONG, MPI_SUM, mpiComm(), AT_, "MPI_IN_PLACE", "solverCount");
9735
9736 grid.setAttributes(&solverCount, attributeName.str(), 1);
9737 }
9738 }
9739
9740
9741 grid.setAttributes(&nodims, "nDim", 1);
9742 grid.setAttributes(&m_noSolvers, "noSolvers", 1);
9743 grid.setAttributes(&tstep, "globalTimeStep", 1);
9744 grid.setAttributes(&m_noTotalCells, "noCells", 1);
9745 grid.setAttributes(&noLeafCells, "noLeafCells", 1);
9746 grid.setAttributes(&noTotalMinLevelCells, "noMinLevelCells", 1);
9747 grid.setAttributes(&m_noTotalPartitionCells, "noPartitionCells", 1);
9748 grid.setAttributes(&totalNoPartitionLevelAncestors, "noPartitionLevelAncestors", 1);
9749 grid.setAttributes(&minLevel, "minLevel", 1);
9750 grid.setAttributes(&maxLevel, "maxLevel", 1);
9751 grid.setAttributes(&m_maxUniformRefinementLevel, "maxUniformRefinementLevel", 1);
9752 grid.setAttributes(&maxPartitionLevelShift, "maxPartitionLevelShift", 1);
9753 grid.setAttributes(&m_lengthOnLevel[0], "lengthLevel0", 1);
9754 grid.setAttributes(&m_centerOfGravity[0], "centerOfGravity", nDim);
9755 grid.setAttributes(&m_boundingBox[0], "boundingBox", 2 * nDim);
9756
9757 // Add additional multisolver information if grid is reordered by a different Hilbert curve
9759 grid.setAttributes(&m_multiSolverLengthLevel0, "multiSolverLengthLevel0", 1);
9760 grid.setAttributes(&m_multiSolverMinLevel, "multiSolverMinLevel", 1);
9761 grid.setAttributes(&m_multiSolverCenterOfGravity[0], "multiSolverCenterOfGravity", nDim);
9762 grid.setAttributes(&m_multiSolverBoundingBox[0], "multiSolverBoundingBox", 2 * nDim);
9763 }
9764
9765 grid.setAttributes(&m_reductionFactor, "reductionFactor", 1);
9766 grid.setAttributes(&m_decisiveDirection, "decisiveDirection", 1);
9767 grid.setAttributes(&totalWorkload, "totalWorkload", 1);
9768 grid.setAttributes(&maxWorkload, "partitionCellMaxWorkload", 1);
9769 grid.setAttributes(&avgWorkload, "partitionCellAverageWorkload", 1);
9770 grid.setAttributes(&maxNoOffsprings, "partitionCellMaxNoOffspring", 1);
9771 grid.setAttributes(&avgOffspring, "partitionCellAverageNoOffspring", 1);
9772 grid.setAttributes(&m_partitionCellWorkloadThreshold, "partitionCellWorkloadThreshold", 1);
9773 grid.setAttributes(&m_partitionCellOffspringThreshold, "partitionCellOffspringThreshold", 1);
9774 grid.setAttributes(&maxNoCPUs, "maxNoBalancedCPUs", 1);
9775
9776 // Update start and count for parallel writing
9777 start = m_cellOffsetPar;
9778 startMinLevelCells = minLevelCellOffset;
9779 startPartitionCells = partitionCellOffset;
9780 count = m_noCells;
9781 countMinLevelCells = noMinLevelCells;
9782 countPartitionCells = m_noPartitionCells;
9783
9784
9785 //---
9786 grid.setOffset(countPartitionCells, startPartitionCells);
9787 //---
9788
9789 { // partitionCellsGlobalIds
9790 MLongScratchSpace tmp(m_noPartitionCells, AT_, "tmp");
9791 for(MInt i = 0; i < m_noPartitionCells; ++i)
9792 tmp[i] = a_globalId(get<0>(m_partitionCellList[i]));
9793 grid.writeArray(tmp.getPointer(), "partitionCellsGlobalId");
9794 }
9795
9796 { // partitionCellsWorkload
9797 MFloatScratchSpace tmp(m_noPartitionCells, AT_, "tmp");
9798 for(MInt i = 0; i < m_noPartitionCells; ++i)
9799 tmp[i] = get<2>(m_partitionCellList[i]);
9800 grid.writeArray(tmp.getPointer(), "partitionCellsWorkload");
9801 }
9802
9803
9804 //---
9805 grid.setOffset(countMinLevelCells, startMinLevelCells);
9806 //---
9807
9808 if(minLevel > 21)
9809 mTerm(1, AT_,
9810 "Tree id can not be stored using 64 bits. Change minLevelCellsTreeId to 128 bits or reduce minLevel to 21 "
9811 "or less.");
9812
9813 { // minLevelCellsTreeId
9814 MLongScratchSpace tmp(noMinLevelCells, AT_, "tmp");
9815
9816 // Use multiSolver information if given
9817 const MLong tmpMinLevel = (m_multiSolverMinLevel > -1) ? m_multiSolverMinLevel : minLevel;
9820
9821 for(MInt i = 0; i < noMinLevelCells; ++i) {
9822 maia::grid::hilbert::coordinatesToTreeId<nDim>(tmp[i], &a_coordinate(minLevelCells[i].second, 0), tmpMinLevel,
9823 tmpCog, tmpLength0);
9824 }
9825 grid.writeArray(tmp.getPointer(), "minLevelCellsTreeId");
9826 }
9827
9828 { // minLevelCellsNghbrIds
9829 MLongScratchSpace tmp(noMinLevelCells, 2 * nDim, AT_, "tmp");
9830 for(MInt i = 0; i < noMinLevelCells; ++i) {
9831 for(MInt j = 0; j < m_noNeighbors; j++) {
9832 tmp(i, j) = a_neighborId(minLevelCells[i].second, j);
9833 }
9834 }
9835 grid.setOffset(2 * nDim * countMinLevelCells, 2 * nDim * startMinLevelCells);
9836 grid.writeArray(tmp.getPointer(), "minLevelCellsNghbrIds");
9837 }
9838
9839 //---
9840 grid.setOffset(count, start);
9841 //---
9842
9843 {
9844 // cellInfo
9845 ScratchSpace<MUchar> tmp(m_noCells, AT_, "tmp");
9846 for(MInt i = 0; i < m_noCells; ++i) {
9847 MLong sortedLocalId = a_globalId(i) - m_cellOffsetPar;
9848 MUint noChilds = (MUint)a_noChildren(i);
9849 MUint isMinLvl = (MUint)isMinLevelCell(i);
9850 MUint position = 0;
9851 if(a_parentId(i) > -1) {
9852 MInt parentId = globalToLocal[a_parentId(i)];
9853 for(MUint j = 0; j < (unsigned)m_maxNoChildren; j++) {
9854 if(a_childId(parentId, j) == a_globalId(i)) position = j;
9855 }
9856 }
9857 MUint tmpBit = noChilds | (position << 4) | (isMinLvl << 7);
9858 tmp[sortedLocalId] = static_cast<MUchar>(tmpBit);
9859 }
9860 grid.writeArray(tmp.begin(), "cellInfo");
9861
9862 // solverAffiliation
9863 if(m_noSolvers > 1 || g_multiSolverGrid) {
9864 for(MInt i = 0; i < m_noCells; ++i) {
9865 MLong sortedLocalId = a_globalId(i) - m_cellOffsetPar;
9866 MUint tmpBit = 0;
9867 for(MInt solver = 0; solver < m_noSolvers; solver++) {
9868 if(a_isInSolver(i, solver)) {
9869 tmpBit |= (1 << solver);
9870 }
9871 }
9872 tmp[sortedLocalId] = static_cast<MUchar>(tmpBit);
9873 }
9874 grid.writeArray(tmp.begin(), "solver");
9875 }
9876 }
9877
9879 ScratchSpace<MFloat> tmp(m_noCells, AT_, "tmp");
9880 for(MInt d = 0; d < nDim; d++) {
9881 for(MInt i = 0; i < m_noCells; ++i) {
9882 const MLong sortedLocalId = a_globalId(i) - m_cellOffsetPar;
9883 tmp[sortedLocalId] = a_coordinate(i, d);
9884 }
9885 grid.writeArray(tmp.begin(), "coordinates_" + std::to_string(d));
9886 }
9887 }
9888
9889 m_log << " + grid file written to file '" << filename << "'" << endl;
9890 outStream << " + grid file written to '" << filename << "'" << endl;
9891
9892 RECORD_TIMER_STOP(m_t_saveGrid);
9893}
MInt * m_noPartitionCellsPerDomain
MBool m_writeCoordinatesToGridFile
MString m_gridOutputFileName
constexpr T mMin(const T &x, const T &y)
Definition: functions.h:90
MBool g_multiSolverGrid
uint32_t MUint
Definition: maiatypes.h:63
unsigned char MUchar
Definition: maiatypes.h:57
void const MInt const MInt const MInt const MInt maxNoCells
Definition: collector.h:240

◆ saveGridDomain()

template<MInt nDim>
void GridgenPar< nDim >::saveGridDomain ( MInt  level_,
MInt  tag 
)
protected
Author
Andreas Lintermann
Date
05.12.2013

Writes the grid in serial per domain.

Parameters
[in]level_the level to write
[in]taga tag which is appended to the file name

Definition at line 9919 of file cartesiangridgenpar.cpp.

9919 {
9920 TRACE();
9921
9922 using namespace maia::parallel_io;
9923
9924 MChar buf0[10];
9925 MChar buf[10];
9926 MChar buf1[10];
9927 MString preName;
9928
9929 sprintf(buf0, "%d", tag);
9930 sprintf(buf, "%d", globalDomainId());
9931 sprintf(buf1, "%d", level_);
9932 preName = buf0;
9933 preName.append("G");
9934 preName.append(buf);
9935 preName.append("_L");
9936 preName.append(buf1);
9937 preName.append("_");
9938 preName.append(m_gridOutputFileName);
9939
9940 size_t size = m_noCells + m_noTotalHaloCells;
9941
9942 size_t sndBuf = size;
9943 MIntScratchSpace noCellsPerDomain(noDomains(), AT_, "noCellsPerDomain");
9944 MPI_Allgather(&sndBuf, 1, MPI_INT, noCellsPerDomain.getPointer(), 1, MPI_INT, mpiComm(), AT_, "sndBuf",
9945 "noCellsPerDomain.getPointer()");
9946
9947 size_t myOffset = 0;
9948 for(MInt d = 0; d < globalDomainId(); d++)
9949 myOffset += noCellsPerDomain[d];
9950
9951 // WARNING: untested switch from NetCDF/Parallel netCDF to ParallelIo
9952 // The method previously used direct I/O calls, which were replaced by
9953 // ParallelIo methods in summer 2015. However, since the method was not
9954 // used by any of the testcases, this code is still *untested*. Thus,
9955 // if your code uses this part of the code, please make sure that the
9956 // I/O still works as expected and then remove this warning as well as
9957 // the subsequent TERMM().
9958 TERMM(1, "untested I/O method, please see comment for how to proceed");
9959 ParallelIo parallelIo(preName.c_str(), maia::parallel_io::PIO_REPLACE, MPI_COMM_SELF);
9960
9961 CartesianNetcdf CN;
9962
9963 MIntScratchSpace variablesVar(33, AT_, "variablesVar");
9964
9965 MString varnames[33] = {"partitionCellsId",
9966 "partitionCellsNoOffsprings",
9967 "partitionCellsWorkLoad",
9968 "partitionCellsLvlDiff",
9969 "parentId",
9970 "noChildIds",
9971 "childIds_0",
9972 "childIds_1",
9973 "childIds_2",
9974 "childIds_3",
9975 "childIds_4",
9976 "childIds_5",
9977 "childIds_6",
9978 "childIds_7",
9979 "level_0",
9980 "level_1",
9981 "level_2",
9982 "noNghbrIds_0",
9983 "noNghbrIds_1",
9984 "noNghbrIds_2",
9985 "noNghbrIds_3",
9986 "noNghbrIds_4",
9987 "noNghbrIds_5",
9988 "nghbrIds_0",
9989 "nghbrIds_1",
9990 "nghbrIds_2",
9991 "nghbrIds_3",
9992 "nghbrIds_4",
9993 "nghbrIds_5",
9994 "weight",
9995 "coordinates_0",
9996 "coordinates_1",
9997 "coordinates_2"};
9998
10003
10004 parallelIo.defineScalar(PIO_INT, "noCells");
10005
10006 for(MInt i = 0; i < 33; i++) {
10007 parallelIo.defineArray(type[i], varnames[i].c_str(), size);
10008 }
10009 parallelIo.setOffset(size, 0);
10010
10011 MInt s = size;
10012 parallelIo.writeScalar(s, "noCells");
10013
10014 MInt shift = m_haloCellOffsetsLevel[level_][0] - m_noCells;
10015
10016 MInt cnt = 0;
10017 // partitionCellsIdDim
10018 {
10019 MIntScratchSpace tmpVars(size, AT_, "tmpVars");
10020 MInt i = 0;
10021 for(; i < m_noCells; i++)
10022 tmpVars[i] = i + myOffset;
10023 if(noDomains() > 1)
10024 for(MInt j = m_haloCellOffsetsLevel[level_][0]; j < m_maxNoCells - 1; j++, i++)
10025 tmpVars[i] = j - shift + myOffset;
10026 parallelIo.writeArray(tmpVars.getPointer(), varnames[cnt].c_str());
10027 cnt++;
10028 }
10029
10030 // partitionCellsIdOffsprings,partitionCellsWorkload,partitionCellsLvlDiff
10031 for(MInt j = 0; j < 3; j++) {
10032 MIntScratchSpace tmpVars(size, AT_, "tmpVars");
10033 MInt i = 0;
10034 for(; i < m_noCells; i++)
10035 tmpVars[i] = 1;
10036 if(noDomains() > 1)
10037 for(MInt k = m_haloCellOffsetsLevel[level_][0]; k < m_maxNoCells - 1; k++, i++)
10038 tmpVars[i] = 1;
10039 parallelIo.writeArray(tmpVars.getPointer(), varnames[cnt].c_str());
10040 cnt++;
10041 }
10042
10043 // parentId
10044 {
10045 MIntScratchSpace tmpVars(size, AT_, "tmpVars");
10046 MInt i = 0;
10047 for(; i < m_noCells; i++) {
10048 if(a_parentId(i) >= 0)
10049 tmpVars[i] = (MInt)a_parentId(i) + myOffset;
10050 else
10051 tmpVars[i] = (MInt)a_parentId(i);
10052 }
10053 if(noDomains() > 1) {
10054 for(MInt j = m_haloCellOffsetsLevel[level_][0]; j < m_maxNoCells - 1; j++, i++) {
10055 if(a_parentId(j) >= 0)
10056 tmpVars[i] = (MInt)a_parentId(j) - shift + myOffset;
10057 else
10058 tmpVars[i] = (MInt)a_parentId(j);
10059 }
10060 }
10061 parallelIo.writeArray(tmpVars.getPointer(), varnames[cnt].c_str());
10062 cnt++;
10063 }
10064
10065 // noChildIds
10066 {
10067 MIntScratchSpace tmpVars(size, AT_, "tmpVars");
10068 MInt i = 0;
10069 for(; i < m_noCells; i++)
10070 tmpVars[i] = 0;
10071 if(noDomains() > 1)
10072 for(MInt j = m_haloCellOffsetsLevel[level_][0]; j < m_maxNoCells - 1; j++, i++)
10073 tmpVars[i] = 0;
10074 parallelIo.writeArray(tmpVars.getPointer(), varnames[cnt].c_str());
10075 cnt++;
10076 }
10077
10078 // childIds
10079 for(MInt j = 0; j < 8; j++) {
10080 MIntScratchSpace tmpVars(size, AT_, "tmpVars");
10081 MInt i = 0;
10082 for(; i < m_noCells; i++) {
10083 if(a_childId(i, j) >= 0)
10084 tmpVars[i] = (MInt)a_childId(i, j) + myOffset;
10085 else
10086 tmpVars[i] = (MInt)a_childId(i, j);
10087 }
10088 if(noDomains() > 1) {
10089 for(MInt k = m_haloCellOffsetsLevel[level_][0]; k < m_maxNoCells - 1; k++, i++) {
10090 if(a_childId(k, j) >= 0)
10091 tmpVars[i] = (MInt)a_childId(k, j) - shift + myOffset;
10092 else
10093 tmpVars[i] = (MInt)a_childId(k, j);
10094 }
10095 }
10096 parallelIo.writeArray(tmpVars.getPointer(), varnames[cnt].c_str());
10097 cnt++;
10098 }
10099
10100 // level
10101 for(MInt j = 0; j < 3; j++) {
10102 MIntScratchSpace tmpVars(size, AT_, "tmpVars");
10103 MInt i = 0;
10104 for(; i < m_noCells; i++)
10105 tmpVars[i] = a_level(i);
10106 if(noDomains() > 1)
10107 for(MInt k = m_haloCellOffsetsLevel[level_][0]; k < m_maxNoCells - 1; k++, i++)
10108 tmpVars[i] = a_level(k);
10109 parallelIo.writeArray(tmpVars.getPointer(), varnames[cnt].c_str());
10110 cnt++;
10111 }
10112
10113 // noNghbrIds
10114 for(MInt j = 0; j < 6; j++) {
10115 MIntScratchSpace tmpVars(size, AT_, "tmpVars");
10116 MInt i = 0;
10117 for(; i < m_noCells; i++)
10118 tmpVars[i] = (a_neighborId(i, j)) >= 0 ? 1 : 0;
10119 if(noDomains() > 1)
10120 for(MInt k = m_haloCellOffsetsLevel[level_][0]; k < m_maxNoCells - 1; k++, i++)
10121 tmpVars[i] = (a_neighborId(k, j)) >= 0 ? 1 : 0;
10122 parallelIo.writeArray(tmpVars.getPointer(), varnames[cnt].c_str());
10123 cnt++;
10124 }
10125
10126 // nghbrIds
10127 for(MInt j = 0; j < 6; j++) {
10128 MIntScratchSpace tmpVars(size, AT_, "tmpVars");
10129 MInt i = 0;
10130 if(noDomains() > 1) {
10131 for(; i < m_noCells; i++) {
10132 if(a_neighborId(i, j) >= 0)
10133 if(a_neighborId(i, j) >= m_noCells)
10134 tmpVars[i] = (MInt)a_neighborId(i, j) - shift; // + myOffset;
10135 else
10136 tmpVars[i] = (MInt)a_neighborId(i, j); // + myOffset;
10137 else
10138 tmpVars[i] = (MInt)a_neighborId(i, j);
10139 }
10140 for(MInt k = m_haloCellOffsetsLevel[level_][0]; k < m_maxNoCells - 1; k++, i++) {
10141 if(a_neighborId(k, j) >= 0)
10142 if(a_neighborId(k, j) >= m_noCells)
10143 tmpVars[i] = (MInt)a_neighborId(k, j) - shift; // + myOffset;
10144 else
10145 tmpVars[i] = (MInt)a_neighborId(k, j); // + myOffset;
10146 else
10147 tmpVars[i] = (MInt)a_neighborId(k, j);
10148 }
10149 } else {
10150 for(; i < m_noCells; i++)
10151 if(a_neighborId(i, j) >= m_noCells)
10152 tmpVars[i] = (MInt)a_neighborId(i, j) + myOffset;
10153 else
10154 tmpVars[i] = (MInt)a_neighborId(i, j);
10155 }
10156 parallelIo.writeArray(tmpVars.getPointer(), varnames[cnt].c_str());
10157 cnt++;
10158 }
10159
10160 // weight
10161 {
10162 MIntScratchSpace tmpVars(size, AT_, "tmpVars");
10163 MInt i = 0;
10164 for(; i < m_noCells; i++)
10165 tmpVars[i] = 1;
10166 if(noDomains() > 1)
10167 for(MInt j = m_haloCellOffsetsLevel[level_][0]; j < m_maxNoCells - 1; j++, i++)
10168 tmpVars[i] = 1;
10169 parallelIo.writeArray(tmpVars.getPointer(), varnames[cnt].c_str());
10170 cnt++;
10171 }
10172
10173 // coordinates
10174 for(MInt j = 0; j < 3; j++) {
10175 MFloatScratchSpace tmpVars(size, AT_, "tmpVars");
10176 MInt i = 0;
10177 for(; i < m_noCells; i++)
10178 tmpVars[i] = a_coordinate(i, j);
10179 if(noDomains() > 1)
10180 for(MInt k = m_haloCellOffsetsLevel[level_][0]; k < m_maxNoCells - 1; k++, i++)
10181 tmpVars[i] = a_coordinate(k, j);
10182 parallelIo.writeArray(tmpVars.getPointer(), varnames[cnt].c_str());
10183 cnt++;
10184 }
10185}
define the names of all variables and attributes in the netcdf file
const MInt PIO_REPLACE
Definition: parallelio.h:36
const MInt PIO_INT
Definition: parallelio.h:48
const MInt PIO_FLOAT
Definition: parallelio.h:46

◆ setCellWeights()

template<MInt nDim>
void GridgenPar< nDim >::setCellWeights ( MFloatScratchSpace weight)
protected
Author
Stephan Schlimpert
Date
03.06.2014
Todo:
labels:GRIDGEN if the weight method is suitable then use the box system like Andi's refinement method

◆ swapCells()

template<MInt nDim>
void GridgenPar< nDim >::swapCells ( MInt  cellId1,
MInt  cellId2 
)
protected
Author
Andreas Lintermann
Date
16.10.2013

The swapping is performed as follows:

Copy cell1 to the temp, copy cell2 to cell1, copy temp to cell2.

Parameters
[in]cellId1the id of the first cell
[in]cellId2the id of the second cell

Definition at line 4110 of file cartesiangridgenpar.cpp.

4110 {
4111 TRACE();
4112
4113 copyCell(cellId1, m_maxNoCells - 1);
4114 copyCell(cellId2, cellId1);
4115 copyCell(m_maxNoCells - 1, cellId2);
4116}

◆ traverseDFGlobalId()

template<MInt nDim>
void GridgenPar< nDim >::traverseDFGlobalId ( MInt  parentId_,
MLong globalId_,
MLongScratchSpace partitionCellList,
MFloatScratchSpace workloadPerCell,
MFloat currentWorkload,
MFloatScratchSpace weight,
MFloatScratchSpace workload,
MInt j 
)
protected
Author
Andreas Lintermann
Date
03.12.2013

Recursively calls itself and changes the global-id of the current cell. It also fills the list partitionCellList with the according cell-id and the number of offsprings.

Parameters
[in]parentIdthe id of the cell to traverse
[in]globalIdthe new global-id to use next
[in]partitionCellLista reference to the list containing all cell information
[in]workloadPerCellstores the work load per cell
[in]currentWorkloadthe current incremental work load
[in]weightthe weighting
[in]workloadbase work load
[in]jpointer to the incrementer

Definition at line 5297 of file cartesiangridgenpar.cpp.

5299 {
5300 TRACE();
5301
5302 MLong* children = &a_childId(parentId_, 0);
5303
5304 for(MInt c = 0; c < m_maxNoChildren; c++) {
5305 if(children[c] > -1) {
5307 && (a_hasProperty((MInt)children[c], 4)
5308 == 1)) { // Added by Jerry for load balanced grid. Skipping halo childs.
5309 continue;
5310 }
5311
5312 // increase the weight by the weight of the children
5313 *currentWorkload = *currentWorkload + weight((MInt)children[c]);
5314 // increase global id by one
5315 *globalId_ = *globalId_ + 1;
5316 // save global id of child
5317 a_globalId((MInt)children[c]) = *globalId_;
5318 // set workload of child to current total work load or parent analog to the global Id
5319 workload((MInt)children[c]) = *currentWorkload;
5320
5321 *j = *j + 1;
5322 partitionCellList(*j, 0) = children[c];
5323
5324 // save last pos
5325 MInt last = *j;
5326
5327 traverseDFGlobalId((MInt)children[c], globalId_, partitionCellList, workloadPerCell, currentWorkload, weight,
5328 workload, j);
5329
5330 MLong noOffsprings = 0;
5331 noOffsprings = *(globalId_)-a_globalId((MInt)children[c]);
5332 // subtract the total workload of the child from the current totally work load to compute the work load of the
5333 // child
5334 MFloat work = *currentWorkload - workload((MInt)children[c]) + weight((MInt)children[c]); // add own weight
5335
5336 // update offsprings + workload of parent
5337 partitionCellList(last, 1) = noOffsprings;
5338 // set current work load of the child
5339 workloadPerCell(last) = work;
5340 }
5341 }
5342}

◆ updateGlobalIdsReferences()

template<MInt nDim>
void GridgenPar< nDim >::updateGlobalIdsReferences
protected
Author
Andreas Lintermann
Date
04.12.2013

Runs over all cells, checks the referenced neighbors, parents, and children and updates the relation to use the global-id of the according cell.

Definition at line 4239 of file cartesiangridgenpar.cpp.

4239 {
4240 TRACE();
4241
4242 for(MInt i = 0; i < m_noCells; i++) {
4243 for(MInt n = 0; n < m_noNeighbors; n++) {
4244 if(a_neighborId(i, n) >= 0 && a_neighborId(i, n) < m_noCells) {
4245 a_neighborId(i, n) = a_globalId((MInt)a_neighborId(i, n));
4246 }
4247 }
4248
4249 for(MInt c = 0; c < m_maxNoChildren; c++)
4250 if(a_childId(i, c) >= 0) a_childId(i, c) = a_globalId((MInt)a_childId(i, c));
4251
4252 if(a_parentId(i) >= 0) a_parentId(i) = a_globalId((MInt)a_parentId(i));
4253 }
4254}

◆ updateHaloOffsets()

template<MInt nDim>
void GridgenPar< nDim >::updateHaloOffsets ( MInt  l,
MInt  noHalos,
MInt rfnCountHalosDom 
)
protected
Author
Andreas Lintermann
Date
12.11.2013

Update the halo offset information and size. This generates a new offset range for the new halo cells on the new level under the assumption that all current halo cells are refined. The offset range is created from the back of the collector, without using the very last element (which is reserved as a temporary item for a swapping operation), i.e., the lower the level, the closer we are to the end of the collector. The information is also stored domain-wise.

Parameters
[in]lthe level to consider

Definition at line 4296 of file cartesiangridgenpar.cpp.

4296 {
4297 TRACE();
4298
4299 m_log << " + updating the halo offsets for the new level for " << noHalos << " halos" << endl;
4300 outStream << " + updating the halo offsets for the new level for " << noHalos << " halos" << endl;
4301
4306
4307 MInt lev_pos = 2 * (l - m_minLevel);
4308 MInt lev_pos_newlevel = 2 * ((l + 1) - m_minLevel);
4309
4310 m_log << " * halo cells on this level for processes [offsets]: " << endl;
4311 outStream << " * halo cells on this level for processes [offsets]: " << endl;
4312 for(MInt dom = 0; dom < m_noNeighborDomains; dom++) {
4313 MInt diff_on_level = 0;
4314 if(noHalos == m_noHaloCellsOnLevel[l])
4315 diff_on_level = m_haloCellOffsets[dom][lev_pos + 1] - m_haloCellOffsets[dom][lev_pos];
4316 else
4317 diff_on_level = rfnCountHalosDom[dom];
4318
4319 if(dom == 0)
4320 m_haloCellOffsets[dom][lev_pos_newlevel] = m_haloCellOffsetsLevel[l + 1][0];
4321 else
4322 m_haloCellOffsets[dom][lev_pos_newlevel] = m_haloCellOffsets[dom - 1][lev_pos_newlevel + 1];
4323
4324 m_haloCellOffsets[dom][lev_pos_newlevel + 1] =
4325 m_haloCellOffsets[dom][lev_pos_newlevel] + diff_on_level * m_maxNoChildren;
4326 m_log << " - " << m_neighborDomains[dom] << ": "
4327 << " " << m_haloCellOffsets[dom][lev_pos_newlevel + 1] - m_haloCellOffsets[dom][lev_pos_newlevel] << " ["
4328 << m_haloCellOffsets[dom][lev_pos_newlevel] << " " << m_haloCellOffsets[dom][lev_pos_newlevel + 1] << "] "
4329 << endl;
4330 outStream << " - " << m_neighborDomains[dom] << ": "
4331 << " " << m_haloCellOffsets[dom][lev_pos_newlevel + 1] - m_haloCellOffsets[dom][lev_pos_newlevel] << " ["
4332 << m_haloCellOffsets[dom][lev_pos_newlevel] << " " << m_haloCellOffsets[dom][lev_pos_newlevel + 1]
4333 << "] " << endl;
4334 }
4335}

◆ updateInterRankNeighbors()

template<MInt nDim>
void GridgenPar< nDim >::updateInterRankNeighbors
protected
Author
Andreas Lintermann
Date
18.10.2013

The algorithm does the following:

a. Get the number of cells created on the other domains. This fills an array m_noCellsPerDomain with the number of cells created on each domain.

b. Determine my own offset. This calulates the offset from where we need to write in the I/O-routine. The value is stored in the variable m_cellOffsetPar.

c. Create lists of window and halo cells. This creates a vector of vectors of window and halo ids (winCellIdsPerDomain, haloCellIdsPerDomain). The first dimensions represents the neighbor domain and the second the according window and halo cell id.

d. Find the halo and window cells for all domains. This runs over all neighbor domains First, all normal cells are cleared and then remarked as window cell domain-wise. They are then collected in winCellIdsPerDomain. At the end the global-ids are updated.

e. Reorder the global ids to be sorted depth-first. This calls reorderGlobalIdsDF(), which reorders only the global-ids. The cells are not moved in moved in memory.

f. Wite parallel geometry if requested.

g. Prepare the communication. This allocates the buffers for the cells to send and receive.

h. Fill the sendbuffer and send it (domain-wise). The buffer is filled by the accroding global-id.

i. Receive from neighbors (domain-wise).

j. Update the neighbors, parents and children to use the global-id. Runs over all cells and checks the global-id of the neighbors, parent, and children and updates the local information accordingly. This is only done for associated cells that are not halo cells.

k. Update the global ids of the halos and the acoording window neighbors. The receive buffer contains all the global-ids from the windows of the neighbors. The halos are filled by these global-ids. Then the according neighbor, which is a window cell in the normal cell collector is updated for its neighborhood, to point to the global-id that we have received.

Definition at line 4759 of file cartesiangridgenpar.cpp.

4759 {
4760 TRACE();
4761
4762 NEW_SUB_TIMER(t_updateInterRankNeighbors, "update inter rank neighbors", m_t_finalizeGrid);
4763 m_t_updateInterRankNeighbors = t_updateInterRankNeighbors;
4764 RECORD_TIMER_START(m_t_updateInterRankNeighbors);
4765
4766 m_log << " + updating the inter rank neighbors" << endl;
4767 outStream << " + updating the inter rank neighbors" << endl;
4768
4769 // a. get the number of cells created on the other domains
4770 MInt* sndBuf = &m_noCells;
4771 MPI_Allgather(sndBuf, 1, MPI_INT, m_noCellsPerDomain, 1, MPI_INT, mpiComm(), AT_, "sndBuf", "m_noCellsPerDomain");
4772
4773 // b. determine my own offset
4774 for(MInt d = 0; d < globalDomainId(); d++)
4776
4777 // c. create lists of window and halo cells
4778 vector<vector<MInt>> winCellIdsPerDomain(m_noNeighborDomains, vector<MInt>(0));
4779 vector<vector<MInt>> haloCellIdsPerDomain(m_noNeighborDomains, vector<MInt>(0));
4780
4781 // d. find the halo and window cells for all domains
4783 findHaloAndWindowCellsKD(winCellIdsPerDomain, haloCellIdsPerDomain);
4784 else
4785 findHaloAndWindowCells(winCellIdsPerDomain, haloCellIdsPerDomain);
4786
4787 // e. reorder the global ids to be sorted depth-first
4789
4790 // f. write parallel geometry if requested
4791 for(MInt solver = 0; solver < m_noSolvers; solver++) {
4792 if(m_geometry->nodeSurfaceType(solver) == STL) {
4794 if(m_STLgeometry->m_parallelGeometry) writeParallelGeometry();
4795 }
4796 }
4797
4798 // g. prepare the communication
4799 MIntScratchSpace noSendWindowPerDomain(m_noNeighborDomains, AT_, "noSendWindowPerDomain");
4800 MIntScratchSpace noReceiveHaloPerDomain(m_noNeighborDomains, AT_, "noReceiveHaloPerDomain");
4801
4802 m_log << " * we need to transfer to domain [no. cells to transfer]: ";
4803 outStream << " * we need to transfer to domain [no. cells to transfer]: ";
4804 for(MInt d = 0; d < m_noNeighborDomains; d++) {
4805 noSendWindowPerDomain[d] = (signed)winCellIdsPerDomain[d].size();
4806 m_log << m_neighborDomains[d] << " [" << noSendWindowPerDomain[d] << "] ";
4807 outStream << m_neighborDomains[d] << " [" << noSendWindowPerDomain[d] << "] ";
4808 }
4809 m_log << endl;
4810 outStream << endl;
4811
4812 m_log << " * we need to receive from domain [no. cells to receive]: ";
4813 outStream << " * we need to receive from domain [no. cells to receive]: ";
4814 for(MInt d = 0; d < m_noNeighborDomains; d++) {
4815 noReceiveHaloPerDomain[d] = (signed)haloCellIdsPerDomain[d].size();
4816 m_log << m_neighborDomains[d] << " [" << noReceiveHaloPerDomain[d] << "] ";
4817 outStream << m_neighborDomains[d] << " [" << noReceiveHaloPerDomain[d] << "] ";
4818 }
4819 m_log << endl;
4820 outStream << endl;
4821
4822 // count all
4823 MInt allSend = 0;
4824 MInt allReceive = 0;
4825 vector<MInt> offsetsSend;
4826 vector<MInt> offsetsReceive;
4827 for(MInt dom = 0; dom < m_noNeighborDomains; dom++) {
4828 offsetsSend.push_back(allSend);
4829 offsetsReceive.push_back(allReceive);
4830 allSend += noSendWindowPerDomain[dom];
4831 allReceive += noReceiveHaloPerDomain[dom];
4832 }
4833
4834 MLongScratchSpace sndBufWin(allSend, AT_, "sndBufWin");
4835 MLongScratchSpace rcvBufHalo(allReceive, AT_, "rcvBufHalo");
4836
4837 // h. fill the sendbuffer and send it
4838 MPI_Request* mpi_request = nullptr;
4839 mAlloc(mpi_request, m_noNeighborDomains, "mpi_request", AT_);
4840 for(MInt d = 0; d < m_noNeighborDomains; d++) {
4841 for(MInt c = 0; c < noSendWindowPerDomain[d]; c++)
4842 sndBufWin[offsetsSend[d] + c] = a_globalId(winCellIdsPerDomain[d][c]);
4843
4844 MPI_Issend(&(sndBufWin[offsetsSend[d]]), noSendWindowPerDomain[d], MPI_LONG, m_neighborDomains[d], 0, mpiComm(),
4845 &mpi_request[d], AT_, "(sndBufWin[offsetsSend[d]])");
4846 }
4847
4848 // i. receive from neighbors
4849 MPI_Status status;
4850 for(MInt d = 0; d < m_noNeighborDomains; d++)
4851 MPI_Recv(&(rcvBufHalo[offsetsReceive[d]]), noReceiveHaloPerDomain[d], MPI_LONG, m_neighborDomains[d], 0, mpiComm(),
4852 &status, AT_, "(rcvBufHalo[offsetsReceive[d]])");
4853
4854
4855 for(MInt d = 0; d < m_noNeighborDomains; d++)
4856 MPI_Wait(&mpi_request[d], &status, AT_);
4857
4858 // j. update the neighbors, parents and children to use the global id
4860
4861 // k. update the global ids of the halos and the acoording window neighbors
4862 for(MInt d = 0; d < m_noNeighborDomains; d++)
4863 for(MInt c = 0; c < noReceiveHaloPerDomain[d]; c++) {
4864 MInt halo = haloCellIdsPerDomain[d][c];
4865 a_globalId(halo) = rcvBufHalo[c + offsetsReceive[d]];
4866 for(MInt n = 0; n < m_noNeighbors; n++) {
4867 if(a_neighborId(halo, n) >= 0 && a_neighborId(halo, n) < m_noCells) {
4868 a_neighborId((MInt)a_neighborId(halo, n), oppositeDirGrid[n]) = a_globalId(halo);
4869 }
4870 }
4871 }
4872
4873 RECORD_TIMER_STOP(m_t_updateInterRankNeighbors);
4874}
MInt nodeSurfaceType(const MInt node)
Definition: geometryroot.h:144
void setGeometryPointerToNode(Geometry< nDim > *&geometryPointer, const MInt node)
MInt m_t_updateInterRankNeighbors
Geometry< nDim > * m_STLgeometry
@ STL
Definition: enums.h:365

◆ updateOffsets()

template<MInt nDim>
void GridgenPar< nDim >::updateOffsets ( MInt  gridLevel)
protected
Author
Andreas Lintermann
Date
02.06.2014
Parameters
[in]gridLevelthe level for which to update the offsets

Definition at line 4265 of file cartesiangridgenpar.cpp.

4265 {
4266 TRACE();
4267
4268 m_levelOffsets[gridLevel + 1][0] = m_noCells;
4269 m_levelOffsets[gridLevel + 1][1] = m_noCells + m_rfnCount * m_maxNoChildren;
4270
4271 m_log << " * cells on level " << gridLevel << " to refine: " << m_rfnCount << endl;
4272 m_log << " - new cells to create: " << m_rfnCount * m_maxNoChildren << endl;
4273 m_log << " - new no. of cells: " << m_noCells + m_rfnCount * m_maxNoChildren << endl;
4274 outStream << " * cells on level " << gridLevel << " to refine: " << m_rfnCount << endl;
4275 outStream << " - new cells to create: " << m_rfnCount * m_maxNoChildren << endl;
4276 outStream << " - new no. of cells: " << m_noCells + m_rfnCount * m_maxNoChildren << endl;
4277}

◆ writeGridInformation()

template<MInt nDim>
void GridgenPar< nDim >::writeGridInformation ( MInt  level_,
MInt  tag 
)
protected
Author
Andreas Lintermann
Date
05.12.2013

Writes certain information to files in serial.

Parameters
[in]level_the level to write
[in]taga tag which is appended to the file name

Definition at line 10199 of file cartesiangridgenpar.cpp.

10199 {
10200 TRACE();
10201
10202 using namespace maia::parallel_io;
10203
10204 outStream << "Writing grid info" << endl;
10205 MChar buf0[10];
10206 MChar buf[10];
10207 MChar buf1[10];
10208 MString preName;
10209 MString preName1;
10210
10211 sprintf(buf0, "%d", tag);
10212 sprintf(buf, "%d", globalDomainId());
10213 sprintf(buf1, "%d", level_);
10214 preName = buf0;
10215 preName.append("G");
10216 preName.append(buf);
10217 preName.append("_L");
10218 preName.append(buf1);
10219 preName.append("_");
10220 preName.append(m_gridOutputFileName);
10221
10222 preName1 = buf0;
10223 preName1.append("Info");
10224 preName1.append(buf);
10225 preName1.append("_L");
10226 preName1.append(buf1);
10227 preName1.append("_");
10228 preName1.append(m_gridOutputFileName);
10229
10230 size_t size = m_noCells + m_noTotalHaloCells;
10231
10232 // WARNING: untested switch from NetCDF/Parallel netCDF to ParallelIo
10233 // The method previously used direct I/O calls, which were replaced by
10234 // ParallelIo methods in summer 2015. However, since the method was not
10235 // used by any of the testcases, this code is still *untested*. Thus,
10236 // if your code uses this part of the code, please make sure that the
10237 // I/O still works as expected and then remove this warning as well as
10238 // the subsequent TERMM().
10239 TERMM(1, "untested I/O method, please see comment for how to proceed");
10240 ParallelIo parallelIo(preName1.c_str(), maia::parallel_io::PIO_REPLACE, MPI_COMM_SELF);
10241
10242 parallelIo.setAttribute(preName.c_str(), "gridFile");
10243
10244 CartesianNetcdf CN;
10245
10246 MString varnames[5] = {"domainId", "haloCode", "windowCode", "bndCut", "inside"};
10247 MInt type[5] = {PIO_INT, PIO_INT, PIO_INT, PIO_INT, PIO_INT};
10248
10249 parallelIo.defineScalar(PIO_INT, "noCells");
10250
10251 for(MInt i = 0; i < 5; i++) {
10252 parallelIo.defineArray(type[i], varnames[i].c_str(), size);
10253 }
10254
10255 MInt cnt = 0;
10256 MInt s = size;
10257 parallelIo.writeScalar(s, "noCells");
10258
10259 parallelIo.setOffset(size, 0);
10260
10261 vector<vector<MInt>> winCellIdsPerDomain;
10262 vector<vector<MInt>> haloCellIdsPerDomain;
10263 for(MInt d = 0; d < m_noNeighborDomains; d++) {
10264 vector<MInt> c;
10265 winCellIdsPerDomain.push_back(c);
10266 vector<MInt> e;
10267 haloCellIdsPerDomain.push_back(e);
10268 }
10269
10270 // find the halo and window cells for all domains
10271 for(MInt dom = 0; dom < m_noNeighborDomains; dom++) {
10272 // clear all cells
10273 for(MInt i = 0; i < m_noCells; i++)
10274 a_hasProperty(i, 3) = 0;
10275
10276 // collect the halo cells and mark the window cells
10277 for(MInt lev = m_minLevel; lev <= m_maxRfnmntLvl; lev++) {
10278 MInt lev_pos = 2 * (lev - m_minLevel);
10279 for(MInt p = m_haloCellOffsets[dom][lev_pos]; p < m_haloCellOffsets[dom][lev_pos + 1]; p++) {
10280 haloCellIdsPerDomain[dom].push_back(p);
10281 MLong* neigh = &a_neighborId(p, 0);
10282 for(MInt n = 0; n < m_noNeighbors; n++)
10283 if(neigh[n] < m_noCells && neigh[n] > -1) {
10284 a_hasProperty(neigh[n], 3) = 1;
10285 }
10286 }
10287 }
10288
10289 // collect the window cells
10290 for(MInt lev = m_minLevel; lev <= m_maxRfnmntLvl; lev++) {
10291 for(MInt i = m_levelOffsets[lev][0]; i < m_levelOffsets[lev][1]; i++)
10292 if(a_hasProperty(i, 3)) {
10293 winCellIdsPerDomain[dom].push_back(i);
10294 }
10295 }
10296 }
10297
10298 // domainId
10299 {
10300 MFloatScratchSpace tmpVars(size, AT_, "tmpVars");
10301 MInt i = 0;
10302 for(; i < m_noCells; i++)
10303 tmpVars[i] = globalDomainId();
10304 if(noDomains() > 1)
10305 for(MInt k = m_haloCellOffsetsLevel[level_][0]; k < m_maxNoCells - 1; k++, i++)
10306 tmpVars[i] = globalDomainId();
10307 parallelIo.writeArray(tmpVars.getPointer(), varnames[cnt].c_str());
10308 cnt++;
10309 }
10310
10311 // haloCells
10312 {
10313 MFloatScratchSpace tmpVars(size, AT_, "tmpVars");
10314 MInt i = 0;
10315 for(; i < m_noCells; i++)
10316 tmpVars[i] = -1;
10317 if(noDomains() > 1)
10318 for(MInt lev = level_; lev >= m_minLevel; lev--)
10319 for(MInt dom = 0; dom < m_noNeighborDomains; dom++) {
10320 MInt lev_pos = 2 * (lev - m_minLevel);
10321 for(MInt p = m_haloCellOffsets[dom][lev_pos]; p < m_haloCellOffsets[dom][lev_pos + 1]; p++, i++)
10322 tmpVars[i] = m_neighborDomains[dom];
10323 }
10324 parallelIo.writeArray(tmpVars.getPointer(), varnames[cnt].c_str());
10325 cnt++;
10326 }
10327
10328 // windowCells
10329 {
10330 MFloatScratchSpace tmpVars(size, AT_, "tmpVars");
10331 MInt i = 0;
10332 for(; i < m_noCells; i++) {
10333 vector<MInt> doms;
10334 for(MInt dom = 0; dom < m_noNeighborDomains; dom++)
10335 for(MInt k = 0; k < (signed)winCellIdsPerDomain[dom].size(); k++)
10336 if(i == winCellIdsPerDomain[dom][k]) doms.push_back(m_neighborDomains[dom]);
10337
10338 if(doms.size() > 0) {
10339 MInt code = 0;
10340 for(MInt l = 0; l < (signed)doms.size(); l++)
10341 code += doms[l] * pow(10, l);
10342 tmpVars[i] = code;
10343 } else
10344 tmpVars[i] = -1;
10345 }
10346
10347 if(noDomains() > 1)
10348 for(MInt k = m_haloCellOffsetsLevel[level_][0]; k < m_maxNoCells - 1; k++, i++)
10349 tmpVars[i] = -2;
10350
10351 parallelIo.writeArray(tmpVars.getPointer(), varnames[cnt].c_str());
10352 cnt++;
10353 }
10354
10355 // bndCut
10356 {
10357 MFloatScratchSpace tmpVars(size, AT_, "tmpVars");
10358 MInt i = 0;
10359 for(; i < m_noCells; i++)
10360 tmpVars[i] = a_hasProperty(i, 1);
10361 if(noDomains() > 1)
10362 for(MInt k = m_haloCellOffsetsLevel[level_][0]; k < m_maxNoCells - 1; k++, i++)
10363 tmpVars[i] = a_hasProperty(k, 1);
10364 parallelIo.writeArray(tmpVars.getPointer(), varnames[cnt].c_str());
10365 cnt++;
10366 }
10367
10368 // inside
10369 {
10370 MFloatScratchSpace tmpVars(size, AT_, "tmpVars");
10371 MInt i = 0;
10372 for(; i < m_noCells; i++)
10373 tmpVars[i] = a_hasProperty(i, 0);
10374 if(noDomains() > 1)
10375 for(MInt k = m_haloCellOffsetsLevel[level_][0]; k < m_maxNoCells - 1; k++, i++)
10376 tmpVars[i] = a_hasProperty(k, 0);
10377 parallelIo.writeArray(tmpVars.getPointer(), varnames[cnt].c_str());
10378 cnt++;
10379 }
10380}

◆ writeGridInformationPar()

template<MInt nDim>
void GridgenPar< nDim >::writeGridInformationPar
protected
Author
Andreas Lintermann
Date
15.10.2013

This simply puts some data into the cell data, so that the result can be shown in ParaView.

Definition at line 10391 of file cartesiangridgenpar.cpp.

10391 {
10392 TRACE();
10393
10394 outStream << "WRITING INFO FILE" << endl;
10395
10396 // the grid is already finalized for output. The cells are somehow
10397 // mixed up and need to be maped ( smart c&p from saveGrid )
10398
10399 // File creation.
10400 using namespace maia::parallel_io;
10401 // ParallelIo grid ("Info.HDF5", PIO_REPLACE, mpiComm());
10402 ParallelIo grid("out/Info.Netcdf", PIO_REPLACE, mpiComm());
10403
10404 // Creating file header.
10405 grid.defineScalar(PIO_INT, "noCells");
10406 grid.defineArray(PIO_INT, "rfnDistance", m_noTotalCells);
10407 grid.defineArray(PIO_INT, "bndCut", m_noTotalCells);
10408 grid.defineArray(PIO_INT, "domainId", m_noTotalCells);
10409
10410 for(MInt solver = 0; solver < m_noSolvers; solver++) {
10411 stringstream ss;
10412 ss << "solver_" << solver;
10413 grid.defineArray(PIO_INT, ss.str(), m_noTotalCells);
10414 }
10415
10416 for(MInt solver = 0; solver < m_noSolvers; solver++) {
10417 stringstream ss;
10418 ss << "solverBoundary_" << solver;
10419 grid.defineArray(PIO_INT, ss.str(), m_noTotalCells);
10420 }
10421
10422 for(MInt solver = 0; solver < m_noSolvers; solver++) {
10423 stringstream ss;
10424 ss << "toRefine_" << solver;
10425 grid.defineArray(PIO_INT, ss.str(), m_noTotalCells);
10426 }
10427 /*
10428 for(MInt dim = 0; dim < nDim; dim++){
10429 stringstream ss;
10430 ss << "coord_" << dim;
10431 grid.defineArray(PIO_FLOAT, ss.str(),m_noTotalCells);
10432 }
10433 */
10434
10435 grid.setAttribute(m_gridOutputFileName, "gridFile");
10436
10437 MPI_Offset start = -1;
10438 MPI_Offset count = -1;
10439
10440 MInt* tmpScratchInt = 0;
10441
10442 // noCells.
10443 start = 0;
10444 count = 1;
10445 grid.setOffset(count, start);
10446
10447 grid.writeScalar(m_noTotalCells, "noCells");
10448
10449 // Update start and count for parallel writing
10450 if(noDomains() == 1)
10451 start = 0;
10452 else
10453 start = m_cellOffsetPar;
10454 count = m_noCells;
10455
10456 grid.setOffset(count, start);
10457
10458 MIntScratchSpace tmp(m_noCells, AT_, "tmp");
10459 tmpScratchInt = tmp.getPointer();
10460
10461 for(MInt j = 0; j < m_noCells; ++j) {
10462 MLong sortedLocalId = a_globalId(j) - m_cellOffsetPar;
10463 tmpScratchInt[sortedLocalId] = a_refinementDistance(j);
10464 }
10465 grid.writeArray(tmpScratchInt, "rfnDistance");
10466
10467 for(MInt j = 0; j < m_noCells; ++j) {
10468 MLong sortedLocalId = a_globalId(j) - m_cellOffsetPar;
10469 tmpScratchInt[sortedLocalId] = a_hasProperty(j, 1);
10470 }
10471 grid.writeArray(tmpScratchInt, "bndCut");
10472
10473 for(MInt j = 0; j < m_noCells; ++j) {
10474 MLong sortedLocalId = a_globalId(j) - m_cellOffsetPar;
10475 tmpScratchInt[sortedLocalId] = globalDomainId();
10476 }
10477 grid.writeArray(tmpScratchInt, "domainId");
10478
10479 for(MInt solver = 0; solver < m_noSolvers; solver++) {
10480 stringstream ss;
10481 ss << "solver_" << solver;
10482 for(MInt j = 0; j < m_noCells; ++j) {
10483 MLong sortedLocalId = a_globalId(j) - m_cellOffsetPar;
10484 tmpScratchInt[sortedLocalId] = a_isInSolver(j, solver);
10485 }
10486 grid.writeArray(tmpScratchInt, ss.str());
10487 }
10488
10489 for(MInt solver = 0; solver < m_noSolvers; solver++) {
10490 stringstream ss;
10491 ss << "solverBoundary_" << solver;
10492 for(MInt j = 0; j < m_noCells; ++j) {
10493 MLong sortedLocalId = a_globalId(j) - m_cellOffsetPar;
10494 tmpScratchInt[sortedLocalId] = a_isSolverBoundary(j, solver);
10495 }
10496 grid.writeArray(tmpScratchInt, ss.str());
10497 }
10498
10499 for(MInt solver = 0; solver < m_noSolvers; solver++) {
10500 stringstream ss;
10501 ss << "toRefine_" << solver;
10502 for(MInt j = 0; j < m_noCells; ++j) {
10503 MLong sortedLocalId = a_globalId(j) - m_cellOffsetPar;
10504 tmpScratchInt[sortedLocalId] = a_isToRefineForSolver(j, solver);
10505 }
10506 grid.writeArray(tmpScratchInt, ss.str());
10507 }
10508 /*
10509 for(MInt dim = 0; dim < nDim; dim++){
10510 MFloatScratchSpace tmpF(m_noCells, AT_, "tmpF");
10511 MFloat* tmpScratchF = tmpF.getPointer();
10512 stringstream ss;
10513 ss << "coord_" << dim;
10514 for (MInt j = 0; j < m_noCells; ++j){
10515 MLong sortedLocalId = a_globalId(j) - m_cellOffsetPar;
10516 tmpScratchF[sortedLocalId] = a_coordinate(j,dim);
10517 }
10518 grid.writeArray(tmpScratchF, ss.str());
10519 }
10520 */
10521}

◆ writeParallelGeometry()

template<MInt nDim>
void GridgenPar< nDim >::writeParallelGeometry
protected

Definition at line 4928 of file cartesiangridgenpar.cpp.

4928 {
4929 TRACE();
4930
4931 NEW_SUB_TIMER(t_parGeom, "parallel geometry", m_t_updateInterRankNeighbors);
4932 RECORD_TIMER_START(t_parGeom);
4933
4934 vector<MInt> cutting_tris;
4935 MInt noBndCells = 0;
4936 MIntScratchSpace noTrisPerPartitionCell((MInt)m_partitionCellList.size(), AT_, "noTrisPerPartitionCell");
4937
4938 MIntScratchSpace dummyInt(1, AT_, "dummyInt");
4939 MFloatScratchSpace dummyFloat(1, AT_, "dummyFloat");
4940
4941 // loop over all cells (which are already in Hilbert order)
4942 for(MInt i = 0; i < (signed)m_partitionCellList.size(); i++) {
4943 MInt partitionCellId = get<0>(m_partitionCellList[i]);
4944 noTrisPerPartitionCell[i] = 0;
4945
4946 // only use the boundary cells
4947 if(a_hasProperty(partitionCellId, 1)) {
4948 // a. Create target for check
4949 MFloat target[6];
4950 MFloat cellHalfLength = m_lengthOnLevel[a_level(partitionCellId) + 1];
4951
4952 // add 0.5%
4953 cellHalfLength += cellHalfLength * 0.005;
4954
4955 std::vector<MInt> nodeList;
4956
4957 for(MInt j = 0; j < nDim; j++) {
4958 target[j] = a_coordinate(partitionCellId, j) - cellHalfLength;
4959 target[j + nDim] = a_coordinate(partitionCellId, j) + cellHalfLength;
4960 }
4961
4962 // b. Do the intersection test
4963 m_STLgeometry->getIntersectionElements(target, nodeList, cellHalfLength, &a_coordinate(partitionCellId, 0));
4964 const MInt noNodes = (signed)nodeList.size();
4965
4966 noTrisPerPartitionCell[i] = noNodes;
4967
4968 for(MInt t = 0; t < noNodes; t++)
4969 cutting_tris.push_back(nodeList[t]);
4970
4971 noBndCells++;
4972 }
4973 }
4974
4975 MInt sumTris = (MInt)cutting_tris.size();
4976
4977 MIntScratchSpace noTrianglesPerDomain(noDomains(), AT_, "noTrianglesPerDomain");
4978 MPI_Allgather(&sumTris, 1, MPI_INT, noTrianglesPerDomain.getPointer(), 1, MPI_INT, mpiComm(), AT_, "sumTris",
4979 "noTrianglesPerDomain.getPointer()");
4980
4981 MInt noLocalPartitionCells = (MInt)m_partitionCellList.size();
4982 MIntScratchSpace noPartitionCellsPerDomain(noDomains(), AT_, "noPartitionCellsPerDomain");
4983 MPI_Allgather(&noLocalPartitionCells, 1, MPI_INT, noPartitionCellsPerDomain.getPointer(), 1, MPI_INT, mpiComm(), AT_,
4984 "noLocalPartitionCells", "noPartitionCellsPerDomain.getPointer()");
4985
4986 MInt sumAllTris = 0;
4987 MInt sumAllPartitionCells = 0;
4988 for(MInt d = 0; d < noDomains(); d++) {
4989 sumAllTris += noTrianglesPerDomain[d];
4990 sumAllPartitionCells += noPartitionCellsPerDomain[d];
4991 }
4992 MInt myTriOffset = 0;
4993 MInt myPartitionCellOffset = 0;
4994 for(MInt d = 0; d < domainId(); d++) {
4995 myTriOffset += noTrianglesPerDomain[d];
4996 myPartitionCellOffset += noPartitionCellsPerDomain[d];
4997 }
4998
4999 using namespace maia::parallel_io;
5000 ParallelIo geomIO(m_STLgeometry->m_parallelGeomFileName, PIO_REPLACE, mpiComm());
5001
5002 geomIO.defineScalar(PIO_INT, "noTriangles");
5003 geomIO.defineScalar(PIO_INT, "noRealTriangles");
5004 geomIO.defineScalar(PIO_FLOAT, "memIncreaseFactor");
5005 geomIO.defineArray(PIO_INT, "noTrisPerPartitionCell", sumAllPartitionCells);
5006 geomIO.defineArray(PIO_INT, "originalTriId", sumAllTris);
5007 geomIO.defineArray(PIO_INT, "segmentId", sumAllTris);
5008
5009 MString normalNames[3] = {"normals0", "normals1", "normals2"};
5010 for(MInt d = 0; d < nDim; d++)
5011 geomIO.defineArray(PIO_FLOAT, normalNames[d], sumAllTris);
5012
5013 MString vertexNames[3][3] = {{"vertices00", "vertices01", "vertices02"},
5014 {"vertices10", "vertices11", "vertices12"},
5015 {"vertices20", "vertices21", "vertices22"}};
5016 for(MInt v = 0; v < nDim; v++)
5017 for(MInt d = 0; d < nDim; d++)
5018 geomIO.defineArray(PIO_FLOAT, vertexNames[v][d], sumAllTris);
5019
5020 geomIO.writeScalar(sumAllTris, "noTriangles");
5021 geomIO.writeScalar(m_STLgeometry->GetNoElements(), "noRealTriangles");
5022 geomIO.writeScalar((MFloat)(sumAllTris) / ((MFloat)(m_STLgeometry->GetNoElements())), "memIncreaseFactor");
5023
5024 geomIO.setOffset(noLocalPartitionCells, myPartitionCellOffset);
5025 if(noLocalPartitionCells == 0)
5026 geomIO.writeArray(dummyInt.getPointer(), "noTrisPerPartitionCell");
5027 else
5028 geomIO.writeArray(noTrisPerPartitionCell.getPointer(), "noTrisPerPartitionCell");
5029
5030 geomIO.setOffset(sumTris, myTriOffset);
5031 if(sumTris == 0)
5032 geomIO.writeArray(dummyInt.getPointer(), "originalTriId");
5033 else
5034 geomIO.writeArray(cutting_tris.data(), "originalTriId");
5035
5036 {
5037 MIntScratchSpace segmentIdEntry(sumTris, AT_, "segmentIdEntry");
5038 for(MInt i = 0; i < sumTris; i++) {
5039 MInt tri = cutting_tris[i];
5040 segmentIdEntry[i] = m_STLgeometry->elements[tri].m_segmentId;
5041 }
5042 if(sumTris == 0)
5043 geomIO.writeArray(dummyInt.getPointer(), "segmentId");
5044 else
5045 geomIO.writeArray(segmentIdEntry.getPointer(), "segmentId");
5046 }
5047
5048
5049 for(MInt d = 0; d < nDim; d++) {
5050 MFloatScratchSpace normalEntry(sumTris, AT_, "normalEntry");
5051 for(MInt i = 0; i < sumTris; i++) {
5052 MInt tri = cutting_tris[i];
5053 normalEntry[i] = m_STLgeometry->elements[tri].m_normal[d];
5054 }
5055 if(sumTris == 0)
5056 geomIO.writeArray(dummyFloat.getPointer(), normalNames[d]);
5057 else
5058 geomIO.writeArray(normalEntry.getPointer(), normalNames[d]);
5059 }
5060
5061 for(MInt v = 0; v < nDim; v++)
5062 for(MInt d = 0; d < nDim; d++) {
5063 MFloatScratchSpace vertexEntry(sumTris, AT_, "vertexEntry");
5064 for(MInt i = 0; i < sumTris; i++) {
5065 MInt tri = cutting_tris[i];
5066 vertexEntry[i] = m_STLgeometry->elements[tri].m_vertices[v][d];
5067 }
5068 if(sumTris == 0)
5069 geomIO.writeArray(dummyFloat.getPointer(), vertexNames[v][d]);
5070 else
5071 geomIO.writeArray(vertexEntry.getPointer(), vertexNames[v][d]);
5072 }
5073
5074 RECORD_TIMER_STOP(t_parGeom);
5075}

Member Data Documentation

◆ m_bndCutInfo

template<MInt nDim>
MBool** GridgenPar< nDim >::m_bndCutInfo = nullptr
private

Definition at line 333 of file cartesiangridgenpar.h.

◆ m_boundingBox

template<MInt nDim>
MFloat* GridgenPar< nDim >::m_boundingBox = nullptr
private

Definition at line 341 of file cartesiangridgenpar.h.

◆ m_cellIdLUT

template<MInt nDim>
std::map<MInt, MInt> GridgenPar< nDim >::m_cellIdLUT
private

Definition at line 365 of file cartesiangridgenpar.h.

◆ m_cellOffsetPar

template<MInt nDim>
MLong GridgenPar< nDim >::m_cellOffsetPar
private

Definition at line 362 of file cartesiangridgenpar.h.

◆ m_cells

template<MInt nDim>
Collector<GridgenCell<nDim> >* GridgenPar< nDim >::m_cells = nullptr
private

Definition at line 292 of file cartesiangridgenpar.h.

◆ m_centerOfGravity

template<MInt nDim>
MFloat* GridgenPar< nDim >::m_centerOfGravity = nullptr
private

Definition at line 343 of file cartesiangridgenpar.h.

◆ m_checkGridLbValidity

template<MInt nDim>
MBool GridgenPar< nDim >::m_checkGridLbValidity = true
private

Definition at line 308 of file cartesiangridgenpar.h.

◆ m_cutOff

template<MInt nDim>
MBool GridgenPar< nDim >::m_cutOff
private

Definition at line 335 of file cartesiangridgenpar.h.

◆ m_decisiveDirection

template<MInt nDim>
MInt GridgenPar< nDim >::m_decisiveDirection
private

Definition at line 344 of file cartesiangridgenpar.h.

◆ m_domainId

template<MInt nDim>
MInt GridgenPar< nDim >::m_domainId
private

Definition at line 287 of file cartesiangridgenpar.h.

◆ m_geometry

template<MInt nDim>
GeometryRoot* GridgenPar< nDim >::m_geometry = nullptr
private

Definition at line 340 of file cartesiangridgenpar.h.

◆ m_geometryExtents

template<MInt nDim>
MFloat* GridgenPar< nDim >::m_geometryExtents = nullptr
private

Definition at line 342 of file cartesiangridgenpar.h.

◆ m_gridOutputFileName

template<MInt nDim>
MString GridgenPar< nDim >::m_gridOutputFileName
private

Definition at line 326 of file cartesiangridgenpar.h.

◆ m_haloCellOffsets

template<MInt nDim>
MInt** GridgenPar< nDim >::m_haloCellOffsets = nullptr
private

Definition at line 364 of file cartesiangridgenpar.h.

◆ m_haloCellOffsetsLevel

template<MInt nDim>
MInt** GridgenPar< nDim >::m_haloCellOffsetsLevel = nullptr
private

Definition at line 361 of file cartesiangridgenpar.h.

◆ m_hasBeenLoadBalanced

template<MInt nDim>
MBool GridgenPar< nDim >::m_hasBeenLoadBalanced
private

Definition at line 383 of file cartesiangridgenpar.h.

◆ m_hasMultiSolverBoundingBox

template<MInt nDim>
MBool GridgenPar< nDim >::m_hasMultiSolverBoundingBox = false
private

Definition at line 318 of file cartesiangridgenpar.h.

◆ m_initialRefinementLevelSerial

template<MInt nDim>
MInt GridgenPar< nDim >::m_initialRefinementLevelSerial
private

Definition at line 298 of file cartesiangridgenpar.h.

◆ m_keepOutsideBndryCellChildren

template<MInt nDim>
MInt GridgenPar< nDim >::m_keepOutsideBndryCellChildren
private

Definition at line 314 of file cartesiangridgenpar.h.

◆ m_lengthOnLevel

template<MInt nDim>
MFloat* GridgenPar< nDim >::m_lengthOnLevel = nullptr
private

Definition at line 345 of file cartesiangridgenpar.h.

◆ m_levelOffsets

template<MInt nDim>
MInt** GridgenPar< nDim >::m_levelOffsets = nullptr
private

Definition at line 347 of file cartesiangridgenpar.h.

◆ m_maxLevels

template<MInt nDim>
MInt GridgenPar< nDim >::m_maxLevels
private

Definition at line 325 of file cartesiangridgenpar.h.

◆ m_maxNoCells

template<MInt nDim>
MInt GridgenPar< nDim >::m_maxNoCells
private

Definition at line 324 of file cartesiangridgenpar.h.

◆ m_maxNoChildren

template<MInt nDim>
MInt GridgenPar< nDim >::m_maxNoChildren
private

Definition at line 348 of file cartesiangridgenpar.h.

◆ m_maxRfnmntLvl

template<MInt nDim>
MInt GridgenPar< nDim >::m_maxRfnmntLvl
private

Definition at line 302 of file cartesiangridgenpar.h.

◆ m_maxUniformRefinementLevel

template<MInt nDim>
MInt GridgenPar< nDim >::m_maxUniformRefinementLevel
private

Definition at line 301 of file cartesiangridgenpar.h.

◆ m_minLevel

template<MInt nDim>
MInt GridgenPar< nDim >::m_minLevel
private

Definition at line 299 of file cartesiangridgenpar.h.

◆ m_mpiComm

template<MInt nDim>
const MPI_Comm GridgenPar< nDim >::m_mpiComm
private

Definition at line 286 of file cartesiangridgenpar.h.

◆ m_multiSolverBoundingBox

template<MInt nDim>
std::vector<MFloat> GridgenPar< nDim >::m_multiSolverBoundingBox {}
private

Definition at line 319 of file cartesiangridgenpar.h.

◆ m_multiSolverCenterOfGravity

template<MInt nDim>
std::vector<MFloat> GridgenPar< nDim >::m_multiSolverCenterOfGravity {}
private

Definition at line 322 of file cartesiangridgenpar.h.

◆ m_multiSolverLengthLevel0

template<MInt nDim>
MFloat GridgenPar< nDim >::m_multiSolverLengthLevel0 = -1.0
private

Definition at line 321 of file cartesiangridgenpar.h.

◆ m_multiSolverMinLevel

template<MInt nDim>
MInt GridgenPar< nDim >::m_multiSolverMinLevel = -1
private

Definition at line 320 of file cartesiangridgenpar.h.

◆ m_neighborDomains

template<MInt nDim>
MInt* GridgenPar< nDim >::m_neighborDomains = nullptr
private

Definition at line 360 of file cartesiangridgenpar.h.

◆ m_noBndIdsPerSolver

template<MInt nDim>
MInt* GridgenPar< nDim >::m_noBndIdsPerSolver = nullptr
private

Definition at line 332 of file cartesiangridgenpar.h.

◆ m_noCells

template<MInt nDim>
MInt GridgenPar< nDim >::m_noCells
private

Definition at line 294 of file cartesiangridgenpar.h.

◆ m_noCellsPerDomain

template<MInt nDim>
MInt* GridgenPar< nDim >::m_noCellsPerDomain = nullptr
private

Definition at line 356 of file cartesiangridgenpar.h.

◆ m_noDomains

template<MInt nDim>
MInt GridgenPar< nDim >::m_noDomains
private

Definition at line 288 of file cartesiangridgenpar.h.

◆ m_noHaloCellsOnLevel

template<MInt nDim>
MInt* GridgenPar< nDim >::m_noHaloCellsOnLevel = nullptr
private

Definition at line 358 of file cartesiangridgenpar.h.

◆ m_noMissingParents

template<MInt nDim>
MInt GridgenPar< nDim >::m_noMissingParents
private

Definition at line 382 of file cartesiangridgenpar.h.

◆ m_noNeighborDomains

template<MInt nDim>
MInt GridgenPar< nDim >::m_noNeighborDomains
private

Definition at line 359 of file cartesiangridgenpar.h.

◆ m_noNeighbors

template<MInt nDim>
MInt GridgenPar< nDim >::m_noNeighbors
private

Definition at line 349 of file cartesiangridgenpar.h.

◆ m_noPartitionCells

template<MInt nDim>
MInt GridgenPar< nDim >::m_noPartitionCells
private

Definition at line 352 of file cartesiangridgenpar.h.

◆ m_noPartitionCellsPerDomain

template<MInt nDim>
MInt* GridgenPar< nDim >::m_noPartitionCellsPerDomain = nullptr
private

Definition at line 357 of file cartesiangridgenpar.h.

◆ m_noSolidLayer

template<MInt nDim>
MInt* GridgenPar< nDim >::m_noSolidLayer = nullptr
private

Definition at line 315 of file cartesiangridgenpar.h.

◆ m_noSolvers

template<MInt nDim>
MInt GridgenPar< nDim >::m_noSolvers
private

Definition at line 331 of file cartesiangridgenpar.h.

◆ m_noTotalCells

template<MInt nDim>
MLong GridgenPar< nDim >::m_noTotalCells
private

Definition at line 351 of file cartesiangridgenpar.h.

◆ m_noTotalHaloCells

template<MInt nDim>
MInt GridgenPar< nDim >::m_noTotalHaloCells
private

Definition at line 354 of file cartesiangridgenpar.h.

◆ m_noTotalPartitionCells

template<MInt nDim>
MLong GridgenPar< nDim >::m_noTotalPartitionCells
private

Definition at line 353 of file cartesiangridgenpar.h.

◆ m_outputDir

template<MInt nDim>
MString GridgenPar< nDim >::m_outputDir = ""
private

Definition at line 312 of file cartesiangridgenpar.h.

◆ m_parallelGeomFileName

template<MInt nDim>
MString GridgenPar< nDim >::m_parallelGeomFileName
private

Definition at line 337 of file cartesiangridgenpar.h.

◆ m_partitionCellList

template<MInt nDim>
std::vector<std::tuple<MInt, MLong, MFloat> > GridgenPar< nDim >::m_partitionCellList
private

Definition at line 355 of file cartesiangridgenpar.h.

◆ m_partitionCellOffspringThreshold

template<MInt nDim>
MLong GridgenPar< nDim >::m_partitionCellOffspringThreshold
private

Definition at line 295 of file cartesiangridgenpar.h.

◆ m_partitionCellWorkloadThreshold

template<MInt nDim>
MFloat GridgenPar< nDim >::m_partitionCellWorkloadThreshold
private

Definition at line 296 of file cartesiangridgenpar.h.

◆ m_pCells

template<MInt nDim>
GridgenCell<nDim>* GridgenPar< nDim >::m_pCells = nullptr
private

Definition at line 293 of file cartesiangridgenpar.h.

◆ m_reductionFactor

template<MInt nDim>
MFloat GridgenPar< nDim >::m_reductionFactor
private

Definition at line 310 of file cartesiangridgenpar.h.

◆ m_rfnCount

template<MInt nDim>
MInt GridgenPar< nDim >::m_rfnCount
private

Definition at line 327 of file cartesiangridgenpar.h.

◆ m_rfnCountHalos

template<MInt nDim>
MInt GridgenPar< nDim >::m_rfnCountHalos
private

Definition at line 328 of file cartesiangridgenpar.h.

◆ m_rfnCountHalosDom

template<MInt nDim>
MInt* GridgenPar< nDim >::m_rfnCountHalosDom = nullptr
private

Definition at line 329 of file cartesiangridgenpar.h.

◆ m_solverRefinement

template<MInt nDim>
SolverRefinement* GridgenPar< nDim >::m_solverRefinement = nullptr
private

Definition at line 300 of file cartesiangridgenpar.h.

◆ m_STLgeometry

template<MInt nDim>
Geometry<nDim>* GridgenPar< nDim >::m_STLgeometry
private

Definition at line 339 of file cartesiangridgenpar.h.

◆ m_t_comp_GG

template<MInt nDim>
MInt GridgenPar< nDim >::m_t_comp_GG = -1
private

Definition at line 369 of file cartesiangridgenpar.h.

◆ m_t_createComputationalGrid

template<MInt nDim>
MInt GridgenPar< nDim >::m_t_createComputationalGrid = -1
private

Definition at line 376 of file cartesiangridgenpar.h.

◆ m_t_createInitialGrid

template<MInt nDim>
MInt GridgenPar< nDim >::m_t_createInitialGrid = -1
private

Definition at line 373 of file cartesiangridgenpar.h.

◆ m_t_createStartGrid

template<MInt nDim>
MInt GridgenPar< nDim >::m_t_createStartGrid = -1
private

Definition at line 375 of file cartesiangridgenpar.h.

◆ m_t_finalizeGrid

template<MInt nDim>
MInt GridgenPar< nDim >::m_t_finalizeGrid = -1
private

Definition at line 377 of file cartesiangridgenpar.h.

◆ m_t_initGeometry

template<MInt nDim>
MInt GridgenPar< nDim >::m_t_initGeometry = -1
private

Definition at line 372 of file cartesiangridgenpar.h.

◆ m_t_initMembers

template<MInt nDim>
MInt GridgenPar< nDim >::m_t_initMembers = -1
private

Definition at line 371 of file cartesiangridgenpar.h.

◆ m_t_parallelizeGrid

template<MInt nDim>
MInt GridgenPar< nDim >::m_t_parallelizeGrid = -1
private

Definition at line 374 of file cartesiangridgenpar.h.

◆ m_t_readProperties

template<MInt nDim>
MInt GridgenPar< nDim >::m_t_readProperties = -1
private

Definition at line 370 of file cartesiangridgenpar.h.

◆ m_t_saveGrid

template<MInt nDim>
MInt GridgenPar< nDim >::m_t_saveGrid = -1
private

Definition at line 378 of file cartesiangridgenpar.h.

◆ m_t_updateInterRankNeighbors

template<MInt nDim>
MInt GridgenPar< nDim >::m_t_updateInterRankNeighbors = -1
private

Definition at line 379 of file cartesiangridgenpar.h.

◆ m_targetGridFileName

template<MInt nDim>
MString GridgenPar< nDim >::m_targetGridFileName = ""
private

Definition at line 311 of file cartesiangridgenpar.h.

◆ m_weightBndCells

template<MInt nDim>
MInt GridgenPar< nDim >::m_weightBndCells
private

Definition at line 304 of file cartesiangridgenpar.h.

◆ m_weightMethod

template<MInt nDim>
MInt GridgenPar< nDim >::m_weightMethod
private

Definition at line 303 of file cartesiangridgenpar.h.

◆ m_weightPatchCells

template<MInt nDim>
MInt GridgenPar< nDim >::m_weightPatchCells
private

Definition at line 305 of file cartesiangridgenpar.h.

◆ m_weightSolverUniformLevel

template<MInt nDim>
MBool GridgenPar< nDim >::m_weightSolverUniformLevel
private

Definition at line 306 of file cartesiangridgenpar.h.

◆ m_writeCoordinatesToGridFile

template<MInt nDim>
MBool GridgenPar< nDim >::m_writeCoordinatesToGridFile = false
private

Definition at line 313 of file cartesiangridgenpar.h.

◆ m_writeGridInformation

template<MInt nDim>
MBool GridgenPar< nDim >::m_writeGridInformation
private

Definition at line 307 of file cartesiangridgenpar.h.

◆ outStream

template<MInt nDim>
std::ostream GridgenPar< nDim >::outStream
private

Definition at line 290 of file cartesiangridgenpar.h.


The documentation for this class was generated from the following files: