| 1 | /**
|
|---|
| 2 | * @file domain_decomposition_mpi.cpp
|
|---|
| 3 | * @author Julian Iseringhausen <isering@ins.uni-bonn.de>
|
|---|
| 4 | * @date Mon Jun 27 12:53:50 2011
|
|---|
| 5 | *
|
|---|
| 6 | * @brief Computes a domain decomposition which separates
|
|---|
| 7 | * the finest grid equally for all processes.
|
|---|
| 8 | *
|
|---|
| 9 | */
|
|---|
| 10 |
|
|---|
| 11 | #ifdef HAVE_CONFIG_H
|
|---|
| 12 | #include <config.h>
|
|---|
| 13 | #endif
|
|---|
| 14 |
|
|---|
| 15 | #include "comm/comm.hpp"
|
|---|
| 16 | #include "comm/domain_decomposition_mpi.hpp"
|
|---|
| 17 | #include "grid/grid.hpp"
|
|---|
| 18 | #include "grid/multigrid.hpp"
|
|---|
| 19 | #include "interface/interface.hpp"
|
|---|
| 20 |
|
|---|
| 21 | using namespace VMG;
|
|---|
| 22 |
|
|---|
| 23 | void DomainDecompositionMPI::Compute(Comm* comm, const Interface* interface, std::vector<GlobalIndices>& global)
|
|---|
| 24 | {
|
|---|
| 25 | GlobalIndices global_l;
|
|---|
| 26 | Index remainder, procs;
|
|---|
| 27 | Index begin_finest, end_finest;
|
|---|
| 28 | Index last_procs = comm->GlobalProcs();
|
|---|
| 29 |
|
|---|
| 30 | global.clear();
|
|---|
| 31 |
|
|---|
| 32 | for (unsigned int i=0; i<interface->Global().size(); ++i) {
|
|---|
| 33 |
|
|---|
| 34 | global_l.BeginFinest() = interface->Global()[i].BeginFinest();
|
|---|
| 35 | global_l.EndFinest() = interface->Global()[i].EndFinest();
|
|---|
| 36 | global_l.SizeFinest() = interface->Global()[i].SizeFinest();
|
|---|
| 37 | global_l.SizeGlobal() = interface->Global()[i].SizeGlobal();
|
|---|
| 38 |
|
|---|
| 39 | global_l.BoundaryType() = interface->Global()[i].BoundaryType();
|
|---|
| 40 |
|
|---|
| 41 | if (IsActive(comm, global_l.SizeGlobal(), procs)) {
|
|---|
| 42 |
|
|---|
| 43 | if (i == 0) {
|
|---|
| 44 |
|
|---|
| 45 | global_l.SizeLocal() = global_l.SizeGlobal() / procs;
|
|---|
| 46 | remainder = global_l.SizeGlobal() % procs;
|
|---|
| 47 |
|
|---|
| 48 | for (int j=0; j<3; ++j)
|
|---|
| 49 | if (comm->GlobalPos()[j] < remainder[j])
|
|---|
| 50 | ++(global_l.SizeLocal()[j]);
|
|---|
| 51 |
|
|---|
| 52 | global_l.BeginLocal() = comm->GlobalPos() * global_l.SizeLocal();
|
|---|
| 53 |
|
|---|
| 54 | for (int j=0; j<3; ++j)
|
|---|
| 55 | if (comm->GlobalPos()[j] >= remainder[j])
|
|---|
| 56 | global_l.BeginLocal()[j] += remainder[j];
|
|---|
| 57 |
|
|---|
| 58 | global_l.EndLocal() = global_l.BeginLocal() + global_l.SizeLocal();
|
|---|
| 59 |
|
|---|
| 60 | }else {
|
|---|
| 61 |
|
|---|
| 62 | for (int j=0; j<3; ++j) {
|
|---|
| 63 |
|
|---|
| 64 | if (procs[j] == last_procs[j]) {
|
|---|
| 65 |
|
|---|
| 66 | begin_finest[j] = (global.back().BeginFinest() +
|
|---|
| 67 | GridIndexTranslations::GlobalToFiner(global.back().BeginLocal(), i-1))[j];
|
|---|
| 68 | end_finest[j] = (global.back().BeginFinest() +
|
|---|
| 69 | GridIndexTranslations::GlobalToFiner(global.back().EndLocal(), i-1))[j];
|
|---|
| 70 |
|
|---|
| 71 | if (global.back().BeginLocal()[j] == 0)
|
|---|
| 72 | begin_finest[j] = global_l.BeginFinest()[j];
|
|---|
| 73 |
|
|---|
| 74 | if (global.back().EndLocal()[j] == global.back().SizeGlobal()[j])
|
|---|
| 75 | end_finest[j] = global_l.EndFinest()[j];
|
|---|
| 76 |
|
|---|
| 77 | begin_finest[j] -= global_l.BeginFinest()[j];
|
|---|
| 78 | end_finest[j] -= global_l.BeginFinest()[j];
|
|---|
| 79 |
|
|---|
| 80 | FineToCoarse(comm, begin_finest[j], end_finest[j], i);
|
|---|
| 81 |
|
|---|
| 82 | global_l.BeginLocal()[j] = begin_finest[j];
|
|---|
| 83 | global_l.EndLocal()[j] = end_finest[j];
|
|---|
| 84 | global_l.SizeLocal()[j] = end_finest[j] - begin_finest[j];
|
|---|
| 85 |
|
|---|
| 86 | }else {
|
|---|
| 87 |
|
|---|
| 88 | global_l.SizeLocal()[j] = global_l.SizeGlobal()[j] / procs[j];
|
|---|
| 89 | remainder[j] = global_l.SizeGlobal()[j] % procs[j];
|
|---|
| 90 |
|
|---|
| 91 |
|
|---|
| 92 | if (comm->GlobalPos()[j] < remainder[j])
|
|---|
| 93 | ++(global_l.SizeLocal()[j]);
|
|---|
| 94 |
|
|---|
| 95 | global_l.BeginLocal()[j] = comm->GlobalPos()[j] * global_l.SizeLocal()[j];
|
|---|
| 96 |
|
|---|
| 97 |
|
|---|
| 98 | if (comm->GlobalPos()[j] >= remainder[j])
|
|---|
| 99 | global_l.BeginLocal()[j] += remainder[j];
|
|---|
| 100 |
|
|---|
| 101 | global_l.EndLocal()[j] = global_l.BeginLocal()[j] + global_l.SizeLocal()[j];
|
|---|
| 102 |
|
|---|
| 103 | }
|
|---|
| 104 | }
|
|---|
| 105 | }
|
|---|
| 106 | }else {
|
|---|
| 107 |
|
|---|
| 108 | global_l.BeginLocal() = 0;
|
|---|
| 109 | global_l.EndLocal() = 0;
|
|---|
| 110 | global_l.SizeLocal() = 0;
|
|---|
| 111 |
|
|---|
| 112 | }
|
|---|
| 113 |
|
|---|
| 114 | last_procs = procs;
|
|---|
| 115 |
|
|---|
| 116 | global.push_back(global_l);
|
|---|
| 117 |
|
|---|
| 118 | }
|
|---|
| 119 | }
|
|---|
| 120 |
|
|---|
| 121 | bool DomainDecompositionMPI::IsActive(Comm* comm, const Index& size_global, Index& procs)
|
|---|
| 122 | {
|
|---|
| 123 | bool is_active = true;
|
|---|
| 124 | const int points_min = 5;
|
|---|
| 125 |
|
|---|
| 126 | procs = size_global / points_min + 1;
|
|---|
| 127 |
|
|---|
| 128 | for (int i=0; i<3; ++i) {
|
|---|
| 129 | procs[i] = std::min(procs[i], comm->GlobalProcs()[i]);
|
|---|
| 130 | is_active &= comm->GlobalPos()[i] < procs[i];
|
|---|
| 131 | }
|
|---|
| 132 |
|
|---|
| 133 | return is_active;
|
|---|
| 134 | }
|
|---|
| 135 |
|
|---|
| 136 | void DomainDecompositionMPI::FineToCoarse(Comm* comm, int& begin, int& end, int levels)
|
|---|
| 137 | {
|
|---|
| 138 | int last_point = end - 1;
|
|---|
| 139 |
|
|---|
| 140 | for (int i=0; i<levels; ++i) {
|
|---|
| 141 |
|
|---|
| 142 | if (begin % 2 == 0)
|
|---|
| 143 | begin /= 2;
|
|---|
| 144 | else
|
|---|
| 145 | begin = (begin+1) / 2;
|
|---|
| 146 |
|
|---|
| 147 | if (last_point % 2 == 0)
|
|---|
| 148 | last_point /= 2;
|
|---|
| 149 | else
|
|---|
| 150 | last_point = (last_point-1) / 2;
|
|---|
| 151 |
|
|---|
| 152 | }
|
|---|
| 153 |
|
|---|
| 154 | end = last_point + 1;
|
|---|
| 155 | }
|
|---|