/* * 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 gsrb.cpp * @author Julian Iseringhausen * @date Mon Apr 18 13:08:20 2011 * * @brief Gauss-Seidel Red Black method * */ #ifdef HAVE_CONFIG_H #include #endif #ifdef HAVE_MPI #include #endif #include "base/discretization.hpp" #include "base/stencil.hpp" #include "comm/comm.hpp" #include "grid/grid.hpp" #include "smoother/gsrb.hpp" using namespace VMG; static inline void ComputePartial(Grid& sol, Grid& rhs, const Stencil& mat, const Index& begin, const Index& end, const vmg_float& prefactor, const vmg_float& diag_inv, const int& off) { int i,j,k; vmg_float temp; Stencil::iterator iter; for (i=begin.X(); iLevelSum(rhs, z_begin - begin.Z()); assert(z_begin - begin.Z() == 0 || z_begin - begin.Z() == 1); assert(off_sum == 0 || off_sum == MG::GetComm()->Size(rhs)); #endif /* DEBUG */ for (k=z_begin; kVal() * sol.GetVal(i+iter->Disp().X(), j+iter->Disp().Y(), k+iter->Disp().Z()); sol(i,j,k) = temp * diag_inv; } } } void GaussSeidelRB::Compute(Grid& sol, Grid& rhs) { const Stencil& mat = MG::GetDiscretization()->GetStencil(); const vmg_float prefactor_inv = 1.0 / MG::GetDiscretization()->OperatorPrefactor(sol); const vmg_float diag_inv = 1.0 / mat.GetDiag(); const int off = rhs.Global().LocalBegin().Sum() - rhs.Global().GlobalBegin().Sum() + rhs.Local().HaloSize1().Sum(); const LocalIndices& local = rhs.Local(); Comm& comm = *MG::GetComm(); /* * Compute first halfstep */ // Start asynchronous communication comm.CommToGhostsAsyncStart(sol); // Smooth part not depending on ghost cells ComputePartial(sol, rhs, mat, local.Begin()+1, local.End()-1, prefactor_inv, diag_inv, off+1); // Finish asynchronous communication comm.CommToGhostsAsyncFinish(sol); /* * Smooth near boundary cells */ ComputePartial(sol, rhs, mat, local.Begin(), Index(local.Begin().X()+1, local.End().Y(), local.End().Z()), prefactor_inv, diag_inv, off+1); ComputePartial(sol, rhs, mat, Index(local.End().X()-1, local.Begin().Y(), local.Begin().Z()), local.End(), prefactor_inv, diag_inv, off+1); ComputePartial(sol, rhs, mat, Index(local.Begin().X()+1, local.Begin().Y(), local.Begin().Z()), Index(local.End().X()-1, local.Begin().Y()+1, local.End().Z()), prefactor_inv, diag_inv, off+1); ComputePartial(sol, rhs, mat, Index(local.Begin().X()+1, local.End().Y()-1, local.Begin().Z()), Index(local.End().X()-1, local.End().Y(), local.End().Z()), prefactor_inv, diag_inv, off+1); ComputePartial(sol, rhs, mat, Index(local.Begin().X()+1, local.Begin().Y()+1, local.Begin().Z()), Index(local.End().X()-1, local.End().Y()-1, local.Begin().Z()+1), prefactor_inv, diag_inv, off+1); ComputePartial(sol, rhs, mat, Index(local.Begin().X()+1, local.Begin().Y()+1, local.End().Z()-1), Index(local.End().X()-1, local.End().Y()-1, local.End().Z()), prefactor_inv, diag_inv, off+1); /* * Compute second halfstep */ // Start asynchronous communication comm.CommToGhostsAsyncStart(sol); // Smooth part not depending on ghost cells ComputePartial(sol, rhs, mat, local.Begin()+1, local.End()-1, prefactor_inv, diag_inv, off); // Finish asynchronous communication comm.CommToGhostsAsyncFinish(sol); /* * Smooth near boundary cells */ ComputePartial(sol, rhs, mat, local.Begin(), Index(local.Begin().X()+1, local.End().Y(), local.End().Z()), prefactor_inv, diag_inv, off); ComputePartial(sol, rhs, mat, Index(local.End().X()-1, local.Begin().Y(), local.Begin().Z()), local.End(), prefactor_inv, diag_inv, off); ComputePartial(sol, rhs, mat, Index(local.Begin().X()+1, local.Begin().Y(), local.Begin().Z()), Index(local.End().X()-1, local.Begin().Y()+1, local.End().Z()), prefactor_inv, diag_inv, off); ComputePartial(sol, rhs, mat, Index(local.Begin().X()+1, local.End().Y()-1, local.Begin().Z()), Index(local.End().X()-1, local.End().Y(), local.End().Z()), prefactor_inv, diag_inv, off); ComputePartial(sol, rhs, mat, Index(local.Begin().X()+1, local.Begin().Y()+1, local.Begin().Z()), Index(local.End().X()-1, local.End().Y()-1, local.Begin().Z()+1), prefactor_inv, diag_inv, off); ComputePartial(sol, rhs, mat, Index(local.Begin().X()+1, local.Begin().Y()+1, local.End().Z()-1), Index(local.End().X()-1, local.End().Y()-1, local.End().Z()), prefactor_inv, diag_inv, off); }