| [de061d] | 1 | /*
 | 
|---|
 | 2 |  *    vmg - a versatile multigrid solver
 | 
|---|
 | 3 |  *    Copyright (C) 2012 Institute for Numerical Simulation, University of Bonn
 | 
|---|
 | 4 |  *
 | 
|---|
 | 5 |  *  vmg is free software: you can redistribute it and/or modify
 | 
|---|
 | 6 |  *  it under the terms of the GNU General Public License as published by
 | 
|---|
 | 7 |  *  the Free Software Foundation, either version 3 of the License, or
 | 
|---|
 | 8 |  *  (at your option) any later version.
 | 
|---|
 | 9 |  *
 | 
|---|
 | 10 |  *  vmg is distributed in the hope that it will be useful,
 | 
|---|
 | 11 |  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
 | 12 |  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
 | 13 |  *  GNU General Public License for more details.
 | 
|---|
 | 14 |  *
 | 
|---|
 | 15 |  *  You should have received a copy of the GNU General Public License
 | 
|---|
 | 16 |  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
|---|
 | 17 |  */
 | 
|---|
 | 18 | 
 | 
|---|
 | 19 | /**
 | 
|---|
 | 20 |  * @file   mg.cpp
 | 
|---|
 | 21 |  * @author Julian Iseringhausen <isering@ins.uni-bonn.de>
 | 
|---|
 | 22 |  * @date   Sat Jun 12 20:36:24 2010
 | 
|---|
 | 23 |  *
 | 
|---|
 | 24 |  * @brief  A multigrid solver
 | 
|---|
 | 25 |  *
 | 
|---|
 | 26 |  * This file contains the implementation of the main class for
 | 
|---|
 | 27 |  * a multigrid solver.
 | 
|---|
 | 28 |  *
 | 
|---|
 | 29 |  */
 | 
|---|
 | 30 | 
 | 
|---|
 | 31 | #ifdef HAVE_CONFIG_H
 | 
|---|
 | 32 | #include <libvmg_config.h>
 | 
|---|
 | 33 | #endif
 | 
|---|
 | 34 | 
 | 
|---|
 | 35 | #ifdef OUTPUT_TIMING
 | 
|---|
 | 36 | #ifdef HAVE_MPI
 | 
|---|
 | 37 | #include <mpi.h>
 | 
|---|
 | 38 | #ifdef HAVE_MARMOT
 | 
|---|
 | 39 | #include <enhancempicalls.h>
 | 
|---|
 | 40 | #include <sourceinfompicalls.h>
 | 
|---|
 | 41 | #endif
 | 
|---|
 | 42 | #endif
 | 
|---|
 | 43 | #endif
 | 
|---|
 | 44 | 
 | 
|---|
 | 45 | #include <cmath>
 | 
|---|
 | 46 | #include <cstdio>
 | 
|---|
 | 47 | #include <cfloat>
 | 
|---|
 | 48 | #include <ctime>
 | 
|---|
 | 49 | #include <string>
 | 
|---|
 | 50 | #include <fstream>
 | 
|---|
 | 51 | #include <sstream>
 | 
|---|
 | 52 | 
 | 
|---|
 | 53 | #include "base/command_list.hpp"
 | 
|---|
 | 54 | #include "base/discretization.hpp"
 | 
|---|
 | 55 | #include "base/factory.hpp"
 | 
|---|
 | 56 | #include "base/interface.hpp"
 | 
|---|
 | 57 | #include "base/timer.hpp"
 | 
|---|
 | 58 | #include "comm/comm.hpp"
 | 
|---|
 | 59 | #include "discretization/boundary_value_setter_open.hpp"
 | 
|---|
 | 60 | #include "cycles/cycle.hpp"
 | 
|---|
 | 61 | #include "grid/grid.hpp"
 | 
|---|
 | 62 | #include "grid/tempgrid.hpp"
 | 
|---|
 | 63 | #include "level/level_operator.hpp"
 | 
|---|
 | 64 | #include "smoother/smoother.hpp"
 | 
|---|
 | 65 | #include "solver/solver.hpp"
 | 
|---|
 | 66 | #include "mg.hpp"
 | 
|---|
 | 67 | 
 | 
|---|
 | 68 | using namespace VMG;
 | 
|---|
 | 69 | 
 | 
|---|
 | 70 | #define REGISTER_COMMAND(a) extern void Initialize##a();Initialize##a();
 | 
