| 1 | /**
|
|---|
| 2 | * @file multigrid.cpp
|
|---|
| 3 | * @author Julian Iseringhausen <isering@ins.uni-bonn.de>
|
|---|
| 4 | * @date Mon Apr 18 12:54:37 2011
|
|---|
| 5 | *
|
|---|
| 6 | * @brief VMG::Multigrid
|
|---|
| 7 | *
|
|---|
| 8 | */
|
|---|
| 9 |
|
|---|
| 10 | #ifdef HAVE_CONFIG_H
|
|---|
| 11 | #include <config.h>
|
|---|
| 12 | #endif
|
|---|
| 13 |
|
|---|
| 14 | #include "base/helper.hpp"
|
|---|
| 15 | #include "base/index.hpp"
|
|---|
| 16 | #include "comm/comm.hpp"
|
|---|
| 17 | #include "grid/grid.hpp"
|
|---|
| 18 | #include "grid/grid_indexing.hpp"
|
|---|
| 19 | #include "grid/multigrid.hpp"
|
|---|
| 20 | #include "interface/interface.hpp"
|
|---|
| 21 |
|
|---|
| 22 | using namespace VMG;
|
|---|
| 23 |
|
|---|
| 24 | Multigrid::Multigrid(Comm* comm, const Interface* interface)
|
|---|
| 25 | {
|
|---|
| 26 | bool active;
|
|---|
| 27 | Index points, remainder;
|
|---|
| 28 | Index procs_l;
|
|---|
| 29 | LocalIndices local_l;
|
|---|
| 30 | GlobalIndices global_l;
|
|---|
| 31 |
|
|---|
| 32 | const Index& pos = comm->Pos();
|
|---|
| 33 | const Index& procs = comm->Procs();
|
|---|
| 34 | const Index points_min = 5 * procs;
|
|---|
| 35 | const std::vector<GlobalIndices>& global = interface->Global();
|
|---|
| 36 | const std::vector<SpatialExtent>& extent = interface->Extent();
|
|---|
| 37 |
|
|---|
| 38 | for (unsigned int i=0; i<global.size(); ++i) {
|
|---|
| 39 |
|
|---|
| 40 | procs_l = global[i].Size() / points_min;
|
|---|
| 41 |
|
|---|
| 42 | active = true;
|
|---|
| 43 | for (int j=0; j<3; ++j) {
|
|---|
| 44 | procs_l[j] = std::max(procs_l[j], 1);
|
|---|
| 45 | procs_l[j] = std::min(procs[j], procs_l[j]);
|
|---|
| 46 | active &= pos[j] < procs_l[j];
|
|---|
| 47 | }
|
|---|
| 48 |
|
|---|
| 49 | if (global[i].BoundaryType() == GlobalMax)
|
|---|
| 50 | levelGlobalMax = interface->MaxLevel() - i;
|
|---|
| 51 |
|
|---|
| 52 | if (active) {
|
|---|
| 53 |
|
|---|
| 54 | // Set boundary type
|
|---|
| 55 | global_l.BoundaryType() = global[i].BoundaryType();
|
|---|
| 56 |
|
|---|
| 57 | // Compute global size
|
|---|
| 58 | global_l.Size() = global[i].Size() / procs_l;
|
|---|
| 59 | remainder = global[i].Size() % procs_l;
|
|---|
| 60 |
|
|---|
| 61 | for (int j=0; j<3; ++j)
|
|---|
| 62 | if (pos[j] < remainder[j])
|
|---|
| 63 | ++(global_l.Size()[j]);
|
|---|
| 64 |
|
|---|
| 65 | // Compute global begin
|
|---|
| 66 | global_l.Begin() = pos * global_l.Size();
|
|---|
| 67 |
|
|---|
| 68 | for (int j=0; j<3; ++j)
|
|---|
| 69 | if (pos[j] >= remainder[j])
|
|---|
| 70 | global_l.Begin()[j] += remainder[j];
|
|---|
| 71 |
|
|---|
| 72 | // Compute global end
|
|---|
| 73 | global_l.End() = global_l.Begin() + global_l.Size();
|
|---|
| 74 |
|
|---|
| 75 | // Set alignment
|
|---|
| 76 | for (int j=0; j<3; ++j) {
|
|---|
| 77 | global_l.AlignmentBegin()[j] = std::max(0, global[i].AlignmentBegin()[j] - global_l.Begin()[j]);
|
|---|
| 78 | global_l.AlignmentEnd()[j] = std::min(global_l.Size()[j], global[i].AlignmentEnd()[j] - global_l.Begin()[j]);
|
|---|
| 79 | }
|
|---|
| 80 |
|
|---|
| 81 | switch (comm->BoundaryConditions())
|
|---|
| 82 | {
|
|---|
| 83 | case Dirichlet:
|
|---|
| 84 | local_l = InitDirichlet(global_l, extent[i], pos, procs_l);
|
|---|
| 85 | break;
|
|---|
| 86 | case Periodic:
|
|---|
| 87 | local_l = InitPeriodic(global_l, extent[i], pos, procs_l);
|
|---|
| 88 | break;
|
|---|
| 89 | case Quasiperiodic:
|
|---|
| 90 | local_l = InitDirichlet(global_l, extent[i], pos, procs_l);
|
|---|
| 91 | break;
|
|---|
| 92 | }
|
|---|
| 93 |
|
|---|
| 94 | grids.push_back(new Grid(global_l, local_l, extent[i]));
|
|---|
| 95 |
|
|---|
| 96 | }else {
|
|---|
| 97 |
|
|---|
| 98 | global_l.Size() = 0;
|
|---|
| 99 | global_l.Begin() = 0;
|
|---|
| 100 | global_l.End() = 0;
|
|---|
| 101 | global_l.AlignmentBegin() = 0;
|
|---|
| 102 | global_l.AlignmentEnd() = 0;
|
|---|
| 103 | global_l.BoundaryType() = EmptyGrid;
|
|---|
| 104 |
|
|---|
| 105 | local_l.Size() = 0;
|
|---|
| 106 | local_l.SizeTotal() = 0;
|
|---|
| 107 | local_l.Begin() = 0;
|
|---|
| 108 | local_l.End() = 0;
|
|---|
| 109 | local_l.HaloBegin1() = 0;
|
|---|
| 110 | local_l.HaloBegin2() = 0;
|
|---|
| 111 | local_l.HaloEnd1() = 0;
|
|---|
| 112 | local_l.HaloEnd2() = 0;
|
|---|
| 113 | local_l.BoundaryBegin1() = 0;
|
|---|
| 114 | local_l.BoundaryBegin2() = 0;
|
|---|
| 115 | local_l.BoundaryEnd1() = 0;
|
|---|
| 116 | local_l.BoundaryEnd2() = 0;
|
|---|
| 117 | local_l.AlignmentBegin() = 0;
|
|---|
| 118 | local_l.AlignmentEnd() = 0;
|
|---|
| 119 |
|
|---|
| 120 | grids.push_back(new Grid(global_l, local_l, extent[i]));
|
|---|
| 121 |
|
|---|
| 122 | }
|
|---|
| 123 | }
|
|---|
| 124 |
|
|---|
| 125 | numLevels = grids.size();
|
|---|
| 126 |
|
|---|
| 127 | levelMax = interface->MaxLevel();
|
|---|
| 128 | levelMin = levelMax - numLevels + 1;
|
|---|
| 129 |
|
|---|
| 130 | levelIndex = 0;
|
|---|
| 131 | levelCurrent = levelMax;
|
|---|
| 132 | }
|
|---|
| 133 |
|
|---|
| 134 | LocalIndices Multigrid::InitDirichlet(const GlobalIndices& global, const SpatialExtent& extent, const Index& pos, const Index& procs)
|
|---|
| 135 | {
|
|---|
| 136 | LocalIndices local;
|
|---|
| 137 |
|
|---|
| 138 | local.HaloBegin1() = local.HaloEnd1() = 0;
|
|---|
| 139 | local.HaloBegin2() = local.HaloEnd2() = 0;
|
|---|
| 140 | local.BoundaryBegin1() = local.BoundaryEnd1() = 0;
|
|---|
| 141 | local.BoundaryBegin2() = local.BoundaryEnd2() = 0;
|
|---|
| 142 |
|
|---|
| 143 | local.SizeTotal() = global.End() - global.Begin() + (global.BoundaryType() == LocallyRefined ? 2 : 0);
|
|---|
| 144 |
|
|---|
| 145 | for (int i=0; i<3; ++i) {
|
|---|
| 146 |
|
|---|
| 147 | if (pos[i] == 0) {
|
|---|
| 148 | local.BoundaryBegin1()[i] = 0;
|
|---|
| 149 | local.BoundaryEnd1()[i] = 1;
|
|---|
| 150 | }else {
|
|---|
| 151 | ++local.SizeTotal()[i];
|
|---|
| 152 | local.HaloBegin1()[i] = 0;
|
|---|
| 153 | local.HaloEnd1()[i] = 1;
|
|---|
| 154 | }
|
|---|
| 155 |
|
|---|
| 156 | if (pos[i] == procs[i]-1) {
|
|---|
| 157 | local.BoundaryBegin2()[i] = local.SizeTotal()[i] - 1;
|
|---|
| 158 | local.BoundaryEnd2()[i] = local.SizeTotal()[i];
|
|---|
| 159 | }else {
|
|---|
| 160 | ++local.SizeTotal()[i];
|
|---|
| 161 | local.HaloBegin2()[i] = local.SizeTotal()[i] - 1;
|
|---|
| 162 | local.HaloEnd2()[i] = local.SizeTotal()[i];
|
|---|
| 163 | }
|
|---|
| 164 |
|
|---|
| 165 | }
|
|---|
| 166 |
|
|---|
| 167 | local.Begin() = 1;
|
|---|
| 168 | local.End() = local.SizeTotal() - 1;
|
|---|
| 169 |
|
|---|
| 170 | local.Size() = local.End() - local.Begin();
|
|---|
| 171 |
|
|---|
| 172 | local.AlignmentBegin() = global.AlignmentBegin() + local.Begin();
|
|---|
| 173 | local.AlignmentEnd() = global.AlignmentEnd() - local.Begin();
|
|---|
| 174 |
|
|---|
| 175 | return local;
|
|---|
| 176 | }
|
|---|
| 177 |
|
|---|
| 178 | LocalIndices Multigrid::InitPeriodic(const GlobalIndices& global, const SpatialExtent& extent, const Index& pos, const Index& procs)
|
|---|
| 179 | {
|
|---|
| 180 | LocalIndices local;
|
|---|
| 181 |
|
|---|
| 182 | local.SizeTotal() = global.End() - global.Begin() + 2;
|
|---|
| 183 |
|
|---|
| 184 | local.BoundaryBegin1() = local.BoundaryEnd1() = 0;
|
|---|
| 185 | local.BoundaryBegin2() = local.BoundaryEnd2() = 0;
|
|---|
| 186 |
|
|---|
| 187 | local.HaloBegin1() = 0;
|
|---|
| 188 | local.HaloEnd1() = 1;
|
|---|
| 189 | local.HaloBegin2() = local.SizeTotal() - 1;
|
|---|
| 190 | local.HaloEnd2() = local.SizeTotal();
|
|---|
| 191 |
|
|---|
| 192 | local.Begin() = 1;
|
|---|
| 193 | local.End() = local.SizeTotal() - 1;
|
|---|
| 194 |
|
|---|
| 195 | local.Size() = local.End() - local.Begin();
|
|---|
| 196 |
|
|---|
| 197 | local.AlignmentBegin() = global.AlignmentBegin() + local.Begin();
|
|---|
| 198 | local.AlignmentEnd() = global.AlignmentEnd() + local.Begin();
|
|---|
| 199 |
|
|---|
| 200 | return local;
|
|---|
| 201 | }
|
|---|
| 202 |
|
|---|
| 203 | void Multigrid::SetLevel(int level)
|
|---|
| 204 | {
|
|---|
| 205 | assert(level >= levelMin && level <= levelMax);
|
|---|
| 206 | levelCurrent = level;
|
|---|
| 207 | levelIndex = levelMax - level;
|
|---|
| 208 | }
|
|---|
| 209 |
|
|---|
| 210 | void Multigrid::ToCoarserLevel()
|
|---|
| 211 | {
|
|---|
| 212 | assert(levelCurrent-1 >= levelMin);
|
|---|
| 213 | --levelCurrent;
|
|---|
| 214 | ++levelIndex;
|
|---|
| 215 | }
|
|---|
| 216 |
|
|---|
| 217 | void Multigrid::ToFinerLevel()
|
|---|
| 218 | {
|
|---|
| 219 | assert(levelCurrent+1 <= levelMax);
|
|---|
| 220 | ++levelCurrent;
|
|---|
| 221 | --levelIndex;
|
|---|
| 222 | }
|
|---|
| 223 |
|
|---|
| 224 | void Multigrid::ClearAll()
|
|---|
| 225 | {
|
|---|
| 226 | for (int i=MinLevel(); i<=MaxLevel(); ++i)
|
|---|
| 227 | (*this)(i).Clear();
|
|---|
| 228 | }
|
|---|
| 229 |
|
|---|
| 230 | // TODO: diff that in case that breaks QP
|
|---|
| 231 | void Multigrid::ClearAllCoarseLevels()
|
|---|
| 232 | {
|
|---|
| 233 | for (int i=MinLevel(); i<MaxLevel(); ++i)
|
|---|
| 234 | (*this)(i).Clear();
|
|---|
| 235 | }
|
|---|
| 236 |
|
|---|
| 237 |
|
|---|
| 238 | void Multigrid::SetCoarserDirichletValues()
|
|---|
| 239 | {
|
|---|
| 240 | Index i_c, i_f;
|
|---|
| 241 |
|
|---|
| 242 | for (int i=GlobalMaxLevel(); i>MinLevel(); --i) {
|
|---|
| 243 |
|
|---|
| 244 | Grid& grid_f = (*this)(i);
|
|---|
| 245 | Grid& grid_c = (*this)(i-1);
|
|---|
| 246 |
|
|---|
| 247 | i_c.X() = grid_c.Local().BoundaryBegin1().X();
|
|---|
| 248 | i_f.X() = grid_f.Local().BoundaryBegin1().X();
|
|---|
| 249 | for (i_c.Y()=grid_c.Local().Begin().Y(); i_c.Y()<grid_c.Local().End().Y(); ++i_c.Y())
|
|---|
| 250 | for (i_c.Z()=grid_c.Local().Begin().Z(); i_c.Z()<grid_c.Local().End().Z(); ++i_c.Z())
|
|---|
| 251 | grid_c(i_c) = grid_f.GetVal(i_f.X(), 2*i_c.Y(), 2*i_c.Z());
|
|---|
| 252 |
|
|---|
| 253 | i_c.X() = grid_c.Local().BoundaryBegin2().X();
|
|---|
| 254 | i_f.X() = grid_f.Local().BoundaryBegin2().X();
|
|---|
| 255 | for (i_c.Y()=grid_c.Local().Begin().Y(); i_c.Y()<grid_c.Local().End().Y(); ++i_c.Y())
|
|---|
| 256 | for (i_c.Z()=grid_c.Local().Begin().Z(); i_c.Z()<grid_c.Local().End().Z(); ++i_c.Z())
|
|---|
| 257 | grid_c(i_c) = grid_f.GetVal(i_f.X(), 2*i_c.Y(), 2*i_c.Z());
|
|---|
| 258 |
|
|---|
| 259 | i_c.Y() = grid_c.Local().BoundaryBegin1().Y();
|
|---|
| 260 | i_f.Y() = grid_f.Local().BoundaryBegin1().Y();
|
|---|
| 261 | for (i_c.X()=0; i_c.X()<grid_c.Local().SizeTotal().X(); ++i_c.X())
|
|---|
| 262 | for (i_c.Z()=grid_c.Local().Begin().Z(); i_c.Z()<grid_c.Local().End().Z(); ++i_c.Z())
|
|---|
| 263 | grid_c(i_c) = grid_f.GetVal(2*i_c.X(), i_f.Y(), 2*i_c.Z());
|
|---|
| 264 |
|
|---|
| 265 | i_c.Y() = grid_c.Local().BoundaryBegin2().Y();
|
|---|
| 266 | i_f.Y() = grid_f.Local().BoundaryBegin2().Y();
|
|---|
| 267 | for (i_c.X()=0; i_c.X()<grid_c.Local().SizeTotal().X(); ++i_c.X())
|
|---|
| 268 | for (i_c.Z()=grid_c.Local().Begin().Z(); i_c.Z()<grid_c.Local().End().Z(); ++i_c.Z())
|
|---|
| 269 | grid_c(i_c) = grid_f.GetVal(2*i_c.X(), i_f.Y(), 2*i_c.Z());
|
|---|
| 270 |
|
|---|
| 271 | i_c.Z() = grid_c.Local().BoundaryBegin1().Z();
|
|---|
| 272 | i_f.Z() = grid_f.Local().BoundaryBegin1().Z();
|
|---|
| 273 | for (i_c.X()=0; i_c.X()<grid_c.Local().SizeTotal().X(); ++i_c.X())
|
|---|
| 274 | for (i_c.Y()=0; i_c.Y()<grid_c.Local().SizeTotal().Y(); ++i_c.Y())
|
|---|
| 275 | grid_c(i_c) = grid_f.GetVal(2*i_c.X(), 2*i_c.Y(), i_f.Z());
|
|---|
| 276 |
|
|---|
| 277 | i_c.Z() = grid_c.Local().BoundaryBegin2().Z();
|
|---|
| 278 | i_f.Z() = grid_f.Local().BoundaryBegin2().Z();
|
|---|
| 279 | for (i_c.X()=0; i_c.X()<grid_c.Local().SizeTotal().X(); ++i_c.X())
|
|---|
| 280 | for (i_c.Y()=0; i_c.Y()<grid_c.Local().SizeTotal().Y(); ++i_c.Y())
|
|---|
| 281 | grid_c(i_c) = grid_f.GetVal(2*i_c.X(), 2*i_c.Y(), i_f.Z());
|
|---|
| 282 |
|
|---|
| 283 | }
|
|---|
| 284 | }
|
|---|
| 285 |
|
|---|
| 286 | Multigrid::~Multigrid()
|
|---|
| 287 | {
|
|---|
| 288 | for (unsigned int i=0; i<grids.size(); ++i)
|
|---|
| 289 | delete grids[i];
|
|---|
| 290 | }
|
|---|