#include #include #include #include #include #ifdef ENABLE_PHANTOM_GRAPE_X86 #include #endif #ifdef ENABLE_GPU_CUDA #define MULTI_WALK #include"force_gpu_cuda.hpp" #endif #include "user-defined.hpp" void makeColdUniformSphere(const PS::F64 mass_glb, const PS::S64 n_glb, const PS::S64 n_loc, PS::F64 *& mass, PS::F64vec *& pos, PS::F64vec *& vel, const PS::F64 eng = -0.25, const PS::S32 seed = 0) { assert(eng < 0.0); { PS::MTTS mt; mt.init_genrand(0); for(PS::S32 i = 0; i < n_loc; i++){ mass[i] = mass_glb / n_glb; const PS::F64 radius = 3.0; do { pos[i][0] = (2. * mt.genrand_res53() - 1.) * radius; pos[i][1] = (2. * mt.genrand_res53() - 1.) * radius; pos[i][2] = (2. * mt.genrand_res53() - 1.) * radius; }while(pos[i] * pos[i] >= radius * radius); vel[i][0] = 0.0; vel[i][1] = 0.0; vel[i][2] = 0.0; } } PS::F64vec cm_pos = 0.0; PS::F64vec cm_vel = 0.0; PS::F64 cm_mass = 0.0; for(PS::S32 i = 0; i < n_loc; i++){ cm_pos += mass[i] * pos[i]; cm_vel += mass[i] * vel[i]; cm_mass += mass[i]; } cm_pos /= cm_mass; cm_vel /= cm_mass; for(PS::S32 i = 0; i < n_loc; i++){ pos[i] -= cm_pos; vel[i] -= cm_vel; } } template void setParticlesColdUniformSphere(Tpsys & psys, const PS::S32 n_glb, PS::S32 & n_loc) { n_loc = n_glb; psys.setNumberOfParticleLocal(n_loc); PS::F64 * mass = new PS::F64[n_loc]; PS::F64vec * pos = new PS::F64vec[n_loc]; PS::F64vec * vel = new PS::F64vec[n_loc]; const PS::F64 m_tot = 1.0; const PS::F64 eng = -0.25; makeColdUniformSphere(m_tot, n_glb, n_loc, mass, pos, vel, eng); for(PS::S32 i = 0; i < n_loc; i++){ psys[i].mass = mass[i]; psys[i].pos = pos[i]; psys[i].vel = vel[i]; psys[i].id = i; } delete [] mass; delete [] pos; delete [] vel; } template void kick(Tpsys & system, const PS::F64 dt) { PS::S32 n = system.getNumberOfParticleLocal(); for(PS::S32 i = 0; i < n; i++) { system[i].vel += system[i].acc * dt; } } template void drift(Tpsys & system, const PS::F64 dt) { PS::S32 n = system.getNumberOfParticleLocal(); for(PS::S32 i = 0; i < n; i++) { system[i].pos += system[i].vel * dt; } } template void calcEnergy(const Tpsys & system, PS::F64 & etot, PS::F64 & ekin, PS::F64 & epot, const bool clear=true){ if(clear){ etot = ekin = epot = 0.0; } PS::F64 etot_loc = 0.0; PS::F64 ekin_loc = 0.0; PS::F64 epot_loc = 0.0; const PS::S32 nbody = system.getNumberOfParticleLocal(); for(PS::S32 i = 0; i < nbody; i++){ ekin_loc += system[i].mass * system[i].vel * system[i].vel; epot_loc += system[i].mass * (system[i].pot + system[i].mass / FPGrav::eps); } ekin_loc *= 0.5; epot_loc *= 0.5; etot_loc = ekin_loc + epot_loc; #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL etot = PS::Comm::getSum(etot_loc); epot = PS::Comm::getSum(epot_loc); ekin = PS::Comm::getSum(ekin_loc); #else etot = etot_loc; epot = epot_loc; ekin = ekin_loc; #endif } void printHelp() { std::cerr<<"o: dir name of output (default: ./result)"< system_grav; system_grav.initialize(); PS::S32 n_loc = 0; PS::F32 time_sys = 0.0; if(PS::Comm::getRank() == 0) { setParticlesColdUniformSphere(system_grav, n_tot, n_loc); } else { system_grav.setNumberOfParticleLocal(n_loc); } const PS::F32 coef_ema = 0.3; PS::DomainInfo dinfo; dinfo.initialize(coef_ema); dinfo.decomposeDomainAll(system_grav); system_grav.exchangeParticle(dinfo); n_loc = system_grav.getNumberOfParticleLocal(); #ifdef ENABLE_PHANTOM_GRAPE_X86 g5_open(); g5_set_eps_to_all(FPGrav::eps); #endif PS::TreeForForceLong::Monopole tree_grav; tree_grav.initialize(n_tot, theta, n_leaf_limit, n_group_limit); #ifdef MULTI_WALK const PS::S32 n_walk_limit = 200; const PS::S32 tag_max = 1; tree_grav.calcForceAllAndWriteBackMultiWalk(DispatchKernelWithSP, RetrieveKernel, tag_max, system_grav, dinfo, n_walk_limit); #else tree_grav.calcForceAllAndWriteBack(CalcGravity, CalcGravity, system_grav, dinfo); #endif PS::F64 Epot0, Ekin0, Etot0, Epot1, Ekin1, Etot1; calcEnergy(system_grav, Etot0, Ekin0, Epot0); PS::F64 time_diag = 0.0; PS::F64 time_snap = 0.0; PS::S64 n_loop = 0; PS::S32 id_snap = 0; while(time_sys < time_end){ if( (time_sys >= time_snap) || ( (time_sys + dt) - time_snap ) > (time_snap - time_sys) ){ char filename[256]; sprintf(filename, "%s/%04d.dat", dir_name, id_snap++); FileHeader header; header.time = time_sys; header.n_body = system_grav.getNumberOfParticleGlobal(); system_grav.writeParticleAscii(filename, header); time_snap += dt_snap; } calcEnergy(system_grav, Etot1, Ekin1, Epot1); if(PS::Comm::getRank() == 0){ if( (time_sys >= time_diag) || ( (time_sys + dt) - time_diag ) > (time_diag - time_sys) ){ fout_eng << time_sys << " " << (Etot1 - Etot0) / Etot0 << std::endl; fprintf(stdout, "time: %10.7f energy error: %+e\n", time_sys, (Etot1 - Etot0) / Etot0); time_diag += dt_diag; } } kick(system_grav, dt * 0.5); time_sys += dt; drift(system_grav, dt); if(n_loop % 4 == 0){ dinfo.decomposeDomainAll(system_grav); } system_grav.exchangeParticle(dinfo); #ifdef MULTI_WALK tree_grav.calcForceAllAndWriteBackMultiWalk(DispatchKernelWithSP, RetrieveKernel, tag_max, system_grav, dinfo, n_walk_limit, true); #else tree_grav.calcForceAllAndWriteBack(CalcGravity, CalcGravity, system_grav, dinfo); #endif kick(system_grav, dt * 0.5); n_loop++; } #ifdef ENABLE_PHANTOM_GRAPE_X86 g5_close(); #endif PS::Finalize(); return 0; }