/* * vmg - a versatile multigrid solver * Copyright (C) 2012 Institute for Numerical Simulation, University of Bonn * * vmg is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * vmg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** * @file multigrid.cpp * @author Julian Iseringhausen * @date Mon Apr 18 12:54:37 2011 * * @brief VMG::Multigrid * */ #ifdef HAVE_CONFIG_H #include #endif #include #include "base/helper.hpp" #include "base/index.hpp" #include "base/interface.hpp" #include "comm/comm.hpp" #include "comm/domain_decomposition.hpp" #include "grid/grid.hpp" #include "grid/grid_properties.hpp" #include "grid/multigrid.hpp" using namespace VMG; Multigrid::Multigrid(const Comm& comm, const Interface& interface) { Index points, remainder; LocalIndices local_l; const std::vector& extent = interface.Extent(); const std::vector& global_separated = comm.DecomposedGlobalMe(); for (unsigned int i=0; i 0) { /* * Initialize some properties with zero */ local_l.HaloBegin1() = 0; local_l.HaloEnd1() = 0; local_l.HaloBegin2() = 0; local_l.HaloEnd2() = 0; local_l.BoundaryBegin1() = 0; local_l.BoundaryEnd1() = 0; local_l.BoundaryBegin2() = 0; local_l.BoundaryEnd2() = 0; /* * Set boundary dependant properties */ for (int j=0; j<3; ++j) { if (comm.BoundaryConditions()[j] == Dirichlet || comm.BoundaryConditions()[j] == Open) { local_l.SizeTotal()[j] = global_separated[i].LocalSize()[j]; /* * We have a boundary at the ends of the process grids * and halo grid points otherwise */ if (global_separated[i].LocalBegin()[j] == global_separated[i].GlobalBegin()[j]) { local_l.BoundaryBegin1()[j] = 0; local_l.BoundaryEnd1()[j] = 1; }else { ++local_l.SizeTotal()[j]; local_l.HaloBegin1()[j] = 0; local_l.HaloEnd1()[j] = 1; } if (global_separated[i].LocalEnd()[j] == global_separated[i].GlobalEnd()[j]) { local_l.BoundaryBegin2()[j] = local_l.SizeTotal()[j] - 1; local_l.BoundaryEnd2()[j] = local_l.SizeTotal()[j]; }else { ++local_l.SizeTotal()[j]; local_l.HaloBegin2()[j] = local_l.SizeTotal()[j] - 1; local_l.HaloEnd2()[j] = local_l.SizeTotal()[j]; } }else if (comm.BoundaryConditions()[j] == Periodic) { local_l.SizeTotal()[j] = global_separated[i].LocalSize()[j] + 2; /* * No boundary */ local_l.BoundaryBegin1()[j] = local_l.BoundaryEnd1()[j] = 0; local_l.BoundaryBegin2()[j] = local_l.BoundaryEnd2()[j] = 0; /* * Halo grid points on all processes */ local_l.HaloBegin1()[j] = 0; local_l.HaloEnd1()[j] = 1; local_l.HaloBegin2()[j] = local_l.SizeTotal()[j] - 1; local_l.HaloEnd2()[j] = local_l.SizeTotal()[j]; } } local_l.Begin() = 1; local_l.End() = local_l.SizeTotal() - 1; local_l.Size() = local_l.End() - local_l.Begin(); local_l.HaloSize1() = local_l.HaloEnd1() - local_l.HaloBegin1(); local_l.HaloSize2() = local_l.HaloEnd2() - local_l.HaloBegin2(); local_l.BoundarySize1() = local_l.BoundaryEnd1() - local_l.BoundaryBegin1(); local_l.BoundarySize2() = local_l.BoundaryEnd2() - local_l.BoundaryBegin2(); }else { local_l.Begin() = 0; local_l.End() = 0; local_l.Size() = 0; local_l.SizeTotal() = 0; local_l.HaloBegin1() = 0; local_l.HaloEnd1() = 0; local_l.HaloSize1() = 0; local_l.HaloBegin2() = 0; local_l.HaloEnd2() = 0; local_l.HaloSize2() = 0; local_l.BoundaryBegin1() = 0; local_l.BoundaryEnd1() = 0; local_l.BoundarySize1() = 0; local_l.BoundaryBegin2() = 0; local_l.BoundaryEnd2() = 0; local_l.BoundarySize2() = 0; } grids.push_back(new Grid(global_separated[i], local_l, extent[i], interface.MaxLevel()-i, this)); } numLevels = grids.size(); levelMax = interface.MaxLevel(); levelMin = levelMax - numLevels + 1; levelIndex = 0; levelCurrent = levelMax; } void Multigrid::SetLevel(int level) { assert(level >= levelMin && level <= levelMax); levelCurrent = level; levelIndex = levelMax - level; } void Multigrid::ToCoarserLevel() { assert(levelCurrent-1 >= levelMin); --levelCurrent; ++levelIndex; } void Multigrid::ToFinerLevel() { assert(levelCurrent+1 <= levelMax); ++levelCurrent; --levelIndex; } void Multigrid::ClearAll() { for (int i=MinLevel(); i<=MaxLevel(); ++i) (*this)(i).Clear(); } // TODO: diff that in case that breaks QP void Multigrid::ClearAllCoarseLevels() { for (int i=MinLevel(); iMinLevel(); --i) { Grid& grid_f = (*this)(i); Grid& grid_c = (*this)(i-1); i_c.X() = grid_c.Local().BoundaryBegin1().X(); i_f.X() = grid_f.Local().BoundaryBegin1().X(); for (i_c.Y()=grid_c.Local().Begin().Y(); i_c.Y()