/*
* 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()