/* * 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 level_operator_cs.cpp * @author Julian Iseringhausen * @date Mon Apr 18 12:59:46 2011 * * @brief VMG::LevelOperatorCS * */ #ifdef HAVE_CONFIG_H #include #endif #include "base/index.hpp" #include "comm/comm.hpp" #include "grid/grid_index_translations.hpp" #include "grid/grid_iterator.hpp" #include "grid/multigrid.hpp" #include "grid/tempgrid.hpp" #include "level/level_operator_cs.hpp" #include "mg.hpp" using namespace VMG; void LevelOperatorCS::Restrict(Multigrid& sol, Multigrid& rhs) { Grid::iterator iter_f, iter_c; Comm& comm = *MG::GetComm(); Grid& sol_f = sol(sol.Level()); Grid& rhs_f = rhs(rhs.Level()); Grid& rhs_c_dist = rhs(rhs.Level()-1); Grid& rhs_c_undist = comm.GetCoarserGrid(rhs); const Stencil& op = OperatorRestrict(); GridIteratorSet bounds_c, bounds_f; GridIndexTranslations::GetGridAlignment(rhs_c_undist, bounds_c, rhs_f, bounds_f); assert(bounds_c.Begin().GetEnd()-bounds_c.Begin().GetBegin() == ((bounds_f.Begin().GetEnd()-bounds_f.Begin().GetBegin())-1)/2+1); // Compute residual TempGrid *temp = MG::GetTempGrid(); temp->SetProperties(sol_f); temp->ImportFromResidual(sol_f, rhs_f); comm.CommToGhosts(*temp); for (iter_f=bounds_f.Begin(), iter_c=bounds_c.Begin(); iter_f!=bounds_f.End(); iter_f+=2, ++iter_c) rhs_c_undist(*iter_c) = op.Apply(*temp, *iter_f); comm.CommSubgrid(rhs_c_undist, rhs_c_dist, 1); if (rhs_c_dist.Global().BoundaryType() == GlobalCoarsened) rhs_c_dist.ClearBoundary(); sol.ToCoarserLevel(); rhs.ToCoarserLevel(); } void LevelOperatorCS::Prolongate(Multigrid& sol, Multigrid& rhs) { Grid::iterator iter_f, iter_c; Stencil::iterator stencil_iter; vmg_float val; Comm& comm = *MG::GetComm(); Grid& sol_c = sol(sol.Level()); Grid& sol_f_dist = sol(sol.Level()+1); Grid& sol_f_undist = comm.GetFinerGrid(sol); const Stencil& op = OperatorProlongate(); GridIteratorSet bounds_c, bounds_f; GridIndexTranslations::GetGridAlignment(sol_c, bounds_c, sol_f_undist, bounds_f); assert(bounds_c.Begin().GetEnd()-bounds_c.Begin().GetBegin() == ((bounds_f.Begin().GetEnd()-bounds_f.Begin().GetBegin())-1)/2+1); sol_f_undist.ClearHalo(); comm.CommSubgrid(sol_f_dist, sol_f_undist, 0); for (iter_f=bounds_f.Begin(), iter_c=bounds_c.Begin(); iter_c!=bounds_c.End(); iter_f+=2, ++iter_c) { val = sol_c.GetVal(*iter_c); sol_f_undist(*iter_f) += op.GetDiag() * val; for (stencil_iter = op.begin(); stencil_iter != op.end(); ++stencil_iter) sol_f_undist(iter_f->X() + stencil_iter->Disp().X(), iter_f->Y() + stencil_iter->Disp().Y(), iter_f->Z() + stencil_iter->Disp().Z()) += stencil_iter->Val() * val; } comm.CommFromGhosts(sol_f_undist); comm.CommSubgrid(sol_f_undist, sol_f_dist, 1); sol.ToFinerLevel(); rhs.ToFinerLevel(); }