|---|
 | 71 | 
 | 
|---|
 | 72 | VMG::CommandFactory MG::command_factory;
 | 
|---|
 | 73 | 
 | 
|---|
 | 74 | static void VMGRegisterBuiltinCommands()
 | 
|---|
 | 75 | {
 | 
|---|
 | 76 |   REGISTER_COMMAND(VMGCommandCheckConsistency);
 | 
|---|
 | 77 |   REGISTER_COMMAND(VMGCommandCheckIterationCounter);
 | 
|---|
 | 78 |   REGISTER_COMMAND(VMGCommandCheckRelativeResidual);
 | 
|---|
 | 79 |   REGISTER_COMMAND(VMGCommandCheckResidual);
 | 
|---|
 | 80 |   REGISTER_COMMAND(VMGCommandClearCoarseLevels);
 | 
|---|
 | 81 |   REGISTER_COMMAND(VMGCommandClearGrid);
 | 
|---|
 | 82 |   REGISTER_COMMAND(VMGCommandComputeResidualNorm);
 | 
|---|
 | 83 |   REGISTER_COMMAND(VMGCommandCopyBoundary);
 | 
|---|
 | 84 |   REGISTER_COMMAND(VMGCommandExecuteCycle);
 | 
|---|
 | 85 |   REGISTER_COMMAND(VMGCommandExecuteCycleLoop);
 | 
|---|
 | 86 |   REGISTER_COMMAND(VMGCommandExecuteFullCycle);
 | 
|---|
 | 87 |   REGISTER_COMMAND(VMGCommandExecuteFullCycleLoop);
 | 
|---|
 | 88 |   REGISTER_COMMAND(VMGCommandExportSolution);
 | 
|---|
 | 89 |   REGISTER_COMMAND(VMGCommandForceDiscreteCompatibility);
 | 
|---|
 | 90 |   REGISTER_COMMAND(VMGCommandImportRightHandSide);
 | 
|---|
 | 91 |   REGISTER_COMMAND(VMGCommandInterpolateFMG);
 | 
|---|
 | 92 |   REGISTER_COMMAND(VMGCommandInitializeIterationCounter);
 | 
|---|
 | 93 |   REGISTER_COMMAND(VMGCommandInitializeResidualNorm);
 | 
|---|
 | 94 |   REGISTER_COMMAND(VMGCommandNOP);
 | 
|---|
 | 95 |   REGISTER_COMMAND(VMGCommandPrintAllSettings);
 | 
|---|
 | 96 |   REGISTER_COMMAND(VMGCommandPrintDefect);
 | 
|---|
 | 97 |   REGISTER_COMMAND(VMGCommandPrintGridStructure);
 | 
|---|
 | 98 |   REGISTER_COMMAND(VMGCommandPrintGrid);
 | 
|---|
 | 99 |   REGISTER_COMMAND(VMGCommandPrintResidualNorm);
 | 
|---|
 | 100 |   REGISTER_COMMAND(VMGCommandPrintRunningTime);
 | 
|---|
 | 101 |   REGISTER_COMMAND(VMGCommandProlongate);
 | 
|---|
 | 102 |   REGISTER_COMMAND(VMGCommandRestrict);
 | 
|---|
 | 103 |   REGISTER_COMMAND(VMGCommandSetAverageToZero);
 | 
|---|
 | 104 |   REGISTER_COMMAND(VMGCommandSetCoarserDirichletValues);
 | 
|---|
 | 105 |   REGISTER_COMMAND(VMGCommandSetLevel);
 | 
|---|
 | 106 |   REGISTER_COMMAND(VMGCommandSmooth);
 | 
|---|
 | 107 |   REGISTER_COMMAND(VMGCommandSolve);
 | 
|---|
 | 108 | }
 | 
|---|
 | 109 | 
 | 
|---|
 | 110 | MG::MG()
 | 
|---|
 | 111 | {
 | 
|---|
 | 112 |   state = 0;
 | 
|---|
 | 113 |   VMGRegisterBuiltinCommands();
 | 
|---|
 | 114 | }
 | 
|---|
 | 115 | 
 | 
|---|
 | 116 | MG::~MG()
 | 
|---|
 | 117 | {
 | 
|---|
 | 118 |   MG::Destroy();
 | 
|---|
 | 119 | }
 | 
