5 #define RSQRT_NR_EPJ_X4
6 #define RSQRT_NR_SPJ_X4
10 #define RSQRT_NR_EPJ_X4
13 #define RSQRT_NR_EPJ_X2
17 #if defined(INTRINSIC_K) || defined(INTRINSIC_X86)
32 int MPI_Isend(
void* buffer,
int count, MPI_Datatype datatype,
int dest,
int tag, MPI_Comm comm, MPI_Request* req)
37 MPI_Type_size(datatype, &size);
38 std::cerr<<
"MPI_ISend count "<<count<<
" dest "<<dest<<
" datatype "<<size<<
" tag "<<tag<<std::endl;
40 ret = PMPI_Isend(buffer, count, datatype, dest, tag, comm, req);
46 int MPI_Irecv(
void* buffer,
int count, MPI_Datatype datatype,
int dest,
int tag, MPI_Comm comm, MPI_Request* req)
51 MPI_Type_size(datatype, &size);
52 std::cerr<<
"MPI_IRecv count "<<count<<
" dest "<<dest<<
" datatype "<<size<<
" tag "<<tag<<std::endl;
54 ret = PMPI_Irecv(buffer, count, datatype, dest, tag, comm, req);
61 #include<particle_simulator.hpp>
121 #ifdef HARD_CHECK_ENERGY
134 #ifdef STELLAR_EVOLUTION
138 #ifdef ADJUST_GROUP_PRINT
154 n_leaf_limit (
input_par_store, 20,
"number-leaf-limit",
"Particle-tree leaf number limit",
"Optimal value should be slightly >= 11 + N_bin_sample (20)"),
162 #ifdef ORBIT_SAMPLING
163 n_split (
input_par_store, 4,
"number-split",
"Number of binary sample points for tree perturbation force"),
165 n_bin (
input_par_store, 0,
"b",
"Number of primordial binaries for initialization (assuming the binaries' IDs are 1,2*n_bin)"),
166 n_step_per_orbit (
input_par_store, 8,
"number-step-tt",
"Number of steps per slow-down binary orbits (binary period/tree timestep) for isolated binaries; also the maximum criterion for activating tidal tensor method"),
170 unit_set (
input_par_store, 0,
"u",
"Input data unit, 0: unknown, referring to G; 1: mass:Msun, length:pc, time:Myr, velocity:pc/Myr"),
171 n_glb (
input_par_store, 100000,
"n",
"Total number of particles, used only for a test with the internal equal-mass Plummer model generator (assuming G=1 and the input data filename is __Plummer)"),
172 id_offset (
input_par_store, -1,
"id-offset",
"Starting ID for artificial particles, total number of real particles must always be smaller than this",
"n_glb+1"),
173 dt_soft (
input_par_store, 0.0,
"s",
"Tree timestep (dt_soft), if the value is zero (default) and --nstep-dt-soft-kepler is not used, then dt_soft = 0.1*r_out/sigma_1D"),
175 nstep_dt_soft_kepler (
input_par_store, 0.0,
"nstep-dt-soft-kepler",
"Determines the tree timestep by P(r_in)/nstep, where P(r_in) is the binary period with the semi-major axis of r_in, nstep is the argument of this option (e.g., 32.0)",
"not used"),
184 #ifdef HARD_CHECK_ENERGY
185 e_err_hard (
input_par_store, 1e-4,
"energy-err-hard",
"Maximum energy error allowed for the hard integrator"),
189 r_out (
input_par_store, 0.0,
"r",
"Outer boundary radius for the changeover function (r_out), if value is zero and -s is not used, use 0.1 GM/[N^(1/3) sigma_3D^2]; if -s is given, calculate r_out from dt_soft"),
190 r_bin (
input_par_store, 0.0,
"r-bin",
"Tidal tensor box size and the radial criterion for detecting multiple systems (binaries, triples, etc.), if value is zero, use 0.8*r_in"),
193 r_escape (
input_par_store, PS::LARGE_FLOAT,
"r-escape",
"Escape radius criterion, 0: no escaper removal; <0: remove particles when r>-r_escape; >0: remove particles when r>r_escape and energy>0"),
195 data_format (
input_par_store, 1,
"i",
"Data read(r)/write(w) format BINARY(B)/ASCII(A): r-B/w-A (3), r-A/w-B (2), rw-A (1), rw-B (0)"),
196 write_style (
input_par_store, 1,
"w",
"File writing style: 0, no output; 1. write snapshots, status, and profile separately; 2. write snapshot and status in one line per step (no MPI support); 3. write only status and profile"),
197 #ifdef STELLAR_EVOLUTION
199 stellar_evolution_option (
input_par_store, 1,
"stellar-evolution",
"Stellar evolution of stars in Hermite+SDAR: 0: off; >=1: using SSE/BSE based codes; ==2: activate dynamical tide and hyperbolic gravitational wave radiation"),
202 stellar_evolution_option (
input_par_store, 0,
"stellar-evolution",
"Not implemented"),
203 interrupt_detection_option(
input_par_store, 0,
"detect-interrupt",
"Interrupt integration in SDAR: 0: turn off; 1: merge two particles if their surfaces overlap; 2. merge two particles and also interrupt the hard integration"),
206 interrupt_detection_option(
input_par_store, 0,
"detect-interrupt",
"Modify orbits of AR groups based on the interruption function: 0: turn off; 1: modify inside AR integration and accumulate energy change; 2. modify and also interrupt the hard drift"),
208 #ifdef ADJUST_GROUP_PRINT
209 adjust_group_write_option(
input_par_store, 1,
"write-group-info",
"Print new and end of groups: 0: no print; 1: print to file [data filename prefix].group.[MPI rank] if -w >0"),
211 append_switcher(
input_par_store, 1,
"a",
"Data output style: 0 - create new output files and overwrite existing ones except snapshots; 1 - append new data to existing files"),
213 fname_par(
input_par_store,
"input.par",
"p",
"Input parameter file (this option should be used first before any other options)"),
225 int read(
int argc,
char *argv[],
const int opt_used_pre=0) {
226 static int petar_flag=-1;
227 static struct option long_options[] = {
228 #ifdef ORBIT_SAMPLING
229 {n_split.
key, required_argument, &petar_flag, 0},
238 {
eps.
key, required_argument, &petar_flag, 8},
241 {
r_bin.
key, required_argument, &petar_flag, 11},
243 {
eta.
key, required_argument, &petar_flag, 13},
244 #ifdef HARD_CHECK_ENERGY
245 {e_err_hard.
key, required_argument, &petar_flag, 14},
248 {
"disable-print-info", no_argument, &petar_flag, 16},
252 #ifdef STELLAR_EVOLUTION
253 {stellar_evolution_option.
key, required_argument, &petar_flag, 20},
255 {
r_escape.
key, required_argument, &petar_flag, 21},
258 #ifdef ADJUST_GROUP_PRINT
259 {adjust_group_write_option.
key, required_argument, &petar_flag, 24},
262 {
"help", no_argument, 0,
'h'},
266 int opt_used = opt_used_pre;
270 while ((copt = getopt_long(argc, argv,
"-i:a:t:s:o:r:b:n:G:u:T:f:p:w:h", long_options, &option_index)) != -1)
273 switch (petar_flag) {
274 #ifdef ORBIT_SAMPLING
276 n_split.
value = atoi(optarg);
279 assert(n_split.
value>=0);
363 #ifdef HARD_CHECK_ENERGY
365 e_err_hard.
value = atof(optarg);
396 #ifdef STELLAR_EVOLUTION
398 stellar_evolution_option.
value = atoi(optarg);
419 #ifdef ADJUST_GROUP_PRINT
421 adjust_group_write_option.
value = atoi(optarg);
515 fprintf(stderr,
"Error: Cannot open file %s.\n",
fname_par.
value.c_str());
522 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
534 std::cout<<
"Usage: petar [option] filename"<<std::endl;
535 std::cout<<
" filename: initial or restart data (snapshot) filename\n"
536 <<
" Data file content:\n"
538 <<
" 1. File_ID: 0 for initialization, else for restarting\n"
539 <<
" 2. N_particle \n"
541 #ifdef RECORD_CM_IN_HEADER
542 <<
" 4-6: offset of system centeral position (assuming galactic center is the coordiante origin in the case of Galpy)\n"
543 <<
" 7-9: offset of system centeral velocity\n"
545 <<
" Following lines:\n";
547 std::cout<<
" PS: (*) show initialization values which should be used together with FILE_ID = 0"<<std::endl;
548 std::cout<<
" [formatted] indicates that the value is only for save, cannot be directly read"<<std::endl;
549 std::cout<<
"Options:\n";
551 std::cout<<
" --disable-print-info: "<<
"Do not print information"<<std::endl;
552 std::cout<<
" --disable-write-info: "<<
"Do not write information"<<std::endl;
553 std::cout<<
" -h(--help): print help"<<std::endl;
554 std::cout<<
"*** PS: dt_soft: tree time step\n"
555 <<
" r_in : transit function inner boundary radius\n"
556 <<
" r_out: transit function outer boundary radius\n"
557 <<
" sigma: half-mass radius velocity dispersion\n"
558 <<
" n_bin: number of primordial binaries\n"
559 <<
" <m> : averaged mass"<<std::endl;
577 if(
print_flag) std::cout<<
"----- Finish reading input options of PeTar -----\n";
584 #ifdef ORBIT_SAMPLING
585 assert(n_split.
value>=0);
620 typedef PS::TreeForForceLong<ForceSoft, EPISoft, EPJSoft>::QuadrupoleWithSymmetrySearch TreeForce;
622 typedef PS::TreeForForceLong<ForceSoft, EPISoft, EPJSoft>::MonopoleWithSymmetrySearch TreeForce;
624 typedef PS::ParticleSystem<FPSoft>
SystemSoft;
627 typedef PS::TreeForForceShort<ForceSoft, EPISoft, EPJSoft>::Symmetry TreeNB;
647 std::ofstream fprofile;
651 std::ofstream fstatus;
663 std::map<PS::S64, PS::S32> id_adr_map;
667 PS::F64 domain_decompose_weight;
668 PS::DomainInfo dinfo;
669 PS::F64ort * pos_domain;
671 PS::CommInfo comm_info;
689 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
695 PS::ReallocatableArray<PS::S32> mass_modify_list;
698 PS::ReallocatableArray<PS::S32> remove_list;
699 PS::ReallocatableArray<PS::S64> remove_id_record;
706 bool read_parameters_flag;
708 bool initial_parameters_flag;
709 bool initial_step_flag;
716 static bool initial_fdps_flag;
729 dn_loop(0), profile(), n_count(), n_count_sum(), tree_soft_profile(), fprofile(),
731 stat(), fstatus(), time_kick(0.0),
733 file_header(), system_soft(), id_adr_map(),
734 n_loop(0), domain_decompose_weight(1.0), dinfo(), pos_domain(NULL),
736 tree_nb(), tree_soft(),
740 hard_manager(), system_hard_one_cluster(), system_hard_isolated(),
741 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
742 system_hard_connected(),
745 mass_modify_list(), remove_list(), remove_id_record(),
747 read_parameters_flag(false), read_data_flag(false), initial_parameters_flag(false), initial_step_flag(false) {
748 assert(initial_fdps_flag);
749 my_rank = PS::Comm::getRank();
750 n_proc = PS::Comm::getNumberOfProc();
758 if (_dt<1)
while (
dt>_dt)
dt *= 0.5;
760 while (
dt<=_dt)
dt *= 2.0;
767 void treeNeighborSearch() {
770 tree_nb.clearNumberOfInteraction();
771 tree_nb.clearTimeProfile();
774 tree_nb.calcForceAllAndWriteBack(SearchNeighborEpEpSimd(), system_soft, dinfo);
776 tree_nb.calcForceAllAndWriteBack(SearchNeighborEpEpFugaku(), system_soft, dinfo);
782 tree_nb_profile += tree_nb.getTimeProfile();
791 void searchCluster() {
803 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
804 search_cluster.connectNodes(pos_domain,tree_nb);
805 search_cluster.setIdClusterGlobalIteration();
806 search_cluster.sendAndRecvCluster(system_soft);
819 void createGroup(
const PS::F64 _dt_tree) {
847 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
852 search_cluster.writeAndSendBackPtcl(system_soft, system_hard_connected.
getPtcl(), mass_modify_list);
853 mass_modify_list.resizeNoInitialize(0);
858 stat.
n_all_loc = system_soft.getNumberOfParticleLocal();
859 stat.
n_all_glb = system_soft.getNumberOfParticleGlobal();
862 #pragma omp parallel for
864 system_soft[i].rank_org = my_rank;
865 system_soft[i].adr = i;
867 assert(system_soft[i].group_data.artificial.isArtificial());
879 void treeSoftForce() {
883 tree_soft.clearNumberOfInteraction();
884 tree_soft.clearTimeProfile();
888 const PS::S32 n_walk_limit = 200;
893 #ifdef PARTICLE_SIMULATOR_GPU_MULIT_WALK_INDEX
894 tree_soft.calcForceAllAndWriteBackMultiWalkIndex(CalcForceWithLinearCutoffCUDAMultiWalk(my_rank, eps2, rout2, G),
900 #else // no multi-walk index
907 #endif // multi-walk index
913 tree_soft.calcForceAllAndWriteBack(CalcForceEpEpWithLinearCutoffFugaku(eps2, rout2, G),
915 CalcForceEpSpQuadFugaku(eps2, G),
917 CalcForceEpSpMonoFugaku(eps2, G),
922 #elif USE_SIMD // end use_gpu
923 tree_soft.calcForceAllAndWriteBack(CalcForceEpEpWithLinearCutoffSimd(),
925 CalcForceEpSpQuadSimd(),
927 CalcForceEpSpMonoSimd(),
931 #else // end use_simd
943 n_count.
ep_ep_interact += tree_soft.getNumberOfInteractionEPEPLocal();
944 n_count_sum.
ep_ep_interact += tree_soft.getNumberOfInteractionEPEPGlobal();
945 n_count.
ep_sp_interact += tree_soft.getNumberOfInteractionEPSPLocal();
946 n_count_sum.
ep_sp_interact += tree_soft.getNumberOfInteractionEPSPGlobal();
948 tree_soft_profile += tree_soft.getTimeProfile();
949 domain_decompose_weight = tree_soft_profile.calc_force;
959 void treeForceCorrectChangeoverTreeNeighbor() {
961 SystemHard::correctForceWithCutoffTreeNeighborOMP<SystemSoft, FPSoft, TreeForce, EPJSoft>(system_soft, tree_soft, system_soft.getNumberOfParticleLocal(), hard_manager.
ap_manager);
965 void treeForceCorrectChangeover() {
970 #ifdef CORRECT_FORCE_DEBUG
972 PS::S64 n_loc_all = system_soft.getNumberOfParticleLocal();
974 FPSoft psys_bk[n_loc_all];
975 #pragma omp parallel for
976 for (
int i=0; i<n_loc_all; i++)
977 psys_bk[i] = system_soft[i];
986 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
991 #ifdef CORRECT_FORCE_DEBUG
993 #pragma omp parallel for
994 for (
int i=0; i<n_loc_all; i++) {
996 psys_bk[i] = system_soft[i];
997 system_soft[i] = ptmp;
1001 SystemHard::correctForceWithCutoffTreeNeighborOMP<SystemSoft, FPSoft, TreeForce, EPJSoft>(system_soft, tree_soft, n_loc, hard_manager.
ap_manager);
1012 for (
int i=0; i<n_loc_all; i++) {
1015 if(dacci*dacci/(system_soft[i].acc*system_soft[i].acc)>1e-8) {
1016 std::cerr<<
"Corrected Acc diff >1e-8: i "<<i<<
" acc(tree): "<<system_soft[i].acc<<
" acc(cluster): "<<psys_bk[i].
acc<<std::endl;
1020 if(abs(dpoti/system_soft[i].pot_tot)>1e-6) {
1021 std::cerr<<
"Corrected pot diff >1e-6: i "<<i<<
" pot(tree): "<<system_soft[i].pot_tot<<
" pot(cluster): "<<psys_bk[i].
pot_tot<<std::endl;
1029 PS::Comm::barrier();
1035 void externalForce() {
1048 PS::S64 n_loc_all = system_soft.getNumberOfParticleLocal();
1049 #pragma omp parallel for
1050 for (
int i=0; i<n_loc_all; i++) {
1051 auto& pi = system_soft[i];
1053 #ifdef RECORD_CM_IN_HEADER
1060 assert(!std::isinf(acc[0]));
1061 assert(!std::isnan(acc[0]));
1062 assert(!std::isinf(pot));
1063 assert(!std::isnan(pot));
1064 pi.acc[0] += acc[0];
1065 pi.acc[1] += acc[1];
1066 pi.acc[2] += acc[2];
1069 #ifdef EXTERNAL_POT_IN_PTCL
1077 PS::Comm::barrier();
1083 void correctPtclVelCM(
const PS::F64& _dt) {
1097 for (
int i=0; i<stat.
n_all_loc; i++) system_soft[i].vel -= dv;
1102 auto& ptcl_iso=system_hard_isolated.
getPtcl();
1103 for (
int i=0; i<ptcl_iso.size(); i++) ptcl_iso[i].vel -= dv;
1112 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
1113 auto& ptcl_con=system_hard_connected.
getPtcl();
1114 for (
int i=0; i<ptcl_con.size(); i++) ptcl_con[i].vel -= dv;
1124 void GradientKick() {
1128 tree_soft.clearNumberOfInteraction();
1129 tree_soft.clearTimeProfile();
1134 tree_soft.calcForceAllAndWriteBack(CalcCorrectEpEpWithLinearCutoffNoSimd(),
1144 n_count.
ep_ep_interact += tree_soft.getNumberOfInteractionEPEPLocal();
1145 n_count_sum.
ep_ep_interact += tree_soft.getNumberOfInteractionEPEPGlobal();
1146 n_count.
ep_sp_interact += tree_soft.getNumberOfInteractionEPSPLocal();
1147 n_count_sum.
ep_sp_interact += tree_soft.getNumberOfInteractionEPSPGlobal();
1149 tree_soft_profile += tree_soft.getTimeProfile();
1150 domain_decompose_weight += tree_soft_profile.calc_force;
1153 PS::Comm::barrier();
1161 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
1168 PS::Comm::barrier();
1200 const PS::ReallocatableArray<PS::S32>& _adr) {
1202 #pragma omp parallel for
1206 _sys[k].vel += _dt*(_sys[k].acc + 9.0/192.0*_dt*_dt*_sys[k].acorr);
1208 _sys[k].vel += _sys[k].acc * _dt;
1210 _sys[k].group_data.artificial.setParticleTypeToSingle();
1221 template<
class Tptcl>
1222 void kickClusterAndRecoverGroupMemberMass(
SystemSoft& _sys,
1223 PS::ReallocatableArray<Tptcl>& _ptcl,
1226 const PS::S64 n= _ptcl.size();
1227 #pragma omp parallel for
1229 auto& pi_artificial = _ptcl[i].group_data.artificial;
1231 if (pi_artificial.isMember()) {
1232 const PS::S64 cm_adr = _ptcl[i].getParticleCMAddress();
1235 assert(pi_artificial.getMassBackup()>0);
1238 _ptcl[i].mass = pi_artificial.getMassBackup();
1240 _ptcl[i].vel += _dt*(_sys[cm_adr].acc + 9.0/192.0*_dt*_dt*_sys[cm_adr].acorr);
1242 #ifdef NAN_CHECK_DEBUG
1243 assert(!std::isnan(_sys[cm_adr].acc[0]));
1244 assert(!std::isnan(_sys[cm_adr].acc[1]));
1245 assert(!std::isnan(_sys[cm_adr].acc[2]));
1247 _ptcl[i].vel += _sys[cm_adr].acc * _dt;
1253 const PS::S64 i_adr =_ptcl[i].adr_org;
1257 assert(pi_artificial.getStatus()==_sys[i_adr].group_data.artificial.getStatus());
1261 _ptcl[i].vel += _dt*(_sys[i_adr].acc + 9.0/192.0*_dt*_dt*_sys[i_adr].acorr);
1263 _ptcl[i].vel += _sys[i_adr].acc * _dt;
1276 const PS::ReallocatableArray<PS::S32>& _adr_ptcl_send,
1279 const PS::S64 n= _adr_ptcl_send.size();
1280 #pragma omp parallel for
1282 const PS::S64 adr = _adr_ptcl_send[i];
1285 if(_sys[adr].group_data.artificial.isSingle() || (_sys[adr].group_data.artificial.isMember() && _sys[adr].getParticleCMAddress()<0)) {
1286 _sys[adr].vel += _sys[adr].acc * _dt;
1288 _sys[adr].vel += _dt*_dt* _sys[adr].acorr /48;
1293 if(_sys[adr].group_data.artificial.isSingle()) assert(_sys[adr].mass>0);
1294 else assert(_sys[adr].group_data.artificial.getMassBackup()>0);
1307 const PS::S32 _adr_artificial_start,
1310 const PS::S64 n_tot= _sys.getNumberOfParticleLocal();
1312 #pragma omp parallel for
1313 for(
PS::S32 i=_adr_artificial_start; i<n_tot; i+= n_artifical_per_group) {
1315 pcm->vel += pcm->acc * _dt;
1317 pcm->vel += _dt*_dt* pcm->acorr /48;
1320 assert(pcm->group_data.artificial.isCM());
1328 const PS::S32 n = system.getNumberOfParticleLocal();
1329 #pragma omp parallel for
1331 if(system[i].n_ngb <= 0){
1332 system[i].pos += system[i].vel *
dt;
1343 void kick(
const PS::F64 _dt_kick) {
1352 kickClusterAndRecoverGroupMemberMass(system_soft, system_hard_isolated.
getPtcl(), _dt_kick);
1356 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
1358 kickClusterAndRecoverGroupMemberMass(system_soft, system_hard_connected.
getPtcl(), _dt_kick);
1362 search_cluster.SendSinglePtcl(system_soft, system_hard_connected.
getPtcl());
1369 #ifdef RECORD_CM_IN_HEADER
1371 correctPtclVelCM(_dt_kick);
1375 time_kick += _dt_kick;
1379 for(
int i=0; i<stat.
n_real_loc; i++) kick_regist[i] = 0;
1383 for(
int i=0; i<system_hard_isolated.
getPtcl().size(); i++) {
1388 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
1389 for(
int i=0; i<system_hard_connected.
getPtcl().size(); i++) {
1391 if(adr>=0) kick_regist[adr]++;
1399 assert(kick_regist[i]==1);
1405 PS::Comm::barrier();
1433 PS::Comm::barrier();
1443 system_hard_isolated.energy.resetEnergyCorrection();
1456 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
1457 n_interrupt_glb = PS::Comm::getSum(n_interrupt_isolated);
1459 n_interrupt_glb = n_interrupt_isolated;
1468 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
1474 system_hard_connected.energy.resetEnergyCorrection();
1484 PS::S32 n_interrupt_connected_glb = PS::Comm::getSum(n_interrupt_connected);
1493 if (n_interrupt_connected_glb==0) {
1494 search_cluster.writeAndSendBackPtcl(system_soft, system_hard_connected.
getPtcl(), mass_modify_list);
1499 n_interrupt_glb += n_interrupt_connected_glb;
1502 PS::Comm::barrier();
1515 return n_interrupt_glb;
1521 PS::S32 finishInterruptDrift() {
1529 PS::S32 n_interrupt_isolated = 0;
1541 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
1542 n_interrupt_glb = PS::Comm::getSum(n_interrupt_isolated);
1544 n_interrupt_glb = n_interrupt_isolated;
1552 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
1558 PS::S32 n_interrupt_connected = 0;
1569 PS::S32 n_interrupt_connected_glb = PS::Comm::getSum(n_interrupt_connected);
1577 if (n_interrupt_connected_glb==0) {
1578 PS::ReallocatableArray<PS::S32> mass_modify_list;
1579 search_cluster.writeAndSendBackPtcl(system_soft, system_hard_connected.
getPtcl(), mass_modify_list);
1583 n_interrupt_glb += n_interrupt_connected_glb;
1587 PS::Comm::barrier();
1592 #ifdef HARD_INTERRUPT_PRINT
1593 if (n_interrupt_glb>0) {
1594 std::cerr<<
"Interrupt detected, number: "<<n_interrupt_glb<<std::endl;
1600 PS::Comm::barrier();
1607 return n_interrupt_glb;
1622 if(_time==0.0)
return _dt_max;
1625 PS::U64 bitmap = _time/_dt_min;
1635 while((bitmap&1)==0) {
1636 bitmap = (bitmap>>1);
1641 return std::min(c*_dt_min,_dt_max);
1646 bool checkTimeConsistence() {
1647 if (abs(time_kick-stat.
time)>1e-13) {
1648 std::cerr<<
"Error: kick time ("<<time_kick<<
") and system time ("<<stat.
time<<
") are inconsistent!"<<std::endl;
1651 time_kick = stat.
time;
1655 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
1663 void writeBackHardParticles() {
1668 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
1670 search_cluster.writeAndSendBackPtcl(system_soft, system_hard_connected.
getPtcl(), mass_modify_list);
1673 mass_modify_list.resizeNoInitialize(0);
1677 PS::Comm::barrier();
1683 void setParticleGroupDataToCMData() {
1687 #ifdef CLUSTER_VELOCITY
1689 system_hard_one_cluster.resetParticleGroupData(system_soft);
1690 system_hard_isolated.setParticleGroupDataToCMData(system_soft);
1691 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
1692 system_hard_connected.setParticleGroupDataToCMData(system_soft);
1693 search_cluster.writeAndSendBackPtcl(system_soft, system_hard_connected.
getPtcl(), mass_modify_list);
1695 mass_modify_list.resizeNoInitialize(0);
1699 PS::Comm::barrier();
1707 void correctForceChangeOverUpdate() {
1715 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
1723 PS::Comm::barrier();
1733 void domainDecompose(
const bool _enforce=
false) {
1739 if(n_loop % 16 == 0 || _enforce) {
1740 dinfo.decomposeDomainAll(system_soft,domain_decompose_weight);
1745 PS::Comm::barrier();
1754 bool adjustDtTreeReduce(
PS::F64& _dt_reduce_factor,
const PS::F64 _dt_tree_base,
const PS::F64 _dt_tree_now) {
1755 bool dt_mod_flag =
false;
1756 PS::F64 dt_tree_new = _dt_tree_base / _dt_reduce_factor;
1757 if(_dt_tree_now!= dt_tree_new) {
1759 if(_dt_tree_now<dt_tree_new) {
1760 PS::F64 dt_tree_max = calcDtLimit(stat.
time, _dt_tree_base, _dt_tree_now);
1761 if (dt_tree_max == _dt_tree_now) {
1763 _dt_reduce_factor= _dt_tree_base/_dt_tree_now;
1768 _dt_reduce_factor =
std::min(_dt_tree_base/dt_tree_max, _dt_reduce_factor);
1772 else dt_mod_flag =
true;
1779 void updateStatus(
const bool _initial_flag) {
1784 if (_initial_flag) {
1787 #ifdef RECORD_CM_IN_HEADER
1792 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
1795 #ifdef HARD_CHECK_ENERGY
1799 #ifndef RECORD_CM_IN_HEADER
1806 #ifdef HARD_CHECK_ENERGY
1811 #ifdef RECORD_CM_IN_HEADER
1816 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
1820 #ifdef HARD_CHECK_ENERGY
1821 HardEnergy energy_local = system_hard_one_cluster.energy;
1822 energy_local += system_hard_isolated.energy;
1823 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
1824 energy_local += system_hard_connected.energy;
1827 stat.
energy.error_hard_cum += PS::Comm::getSum(energy_local.
de);
1828 stat.
energy.error_hard_sd_cum += PS::Comm::getSum(energy_local.
de_sd);
1834 PS::F64 etot_sd_correction = ekin_sd_correction + epot_sd_correction;
1839 stat.
energy.de_change_cum += de_change_cum;
1840 stat.
energy.de_change_binary_interrupt += de_change_binary_interrupt;
1841 stat.
energy.de_change_modify_single += de_change_modify_single;
1846 stat.
energy.etot_sd_ref += de_sd_change_cum;
1847 stat.
energy.de_sd_change_cum += de_sd_change_cum;
1848 stat.
energy.de_sd_change_binary_interrupt += de_sd_change_binary_interrupt;
1849 stat.
energy.de_sd_change_modify_single += de_sd_change_modify_single;
1851 system_hard_one_cluster.energy.clear();
1852 system_hard_isolated.energy.clear();
1853 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
1854 system_hard_connected.energy.clear();
1857 #ifndef RECORD_CM_IN_HEADER
1866 PS::Comm::barrier();
1876 bool print_flag = input_parameters.
print_flag;
1882 std::cout<<std::endl;
1883 stat.
print(std::cout);
1886 if (print_flag) galpy_manager.
printData(std::cout);
1889 if(write_style==1) {
1894 file_header.
nfile++;
1895 #ifdef RECORD_CM_IN_HEADER
1896 file_header.pos_offset = stat.
pcm.
pos;
1897 file_header.vel_offset = stat.
pcm.
vel;
1900 std::string fname = input_parameters.
fname_snp.
value+
"."+std::to_string(file_header.
nfile);
1902 assert(system_soft.getNumberOfParticleLocal()== stat.
n_all_loc);
1904 system_soft.setNumberOfParticleLocal(stat.
n_real_loc);
1906 system_soft.writeParticleAscii(fname.c_str(), file_header);
1908 system_soft.writeParticleBinary(fname.c_str(), file_header);
1909 system_soft.setNumberOfParticleLocal(stat.
n_all_loc);
1923 else if(write_style==2&&my_rank==0) {
1927 #ifdef RECORD_CM_IN_HEADER
1928 system_soft[i].printColumnWithOffset(stat.
pcm, fstatus,
WRITE_WIDTH);
1936 else if(write_style==3&&my_rank==0) {
1946 PS::Comm::barrier();
1952 void calcProfile() {
1957 PS::S32 n_hard_single = system_hard_one_cluster.
getPtcl().size();
1963 n_count_sum.
hard_single += PS::Comm::getSum(n_hard_single);
1964 n_count_sum.
hard_isolated += PS::Comm::getSum(n_hard_isolated);
1966 PS::S64 ARC_substep_sum = system_hard_isolated.ARC_substep_sum;
1967 PS::S64 ARC_tsyn_step_sum = system_hard_isolated.ARC_tsyn_step_sum;
1968 PS::S64 ARC_n_groups = system_hard_isolated.ARC_n_groups;
1969 PS::S64 ARC_n_groups_iso = system_hard_isolated.ARC_n_groups_iso;
1970 PS::S64 H4_step_sum = system_hard_isolated.H4_step_sum;
1971 #ifdef HARD_COUNT_NO_NEIGHBOR
1972 PS::S64 n_neighbor_zero = system_hard_isolated.n_neighbor_zero;
1975 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
1976 PS::S32 n_hard_connected = system_hard_connected.
getPtcl().size();
1978 n_count_sum.
hard_connected += PS::Comm::getSum(n_hard_connected);
1980 ARC_substep_sum += system_hard_connected.ARC_substep_sum;
1981 ARC_tsyn_step_sum += system_hard_connected.ARC_tsyn_step_sum;
1982 ARC_n_groups += system_hard_connected.ARC_n_groups;
1983 ARC_n_groups_iso += system_hard_connected.ARC_n_groups_iso;
1984 H4_step_sum += system_hard_connected.H4_step_sum;
1985 #ifdef HARD_COUNT_NO_NEIGHBOR
1986 n_neighbor_zero+= system_hard_connected.n_neighbor_zero;
1995 #ifdef HARD_COUNT_NO_NEIGHBOR
2001 n_count_sum.
ARC_n_groups += PS::Comm::getSum(ARC_n_groups);
2003 n_count_sum.
H4_step_sum += PS::Comm::getSum(H4_step_sum);
2004 #ifdef HARD_COUNT_NO_NEIGHBOR
2008 system_hard_isolated.ARC_substep_sum = 0;
2009 system_hard_isolated.ARC_tsyn_step_sum=0;
2010 system_hard_isolated.ARC_n_groups = 0;
2011 system_hard_isolated.ARC_n_groups_iso = 0;
2012 system_hard_isolated.H4_step_sum = 0;
2013 #ifdef HARD_COUNT_NO_NEIGHBOR
2014 system_hard_isolated.n_neighbor_zero = 0;
2017 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
2018 system_hard_connected.ARC_substep_sum = 0;
2019 system_hard_connected.ARC_tsyn_step_sum=0;
2020 system_hard_connected.ARC_n_groups = 0;
2021 system_hard_connected.ARC_n_groups_iso = 0;
2022 system_hard_connected.H4_step_sum = 0;
2023 #ifdef HARD_COUNT_NO_NEIGHBOR
2024 system_hard_connected.n_neighbor_zero = 0;
2036 for (
PS::S32 i=0; i<n_isolated_cluster; i++) n_count.
clusterCount(isolated_cluster_n_list[i]);
2038 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
2043 for (
PS::S32 i=0; i<n_connected_cluster; i++) n_count.
clusterCount(connected_cluster_n_list[i]);
2046 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
2048 PS::S32 n_member_in_cluster_loc[cluster_hist_size_loc];
2049 PS::S32 n_cluster_loc[cluster_hist_size_loc];
2050 n_count.
getherClusterCount(n_member_in_cluster_loc, n_cluster_loc, cluster_hist_size_loc);
2051 PS::S32 cluster_hist_size_recv[n_proc];
2052 PS::S32 cluster_hist_size_disp[n_proc+1];
2053 PS::Comm::allGather(&cluster_hist_size_loc, 1, cluster_hist_size_recv);
2054 cluster_hist_size_disp[0] = 0;
2055 for (
PS::S32 i=0; i<n_proc; i++){
2056 cluster_hist_size_disp[i+1] = cluster_hist_size_recv[i] + cluster_hist_size_disp[i];
2058 PS::S32 cluster_hist_size_total = cluster_hist_size_disp[n_proc];
2059 PS::S32 n_member_in_cluster_recv[cluster_hist_size_total];
2060 PS::S32 n_cluster_recv[cluster_hist_size_total];
2061 PS::Comm::allGatherV(n_member_in_cluster_loc, cluster_hist_size_loc,
2062 n_member_in_cluster_recv, cluster_hist_size_recv, cluster_hist_size_disp);
2063 PS::Comm::allGatherV(n_cluster_loc, cluster_hist_size_loc,
2064 n_cluster_recv, cluster_hist_size_recv, cluster_hist_size_disp);
2065 for (
PS::S32 i=0; i<cluster_hist_size_total; i++) {
2066 n_count_sum.
clusterCount(n_member_in_cluster_recv[i], n_cluster_recv[i]);
2077 void clearProfile() {
2079 tree_soft_profile.clear();
2080 tree_nb_profile.clear();
2081 #if defined(USE_GPU) && defined(GPU_PROFILE)
2082 gpu_profile.clear();
2083 gpu_counter.clear();
2086 n_count_sum.
clear();
2091 void printProfile() {
2096 std::cout<<std::setprecision(5);
2097 std::cout<<
"Tree step number: "<<dn_loop<<std::endl;
2100 std::cout<<
"**** Wallclock time per step (local): [Min/Max]\n";
2103 std::cout<<std::endl;
2106 profile_min.
dump(std::cout,dn_loop);
2107 std::cout<<std::endl;
2108 profile.
dump(std::cout,dn_loop);
2109 std::cout<<std::endl;
2111 std::cout<<
"**** FDPS tree soft force time profile (local):\n";
2112 tree_soft_profile.
dumpName(std::cout);
2113 std::cout<<std::endl;
2114 tree_soft_profile.
dump(std::cout,dn_loop);
2115 std::cout<<std::endl;
2117 std::cout<<
"**** Tree neighbor time profile (local):\n";
2118 tree_nb_profile.
dumpName(std::cout);
2119 std::cout<<std::endl;
2120 tree_nb_profile.
dump(std::cout,dn_loop);
2121 std::cout<<std::endl;
2123 #if defined(USE_GPU) && defined(GPU_PROFILE)
2124 std::cout<<
"**** GPU time profile (local):\n";
2125 gpu_profile.dumpName(std::cout);
2126 gpu_counter.dumpName(std::cout);
2127 std::cout<<std::endl;
2128 gpu_profile.dump(std::cout,dn_loop);
2129 gpu_counter.dump(std::cout,dn_loop);
2130 std::cout<<std::endl;
2133 std::cout<<
"**** Number per step (global):\n";
2135 std::cout<<std::endl;
2136 n_count_sum.
dump(std::cout,dn_loop);
2137 std::cout<<std::endl;
2139 std::cout<<
"**** Number of members in clusters (global):\n";
2140 n_count_sum.
printHist(std::cout,dn_loop);
2153 #if defined(USE_GPU) && defined(GPU_PROFILE)
2158 fprofile<<std::endl;
2165 auto item = id_adr_map.find(_id);
2166 if (item==id_adr_map.end())
return -1;
2167 else return item->second;
2171 void addParticleInIdAdrMap(
FPSoft& _ptcl) {
2172 id_adr_map[_ptcl.
id] = _ptcl.
adr;
2176 void reconstructIdAdrMap() {
2181 #ifdef STELLAR_EVOLUTION
2182 void correctSoftPotMassChange() {
2185 #pragma omp parallel for
2186 for (
int k=0; k<mass_modify_list.size(); k++) {
2187 PS::S32 i = mass_modify_list[k];
2188 auto& pi = system_soft[i];
2189 PS::F64 dpot = pi.dm*pi.pot_soft;
2191 stat.
energy.de_change_cum += dpot;
2192 stat.
energy.etot_sd_ref += dpot;
2193 stat.
energy.de_sd_change_cum += dpot;
2200 mass_modify_list.resizeNoInitialize(0);
2206 auto item = id_adr_map.find(_id);
2207 if (item==id_adr_map.end())
return -1;
2210 id_adr_map.erase(item);
2216 void removeParticles() {
2218 assert(n_interrupt_glb==0);
2224 system_soft.setNumberOfParticleLocal(stat.
n_real_loc);
2227 PS::S32 n_remove = remove_list.size();
2228 for (
PS::S32 i=0; i<n_remove; i++) {
2229 auto& pi = system_soft[remove_list[i]];
2230 pi.group_data.artificial.setParticleTypeToUnused();
2233 PS::F64 dpot = pi.mass*pi.pot_tot;
2234 PS::F64 dkin = 0.5*pi.mass*(pi.vel*pi.vel);
2237 stat.
energy.de_change_cum -= eloss;
2238 stat.
energy.etot_sd_ref -= eloss;
2239 stat.
energy.de_sd_change_cum -= eloss;
2243 remove_list.resizeNoInitialize(0);
2246 const PS::S32 num_thread = PS::Comm::getNumberOfThread();
2247 PS::ReallocatableArray<PS::S32> remove_list_thx[num_thread];
2248 for (
PS::S32 i=0; i<num_thread; i++) remove_list_thx[i].resizeNoInitialize(0);
2250 #pragma omp parallel
2252 const PS::S32 ith = PS::Comm::getThreadNum();
2255 auto& pi = system_soft[i];
2257 remove_list_thx[ith].push_back(i);
2258 PS::F64 dpot = pi.mass*pi.pot_tot;
2259 PS::F64 dkin = 0.5*pi.mass*(pi.vel*pi.vel);
2262 stat.
energy.de_change_cum -= eloss;
2263 stat.
energy.etot_sd_ref -= eloss;
2264 stat.
energy.de_sd_change_cum -= eloss;
2267 else if (pi.mass==0.0&&pi.group_data.artificial.isUnused())
2268 remove_list_thx[ith].push_back(i);
2274 for (
PS::S32 i=0; i<num_thread; i++)
2275 for (
PS::S32 k=0; k<remove_list_thx[i].size(); k++) {
2276 PS::S32 index=remove_list_thx[i][k];
2277 remove_list.push_back(index);
2278 remove_id_record.push_back(system_soft[index].
id);
2279 if (system_soft[index].mass>0) {
2290 n_remove = remove_list.size();
2291 system_soft.removeParticle(remove_list.getPointer(), remove_list.size());
2298 system_soft.setNumberOfParticleLocal(stat.
n_real_loc);
2299 stat.
n_real_glb = system_soft.getNumberOfParticleGlobal();
2300 remove_list.resizeNoInitialize(0);
2303 #pragma omp parallel for
2305 assert(system_soft[i].mass!=0.0);
2306 assert(!std::isinf(system_soft[i].pos[0]));
2307 assert(!std::isnan(system_soft[i].pos[0]));
2308 assert(!std::isinf(system_soft[i].vel[0]));
2309 assert(!std::isnan(system_soft[i].vel[0]));
2315 PS::Comm::barrier();
2322 PS::S32 getNumberOfRemovedParticlesLocal()
const {
2323 return remove_id_record.size();
2327 PS::S32 getNumberOfRemovedParticlesGlobal()
const {
2328 PS::S32 n_remove_loc = remove_id_record.size();
2329 return PS::Comm::getSum(n_remove_loc);
2333 PS::S64* getRemovedIDListLocal()
const {
2334 return remove_id_record.getPointer();
2338 void clearRemovedIDList() {
2339 remove_id_record.resizeNoInitialize(0);
2343 void exchangeParticle() {
2344 assert(n_interrupt_glb==0);
2349 system_soft.exchangeParticle(dinfo);
2351 const PS::S32 n_loc = system_soft.getNumberOfParticleLocal();
2353 #pragma omp parallel for
2354 for(
PS::S32 i=0; i<n_loc; i++){
2355 system_soft[i].rank_org = my_rank;
2356 system_soft[i].adr = i;
2362 assert(stat.
n_real_glb==system_soft.getNumberOfParticleGlobal());
2367 PS::Comm::barrier();
2373 static void initialFDPS(
int argc,
char *argv[]) {
2374 if (!initial_fdps_flag) {
2375 PS::Initialize(argc, argv);
2376 initial_fdps_flag =
true;
2381 static void finalizeFDPS() {
2382 if (initial_fdps_flag) {
2384 initial_fdps_flag =
false;
2395 void createCommunicator(
const int n,
const int rank[]) {
2396 assert(initial_fdps_flag);
2397 assert(!initial_parameters_flag);
2398 comm_info.create(n,rank);
2399 system_soft.setCommInfo(comm_info);
2400 dinfo.setCommInfo(comm_info);
2401 tree_nb.setCommInfo(comm_info);
2402 tree_soft.setCommInfo(comm_info);
2403 my_rank = comm_info.getRank();
2404 n_proc = comm_info.getNumberOfProc();
2412 void setCommunicator(
const PS::CommInfo &_comm_info) {
2413 assert(initial_fdps_flag);
2414 assert(!initial_parameters_flag);
2415 comm_info = _comm_info;
2416 system_soft.setCommInfo(comm_info);
2417 dinfo.setCommInfo(comm_info);
2418 tree_nb.setCommInfo(comm_info);
2419 tree_soft.setCommInfo(comm_info);
2420 my_rank = comm_info.getRank();
2421 n_proc = comm_info.getNumberOfProc();
2426 void printLogo(std::ostream & fout)
const {
2427 fout<<
"\n ******************************************\n"
2428 <<
" ██████╗ ███████╗████████╗ █████╗ ██████╗\n"
2429 <<
" ██╔══██╗██╔════╝╚══██╔══╝██╔══██╗██╔══██╗\n"
2430 <<
" ██████╔╝█████╗ ██║ ███████║██████╔╝\n"
2431 <<
" ██╔═══╝ ██╔══╝ ██║ ██╔══██║██╔══██╗\n"
2432 <<
" ██║ ███████╗ ██║ ██║ ██║██║ ██║\n"
2433 <<
" ╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝\n"
2434 <<
" ******************************************\n"
2440 void printReference(std::ostream & fout)
const{
2441 fout<<
"============== PeTar ================\n"
2442 <<
" Online document: (preparing)\n"
2443 <<
" GitHub page: https://github.com/lwang-astro/PeTar\n"
2445 <<
" Please cite the following papers when you use PeTar for any publications\n"
2446 <<
" FDPS: see above FPDS Logo message\n";
2447 AR::printReference(fout);
2448 fout<<
" PeTar: Wang L., Iwasawa M., Nitadori K., Makino J., 2020, MNRAS, 497, 536\n";
2455 fout<<
" Copyright (C) 2017\n"
2456 <<
" Long Wang, Masaki Iwasawa, Keigo Nitadori, Junichiro Makino and many others\n";
2457 fout<<
"====================================="
2462 void printFeatures(std::ostream & fout)
const {
2464 fout<<
"Use quadrupole moment in tree force calculation\n";
2468 #ifdef TIDAL_TENSOR_3RD
2469 fout<<
"Use 3rd order tidal tensor method\n";
2471 fout<<
"Use 2nd order tidal tensor method\n";
2475 #ifdef ORBIT_SAMPLING
2476 fout<<
"Use orbit-sampling method\n";
2478 fout<<
"Use Pseudoparticle multipole method\n";
2481 #ifdef STELLAR_EVOLUTION
2482 fout<<
"Use stellar evolution method: ";
2491 fout<<
"Use external potential: Galpy\n";
2495 fout<<
"Use 2nd-order KDKDK mode for tree step\n";
2498 fout<<
"Use 4th-order KDKDK mode for tree step\n";
2501 #ifdef CLUSTER_VELOCITY
2502 fout<<
"Use orbit-dependent neighbor criterion\n";
2505 #ifdef HARD_CHECK_ENERGY
2506 fout<<
"Check energy of short-range (hard) integration\n";
2509 #ifdef HARD_COUNT_NO_NEIGHBOR
2510 fout<<
"Count isolated particles in hard clusters\n";
2516 fout<<
"Use 64 bit SIMD n";
2521 fout<<
"Use Fugaku\n";
2528 #ifdef GPERF_PROFILE
2529 fout<<
"Use gperftools\n";
2533 fout<<
"Calculate profile\n";
2537 fout<<
"Calculate GPU profile\n";
2540 AR::printFeatures(fout);
2541 H4::printFeatures(fout);
2545 void printDebugFeatures(std::ostream & fout)
const {
2547 fout<<
"Debug mode: PETAR\n";
2549 #ifdef STABLE_CHECK_DEBUG
2550 fout<<
"Debug mode: STABLE_CHECK\n";
2552 #ifdef CLUSTER_DEBUG
2553 fout<<
"Debug mode: CLUSTER\n";
2555 #ifdef ARTIFICIAL_PARTICLE_DEBUG
2556 fout<<
"Debug mode: ARTIFICIAL_PARTICLE\n";
2559 fout<<
"Debug mode: HARD\n";
2561 #ifdef NAN_CHECK_DEBUG
2562 fout<<
"Debug mode: NAN_CHECK\n";
2564 AR::printDebugFeatures(fout);
2565 H4::printDebugFeatures(fout);
2574 int readParameters(
int argc,
char *argv[]) {
2577 printLogo(std::cerr);
2578 printReference(std::cerr);
2579 printFeatures(std::cerr);
2580 printDebugFeatures(std::cerr);
2581 std::cerr<<
"====================================="<<std::endl;
2585 assert(!read_parameters_flag);
2588 read_parameters_flag =
true;
2589 if (my_rank==0) input_parameters.
print_flag=
true;
2591 int read_flag = input_parameters.
read(argc,argv);
2593 if (my_rank==0) bse_parameters.
print_flag=
true;
2595 bse_parameters.
read(argc,argv);
2598 if (my_rank==0) galpy_parameters.
print_flag=
true;
2600 galpy_parameters.
read(argc,argv);
2604 if (read_flag==-1) {
2612 bool print_flag = input_parameters.
print_flag;
2617 std::cout<<
"----- Parallelization information -----\n";
2618 std::cout<<
"MPI processors: "<<n_proc<<std::endl;
2619 std::cout<<
"OMP threads: "<<PS::Comm::getNumberOfThread()<<std::endl;
2624 std::string fproname=input_parameters.
fname_snp.
value+
".prof.rank."+std::to_string(my_rank);
2625 if(input_parameters.
append_switcher.
value==1) fprofile.open(fproname.c_str(),std::ofstream::out|std::ofstream::app);
2627 fprofile.open(fproname.c_str(),std::ofstream::out);
2637 #if defined(USE_GPU) && defined(GPU_PROFILE)
2642 fprofile<<std::endl;
2651 if(write_style>0&&my_rank==0) {
2653 fstatus.open((fname_snp+
".status").c_str(),std::ofstream::out|std::ofstream::app);
2655 fstatus.open((fname_snp+
".status").c_str(),std::ofstream::out);
2658 if (write_style==2) {
2668 std::string my_rank_str = std::to_string(my_rank);
2669 std::string fname_esc = fname_snp +
".esc." + my_rank_str;
2671 fesc.open(fname_esc.c_str(), std::ofstream::out|std::ofstream::app);
2673 fesc.open(fname_esc.c_str(), std::ofstream::out);
2683 std::string fsse_name = fname_snp + fsse_par_suffix +
"." + my_rank_str;
2684 std::string fbse_name = fname_snp + fbse_par_suffix +
"." + my_rank_str;
2686 hard_manager.
ar_manager.interaction.fout_sse.open(fsse_name.c_str(), std::ofstream::out|std::ofstream::app);
2687 hard_manager.
ar_manager.interaction.fout_bse.open(fbse_name.c_str(), std::ofstream::out|std::ofstream::app);
2690 hard_manager.
ar_manager.interaction.fout_sse.open(fsse_name.c_str(), std::ofstream::out);
2691 hard_manager.
ar_manager.interaction.fout_bse.open(fbse_name.c_str(), std::ofstream::out);
2697 #ifdef ADJUST_GROUP_PRINT
2699 if (input_parameters.adjust_group_write_option.value==1) {
2700 std::string fgroup_name = fname_snp +
".group." + my_rank_str;
2702 hard_manager.
h4_manager.fgroup.open(fgroup_name.c_str(), std::ofstream::out|std::ofstream::app);
2704 hard_manager.
h4_manager.fgroup.open(fgroup_name.c_str(), std::ofstream::out);
2712 const PS::S32 num_thread = PS::Comm::getNumberOfThread();
2713 hard_dump.initial(num_thread, my_rank);
2717 system_soft.initialize();
2720 system_soft.setAverageTargetNumberOfSampleParticlePerProcess(input_parameters.
n_smp_ave.
value);
2722 domain_decompose_weight=1.0;
2723 dinfo.initialize(coef_ema);
2725 if(pos_domain==NULL) {
2726 pos_domain =
new PS::F64ort[n_proc];
2727 for(
PS::S32 i=0; i<n_proc; i++) pos_domain[i] = dinfo.getPosDomain(i);
2744 void readDataFromFile() {
2745 assert(read_parameters_flag);
2747 std::cerr<<
"Error: the input data filename is not provided, make sure your options have the correct format."<<std::endl;
2754 if(data_format==1||data_format==2||data_format==4)
2755 system_soft.readParticleAscii(data_filename, file_header);
2757 system_soft.readParticleBinary(data_filename, file_header);
2758 PS::Comm::broadcast(&file_header, 1, 0);
2759 PS::S64 n_glb = system_soft.getNumberOfParticleGlobal();
2760 PS::S64 n_loc = system_soft.getNumberOfParticleLocal();
2764 std::cout<<
"----- Reading file: "<<data_filename<<
" -----"<<std::endl
2765 <<
"Number of particles = "<<n_glb<<std::endl
2766 <<
"Time = "<<file_header.
time<<std::endl;
2772 #ifdef RECORD_CM_IN_HEADER
2774 for (
int i=0; i<n_loc; i++) mass += system_soft[i].mass;
2775 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
2776 stat.
pcm.
mass = PS::Comm::getSum(mass);
2780 stat.
pcm.
pos = file_header.pos_offset;
2781 stat.
pcm.
vel = file_header.vel_offset;
2787 read_data_flag =
true;
2795 template <
class Tptcl>
2796 void readDataFromArray(
PS::S64 _n_partcle, Tptcl* _particle) {
2797 assert(read_parameters_flag);
2800 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
2801 PS::S64 n_loc = n_glb / n_proc;
2802 if( n_glb % n_proc > my_rank) n_loc++;
2803 PS::S64 i_h = n_glb/n_proc*my_rank;
2804 if( n_glb % n_proc > my_rank) i_h += my_rank;
2805 else i_h += n_glb % n_proc;
2811 system_soft.setNumberOfParticleLocal(n_loc);
2812 for(
PS::S32 i=0; i<n_loc; i++){
2814 system_soft[i].mass = _particle[k].getMass();
2815 system_soft[i].pos.x = _particle[k].getPos()[0];
2816 system_soft[i].pos.y = _particle[k].getPos()[1];
2817 system_soft[i].pos.z = _particle[k].getPos()[2];
2818 system_soft[i].vel.x = _particle[k].getVel()[0];
2819 system_soft[i].vel.y = _particle[k].getVel()[1];
2820 system_soft[i].vel.z = _particle[k].getVel()[2];
2821 system_soft[i].id = i_h+i+1;
2822 system_soft[i].group_data.artificial.setParticleTypeToSingle();
2825 file_header.
nfile = 0;
2826 file_header.
n_body = n_glb;
2827 file_header.
time = 0.0;
2832 #ifdef RECORD_CM_IN_HEADER
2834 file_header.pos_offset = stat.
pcm.
pos;
2835 file_header.vel_offset = stat.
pcm.
vel;
2839 read_data_flag =
true;
2855 assert(read_parameters_flag);
2858 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
2859 PS::S64 n_loc = n_glb / n_proc;
2860 if( n_glb % n_proc > my_rank) n_loc++;
2861 PS::S64 i_h = n_glb/n_proc*my_rank;
2862 if( n_glb % n_proc > my_rank) i_h += my_rank;
2863 else i_h += n_glb % n_proc;
2869 system_soft.setNumberOfParticleLocal(n_loc);
2871 for(
PS::S32 i=0; i<n_loc; i++){
2872 system_soft[i].mass = _mass[i_h+i];
2873 system_soft[i].pos.x = _x[i_h+i];
2874 system_soft[i].pos.y = _y[i_h+i];
2875 system_soft[i].pos.z = _z[i_h+i];
2876 system_soft[i].vel.x = _vx[i_h+i];
2877 system_soft[i].vel.y = _vy[i_h+i];
2878 system_soft[i].vel.z = _vz[i_h+i];
2879 system_soft[i].id = _id[i_h+i];
2880 system_soft[i].group_data.artificial.setParticleTypeToSingle();
2881 assert(_id[i_h+i]>0);
2885 for(
PS::S32 i=0; i<n_loc; i++){
2886 system_soft[i].mass = _mass[i_h+i];
2887 system_soft[i].pos.x = _x[i_h+i];
2888 system_soft[i].pos.y = _y[i_h+i];
2889 system_soft[i].pos.z = _z[i_h+i];
2890 system_soft[i].vel.x = _vx[i_h+i];
2891 system_soft[i].vel.y = _vy[i_h+i];
2892 system_soft[i].vel.z = _vz[i_h+i];
2893 system_soft[i].id = i_h+i+1;
2894 system_soft[i].group_data.artificial.setParticleTypeToSingle();
2897 file_header.
nfile = 0;
2898 file_header.
n_body = n_glb;
2899 file_header.
time = 0.0;
2904 #ifdef RECORD_CM_IN_HEADER
2907 file_header.pos_offset = stat.
pcm.
pos;
2908 file_header.vel_offset = stat.
pcm.
vel;
2913 read_data_flag =
true;
2917 void generatePlummer() {
2919 assert(read_parameters_flag);
2924 PS::S64 n_loc = n_glb / n_proc;
2925 if( n_glb % n_proc > my_rank) n_loc++;
2926 system_soft.setNumberOfParticleLocal(n_loc);
2937 PS::S64 i_h = n_glb/n_proc*my_rank;
2938 if( n_glb % n_proc > my_rank) i_h += my_rank;
2939 else i_h += n_glb % n_proc;
2940 for(
PS::S32 i=0; i<n_loc; i++){
2941 system_soft[i].mass = mass[i];
2942 system_soft[i].pos = pos[i];
2943 system_soft[i].vel = vel[i];
2944 system_soft[i].id = i_h + i + 1;
2945 #ifdef STELLAR_EVOLUTION
2946 system_soft[i].radius = 0.0;
2947 system_soft[i].dm = 0.0;
2948 system_soft[i].time_record = 0.0;
2949 system_soft[i].time_interrupt = 0.0;
2950 system_soft[i].binary_state = 0;
2952 system_soft[i].star.initial(mass[i]*bse_parameters.
mscale.
value);
2955 system_soft[i].group_data.artificial.setParticleTypeToSingle();
2958 file_header.
nfile = 0;
2959 file_header.
n_body = n_glb;
2960 file_header.
time = 0.0;
2966 #ifdef RECORD_CM_IN_HEADER
2968 file_header.pos_offset = stat.
pcm.
pos;
2969 file_header.vel_offset = stat.
pcm.
vel;
2972 read_data_flag =
true;
2982 void generateKeplerDisk(
const PS::F64 ax_in,
2988 const double a_ice = 0.0,
2989 const double f_ice = 1.0,
2990 const double power = -1.5,
2994 assert(read_parameters_flag);
2999 PS::S64 n_loc = n_glb / n_proc;
3000 if( n_glb % n_proc > my_rank) n_loc++;
3001 system_soft.setNumberOfParticleLocal(n_loc);
3009 ax_in, ax_out, ecc_rms, inc_rms, dens, mass_sun, a_ice, f_ice, power, seed);
3011 PS::S64 i_h = n_glb/n_proc*my_rank;
3012 if( n_glb % n_proc > my_rank) i_h += my_rank;
3013 else i_h += n_glb % n_proc;
3014 for(
PS::S32 i=0; i<n_loc; i++){
3015 system_soft[i].mass = mass[i];
3016 system_soft[i].pos = pos[i];
3017 system_soft[i].vel = vel[i];
3018 system_soft[i].id = i_h + i + 1;
3019 system_soft[i].group_data.artificial.setParticleTypeToSingle();
3022 file_header.
nfile = 0;
3023 stat.
time = file_header.
time = 0.0;
3024 file_header.
n_body = n_glb;
3029 #ifdef RECORD_CM_IN_HEADER
3031 file_header.pos_offset = stat.
pcm.
pos;
3032 file_header.vel_offset = stat.
pcm.
vel;
3035 read_data_flag =
true;
3043 void initialParameters() {
3045 assert(read_data_flag);
3048 bool print_flag = input_parameters.
print_flag;
3062 std::cout<<
"----- Unit set 1: Msun, pc, Myr -----\n"
3065 std::cout<<
"----- Unit conversion for BSE ----- \n"
3066 <<
" tscale = "<<bse_parameters.
tscale.
value<<
" Myr / Myr\n"
3067 <<
" mscale = "<<bse_parameters.
mscale.
value<<
" Msun / Msun\n"
3068 <<
" rscale = "<<bse_parameters.
rscale.
value<<
" Rsun / pc\n"
3069 <<
" vscale = "<<bse_parameters.
vscale.
value<<
" [km/s] / [pc/Myr]\n";
3080 PS::F64 r_in, mass_average, vel_disp;
3095 const PS::S64 n_loc = system_soft.getNumberOfParticleLocal();
3108 for(
PS::S64 i=0; i<n_loc; i++){
3109 PS::F64 mi = system_soft[i].mass;
3117 vel_cm_loc += mi * vi;
3118 pos_cm_loc += mi * ri;
3123 rmax = std::sqrt(rmax);
3124 PS::F64 rmax_glb = PS::Comm::getMaxValue(rmax);
3127 PS::F64 mass_cm_glb = PS::Comm::getSum(mass_cm_loc);
3129 PS::F64vec pos_cm_glb = PS::Comm::getSum(pos_cm_loc);
3130 PS::F64vec vel_cm_glb = PS::Comm::getSum(vel_cm_loc);
3131 pos_cm_glb /= mass_cm_glb;
3132 vel_cm_glb /= mass_cm_glb;
3134 PS::F64 rmin_glb = std::sqrt(pos_cm_glb*pos_cm_glb);
3141 PS::S64 single_start_index = 0;
3142 const PS::S64 bin_last_id = 2*n_bin;
3143 if (system_soft[0].
id<bin_last_id) {
3144 single_start_index =
std::min(bin_last_id - system_soft[0].
id + 1,n_loc);
3145 if(single_start_index%2!=0) single_start_index--;
3148 const PS::S64 binary_start_index = (system_soft[0].id%2==0)?1:0;
3151 for (
PS::S64 i=binary_start_index; i<single_start_index; i+=2) {
3152 PS::F64 m1 = system_soft[i].mass;
3153 PS::F64 m2 = system_soft[i+1].mass;
3154 PS::F64vec dv = (m1*system_soft[i].vel + m2*system_soft[i+1].vel)/(m1+m2) - vel_cm_glb;
3155 vel_sq_loc += dv * dv;
3159 if (single_start_index <n_loc)
3160 for (
PS::S64 i=single_start_index; i<n_loc; i++){
3161 PS::F64vec dv = system_soft[i].vel - vel_cm_glb;
3162 vel_sq_loc += dv * dv;
3166 const PS::S64 n_vel_glb_count= PS::Comm::getSum(n_vel_loc_count);
3167 const PS::S64 n_glb = PS::Comm::getSum(n_loc);
3168 const PS::F64 vel_sq_glb = PS::Comm::getSum(vel_sq_loc);
3169 vel_disp = sqrt(vel_sq_glb / 3.0 / (
PS::F64)n_vel_glb_count);
3172 mass_average = mass_average_glb;
3175 bool r_out_flag = (r_out>0);
3178 if (r_out_flag) r_in = r_out * ratio_r_cut;
3182 r_out =
std::min(0.1*G*mass_cm_glb/(std::pow(n_glb,1.0/3.0)) / (3*vel_disp*vel_disp), 3.0*(rmax_glb-rmin_glb));
3183 r_in = r_out * ratio_r_cut;
3188 r_in = r_out*ratio_r_cut;
3189 if (print_flag) std::cout<<
"In one particle case, changeover radius is set to a small value\n";
3196 if (print_flag) std::cout<<
"In one particle case, tree time step is finishing - starting time\n";
3201 if (nstep_dt_soft_kepler>0)
3202 dt_soft = regularTimeStep(COMM::Binary::semiToPeriod(r_in, mass_average, G)/nstep_dt_soft_kepler);
3204 dt_soft = regularTimeStep(0.1*r_out / vel_disp);
3208 dt_soft = regularTimeStep(dt_soft);
3212 if (nstep_dt_soft_kepler>0) {
3213 r_in = COMM::Binary::periodToSemi(dt_soft*nstep_dt_soft_kepler, mass_average, G);
3214 r_out = r_in / ratio_r_cut;
3217 r_out = 10.0*dt_soft*vel_disp;
3218 r_in = r_out * ratio_r_cut;
3223 r_in = r_out*ratio_r_cut;
3224 if (print_flag) std::cout<<
"In one particle case, changeover radius is set to a small value\n";
3230 if (r_bin==0.0) r_bin = 0.8*r_in;
3233 if (r_search_min==0.0) r_search_min = search_vel_factor*vel_disp*dt_soft + r_out;
3240 dt_snap = regularTimeStep(dt_snap);
3255 std::cout<<
"----- Parameter list: -----\n";
3256 std::cout<<
" mass_average = "<<mass_average <<std::endl
3257 <<
" r_in = "<<r_in <<std::endl
3258 <<
" r_out = "<<r_out <<std::endl
3259 <<
" r_bin = "<<r_bin <<std::endl
3260 <<
" r_search_min = "<<r_search_min <<std::endl
3261 <<
" vel_disp = "<<vel_disp <<std::endl
3262 <<
" dt_soft = "<<dt_soft <<std::endl;
3266 bool restart_flag = file_header.
nfile;
3271 assert(stat.
n_real_glb == system_soft.getNumberOfParticleGlobal());
3274 id_offset = id_offset==-1 ? stat.
n_real_glb+1 : id_offset;
3277 if (!restart_flag) {
3278 #pragma omp parallel for
3281 PS::S64 id = system_soft[i].id;
3282 assert(id_offset>
id);
3287 system_soft[i].changeover.setR(m_fac, r_in, r_out);
3290 if(
id<=2*n_bin) system_soft[i].r_search =
std::max(r_search_min,vel_disp*dt_soft*search_vel_factor + system_soft[i].changeover.getRout());
3291 else system_soft[i].calcRSearch(dt_soft);
3293 auto& pi_cm = system_soft[i].group_data.cm;
3294 pi_cm.mass = pi_cm.vel.x = pi_cm.vel.y = pi_cm.vel.z = 0.0;
3299 #pragma omp parallel for
3301 auto& pi_cm = system_soft[i].group_data.cm;
3306 system_soft[i].changeover.setR(m_fac, r_in, r_out);
3311 if (pi_cm.mass!=0.0) {
3313 system_soft[i].r_search =
std::max(r_search_min, vel_disp*dt_soft*search_vel_factor + system_soft[i].changeover.getRout());
3320 else system_soft[i].calcRSearch(dt_soft);
3323 pi_cm.mass = pi_cm.vel.x = pi_cm.vel.y = pi_cm.vel.z = 0.0;
3325 #ifdef RECORD_CM_IN_HEADER
3334 std::string galpy_conf_filename = input_parameters.
fname_inp.
value+
".galpy";
3335 galpy_manager.
initial(galpy_parameters, stat.
time, galpy_conf_filename, restart_flag, print_flag);
3344 #ifdef HARD_CHECK_ENERGY
3352 #ifdef ORBIT_SAMPLING
3360 hard_manager.
ar_manager.step.initialSymplecticCofficients(-6);
3364 #ifdef SLOWDOWN_MASSRATIO
3365 hard_manager.
ar_manager.slowdown_mass_ref = mass_average;
3368 #ifdef STELLAR_EVOLUTION
3369 hard_manager.
ar_manager.interaction.stellar_evolution_option = input_parameters.stellar_evolution_option.value;
3370 if (write_style) hard_manager.
ar_manager.interaction.stellar_evolution_write_flag =
true;
3371 else hard_manager.
ar_manager.interaction.stellar_evolution_write_flag =
false;
3373 if (input_parameters.stellar_evolution_option.value>0) {
3374 hard_manager.
ar_manager.interaction.bse_manager.initial(bse_parameters, print_flag);
3375 hard_manager.
ar_manager.interaction.tide.speed_of_light = hard_manager.
ar_manager.interaction.bse_manager.getSpeedOfLight();
3379 #ifdef ADJUST_GROUP_PRINT
3381 if (write_style&&input_parameters.adjust_group_write_option.value==1)
3382 hard_manager.
h4_manager.adjust_group_write_flag=
true;
3384 hard_manager.
h4_manager.adjust_group_write_flag=
false;
3392 system_hard_one_cluster.
manager = &hard_manager;
3396 system_hard_isolated.
manager = &hard_manager;
3399 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
3401 system_hard_connected.
manager = &hard_manager;
3405 time_kick = stat.
time;
3407 if(write_style>0&&my_rank==0) {
3408 if (print_flag) std::cout<<
"----- Dump parameter files -----"<<std::endl;
3411 if (print_flag) std::cout<<
"Save input parameters to file "<<fname_par<<std::endl;
3413 if( (fpar_out = fopen(fname_par.c_str(),
"w")) == NULL) {
3414 fprintf(stderr,
"Error: Cannot open file %s.\n", fname_par.c_str());
3421 std::string fhard_par = input_parameters.
fname_par.
value +
".hard";
3422 if (print_flag) std::cout<<
"Save hard_manager parameters to file "<<fhard_par<<std::endl;
3423 if( (fpar_out = fopen(fhard_par.c_str(),
"w")) == NULL) {
3424 fprintf(stderr,
"Error: Cannot open file %s.\n", fhard_par.c_str());
3432 std::string fbse_par = input_parameters.
fname_par.
value + fbse_par_suffix;
3433 if (print_flag) std::cout<<
"Save bse_parameters to file "<<fbse_par<<std::endl;
3434 if( (fpar_out = fopen(fbse_par.c_str(),
"w")) == NULL) {
3435 fprintf(stderr,
"Error: Cannot open file %s.\n", fbse_par.c_str());
3444 std::string fgalpy_par = input_parameters.
fname_par.
value +
".galpy";
3445 if (print_flag) std::cout<<
"Save galpy_parameters to file "<<fgalpy_par<<std::endl;
3446 if( (fpar_out = fopen(fgalpy_par.c_str(),
"w")) == NULL) {
3447 fprintf(stderr,
"Error: Cannot open file %s.\n", fgalpy_par.c_str());
3458 if (print_flag) std::cout<<
"----- Finish parameter initialization -----"<<std::endl;
3460 initial_parameters_flag =
true;
3464 void initialStep() {
3465 assert(initial_parameters_flag);
3466 if (initial_step_flag)
return;
3468 assert(checkTimeConsistence());
3474 if (stat.
n_real_loc==1) system_soft[0].clearForce();
3486 file_header.
nfile--;
3492 initial_step_flag =
true;
3508 treeNeighborSearch();
3517 createGroup(dt_tree);
3528 treeForceCorrectChangeover();
3531 correctForceChangeOverUpdate();
3534 kickClusterAndRecoverGroupMemberMass(system_soft, system_hard_isolated.
getPtcl(), 0);
3536 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
3538 kickClusterAndRecoverGroupMemberMass(system_soft, system_hard_connected.
getPtcl(), 0);
3542 search_cluster.SendSinglePtcl(system_soft, system_hard_connected.
getPtcl());
3546 writeBackHardParticles();
3552 file_header.
nfile--;
3556 system_soft.setNumberOfParticleLocal(stat.
n_real_loc);
3558 #ifdef CLUSTER_VELOCITY
3559 setParticleGroupDataToCMData();
3565 initial_step_flag =
true;
3571 assert(initial_step_flag);
3576 if (stat.
time>=time_break)
return 0;
3583 assert(system_soft.getNumberOfParticleLocal()==1);
3584 auto& p = system_soft[0];
3597 #ifdef RECORD_CM_IN_HEADER
3601 bool interrupt_flag =
false;
3602 bool output_flag =
false;
3621 output_flag = (fmod(stat.
time, dt_output) == 0.0);
3624 interrupt_flag = (stat.
time>=time_break);
3633 p.vel += p.acc * dt_kick;
3637 time_kick += dt_kick;
3642 updateStatus(
false);
3647 PS::Comm::barrier();
3653 PS::Comm::barrier();
3659 if(interrupt_flag) {
3660 assert(checkTimeConsistence());
3663 PS::Comm::barrier();
3672 p.vel += p.acc * dt_kick;
3676 #ifdef RECORD_CM_IN_HEADER
3678 correctPtclVelCM(dt_kick);
3680 time_kick += dt_kick;
3686 p.pos += p.vel * dt_drift;
3695 #ifdef STELLAR_EVOLUTION
3698 int modify_flag = hard_manager.
ar_manager.interaction.modifyOneParticle(p, stat.
time, stat.
time + dt_drift);
3701 PS::F64 de_kin = 0.5*(p.mass*(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]) - mbk*(vbk[0]*vbk[0]+vbk[1]*vbk[1]+vbk[2]*vbk[2]));
3702 stat.
energy.de_sd_change_cum += de_kin;
3703 stat.
energy.de_sd_change_modify_single += de_kin;
3704 stat.
energy.de_change_cum += de_kin;
3705 stat.
energy.de_change_modify_single += de_kin;
3707 stat.
energy.etot_sd_ref += de_kin;
3713 stat.
time += dt_drift;
3717 PS::Comm::barrier();
3726 while (stat.
time < time_break) {
3727 stat.
time += dt_tree;
3728 time_kick = stat.
time;
3743 assert(initial_step_flag);
3746 if (stat.
n_real_glb==1)
return integrateOneToTime(_time_break);
3749 if (n_interrupt_glb>0) finishInterruptDrift();
3751 if (n_interrupt_glb>0)
return n_interrupt_glb;
3755 if (stat.
time>=time_break)
return 0;
3766 #ifdef STELLAR_EVOLUTION
3768 correctSoftPotMassChange();
3774 #ifdef RECORD_CM_IN_HEADER
3787 treeNeighborSearch();
3795 createGroup(dt_tree);
3807 treeForceCorrectChangeover();
3815 bool interrupt_flag =
false;
3816 bool output_flag =
false;
3818 bool changeover_flag =
false;
3825 correctForceChangeOverUpdate();
3851 output_flag = (fmod(stat.
time, dt_output) == 0.0);
3856 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
3858 PS::S32 n_changeover_modify_global = PS::Comm::getSum(n_changeover_modify_local);
3859 if (n_changeover_modify_global>0) changeover_flag =
true;
3863 interrupt_flag = (stat.
time>=time_break);
3866 if (output_flag||changeover_flag||interrupt_flag) dt_kick = dt_manager.
getDtEndContinue();
3872 PS::Comm::barrier();
3882 if(output_flag||interrupt_flag) {
3884 writeBackHardParticles();
3890 updateStatus(
false);
3896 PS::Comm::barrier();
3902 PS::Comm::barrier();
3919 if(interrupt_flag) {
3920 #ifdef CLUSTER_VELOCITY
3921 setParticleGroupDataToCMData();
3924 correctForceChangeOverUpdate();
3927 system_soft.setNumberOfParticleLocal(stat.
n_real_loc);
3929 assert(checkTimeConsistence());
3933 PS::Comm::barrier();
3941 if(output_flag||changeover_flag) {
3943 assert(checkTimeConsistence());
3954 correctForceChangeOverUpdate();
3965 #ifdef STELLAR_EVOLUTION
3967 hard_manager.
ar_manager.interaction.time_interrupt_max = stat.
time + dt_drift;
3979 PS::Comm::barrier();
3986 if (n_interrupt_glb>0) {
3987 #ifdef HARD_INTERRUPT_PRINT
3988 std::cerr<<
"Interrupt detected, number: "<<n_interrupt_glb<<std::endl;
3990 return n_interrupt_glb;
4000 if (fstatus.is_open()) fstatus.close();
4001 if (fesc.is_open()) fesc.close();
4003 if (fprofile.is_open()) fprofile.close();
4007 auto& interaction = hard_manager.
ar_manager.interaction;
4008 if (interaction.fout_sse.is_open()) interaction.fout_sse.close();
4009 if (interaction.fout_bse.is_open()) interaction.fout_bse.close();
4011 #ifdef ADJUST_GROUP_PRINT
4015 delete[] pos_domain;
4020 remove_list.resizeNoInitialize(0);
4021 n_interrupt_glb = 0;
4023 read_parameters_flag =
false;
4024 read_data_flag =
false;
4025 initial_parameters_flag =
false;
4026 initial_step_flag =
false;
4029 ~PeTar() { clear();}
4032 bool PeTar::initial_fdps_flag =
false;