29 const MInt noDomains_)
30 : m_noBlocks(noBlocks_),
32 m_noDomains(noDomains_),
34 m_eps(std::numeric_limits<
MFloat>::epsilon()) {
47 MString sBlockName =
"/block" + std::to_string(i);
48 std::vector<ParallelIo::size_type> tmp(nDim, 0);
50 std::copy(tmp.begin(), tmp.end(), &dataSetSize[i * nDim]);
66 for(
MInt j = 0; j < nDim; j++) {
67 m_blockInfo[i]->size[j] = dataSetSize[i * nDim + j] - 1;
88 const MInt noDomains_)
89 : m_noBlocks(noBlocks_),
91 m_noDomains(noDomains_),
93 m_eps(std::numeric_limits<
MFloat>::epsilon()) {
98 ParallelIo::size_type ijk_max[3] = {0};
101 MString sBlockName =
"/block" + std::to_string(i);
105 for(
MInt j = 0; j < nDim; j++) {
129 const MInt (&level2dimension1D)[nDim],
130 MInt& partitionCounter,
131 MInt (&beginPartitionHelper)[nDim],
132 MInt (&endPartitionHelper)[nDim],
133 MInt (&divisor)[nDim]) {
135 MInt beginBlock[nDim]{0};
136 MInt endBlock[nDim]{0};
138 divisor[level2dimension1D[treePointer->
level]] = treePointer->
noLeaves;
140 if(treePointer->
level < (nDim - 1)) {
141 beginPartitionHelper[level2dimension1D[treePointer->
level]] = 0;
144 beginPartitionHelper[level2dimension1D[treePointer->
level]] =
145 beginPartitionHelper[level2dimension1D[treePointer->
level]] + treePointer->
childs[i - 1]->
noLeaves;
147 endPartitionHelper[level2dimension1D[treePointer->
level]] =
148 beginPartitionHelper[level2dimension1D[treePointer->
level]] + treePointer->
childs[i]->
noLeaves;
149 myTreePointer = treePointer->
childs[i];
150 setPartitionInfoHelper(myTreePointer, blockId, level2dimension1D, partitionCounter, beginPartitionHelper,
151 endPartitionHelper, divisor);
155 beginPartitionHelper[level2dimension1D[treePointer->
level]] = i;
156 endPartitionHelper[level2dimension1D[treePointer->
level]] = i + 1;
157 for(
MInt j = 0; j < nDim; j++) {
158 beginBlock[j] = rounding(((
MFloat)m_blockInfo[blockId]->size[j]) * ((
MFloat)beginPartitionHelper[j])
161 rounding(((
MFloat)m_blockInfo[blockId]->size[j]) * ((
MFloat)endPartitionHelper[j]) / ((
MFloat)divisor[j]));
163 m_partitionInfo[partitionCounter]->weight = m_blockInfo[blockId]->weight;
164 m_partitionInfo[partitionCounter]->totalSize = 1;
166 for(
MInt j = 0; j < nDim; j++) {
167 m_partitionInfo[partitionCounter]->size[j] = endBlock[j] - beginBlock[j] + 1;
168 m_partitionInfo[partitionCounter]->totalSize *= (m_partitionInfo[partitionCounter]->size[j]);
169 m_partitionInfo[partitionCounter]->offset[j] = beginBlock[j];
172 m_partitionInfo[partitionCounter]->blockId = blockId;
173 m_partitionInfo[partitionCounter]->partitionId = partitionCounter;
187 MInt beginPartitionHelper[nDim]{0};
188 MInt endPartitionHelper[nDim]{0};
189 MInt divisor[nDim]{0};
191 m_partitionInfo.clear();
192 for(
MInt j = 0; j < m_noPartitions; j++) {
196 MInt partitionCounter = 0;
197 for(
MInt i = 0; i < m_noBlocks; i++) {
198 myTreeRootPointer = treeRoot[i];
199 MInt level2dimension1D[nDim]{0};
201 for(
MInt j = 0; j < nDim; j++) {
202 level2dimension1D[j] = level2dimension(j, i);
205 setPartitionInfoHelper(myTreeRootPointer, i, level2dimension1D, partitionCounter, beginPartitionHelper,
206 endPartitionHelper, divisor);
218 const MInt (&level2dimension1D)[nDim],
225 * ((
MFloat)m_blockInfo[blockId]->size[level2dimension1D[insertTreePointer->
level]] + 1.0))
227 * ((
MFloat)m_blockInfo[blockId]->size[level2dimension1D[treePointer->
level]] + 1.0)))
229 * ((
MFloat)(m_blockInfo[blockId]->size[level2dimension1D[insertTreePointer->
level]]) + 1.0)),
231 * ((
MFloat)(m_blockInfo[blockId]->size[level2dimension1D[treePointer->
level]]) + 1.0)),
233 && (treePointer->
level < insertTreePointer->
level))) {
234 insertTreePointer = treePointer;
237 if(treePointer->
level < (nDim - 1)) {
239 myTreePointer = treePointer->
childs[0];
242 myTreePointer = treePointer->
childs[i];
247 traverseForInsertionNode(myTreePointer, blockId, level2dimension1D, insertTreePointer);
258 if(treePointer->
level < (nDim - 1)) {
263 for(
MInt countChild = 0; countChild < treePointer->
noChilds; countChild++) {
266 initializeChilds(myTreePointer);
277 if(treePointer->
level < (nDim - 1)) {
280 destroyChilds(myTreePointer);
282 delete[] treePointer->
childs;
296 if(treePointer->
level < (nDim - 1)) {
299 myTreePointer = treePointer->
childs[i];
300 sumLeaf += sumLeaves(myTreePointer);
318 const MInt (&level2dimension1D)[nDim]) {
319 destroyChilds(insertTreePointer);
322 initializeChilds(insertTreePointer);
324 if(insertTreePointer->
level < (nDim - 1)) {
325 for(
MInt i = insertTreePointer->
noChilds + 1; i <= myNoLeaves; i++) {
326 treeNode* myInsertTreePointer = insertTreePointer;
327 traverseForInsertionNode(insertTreePointer, blockId, level2dimension1D, myInsertTreePointer);
328 insertChildAtNode(myInsertTreePointer, blockId, level2dimension1D);
329 insertTreePointer->
noLeaves = sumLeaves(insertTreePointer);
344 for(
MInt i = 0; i < m_noPartitions; i++) {
345 const MLongFloat weightedSize = m_partitionInfo[i]->totalSize * m_partitionInfo[i]->weight;
346 if(weightedSize > maxWeightedSize) {
347 blockId = m_partitionInfo[i]->blockId;
348 maxWeightedSize = weightedSize;
353 treeNode* myTreeRootPointer = treeRoot[blockId];
354 treeNode* myInsertTreePointer = treeRoot[blockId];
357 MInt level2dimension1D[nDim];
358 for(
MInt i = 0; i < nDim; i++) {
359 level2dimension1D[i] = level2dimension(i, blockId);
363 traverseForInsertionNode(myTreeRootPointer, blockId, level2dimension1D, myInsertTreePointer);
364 insertChildAtNode(myInsertTreePointer, blockId, level2dimension1D);
365 myTreeRootPointer->
noLeaves = sumLeaves(myTreeRootPointer);
369 setPartitionInfo(treeRoot, level2dimension);
380 m_noPartitions = m_noBlocks;
381 myTreeRoot =
new treeNode*[m_noBlocks];
384 for(
MInt i = 0; i < m_noBlocks; i++) {
388 for(countBlock = 0; countBlock < m_noBlocks; countBlock++) {
389 myTreeRootPointer = myTreeRoot[countBlock];
390 initializeChilds(myTreeRootPointer);
394 MIntScratchSpace level2dimensionA(nDim, m_noBlocks, AT_,
"level2dimensionA");
395 level2dimensionA.
fill(0);
397 for(
MInt k = 0; k < m_noBlocks; k++) {
398 std::vector<std::pair<MInt, MInt>> dummy{};
399 for(
MInt i = 0; i < nDim; i++) {
400 dummy.push_back({m_blockInfo[k]->size[i], i});
403 std::sort(dummy.begin(), dummy.end(), [](
auto& left,
auto& right) { return left.first > right.first; });
404 for(
MInt i = 0; i < nDim; i++) {
405 level2dimensionA(i, k) = dummy[i].second;
409 setPartitionInfo(myTreeRoot, level2dimensionA);
412 while(m_noPartitions < m_noDomains) {
413 addLeaf(myTreeRoot, level2dimensionA);
417 for(
MInt i = 0; i < m_noBlocks; i++) {
418 myTreeRootPointer = myTreeRoot[i];
419 destroyChilds(myTreeRootPointer);
422 for(
MInt j = 0; j < m_noBlocks; j++) {
423 delete myTreeRoot[j];
436 MIntScratchSpace filePartitionInfo((3 + 3 + 4) * m_noDomains,
"filePartitionInfo", AT_);
437 filePartitionInfo.
fill(0);
446 MPI_Bcast(&noCPUs, 1, MPI_INT, 0, m_mpiComm, AT_,
"noCPUs");
447 if(noCPUs != m_noDomains) {
448 m_log <<
"WARNING no CPUs is not equal to ones given in partitionFile" << endl;
455 ParallelIo::size_type asize[2] = {noCPUs, 10};
460 "filePartitionInfo.getPointer()");
462 m_noPartitions = noCPUs;
463 for(
MInt j = 0; j < m_noPartitions; j++) {
468 for(
MInt j = 0; j < m_noPartitions; j++) {
469 for(
MInt dim = 0; dim < nDim; dim++) {
470 m_partitionInfo[j]->size[dim] = filePartitionInfo[j * 10 + dim];
471 m_partitionInfo[j]->offset[dim] = filePartitionInfo[j * 10 + 3 + dim];
474 m_partitionInfo[j]->blockId = filePartitionInfo[j * 10 + 6];
475 m_partitionInfo[j]->partitionId = filePartitionInfo[j * 10 + 7];
476 m_partitionInfo[j]->cpu = filePartitionInfo[j * 10 + 8];
477 m_partitionInfo[j]->totalSize = filePartitionInfo[j * 10 + 9];
486 ((x - floor(x)) >= 0.5) ?
a = ceil(x) :
a = floor(x);
void getAttribute(T *value, const MString &name, const MString &datasetName="")
Retrieve a file or dataset attribute.
MBool hasAttribute(const MString &name, const MString &path="")
Check if a given attribute exists in the file.
size_type getArraySize(const MString &name, const size_type dimensionId=0)
Get the length of an array in the file.
void readArray(T *array, const MString &name, size_type memoryStride=-1, size_type diskStride=-1)
Read array data from file. [MPI]
This class is a ScratchSpace.
T * getPointer() const
Deprecated: use begin() instead!
void fill(T val)
fill the scratch with a given value
Class for the decomposition (partition) of structured grids.
MBool readFromFile()
Read a precomputed partition info from an external file.
MInt sumLeaves(treeNode *&treePointer)
Compute the number of leaves of a tree nodes.
void addLeaf(treeNode **&treeRoot, MIntScratchSpace &level2dimension)
Add a leaf into the tree.
void decompose()
Decompose the grid into partitions for the set number of domains.
std::vector< std::unique_ptr< PartitionInfo< nDim > > > m_blockInfo
StructuredDecomposition(const MInt, const MString, MPI_Comm, const MInt)
Constructor for HDF5 grid file name Reads the size of the coordinate datasets for all blocks.
void destroyChilds(treeNode *&treePointer)
Recursively destroy all childs of a tree node.
void setPartitionInfo(treeNode **&, MIntScratchSpace &)
Computes partition information from given BCT.
void insertChildAtNode(treeNode *&, const MInt, const MInt(&)[nDim])
Inserts new child node below given tree node.
void traverseForInsertionNode(treeNode *&treePointer, const MInt, const MInt(&)[nDim], treeNode *&)
Recursively traverses the given tree to find the next insertion position.
void initializeChilds(treeNode *&treePointer)
Initializes the childs of the given tree node.
void setPartitionInfoHelper(treeNode *&, const MInt, const MInt(&)[nDim], MInt &, MInt(&)[nDim], MInt(&)[nDim], MInt(&)[nDim])
Helper function for setPartionInfo.
MBool approx(const T &, const U &, const T)
MInt globalDomainId()
Return global domain id.
std::basic_string< char > MString
int MPI_Bcast(void *buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm, const MString &name, const MString &varname)
same as MPI_Bcast