|---|
 | 120 | 
 | 
|---|
 | 121 | // Brings Multigrid back to starting state.
 | 
|---|
 | 122 | void MG::Destroy()
 | 
|---|
 | 123 | {
 | 
|---|
 | 124 |   MG::Instance()->factories.clear();
 | 
|---|
 | 125 |   MG::Instance()->state = 0;
 | 
|---|
 | 126 |   Timer::Clear();
 | 
|---|
 | 127 | }
 | 
|---|
 | 128 | 
 | 
|---|
 | 129 | /*
 | 
|---|
 | 130 |  * Post init communication class
 | 
|---|
 | 131 |  */
 | 
|---|
 | 132 | void MG::PostInit()
 | 
|---|
 | 133 | {
 | 
|---|
 | 134 |   if (GetFactory().TestObject("COMM") && GetFactory().TestObject("INTERFACE")) {
 | 
|---|
 | 135 | 
 | 
|---|
 | 136 |     Comm& comm = *GetComm();
 | 
|---|
 | 137 |     Interface& interface = *GetInterface();
 | 
|---|
 | 138 | 
 | 
|---|
 | 139 |     comm.ComputeDomainDecomposition(interface);
 | 
|---|
 | 140 | 
 | 
|---|
 | 141 |     Multigrid* sol = new Multigrid(comm, interface);
 | 
|---|
 | 142 |     sol->Register("SOL");
 | 
|---|
 | 143 | 
 | 
|---|
 | 144 |     Multigrid* rhs = new Multigrid(comm, interface);
 | 
|---|
 | 145 |     rhs->Register("RHS");
 | 
|---|
 | 146 | 
 | 
|---|
 | 147 |     TempGrid* temp = new TempGrid();
 | 
|---|
 | 148 |     temp->Register("TEMPGRID");
 | 
|---|
 | 149 | 
 | 
|---|
 | 150 |     new ObjectStorage<int>("GLOBAL_MAXLEVEL", sol->GlobalMaxLevel());
 | 
|---|
 | 151 |     new ObjectStorage<int>("MINLEVEL", sol->MinLevel());
 | 
|---|
 | 152 |     new ObjectStorage<int>("MAXLEVEL", sol->MaxLevel());
 | 
|---|
 | 153 | 
 | 
|---|
 | 154 |     if (GetFactory().TestObject("CYCLE"))
 | 
|---|
 | 155 |       GetCycle()->Generate();
 | 
|---|
 | 156 | 
 | 
|---|
 | 157 |     if (comm.BoundaryConditions()[0] == Open &&
 | 
|---|
 | 158 |         comm.BoundaryConditions()[1] == Open &&
 | 
|---|
 | 159 |         comm.BoundaryConditions()[2] == Open) {
 | 
|---|
 | 160 |       new BoundaryValueSetterOpen();
 | 
|---|
 | 161 |     }
 | 
|---|
 | 162 | 
 | 
|---|
 | 163 |     comm.PostInit(*GetSol(), *GetRhs());
 | 
|---|
 | 164 | 
 | 
|---|
 | 165 |   }
 | 
|---|
 | 166 | }
 | 
|---|
 | 167 | 
 | 
|---|
 | 168 | /**
 | 
|---|
 | 169 |  * Solves a given system with a multigrid method
 | 
|---|
 | 170 |  *
 | 
|---|
 | 171 |  */
 | 
|---|
 | 172 | void MG::Solve()
 | 
|---|
 | 173 | {
 | 
|---|
 | 174 | #ifdef OUTPUT_TIMING
 | 
|---|
 | 175 |   GetComm()->Barrier();
 | 
|---|
 | 176 |   Timer::Start("CompleteRunningTime");
 | 
|---|
 | 177 | #endif
 | 
|---|
 | 178 | 
 | 
|---|
 | 179 |   CommandList* cl_init = MG::GetFactory().Get("COMMANDLIST_INIT")->Cast<CommandList>();
 | 
|---|
 | 180 |   CommandList* cl_loop = MG::GetFactory().Get("COMMANDLIST_LOOP")->Cast<CommandList>();
 | 
|---|
 | 181 |   CommandList* cl_finalize = MG::GetFactory().Get("COMMANDLIST_FINALIZE")->Cast<CommandList>();
 | 
|---|
 | 182 | 
 | 
|---|
 | 183 |   cl_init->ExecuteList();
 | 
|---|
 | 184 | 
 | 
|---|
 | 185 |   while (cl_loop->ExecuteList() == Continue);
 | 
|---|
 | 186 | 
 | 
|---|
 | 187 |   cl_finalize->ExecuteList();
 | 
|---|
 | 188 | 
 | 
|---|
 | 189 | #ifdef OUTPUT_TIMING
 | 
|---|
 | 190 |   GetComm()->Barrier();
 | 
|---|
 | 191 |   Timer::Stop("CompleteRunningTime");
 | 
|---|
 | 192 | #ifdef HAVE_MPI
 | 
|---|
 | 193 |   Timer::PrintGlobal();
 | 
|---|
 | 194 | #else
 | 
|---|
 | 195 |   Timer::Print();
 | 
|---|
 | 196 | #endif
 | 
|---|
 | 197 | #endif
 | 
|---|
 | 198 | }
 | 
