/** * @file interface_particles.cpp * @author Julian Iseringhausen * @date Mon Apr 18 12:56:48 2011 * * @brief VMG::InterfaceParticles * */ #ifdef HAVE_CONFIG_H #include #endif #ifdef HAVE_MPI #include #ifdef HAVE_MARMOT #include #include #endif #endif #include #include #include #include "base/helper.hpp" #include "base/index.hpp" #include "base/interpolate_polynomial.hpp" #include "base/linked_cell_list.hpp" #include "base/math.hpp" #include "base/vector.hpp" #include "comm/comm.hpp" #include "grid/grid.hpp" #include "grid/multigrid.hpp" #include "grid/tempgrid.hpp" #include "interface/interface_particles.hpp" #include "mg.hpp" using namespace VMG; void InterfaceParticles::ImportRightHandSide(Multigrid& multigrid) { Index index_global, index_local, index; Vector pos_rel, pos_abs, grid_val; Factory& factory = MG::GetFactory(); Comm& comm = *MG::GetComm(); const int& near_field_cells = factory.GetObjectStorageVal("PARTICLE_NEAR_FIELD_CELLS"); Grid& grid = multigrid(multigrid.MaxLevel()); Grid& particle_grid = comm.GetParticleGrid(); particle_grid.Clear(); assert(particle_grid.Global().LocalSize().IsComponentwiseGreater(near_field_cells)); /* * Distribute particles to their processes */ particles.clear(); comm.CommParticles(grid, particles); /* * Charge assignment on the grid */ std::list::iterator iter; #ifdef DEBUG_OUTPUT vmg_float particle_charges = 0.0; for (iter=particles.begin(); iter!=particles.end(); ++iter) particle_charges += iter->Charge(); particle_charges = MG::GetComm()->GlobalSumRoot(particle_charges); comm.PrintStringOnce("Particle list charge sum: %e", particle_charges); comm.PrintString("Local number of particles: %d", particles.size()); #endif for (iter=particles.begin(); iter!=particles.end(); ++iter) spl.SetSpline(particle_grid, *iter, near_field_cells); // Communicate charges over halo comm.CommFromGhosts(particle_grid); // Assign charge values to the right hand side for (index.X()=0; index.X()GlobalSum(charge_sum); comm.PrintStringOnce("Grid charge sum: %e", charge_sum); #endif } void InterfaceParticles::ExportSolution(Grid& grid) { Index i; vmg_float length; #ifdef DEBUG_OUTPUT vmg_float e = 0.0; vmg_float e_long = 0.0; vmg_float e_self = 0.0; vmg_float e_short_peak = 0.0; vmg_float e_short_spline = 0.0; #endif Factory& factory = MG::GetFactory(); Comm& comm = *MG::GetComm(); /* * Get parameters and arrays */ const vmg_int& num_particles_local = factory.GetObjectStorageVal("PARTICLE_NUM_LOCAL"); const vmg_int& near_field_cells = factory.GetObjectStorageVal("PARTICLE_NEAR_FIELD_CELLS"); const vmg_int& interpolation_degree = factory.GetObjectStorageVal("PARTICLE_INTERPOLATION_DEGREE"); vmg_float* p = factory.GetObjectStorageArray("PARTICLE_POTENTIAL_ARRAY"); vmg_float* f = factory.GetObjectStorageArray("PARTICLE_FIELD_ARRAY"); InterpolatePolynomial ip(interpolation_degree); const vmg_float r_cut = near_field_cells * grid.Extent().MeshWidth().Max(); // Initialize field std::fill(f, f+3*num_particles_local, 0.0); /* * Copy potential values to a grid with sufficiently large halo size. * This may be optimized in future. * The parameters of this grid have been set in the import step. */ Grid& particle_grid = comm.GetParticleGrid(); for (i.X()=0; i.X()& lc_1 = lc(*iter); for (p1=lc_1.begin(); p1!=lc_1.end(); ++p1) { (*p1)->Pot() = ip.Evaluate((*p1)->Pos()) - (*p1)->Charge() * spl.GetAntiDerivativeAtZero(); #ifdef DEBUG_OUTPUT e_long += 0.5 * (*p1)->Charge() * ip.Evaluate((*p1)->Pos()); e_self += 0.5 * (*p1)->Charge() * (*p1)->Charge() * spl.GetAntiDerivativeAtZero(); #endif for (i.X()=-1*near_field_cells; i.X()<=near_field_cells; ++i.X()) for (i.Y()=-1*near_field_cells; i.Y()<=near_field_cells; ++i.Y()) for (i.Z()=-1*near_field_cells; i.Z()<=near_field_cells; ++i.Z()) { std::list& lc_2 = lc(*iter+i); for (p2=lc_2.begin(); p2!=lc_2.end(); ++p2) if (*p1 != *p2) { length = ((*p2)->Pos() - (*p1)->Pos()).Length(); if (length < r_cut) { (*p1)->Pot() += (*p2)->Charge() / length * (1.0 + spl.EvaluatePotential(length)); #ifdef DEBUG_OUTPUT e_short_peak += 0.5 * (*p1)->Charge() * (*p2)->Charge() / length; e_short_spline += 0.5 * (*p1)->Charge() * (*p2)->Charge() / length * spl.EvaluatePotential(length); #endif } } } } } comm.CommParticlesBack(particles); #ifdef DEBUG_OUTPUT vmg_float* q = factory.GetObjectStorageArray("PARTICLE_CHARGE_ARRAY"); e_long = comm.GlobalSumRoot(e_long); e_short_peak = comm.GlobalSumRoot(e_short_peak); e_short_spline = comm.GlobalSumRoot(e_short_spline); e_self = comm.GlobalSumRoot(e_self); for (int j=0; j