|
| 1 | +#include <memory> |
| 2 | + |
| 3 | +#include <pfasst.hpp> |
| 4 | +#include <pfasst/config.hpp> |
| 5 | +#include <pfasst/logging.hpp> |
| 6 | +#include <pfasst/controller/pfasst.hpp> |
| 7 | +#include <pfasst/mpi_communicator.hpp> |
| 8 | +using namespace pfasst; |
| 9 | + |
| 10 | +#include "particle.hpp" |
| 11 | +#include "particle_cloud.hpp" |
| 12 | +#include "bindings/wrapper_interface.hpp" |
| 13 | +#include "bindings/wrapper_simple_physics_solver.hpp" |
| 14 | +#include "boris_sweeper.hpp" |
| 15 | +#include "injective_transfer.hpp" |
| 16 | + |
| 17 | + |
| 18 | +namespace pfasst |
| 19 | +{ |
| 20 | + namespace examples |
| 21 | + { |
| 22 | + namespace boris |
| 23 | + { |
| 24 | + template<typename scalar> |
| 25 | + error_map<scalar> run_boris_pfasst(const size_t nsteps, const scalar dt, const size_t nnodes, |
| 26 | + const size_t nparticles, const size_t niters, |
| 27 | + const double abs_res_tol, const double rel_res_tol) |
| 28 | + { |
| 29 | + PFASST<> controller; |
| 30 | + mpi::MPICommunicator comm(MPI_COMM_WORLD); |
| 31 | + controller.set_comm(&comm); |
| 32 | + |
| 33 | + const double mass = 1.0; |
| 34 | + const double charge = 1.0; |
| 35 | + |
| 36 | + shared_ptr<bindings::WrapperInterface<double, double>> impl_solver = \ |
| 37 | + make_shared<bindings::WrapperSimplePhysicsSolver<double, double>>(); |
| 38 | + bindings::setup(dynamic_pointer_cast<bindings::WrapperSimplePhysicsSolver<double, double>>(impl_solver)); |
| 39 | + |
| 40 | + // fine level |
| 41 | + auto quad1 = quadrature::quadrature_factory<double>(nnodes, |
| 42 | + quadrature::QuadratureType::GaussLobatto); |
| 43 | + auto factory1 = make_shared<ParticleCloudFactory<double>>(nparticles, 3, mass, charge); |
| 44 | + string data_file1 = "s" + to_string(nsteps) + "_i" + to_string(niters) |
| 45 | + + "_dt" + to_string(dt) + "_m" + to_string(nnodes) |
| 46 | + + "_p" + to_string(nparticles) + "_level1.csv"; |
| 47 | + auto sweeper1 = make_shared<BorisSweeper<double, double>>(impl_solver, data_file1); |
| 48 | + auto transfer1 = make_shared<InjectiveTransfer<double, double>>(); |
| 49 | + sweeper1->set_quadrature(quad1); |
| 50 | + sweeper1->set_factory(factory1); |
| 51 | + sweeper1->set_residual_tolerances(abs_res_tol, rel_res_tol); |
| 52 | + controller.add_level(sweeper1, transfer1); |
| 53 | + |
| 54 | + // coarse level |
| 55 | + auto quad2 = quadrature::quadrature_factory<double>(nnodes, |
| 56 | + quadrature::QuadratureType::GaussLobatto); |
| 57 | + auto factory2 = make_shared<ParticleCloudFactory<double>>(nparticles, 3, mass, charge); |
| 58 | + string data_file2 = "s" + to_string(nsteps) + "_i" + to_string(niters) |
| 59 | + + "_dt" + to_string(dt) + "_m" + to_string(nnodes) |
| 60 | + + "_p" + to_string(nparticles) + "_level2.csv"; |
| 61 | + auto sweeper2 = make_shared<BorisSweeper<double, double>>(impl_solver, data_file2); |
| 62 | + auto transfer2 = make_shared<InjectiveTransfer<double, double>>(); |
| 63 | + sweeper2->set_quadrature(quad2); |
| 64 | + sweeper2->set_factory(factory2); |
| 65 | + controller.add_level(sweeper2, transfer2); |
| 66 | + |
| 67 | + controller.set_duration(0.0, nsteps*dt, dt, niters); |
| 68 | + controller.set_options(); |
| 69 | + controller.setup(); |
| 70 | + |
| 71 | + shared_ptr<Particle<double>> center = make_shared<Particle<double>>(); |
| 72 | + center->pos()[0] = 10; |
| 73 | + center->vel()[0] = 100; |
| 74 | + center->vel()[2] = 100; |
| 75 | + |
| 76 | + auto fine_sweeper = controller.get_finest<BorisSweeper<double, double>>(); |
| 77 | + shared_ptr<ParticleCloud<double>> q0 = \ |
| 78 | + dynamic_pointer_cast<ParticleCloud<double>>(fine_sweeper->get_start_state()); |
| 79 | + q0->distribute_around_center(center); |
| 80 | + CLOG(INFO, "Boris") << "Initial Particle (fine) : " |
| 81 | + << *(dynamic_pointer_cast<ParticleCloud<double>>(fine_sweeper->get_start_state())); |
| 82 | + fine_sweeper->set_initial_energy(); |
| 83 | + |
| 84 | + controller.run(); |
| 85 | + |
| 86 | + return fine_sweeper->get_errors(); |
| 87 | + } |
| 88 | + } // ::pfasst::examples::boris |
| 89 | + } // ::pfasst::examples |
| 90 | +} // ::pfasst |
| 91 | + |
| 92 | +#ifndef PFASST_UNIT_TESTING |
| 93 | +int main(int argc, char** argv) |
| 94 | +{ |
| 95 | + MPI_Init(&argc, &argv); |
| 96 | + pfasst::init(argc, argv, pfasst::examples::boris::init_opts<double>); |
| 97 | + pfasst::log::add_custom_logger("Boris"); |
| 98 | + pfasst::log::add_custom_logger("BorisTransfer"); |
| 99 | + pfasst::log::add_custom_logger("Solver"); |
| 100 | + |
| 101 | + const size_t nsteps = pfasst::config::get_value<size_t>("num_steps", 1); |
| 102 | + const double dt = pfasst::config::get_value<double>("delta_step", 0.015625); |
| 103 | + const size_t nnodes = pfasst::config::get_value<size_t>("num_nodes", 5); |
| 104 | + const size_t nparticles = pfasst::config::get_value<size_t>("num_particles", 1); |
| 105 | + const size_t niters = pfasst::config::get_value<size_t>("num_iter", 2); |
| 106 | + const double abs_res_tol = pfasst::config::get_value<double>("abs_res_tol", 0.0); |
| 107 | + const double rel_res_tol = pfasst::config::get_value<double>("rel_res_tol", 0.0); |
| 108 | + |
| 109 | + LOG(INFO) << "nsteps=" << nsteps << ", " |
| 110 | + << "dt=" << dt << ", " |
| 111 | + << "nnodes=" << nnodes << ", " |
| 112 | + << "nparticles=" << nparticles << ", " |
| 113 | + << "niter=" << niters << ", " |
| 114 | + << "abs res=" << abs_res_tol << ", " |
| 115 | + << "rel res=" << rel_res_tol; |
| 116 | + |
| 117 | + pfasst::examples::boris::run_boris_pfasst<double>(nsteps, dt, nnodes, nparticles, niters, abs_res_tol, rel_res_tol); |
| 118 | + MPI_Finalize(); |
| 119 | +} |
| 120 | +#endif |
0 commit comments