|---|
 | 199 | 
 | 
|---|
 | 200 | void MG::SetState(const int& state_)
 | 
|---|
 | 201 | {
 | 
|---|
 | 202 |   MG::Instance()->state = state_;
 | 
|---|
 | 203 | }
 | 
|---|
 | 204 | 
 | 
|---|
 | 205 | VMG::Factory& MG::GetFactory()
 | 
|---|
 | 206 | {
 | 
|---|
 | 207 |   std::map<int, VMG::Factory>::iterator iter = MG::Instance()->factories.find(MG::Instance()->state);
 | 
|---|
 | 208 | 
 | 
|---|
 | 209 |   if (iter == MG::Instance()->factories.end())
 | 
|---|
 | 210 |     iter = MG::Instance()->factories.insert(std::make_pair(MG::Instance()->state, Factory())).first;
 | 
|---|
 | 211 | 
 | 
|---|
 | 212 |   assert(iter != MG::Instance()->factories.end());
 | 
|---|
 | 213 | 
 | 
|---|
 | 214 |   return iter->second;
 | 
|---|
 | 215 | }
 | 
|---|
 | 216 | 
 | 
|---|
 | 217 | VMG::CommandFactory& MG::GetCommands()
 | 
|---|
 | 218 | {
 | 
|---|
 | 219 |   return MG::command_factory;
 | 
|---|
 | 220 | }
 | 
|---|
 | 221 | 
 | 
|---|
 | 222 | Comm* MG::GetComm()
 | 
|---|
 | 223 | {
 | 
|---|
 | 224 |   return MG::GetFactory().Get("COMM")->Cast<VMG::Comm>();
 | 
|---|
 | 225 | }
 | 
|---|
 | 226 | 
 | 
|---|
 | 227 | Cycle* MG::GetCycle()
 | 
|---|
 | 228 | {
 | 
|---|
 | 229 |   return MG::GetFactory().Get("CYCLE")->Cast<VMG::Cycle>();
 | 
|---|
 | 230 | }
 | 
|---|
 | 231 | 
 | 
|---|
 | 232 | Discretization* MG::GetDiscretization()
 | 
|---|
 | 233 | {
 | 
|---|
 | 234 |   return MG::GetFactory().Get("DISCRETIZATION")->Cast<VMG::Discretization>();
 | 
|---|
 | 235 | }
 | 
|---|
 | 236 | 
 | 
|---|
 | 237 | LevelOperator* MG::GetLevelOperator()
 | 
|---|
 | 238 | {
 | 
|---|
 | 239 |   return MG::GetFactory().Get("LEVEL_OPERATOR")->Cast<VMG::LevelOperator>();
 | 
|---|
 | 240 | }
 | 
|---|
 | 241 | 
 | 
|---|
 | 242 | Multigrid* MG::GetRhs()
 | 
|---|
 | 243 | {
 | 
|---|
 | 244 |   return MG::GetFactory().Get("RHS")->Cast<VMG::Multigrid>();
 | 
|---|
 | 245 | }
 | 
|---|
 | 246 | 
 | 
|---|
 | 247 | Multigrid* MG::GetSol()
 | 
|---|
 | 248 | {
 | 
|---|
 | 249 |   return MG::GetFactory().Get("SOL")->Cast<VMG::Multigrid>();
 | 
|---|
 | 250 | }
 | 
|---|
 | 251 | 
 | 
|---|
 | 252 | VMG::Grid& MG::GetRhsMaxLevel()
 | 
