/*
* 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 comm.hpp
* @author Julian Iseringhausen
* @date Wed Jun 16 13:21:06 2010
*
* @brief Base class for communication.
*
*/
#ifdef HAVE_CONFIG_H
#include
#endif
#ifdef HAVE_BOOST_FILESYSTEM_PATH_HPP
#include
namespace fs = boost::filesystem;
#endif
#include "base/discretization.hpp"
#include "base/helper.hpp"
#include "base/stencil.hpp"
#include "comm/comm.hpp"
#include "comm/domain_decomposition.hpp"
#include "grid/grid.hpp"
#include "mg.hpp"
using namespace VMG;
vmg_float Comm::ComputeResidualNorm(Multigrid& sol_mg, Multigrid& rhs_mg)
{
Stencil::iterator stencil_iter;
vmg_float norm = 0.0;
const vmg_float prefactor = MG::GetDiscretization()->OperatorPrefactor(sol_mg());
const Stencil& A = MG::GetDiscretization()->GetStencil();
this->CommToGhosts(sol_mg());
if (sol_mg().Global().BoundaryType() == LocallyRefined)
MG::GetDiscretization()->SetInnerBoundary(sol_mg(), rhs_mg(), sol_mg(sol_mg.Level()-1));
const Grid& sol = sol_mg();
const Grid& rhs = rhs_mg();
#ifdef DEBUG_MATRIX_CHECKS
sol.IsCompatible(rhs);
sol.IsConsistent();
rhs.IsConsistent();
#endif
for (int i=rhs.Local().Begin().X(); iVal() * sol.GetVal(i + stencil_iter->Disp().X(),
j + stencil_iter->Disp().Y(),
k + stencil_iter->Disp().Z());
norm += val*val;
}
norm = GlobalSum(norm);
norm = std::sqrt(sol.Extent().MeshWidth().Product() * norm);
return norm;
}
Grid& Comm::GetParticleGrid()
{
if (particle_grid != NULL)
return *particle_grid;
const Grid& grid = (*MG::GetRhs())(MG::GetRhs()->MaxLevel());
LocalIndices local = grid.Local();
GlobalIndices global = grid.Global();
SpatialExtent extent = grid.Extent();
const int& near_field_cells = MG::GetFactory().GetObjectStorageVal("PARTICLE_NEAR_FIELD_CELLS");
for (int i=0; i<3; ++i) {
if (BoundaryConditions()[i] == Open || BoundaryConditions()[i] == Dirichlet) {
if (global.LocalBegin()[i] == global.GlobalBegin()[i])
global.LocalBegin()[i] += 1;
if (global.LocalEnd()[i] == global.GlobalEnd()[i])
global.LocalEnd()[i] -= 1;
global.LocalSize()[i] = global.LocalEnd()[i] - global.LocalBegin()[i];
global.GlobalBegin()[i] += 1;
global.GlobalEnd()[i] -= 1;
global.GlobalSize()[i] = global.GlobalEnd()[i] - global.GlobalBegin()[i];
extent.Begin()[i] += extent.MeshWidth()[i];
extent.End()[i] -= extent.MeshWidth()[i];
extent.Size()[i] = extent.End()[i] - extent.Begin()[i];
}
}
local.BoundaryBegin1() = local.BoundaryEnd1() = local.BoundarySize1() = 0;
local.BoundaryBegin2() = local.BoundaryEnd2() = local.BoundarySize2() = 0;
local.End() -= local.Begin();
local.Begin() = 0;
// Set grid size of intermediate temporary grid
for (int i=0; i<3; ++i) {
if (local.HaloSize1()[i] > 0) {
local.HaloBegin1()[i] = 0;
local.HaloEnd1()[i] = near_field_cells;
local.HaloSize1()[i] = near_field_cells;
local.Begin()[i] = near_field_cells;
local.End()[i] = local.Begin()[i] + local.Size()[i];
}
if (local.HaloSize2()[i] > 0) {
local.HaloBegin2()[i] = local.End()[i];
local.HaloEnd2()[i] = local.HaloBegin2()[i] + near_field_cells;
local.HaloSize2()[i] = near_field_cells;
}
}
local.SizeTotal() = local.Size() + local.HaloSize1() + local.HaloSize2();
particle_grid = new Grid(global, local, extent);
return *particle_grid;
}
Comm::~Comm()
{
delete dd;
delete particle_grid;
}
const std::string& Comm::OutputPath()
{
if (!output_directory_is_created) {
output_path_str = CreateOutputDirectory();
output_directory_is_created = true;
}
return output_path_str;
}