/*
* 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 grid_index_translations.cpp
* @author Julian Iseringhausen
* @date Tue May 17 11:46:37 2011
*
* @brief Class to convert different representations of grid
* indices.
*
*/
#ifdef HAVE_CONFIG_H
#include
#endif
#include "base/helper.hpp"
#include "comm/comm.hpp"
#include "grid/grid_double_iterator.hpp"
#include "grid/grid_index_translations.hpp"
#include "grid/grid.hpp"
#include "grid/multigrid.hpp"
#include "mg.hpp"
using namespace VMG;
bool GridIndexTranslations::IsGridPointOf(const Grid& grid, const Index& index_finest)
{
const int max_level = MG::GetSol()->MaxLevel();
return index_finest[0] % Helper::intpow(2, max_level - grid.Level()) == 0 &&
index_finest[1] % Helper::intpow(2, max_level - grid.Level()) == 0 &&
index_finest[2] % Helper::intpow(2, max_level - grid.Level()) == 0;
}
Index GridIndexTranslations::LocalToGlobal(const Grid& grid, const Index& index_local)
{
return index_local - grid.Local().HaloSize1() + grid.Global().LocalBegin();
}
Index GridIndexTranslations::LocalToGlobalFinest(const Grid& grid, const Index& index_local)
{
return GlobalToGlobalFinest(grid, LocalToGlobal(grid, index_local));
}
Index GridIndexTranslations::GlobalToLocal(const Grid& grid, const Index& index_global)
{
return index_global - grid.Global().LocalBegin() + grid.Local().HaloSize1();
}
Index GridIndexTranslations::GlobalToGlobalFinest(const Grid& grid, const Index& index_global)
{
return Helper::intpow(2, MG::GetSol()->MaxLevel() - grid.Level()) * index_global;
}
Index GridIndexTranslations::GlobalFinestToLocal(const Grid& grid, const Index& index_finest)
{
return GlobalToLocal(grid, GlobalFinestToGlobal(grid, index_finest));
}
Index GridIndexTranslations::GlobalFinestToGlobal(const Grid& grid, const Index& index_finest)
{
assert(IsGridPointOf(grid, index_finest));
return index_finest / Helper::intpow(2, MG::GetSol()->MaxLevel() - grid.Level());
}
void GridIndexTranslations::GlobalCoarseToFine(Index& begin, Index& end)
{
for (int j=0; j<3; ++j) {
begin[j] = 2 * begin[j];
end[j] = 2 * (end[j]-1) + 1;
}
}
void GridIndexTranslations::GlobalFineToCoarse(Index& begin, Index& end)
{
for (int j=0; j<3; ++j) {
begin[j] = Helper::RoundUpToNextMultiple(begin[j], 2) / 2;
end[j] = Helper::RoundDownToNextMultiple(end[j]-1, 2) / 2 + 1;
}
}
void GridIndexTranslations::GetGridAlignment(const Grid& grid_1, GridIteratorSet& bounds_1,
const Grid& grid_2, GridIteratorSet& bounds_2)
{
const Boundary& boundary = MG::GetComm()->BoundaryConditions();
if (grid_1.Level() == grid_2.Level()) {
Index begin_global = grid_1.Global()
.LocalBegin()
.Clamp(grid_2.Global().LocalBegin(), grid_2.Global().LocalEnd());
Index end_global = grid_1.Global()
.LocalEnd()
.Clamp(grid_2.Global().LocalBegin(), grid_2.Global().LocalEnd());
for (int j=0; j<3; ++j) {
if (boundary[j] == Dirichlet) {
if (begin_global[j] == grid_1.Global().GlobalBegin()[j] || begin_global[j] == grid_2.Global().GlobalBegin()[j])
begin_global[j] += 1;
if (end_global[j] == grid_1.Global().GlobalEnd()[j] || end_global[j] == grid_2.Global().GlobalEnd()[j])
end_global[j] -= 1;
}
}
bounds_1 = GridIteratorSet(GlobalToLocal(grid_1, begin_global), GlobalToLocal(grid_2, end_global));
bounds_2 = GridIteratorSet(GlobalToLocal(grid_2, begin_global), GlobalToLocal(grid_2, end_global));
} else {
const Grid& grid_c = (grid_1.Level() < grid_2.Level() ? grid_1 : grid_2);
const int global_mult = Helper::intpow(2, MG::GetSol()->MaxLevel() - grid_c.Level());
Index begin_finest = GlobalToGlobalFinest(grid_1, grid_1.Global().LocalBegin())
.Clamp(GlobalToGlobalFinest(grid_2, grid_2.Global().LocalBegin()),
GlobalToGlobalFinest(grid_2, grid_2.Global().LocalEnd()-1));
Index end_finest = GlobalToGlobalFinest(grid_1, grid_1.Global().LocalEnd()-1)
.Clamp(GlobalToGlobalFinest(grid_2, grid_2.Global().LocalBegin()),
GlobalToGlobalFinest(grid_2, grid_2.Global().LocalEnd()-1));
for (int j=0; j<3; ++j) {
begin_finest[j] = Helper::RoundUpToNextMultiple(begin_finest[j], global_mult);
end_finest[j] = Helper::RoundDownToNextMultiple(end_finest[j], global_mult);
}
for (int j=0; j<3; ++j) {
if (boundary[j] == Dirichlet) {
if (grid_1.Global().LocalBegin()[j] == grid_1.Global().GlobalBegin()[j] || grid_2.Global().LocalBegin()[j] == grid_2.Global().GlobalBegin()[j])
begin_finest[j] += global_mult;
if (grid_1.Global().LocalEnd()[j] == grid_1.Global().GlobalEnd()[j] || grid_2.Global().LocalEnd()[j] == grid_2.Global().GlobalEnd()[j])
end_finest[j] -= global_mult;
}
}
bounds_1 = GridIteratorSet(GlobalFinestToLocal(grid_1, begin_finest), GlobalFinestToLocal(grid_1, end_finest)+1);
bounds_2 = GridIteratorSet(GlobalFinestToLocal(grid_2, begin_finest), GlobalFinestToLocal(grid_2, end_finest)+1);
}
}