|---|
 | 253 | {
 | 
|---|
 | 254 |   return (*MG::GetRhs())(MG::GetRhs()->MaxLevel());
 | 
|---|
 | 255 | }
 | 
|---|
 | 256 | 
 | 
|---|
 | 257 | VMG::Grid& MG::GetSolMaxLevel()
 | 
|---|
 | 258 | {
 | 
|---|
 | 259 |   return (*MG::GetSol())(MG::GetSol()->MaxLevel());
 | 
|---|
 | 260 | }
 | 
|---|
 | 261 | 
 | 
|---|
 | 262 | Smoother* MG::GetSmoother()
 | 
|---|
 | 263 | {
 | 
|---|
 | 264 |   return MG::GetFactory().Get("SMOOTHER")->Cast<VMG::Smoother>();
 | 
|---|
 | 265 | }
 | 
|---|
 | 266 | 
 | 
|---|
 | 267 | Solver* MG::GetSolver()
 | 
|---|
 | 268 | {
 | 
|---|
 | 269 |   return MG::GetFactory().Get("SOLVER")->Cast<VMG::Solver>();
 | 
|---|
 | 270 | }
 | 
|---|
 | 271 | 
 | 
|---|
 | 272 | TempGrid* MG::GetTempGrid()
 | 
|---|
 | 273 | {
 | 
|---|
 | 274 |   return MG::GetFactory().Get("TEMPGRID")->Cast<VMG::TempGrid>();
 | 
|---|
 | 275 | }
 | 
|---|
 | 276 | 
 | 
|---|
 | 277 | Interface* MG::GetInterface()
 | 
|---|
 | 278 | {
 | 
|---|
 | 279 |   return MG::GetFactory().Get("INTERFACE")->Cast<VMG::Interface>();
 | 
|---|
 | 280 | }
 | 
|---|
 | 281 | 
 | 
|---|
 | 282 | BoundaryValueSetter* MG::GetBoundaryValueSetter()
 | 
|---|
 | 283 | {
 | 
|---|
 | 284 |   return MG::GetFactory().Get("BOUNDARY_VALUE_SETTER")->Cast<VMG::BoundaryValueSetter>();
 | 
|---|
 | 285 | }
 | 
|---|
 | 286 | 
 | 
|---|
 | 287 | bool MG::IsInitialized()
 | 
|---|
 | 288 | {
 | 
|---|
 | 289 |   const Factory& f = GetFactory();
 | 
|---|
 | 290 | 
 | 
|---|
 | 291 |   bool init = true;
 | 
|---|
 | 292 | 
 | 
|---|
 | 293 |   init &= f.TestObject("COMM");
 | 
|---|
 | 294 |   init &= f.TestObject("LEVEL_OPERATOR");
 | 
|---|
 | 295 |   init &= f.TestObject("RHS");
 | 
|---|
 | 296 |   init &= f.TestObject("SOL");
 | 
|---|
 | 297 |   init &= f.TestObject("SOLVER");
 | 
|---|
 | 298 |   init &= f.TestObject("SMOOTHER");
 | 
|---|
 | 299 |   init &= f.TestObject("DISCRETIZATION");
 | 
|---|
 | 300 |   init &= f.TestObject("MAX_ITERATION");
 | 
|---|
 | 301 |   init &= f.TestObject("PRECISION");
 | 
|---|
 | 302 |   init &= f.TestObject("PRESMOOTHSTEPS");
 | 
|---|
 | 303 |   init &= f.TestObject("POSTSMOOTHSTEPS");
 | 
|---|
 | 304 |   init &= f.TestObject("COMMANDLIST_INIT");
 | 
|---|
 | 305 |   init &= f.TestObject("COMMANDLIST_LOOP");
 | 
|---|
 | 306 |   init &= f.TestObject("COMMANDLIST_FINALIZE");
 | 
|---|
 | 307 |   init &= f.TestObject("MINLEVEL");
 | 
|---|
 | 308 |   init &= f.TestObject("MAXLEVEL");
 | 
|---|
 | 309 |   init &= f.TestObject("GLOBAL_MAXLEVEL");
 | 
|---|
 | 310 |   init &= f.TestObject("INTERFACE");
 | 
|---|
 | 311 | 
 | 
|---|
 | 312 |   return init;
 | 
|---|
 | 313 | }
 | 
|---|