/* * Project: MoleCuilder * Description: creates and alters molecular systems * Copyright (C) 2012 University of Bonn. All rights reserved. * Copyright (C) 2013 Frederik Heber. All rights reserved. * * * This file is part of MoleCuilder. * * MoleCuilder 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 2 of the License, or * (at your option) any later version. * * MoleCuilder 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 MoleCuilder. If not, see . */ /* * VMGJob.cpp * * Created on: Jul 13, 2012 * Author: heber */ // include config.h #ifdef HAVE_CONFIG_H #include #endif #ifdef HAVE_MPI #include "mpi.h" #endif // include headers that implement a archive in simple text format // otherwise BOOST_CLASS_EXPORT_IMPLEMENT has no effect #include #include #include "mg.hpp" #include "base/object.hpp" #include "base/defs.hpp" #ifdef HAVE_MPI #include "comm/comm_mpi.hpp" #include "comm/domain_decomposition_mpi.hpp" #else #include "comm/comm_serial.hpp" #endif // periodic boundary conditions #include "cycles/cycle_cs_periodic.hpp" #include "discretization/discretization_poisson_fd.hpp" #include "level/level_operator_cs.hpp" #include "smoother/gsrb_poisson_4.hpp" #include "solver/solver_singular.hpp" // open boundary conditions #include "cycles/cycle_fas_dirichlet.hpp" #include "discretization/discretization_poisson_fv.hpp" #include "grid/multigrid.hpp" //#include "grid/tempgrid.hpp" #include "level/level_operator_fas.hpp" #include "level/stencils.hpp" #include "smoother/gsrb_poisson_2.hpp" #include "solver/givens.hpp" #include "solver/solver_regular.hpp" #include "units/particle/comm_mpi_particle.hpp" #include "CodePatterns/MemDebug.hpp" #include "Jobs/VMGJob.hpp" #include "LinearAlgebra/defs.hpp" #include "Jobs/InterfaceVMGJob.hpp" #include "CodePatterns/Assert.hpp" using namespace VMG; VMGJob::VMGJob( const JobId_t _JobId, const SamplingGrid &_density_grid, const std::vector< std::vector< double > > &_particle_positions, const std::vector< double > &_particle_charges, const size_t _near_field_cells, const size_t _interpolation_degree, const bool _DoImportParticles, const bool _DoPrintDebug, const bool _OpenBoundaryConditions, const bool _DoSmearCharges) : FragmentJob(_JobId), density_grid(_density_grid), particle_positions(_particle_positions), particle_charges(_particle_charges), near_field_cells(_near_field_cells), interpolation_degree(_interpolation_degree), DoImportParticles(_DoImportParticles), DoPrintDebug(_DoPrintDebug), OpenBoundaryConditions(_OpenBoundaryConditions), DoSmearCharges(_DoSmearCharges), returndata(static_cast(_density_grid)), particles() {} VMGJob::VMGJob() : FragmentJob(JobId::IllegalJob), near_field_cells(3), interpolation_degree(3), DoImportParticles(true), DoPrintDebug(false), OpenBoundaryConditions(false), DoSmearCharges(false), particles() {} VMGJob::~VMGJob() { } VMGJob::particle_arrays::particle_arrays() : num_particles(0), f(NULL), x(NULL), p(NULL), q(NULL) {} VMGJob::particle_arrays::~particle_arrays() { delete[] f; delete[] x; delete[] p; delete[] q; } void VMGJob::particle_arrays::init(const size_t _num_particles) { num_particles = _num_particles; f = new double[num_particles*3]; x = new double[num_particles*3]; p = new double[num_particles]; q = new double[num_particles]; } void VMGJob::InitVMGArrays() { particles.init(particle_charges.size()); { size_t index=0; for (std::vector< std::vector< double > >::const_iterator iter = particle_positions.begin(); iter != particle_positions.end(); ++iter) { for (std::vector< double >::const_iterator positer = (*iter).begin(); positer != (*iter).end(); ++positer) { particles.f[index] = 0.; particles.x[index++] = *positer; } } ASSERT( index == particles.num_particles*3, "VMGJob::VMGJob() - too many particles or components in particle_positions."); } { size_t index = 0; for (std::vector< double >::const_iterator iter = particle_charges.begin(); iter != particle_charges.end(); ++iter) { particles.p[index] = 0.; particles.q[index++] = *iter; } ASSERT( index == particles.num_particles, "VMGJob::VMGJob() - too many charges in particle_charges."); } } FragmentResult::ptr VMGJob::Work() { // initialize VMG library solver InitVMG(); /* * Start the multigrid solver */ MG::Solve(); /// create and fill result object // place into returnstream std::stringstream returnstream; { const VMGData archivedata(returndata); boost::archive::text_oarchive oa(returnstream); oa << archivedata; } FragmentResult::ptr ptr( new FragmentResult(getId(), returnstream.str()) ); /* * Delete all data. */ MG::Destroy(); return ptr; } /** Initialization of VMG library. * * The contents is heavily inspired from interface_fcs.cpp: VMG_fcs_init() of * the ScaFaCoS project. * */ void VMGJob::InitVMG() { Boundary *boundary = NULL; if (OpenBoundaryConditions) boundary = new Boundary(Open, Open, Open); else boundary = new Boundary(Periodic, Periodic, Periodic); /* * Choose multigrid components (self-registering) */ #ifdef HAVE_MPI new Particle::CommMPI(*boundary, new DomainDecompositionMPI()); #else new CommSerial(*boundary); #endif if (OpenBoundaryConditions) new DiscretizationPoissonFV(2); else new DiscretizationPoissonFD(4); new VMGInterfaces::InterfaceVMGJob( density_grid, returndata, particle_positions, particle_charges, *boundary, 2, density_grid.level, Vector(density_grid.begin), density_grid.end[0]-density_grid.begin[0], near_field_cells, DoImportParticles ? VMGInterfaces::InterfaceVMGJob::DoImportParticles : VMGInterfaces::InterfaceVMGJob::DontImportParticles, DoPrintDebug, DoSmearCharges); const int cycle_type = 1; // V-type if (OpenBoundaryConditions) { new LevelOperatorFAS(Stencils::RestrictionFullWeight, Stencils::Injection, Stencils::InterpolationTrilinear); new Givens(); new CycleFASDirichlet(cycle_type); new GaussSeidelRBPoisson2(); } else { new LevelOperatorCS(Stencils::RestrictionFullWeight, Stencils::InterpolationTrilinear); new Givens(); new CycleCSPeriodic(cycle_type); new GaussSeidelRBPoisson4(); } delete boundary; /* * Register required parameters */ new ObjectStorage("PRESMOOTHSTEPS", 3); new ObjectStorage("POSTSMOOTHSTEPS", 3); new ObjectStorage("PRECISION", 1.0e-10); new ObjectStorage("MAX_ITERATION", 15); new ObjectStorage("PARTICLE_NEAR_FIELD_CELLS", near_field_cells); new ObjectStorage("PARTICLE_INTERPOLATION_DEGREE", interpolation_degree); // first initialize f,x,p,q,... from STL vectors InitVMGArrays(); // then initialize as objects with VMG's storage new ObjectStorage("PARTICLE_POS_ARRAY", particles.x); new ObjectStorage("PARTICLE_CHARGE_ARRAY", particles.q); new ObjectStorage("PARTICLE_POTENTIAL_ARRAY", particles.p); new ObjectStorage("PARTICLE_FIELD_ARRAY", particles.f); new ObjectStorage("PARTICLE_NUM_LOCAL", particles.num_particles); /* * Post init */ MG::PostInit(); /* * Check whether the library is correctly initialized now. */ MG::IsInitialized(); } // we need to explicitly instantiate the serialization functions as // its is only serialized through its base class FragmentJob BOOST_CLASS_EXPORT_IMPLEMENT(VMGJob)