10 #include "../src/io.hpp"
12 #include <integrateFullOrbit.h>
31 type_args (
input_par_store,
"__NONE__",
"galpy-type-arg",
"Add potential types and argumentsto the potential list in the center of the galactic reference frame"),
35 rscale(
input_par_store, 1.0,
"galpy-rscale",
"Radius scale factor from unit of the input particle data (IN) to Galpy distance unit (1.0)"),
37 vscale(
input_par_store, 1.0,
"galpy-vscale",
"Velocity scale factor from unit of the input particle data (IN) to Galpy velocity unit (1.0)"),
49 int read(
int argc,
char *argv[],
const int opt_used_pre=0) {
50 static int galpy_flag=-1;
51 const struct option long_options[] = {
55 {
rscale.
key, required_argument, &galpy_flag, 3},
57 {
vscale.
key, required_argument, &galpy_flag, 5},
60 {
"help", no_argument, 0,
'h'},
64 int opt_used=opt_used_pre;
67 std::string fname_par;
69 while ((copt = getopt_long(argc, argv,
"-p:h", long_options, &option_index)) != -1)
120 std::string fgalpy_par = fname_par+
".galpy";
122 if( (fpar_in = fopen(fgalpy_par.c_str(),
"r")) == NULL) {
123 fprintf(stderr,
"Error: Cannot open file %s.\n", fgalpy_par.c_str());
130 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
137 std::cout<<
"Galpy options:"<<std::endl;
139 std::cout<<
"***PS: use petar.galpy.help to check how to setup --galpy-type-arg and --galpy-conf-file."
150 if(
print_flag) std::cout<<
"----- Finish reading input options of Galpy -----\n";
157 double kms_pcmyr=1.022712165045695;
160 double vb_pcmyr = vbase*kms_pcmyr;
169 std::cout<<
"----- Unit conversion for Galpy -----\n"
171 <<
"vscale = "<<
vscale.
value<<
" [220 km/s] / [pc/Myr]\n"
172 <<
"tscale = "<<tscale <<
" [Solar orbital period/2 pi] / Myr\n"
173 <<
"fscale = "<<fscale <<
" [galpy acceleration unit] / [pc/Myr^2]\n"
174 <<
"pscale = "<<pscale <<
" [galpy potential unit] / [pc^2/Myr^2]\n"
175 <<
"GMscale = "<<GMscale<<
" [galpy gravitational constant * mass unit] / [pc^3/Myr^2]\n";
214 double kms_pcmyr=1.022712165045695;
235 for (
int k=0; k<10; k++) {
237 a_tmp =
a + 0.5*(adot_new+adot)*
dt_scale*_dt;
279 template <
class Tstream>
280 void labelCheck(Tstream& fconf,
const char* match) {
284 std::cerr<<
"Galpy MWPotentialEvolve config: reading label error, should be "<<match<<
" given "<<label<<std::endl;
289 void eofCheck(std::ifstream& fconf,
const char* message) {
291 std::cerr<<
"Galpy MWPotentialEvolve config: reading "<<message<<
" fails! File reaches EOF."<<std::endl;
344 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
345 int my_rank = PS::Comm::getRank();
349 fconf.open(_filename.c_str(), std::ifstream::in);
350 if (!fconf.is_open()) {
351 std::cerr<<
"Galpy MWPotentialEvolve config: configure file "<<_filename.c_str()<<
" cannot be open!"<<std::endl;
355 labelCheck(fconf,
"Time");
357 eofCheck(fconf,
"current time (Myr)");
358 labelCheck(fconf,
"a");
360 eofCheck(fconf,
"scale factor");
361 labelCheck(fconf,
"H0");
363 eofCheck(fconf,
"Hubble constant");
364 labelCheck(fconf,
"Omega");
366 eofCheck(fconf,
"cosmological densities");
367 labelCheck(fconf,
"dt_scale");
369 eofCheck(fconf,
"time scale");
370 labelCheck(fconf,
"dt_max");
373 eofCheck(fconf,
"maximum time step (Myr)");
374 labelCheck(fconf,
"Halo");
376 eofCheck(fconf,
"Halo parameters");
377 labelCheck(fconf,
"Disk");
379 eofCheck(fconf,
"Disk parameters");
380 labelCheck(fconf,
"Bulge");
381 fconf>>
init.rho_bulge>>
init.alpha_bulge>>
init.rcut_bulge;
382 eofCheck(fconf,
"Bulge parameters");
385 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
387 PS::Comm::broadcast(&
frw, 1, 0);
388 PS::Comm::broadcast(&
init, 1, 0);
392 std::cerr<<
"Error: the time recorded in the MWpotential parameter file, "<<
frw.
time<<
", is not equal to the current system time, "<<_time<<
"!"<<std::endl;
411 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
412 int my_rank = PS::Comm::getRank();
416 fconf.open(_filename.c_str(), std::ifstream::in);
417 if (!fconf.is_open()) {
418 std::cerr<<
"Galpy MWPotentialEvolve config: configure file "<<_filename.c_str()<<
" cannot be open!"<<std::endl;
422 for (
int i=0; i<npar; i++) {
425 std::cerr<<
"Galpy MWPotentialEvolve config: reading number of parameters is "<<npar<<
" parameters, only "<<i<<
" given!"<<std::endl;
430 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
432 PS::Comm::broadcast(pars, npar, 0);
437 std::cerr<<
"Error: the time recorded in the MWpotential parameter file, "<<
frw.
time<<
", is not equal to the current system time, "<<_time<<
"!"<<std::endl;
451 init.m_vir_halo = pars[8];
452 init.c_halo = pars[9];
453 init.ac_halo = pars[10];
454 init.m_disk = pars[11];
455 init.ra_disk = pars[12];
456 init.rb_disk = pars[13];
457 init.rho_bulge = pars[14];
458 init.alpha_bulge = pars[15];
459 init.rcut_bulge = pars[16];
468 fout.open(_filename.c_str(), std::ifstream::out);
469 if (!fout.is_open()) {
470 std::cerr<<
"Error: Galpy potential parameter file to write, "<<_filename<<
", cannot be open!"<<std::endl;
473 fout<<std::setprecision(14)
482 <<
init.m_vir_halo<<
" "
488 <<
init.rho_bulge<<
" "
489 <<
init.alpha_bulge<<
" "
503 const double G_astro = 0.0044983099795944;
504 const double pi = 3.141592653589793;
506 double z = 1/
frw.
a-1;
511 double delta = 18*pi*pi + 82*mass_density_m1 - 39*mass_density_m1*mass_density_m1;
512 double delta0 = 18*pi*pi + 82*mass_density_m1_z0 - 39*mass_density_m1_z0*mass_density_m1_z0;
513 now.rho_c_halo = 3*Ht*Ht/(8*pi*G_astro);
514 double rho_c_halo0 = 3*H0*H0/(8*pi*G_astro);
517 double mass_z_factor = std::exp(-2*
init.ac_halo*z);
518 now.m_vir_halo =
init.m_vir_halo*mass_z_factor;
520 now.r_vir_halo = std::pow(3*
now.m_vir_halo/(4*pi*delta*
now.rho_c_halo),1.0/3.0);
521 double rvir_z_factor = std::pow(mass_z_factor*delta0*rho_c_halo0/(delta*
now.rho_c_halo), 1.0/3.0);
524 double c0 =
init.c_halo;
526 double c_factor = 1.0/(std::log(1+c) - c/(1+c));
528 now.gm_halo = G_astro*
now.m_vir_halo*c_factor;
529 now.rs_halo =
now.r_vir_halo/c;
532 now.gm_disk = G_astro*
init.m_disk*mass_z_factor;
533 now.ra_disk =
init.ra_disk*rvir_z_factor;
534 now.rb_disk =
init.rb_disk*rvir_z_factor;
536 now.grho_bulge = G_astro*
init.rho_bulge*mass_z_factor/std::pow(rvir_z_factor,3-
init.alpha_bulge);
537 now.alpha_bulge =
init.alpha_bulge;
538 now.rcut_bulge =
init.rcut_bulge*rvir_z_factor;
551 PotentialSetPar():
mode(-1),
gm(0),
pos{0.0,0.0,0.0},
vel{0.0,0.0,0.0},
acc{0.0,0.0,0.0} {}
557 for (std::size_t i=0; i<3; i++) fout<<
pos[i]<<
" ";
558 for (std::size_t i=0; i<3; i++) fout<<
vel[i]<<
" ";
559 for (std::size_t i=0; i<3; i++) fout<<
acc[i]<<
" ";
570 void setOrigin(
const int _mode,
const double _gm=0,
const double* _pos=NULL,
const double* _vel=NULL,
const double* _acc=NULL) {
571 assert(_mode>=0&&_mode<=2);
618 #ifdef GALPY_VERSION_1_7_1
621 parse_leapFuncArgs_Full(
npot,
arguments, &_type, &_arg, NULL);
660 template <
class Tstream>
661 void labelCheck(Tstream&
fconf,
const char* match) {
665 std::cerr<<
"Galpy config: reading label error, should be "<<match<<
" given "<<label<<std::endl;
670 void eofCheck(std::ifstream&
fconf,
const char* message) {
672 std::cerr<<
"Galpy config: reading "<<message<<
" fails! File reaches EOF."<<std::endl;
677 void gtZeroCheck(
const int n,
const char* message) {
679 std::cerr<<
"Galpy config: "<<message<<
" <=0!"<<std::endl;
684 void geZeroCheck(
const int n,
const char* message) {
686 std::cerr<<
"Galpy config: "<<message<<
" <0!"<<std::endl;
699 template <
class ttype>
700 void resizeArray(
const int n_diff,
const int index, std::vector<ttype>& array, std::vector<int>& array_offset) {
701 int offset = array_offset[index];
704 std::vector<ttype> data(n_diff,ttype());
705 array.insert(array.begin()+offset, data.begin(), data.end());
708 array.erase(array.begin()+offset, array.begin()+offset-n_diff);
709 for (
size_t i=index+1; i<array_offset.size(); i++)
710 array_offset[i] += n_diff;
720 template <
class ttype>
721 void eraseArray(
const int index, std::vector<ttype>& array, std::vector<int>& array_offset) {
722 int n = array_offset[index+1] - array_offset[index];
723 int offset = array_offset[index];
725 array.erase(array.begin()+offset, array.begin()+offset+n);
727 for (
size_t i=index+1; i<array_offset.size(); i++)
728 array_offset[i] = array_offset[i+1]-n;
729 array_offset.pop_back();
730 assert(array_offset.back()==
int(array.size()));
764 pot_set_pars(),
pot_sets(),
update_time(0.0),
rscale(1.0),
vscale(1.0),
tscale(1.0),
fscale(1.0),
pscale(1.0),
gmscale(1.0),
fconf(),
set_name(),
set_parfile(),
mw_evolve() {}
768 fout<<
"Galpy parameters, time: "<<
time;
772 for (
int k=0; k<nset; k++) {
774 fout<<
"Potential set "<<k+1<<
" Mode: "<<pot_set_par_k.mode
775 <<
" GM: "<<pot_set_par_k.gm
776 <<
" Pos: "<<pot_set_par_k.pos[0]<<
" "<<pot_set_par_k.pos[1]<<
" "<<pot_set_par_k.pos[2]
777 <<
" Vel: "<<pot_set_par_k.vel[0]<<
" "<<pot_set_par_k.vel[1]<<
" "<<pot_set_par_k.vel[2]
778 <<
" Acc: "<<pot_set_par_k.acc[0]<<
" "<<pot_set_par_k.acc[1]<<
" "<<pot_set_par_k.acc[2]
779 <<
"\nPotential type indice: ";
782 fout<<
"\nPotential arguments: ";
785 fout<<
"\nChange argument [index mode rate]:";
798 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
799 void broadcastDataMPI() {
802 int my_rank = PS::Comm::getRank();
804 PS::Comm::broadcast(&nset, 1, 0);
852 void initial(
const IOParamsGalpy& _input,
const double _time,
const std::string _conf_name,
const bool _restart_flag,
const bool _print_flag=
false) {
867 std::size_t ipar =
set_name.find_first_of(
":");
868 if (ipar!=std::string::npos) {
880 pot_set_par_k.setOrigin(0);
903 pot_args.insert(
pot_args.end(), {251.63858935563147, 1.8, 1899.9999999999998,
904 306770418.38588977, 3000.0, 280.0,
905 1965095308.192175, 16000.0});
913 if (
set_name==
"MWPotentialEvolve") {
931 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
932 int my_rank = PS::Comm::getRank();
936 if (!
fconf.is_open()) {
937 std::cerr<<
"Error: Galpy configure file "<<_input.
config_filename.
value.c_str()<<
" cannot be open!"<<std::endl;
940 labelCheck(
fconf,
"Time");
944 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
960 std::cout<<
"----- Finish initialize Galpy potential -----\n";
973 for (
int k=0; k<nset; k++) {
987 if (_type_args!=
"__NONE__") {
991 pot_set_par_k.setOrigin(0);
993 std::vector<std::string> type_args_pair;
996 std::size_t istart = 0;
997 std::size_t inext = _type_args.find_first_of(
"|");
998 while (inext!=std::string::npos) {
999 type_args_pair.push_back(_type_args.substr(istart,inext-istart));
1001 inext = _type_args.find_first_of(
"|",istart);
1003 if (istart!=_type_args.size()) type_args_pair.push_back(_type_args.substr(istart));
1005 if (_print_flag) std::cout<<
"Galpy Potential combination list:\n";
1007 for (std::size_t i=0; i<type_args_pair.size(); i++) {
1010 inext = type_args_pair[i].find_first_of(
":");
1011 if (inext==std::string::npos) {
1012 std::cerr<<
"Error: potential type index delimiter ':' is not found in input string "<<type_args_pair[i]<<std::endl;
1015 std::string type_str = type_args_pair[i].substr(0,inext);
1016 std::string arg_str = type_args_pair[i].substr(inext+1);
1018 inext = type_str.find_first_of(
",");
1019 if (_print_flag) std::cout<<
"Type index: ";
1020 while (inext!=std::string::npos) {
1021 int type_i=std::stoi(type_str.substr(istart, inext-istart));
1023 if (_print_flag) std::cout<<type_i<<
" ";
1025 inext = type_str.find_first_of(
",",istart);
1027 if (istart!=type_str.size()) {
1028 int type_i=std::stoi(type_str.substr(istart));
1030 if (_print_flag) std::cout<<type_i<<
" ";
1032 if (_print_flag) std::cout<<
"args:";
1036 inext = arg_str.find_first_of(
",",istart);
1037 while (inext!=std::string::npos) {
1038 double arg_i = std::stod(arg_str.substr(istart, inext-istart));
1040 if (_print_flag) std::cout<<
" "<<arg_i;
1042 inext = arg_str.find_first_of(
",",istart);
1044 if(istart!=arg_str.size()) {
1045 double arg_i = std::stod(arg_str.substr(istart));
1047 if (_print_flag) std::cout<<
" "<<arg_i;
1049 if (_print_flag) std::cout<<std::endl;
1075 if (_initial_flag) {
1078 pot_set_par_k.setOrigin(0);
1092 for (
int i=0; i<8; i++)
pot_args[i] = pot_arg_mw[i];
1096 std::cout<<std::setprecision(14)
1098 <<
" NFW Halo: M_vir[Msun]: "<<mwpot.m_vir_halo<<
" R_vir[pc]: "<<mwpot.r_vir_halo<<std::endl;
1112 double time_scaled= _system_time*
tscale;
1114 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
1115 int my_rank = PS::Comm::getRank();
1118 if (
fconf.is_open()) {
1121 double update_time_next;
1124 labelCheck(
fconf,
"Task");
1129 labelCheck(
fconf,
"Nset");
1131 eofCheck(
fconf,
"number of new potential sets");
1132 gtZeroCheck(nset,
"number of new potential sets");
1134 for (
int k=0; k<nset; k++) {
1138 labelCheck(
fconf,
"Set");
1141 eofCheck(
fconf,
"set index");
1143 std::cerr<<
"Galpy config: reading set index not match the expected one, should be "<<k<<
" given "<<set_index<<std::endl;
1147 labelCheck(
fconf,
"Ntype");
1150 eofCheck(
fconf,
"number of potential types");
1151 gtZeroCheck(n_pot_k,
"number of potential types");
1154 labelCheck(
fconf,
"Mode");
1157 eofCheck(
fconf,
"mode");
1158 if (mode_k<0 || mode_k>2) {
1159 std::cerr<<
"Galpy config: mode should be 0, 1, 2, given "<<mode_k<<std::endl;
1162 pot_set_par_k.mode = mode_k;
1165 labelCheck(
fconf,
"GM");
1166 fconf>>pot_set_par_k.gm;
1167 eofCheck(
fconf,
"g*m");
1169 labelCheck(
fconf,
"Pos");
1170 for (
int j=0; j<3; j++) fconf>>pot_set_par_k.pos[j];
1171 eofCheck(
fconf,
"position");
1173 labelCheck(
fconf,
"Vel");
1174 for (
int j=0; j<3; j++) fconf>>pot_set_par_k.vel[j];
1175 eofCheck(
fconf,
"velocity");
1179 labelCheck(
fconf,
"Type");
1180 for (
int i=0; i<n_pot_k; i++) {
1183 eofCheck(
fconf,
"potential type");
1190 std::getline(
fconf, line);
1191 std::getline(
fconf, line);
1192 std::istringstream fin(line);
1195 labelCheck(fin,
"Arg");
1196 while (fin>>arg_i) {
1203 labelCheck(
fconf,
"Nchange");
1206 eofCheck(
fconf,
"number of changing arguments");
1207 geZeroCheck(n_change,
"number of changing arguments");
1211 labelCheck(
fconf,
"Index");
1212 for (
int i=0; i<n_change; i++) {
1215 eofCheck(
fconf,
"index of the changing argument");
1216 if (index_i<-1 || index_i>=n_arg) {
1217 std::cerr<<
"Galpy config: index of the changing argument should be >=-1 and <"<<n_arg<<
", given "<<index_i<<std::endl;
1222 labelCheck(
fconf,
"ChangeMode");
1223 for (
int i=0; i<n_change; i++) {
1225 fconf>>change_mode_i;
1226 eofCheck(
fconf,
"changing mode");
1227 if (!(change_mode_i==1||change_mode_i==2)) {
1228 std::cerr<<
"Galpy config: change mode must be 1 or 2, given "<<change_mode_i<<std::endl;
1233 labelCheck(
fconf,
"ChangeRate");
1234 for (
int i=0; i<n_change; i++) {
1237 eofCheck(
fconf,
"changing rate");
1245 else if (task==
"update") {
1246 labelCheck(
fconf,
"Nset");
1248 eofCheck(
fconf,
"number of update potential sets");
1249 gtZeroCheck(nset,
"number of update potential sets");
1251 for (
int i=0; i<nset; i++) {
1253 labelCheck(
fconf,
"Set");
1256 eofCheck(
fconf,
"set index");
1257 if (k<0 || k>=n_set_old) {
1258 std::cerr<<
"Galpy config: changing set index incorrect, should be from 0 to "<<n_set_old-1<<
", given "<<k<<std::endl;
1264 labelCheck(
fconf,
"Ntype");
1267 eofCheck(
fconf,
"number of potential types");
1268 gtZeroCheck(n_pot_k,
"number of potential types");
1271 labelCheck(
fconf,
"Mode");
1274 eofCheck(
fconf,
"mode");
1275 if (mode_k<-2 || mode_k==-1 || mode_k>2) {
1276 std::cerr<<
"Galpy config: mode should be 0, 1, 2 or -2, given "<<mode_k<<std::endl;
1281 labelCheck(
fconf,
"GM");
1282 fconf>>pot_set_par_k.gm;
1283 eofCheck(
fconf,
"gm");
1287 labelCheck(
fconf,
"Pos");
1288 for (
int j=0; j<3; j++) fconf>>pot_set_par_k.pos[j];
1289 eofCheck(
fconf,
"position");
1290 labelCheck(
fconf,
"Vel");
1291 for (
int j=0; j<3; j++) fconf>>pot_set_par_k.vel[j];
1292 eofCheck(
fconf,
"velocity");
1296 labelCheck(
fconf,
"Pos");
1297 for (
int j=0; j<3; j++) fconf>>dtmp;
1298 eofCheck(
fconf,
"position");
1299 labelCheck(
fconf,
"Vel");
1300 for (
int j=0; j<3; j++) fconf>>dtmp;
1301 eofCheck(
fconf,
"velocity");
1304 pot_set_par_k.mode = mode_k;
1312 labelCheck(
fconf,
"Type");
1313 for (
int j=0; j<n_pot_k; j++) {
1316 eofCheck(
fconf,
"potential type");
1322 std::getline(
fconf, line);
1323 std::getline(
fconf, line);
1324 std::istringstream fin(line);
1325 labelCheck(fin,
"Arg");
1326 std::vector<double> arg_k;
1328 while (fin>>arg_tmp) {
1329 arg_k.push_back(arg_tmp);
1334 for (
size_t j=0; j<arg_k.size(); j++) {
1339 labelCheck(
fconf,
"Nchange");
1342 eofCheck(
fconf,
"number of changing arguments");
1343 geZeroCheck(n_change,
"changing arguments");
1349 labelCheck(
fconf,
"Index");
1350 for (
int j=0; j<n_change; j++) {
1353 eofCheck(
fconf,
"index of the changing argument");
1354 if (index_j<-1 || index_j>=
int(arg_k.size())) {
1355 std::cerr<<
"Galpy config: index of the changing argument should be >=-1 and <"<<(arg_k.size())<<
", given "<<index_j<<std::endl;
1360 labelCheck(
fconf,
"ChangeMode");
1361 for (
int j=0; j<n_change; j++) {
1363 fconf>>change_mode_j;
1364 eofCheck(
fconf,
"changing mode");
1365 if (!(change_mode_j==1||change_mode_j==2)) {
1366 std::cerr<<
"Galpy config: change mode must be 1 or 2, given "<<change_mode_j<<std::endl;
1371 labelCheck(
fconf,
"ChangeRate");
1372 for (
int j=0; j<n_change; j++) {
1375 eofCheck(
fconf,
"changing rate");
1382 else if (task==
"remove") {
1383 labelCheck(
fconf,
"Nset");
1385 eofCheck(
fconf,
"number of removing potential sets");
1386 gtZeroCheck(nset,
"number of removing potential sets");
1388 labelCheck(
fconf,
"Index");
1389 std::vector<int> rm_indices;
1390 for (
int i=0; i<nset; i++) {
1393 eofCheck(
fconf,
"removing set index");
1394 rm_indices.push_back(k);
1396 std::sort(rm_indices.begin(), rm_indices.end());
1397 for (
int i=0; i<nset; i++) {
1398 int idel = rm_indices[i]-i;
1404 nset = n_set_old - nset;
1405 geZeroCheck(nset,
"number of potential sets after remove");
1408 std::cerr<<
"Galpy config: Task must be add, update or remove, given "<<task<<std::endl;
1419 std::cerr<<
"Galpy config: reading label error, should be Time given "<<label<<std::endl;
1422 fconf>>update_time_next;
1423 if (update_time_next>time_scaled) {
1430 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
1433 PS::Comm::broadcast(&nset, 1, 0);
1453 bool update_flag =
false;
1454 if (
set_name==
"MWPotentialEvolve") {
1461 if (update_flag && _print_flag)
printData(std::cout);
1462 update_flag = (update_flag || change_flag);
1475 if (
set_name==
"MWPotentialEvolve") {
1487 for (
int i=0; i<offset; i++) fout<<
" ";
1488 fout<<
"Galpy: Bovy J., 2015, ApJS, 216, 29"<<std::endl;
1495 acc_pot[0] = acc_pot[1] = acc_pot[2] = 0.0;
1507 assert(mode_k>=0||mode_k<=2);
1511 vel_k[0] += acc_k[0]*dt_scale;
1512 vel_k[1] += acc_k[1]*dt_scale;
1513 vel_k[2] += acc_k[2]*dt_scale;
1526 assert(mode_k>=0||mode_k<=2);
1530 pos_k[0] += vel_k[0]*dt_scale;
1531 pos_k[1] += vel_k[1]*dt_scale;
1532 pos_k[2] += vel_k[2]*dt_scale;
1549 assert(mode_k>=0||mode_k<=2);
1560 dx = pos_k[0]-pos_j[0]-pos_pcm[0];
1561 dy = pos_k[1]-pos_j[1]-pos_pcm[1];
1562 dz = pos_k[2]-pos_j[2]-pos_pcm[2];
1565 dx = pos_k[0]-pos_j[0];
1566 dy = pos_k[1]-pos_j[1];
1567 dz = pos_k[2]-pos_j[2];
1569 double rxy= std::sqrt(dx*dx+dy*dy);
1571 double phi= std::atan2(dy, dx);
1572 double sinphi = dy/rxy;
1573 double cosphi = dx/rxy;
1576 double acc_rxy = calcRforce(rxy, dz, phi, t, npot,
pot_args);
1577 double acc_z = calczforce(rxy, dz, phi, t, npot,
pot_args);
1578 #if (defined GALPY_VERSION_1_7_9) || (defined GALPY_VERSION_1_7_1)
1579 double acc_phi = calcPhiforce(rxy, dz, phi, t, npot,
pot_args);
1581 double acc_phi = calcphitorque(rxy, dz, phi, t, npot,
pot_args);
1584 acc_pot[0] += (cosphi*acc_rxy - sinphi*acc_phi/rxy);
1585 acc_pot[1] += (sinphi*acc_rxy + cosphi*acc_phi/rxy);
1586 acc_pot[2] += acc_z;
1603 void calcAccPot(
double* acc,
double& pot,
const double _time,
const double gm,
const double* pos_g,
const double* pos_l) {
1615 acc[0] = acc[1] = acc[2] = 0.0;
1619 for (
int k=0; k<nset; k++) {
1621 assert(mode_k>=0||mode_k<=2);
1624 int i = (mode_k & 1);
1626 double dx = x[i]-pos_k[0];
1627 double dy = y[i]-pos_k[1];
1628 double dz = z[i]-pos_k[2];
1629 double rxy= std::sqrt(dx*dx+dy*dy);
1630 double phi= std::atan2(dy, dx);
1631 double sinphi = dy/rxy;
1632 double cosphi = dx/rxy;
1635 double acc_rxy = calcRforce(rxy, dz, phi, t, npot,
pot_args);
1636 double acc_z = calczforce(rxy, dz, phi, t, npot,
pot_args);
1637 #if (defined GALPY_VERSION_1_7_9) || (defined GALPY_VERSION_1_7_1)
1638 double acc_phi = calcPhiforce(rxy, dz, phi, t, npot,
pot_args);
1640 double acc_phi = calcphitorque(rxy, dz, phi, t, npot,
pot_args);
1643 double pot_i = evaluatePotentials(rxy, dz, npot,
pot_args);
1646 assert(!std::isinf(acc_rxy));
1647 assert(!std::isnan(acc_rxy));
1648 assert(!std::isinf(acc_phi));
1649 assert(!std::isnan(acc_phi));
1650 assert(!std::isinf(pot));
1651 assert(!std::isnan(pot));
1653 double acc_x = (cosphi*acc_rxy - sinphi*acc_phi/rxy);
1654 double acc_y = (sinphi*acc_rxy + cosphi*acc_phi/rxy);
1660 acc_pot[0] -= gm*acc_x/gm_pot;
1661 acc_pot[1] -= gm*acc_y/gm_pot;
1662 acc_pot[2] -= gm*acc_z/gm_pot;
1674 acc[0] = acc[1] = acc[2] = pot = 0.0;
1695 fout.open(_filename.c_str(), std::ifstream::out);
1696 if (!fout.is_open()) {
1697 std::cerr<<
"Error: Galpy potential parameter file to write, "<<_filename<<
", cannot be open!"<<std::endl;
1700 fout<<std::setprecision(14);
1705 std::size_t n_arg =
pot_args.size();
1712 for (std::size_t i=0; i<n_set; i++) {
1716 fout<<std::endl<<n_pot_offset<<
" ";
1717 for (std::size_t i=0; i<n_pot_offset; i++) {
1720 fout<<std::endl<<
n_pot<<
" ";
1721 for (std::size_t i=0; i<
n_pot; i++) {
1724 fout<<std::endl<<n_arg_offset<<
" ";
1725 for (std::size_t i=0; i<n_arg_offset; i++) {
1728 fout<<std::endl<<n_arg<<
" ";
1729 for (std::size_t i=0; i<n_arg; i++) {
1732 fout<<std::endl<<n_change_offset<<
" ";
1733 for (std::size_t i=0; i<n_change_offset; i++) {
1736 fout<<std::endl<<n_change<<
" ";
1737 for (std::size_t i=0; i<n_change; i++) {
1752 std::size_t n_set,
n_pot, n_pot_offset, n_arg, n_arg_offset, n_change, n_change_offset;
1754 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
1755 int my_rank = PS::Comm::getRank();
1760 fin.open(_filename.c_str(), std::ifstream::in);
1761 if (!fin.is_open()) {
1762 std::cerr<<
"Error: Galpy configure file for restart "<<_filename.c_str()<<
" cannot be open!"<<std::endl;
1767 eofCheck(fin,
"time and number of potential sets");
1768 geZeroCheck(n_set,
"number of potential sets");
1770 for (std::size_t i=0; i<n_set; i++) {
1772 eofCheck(fin,
"potential set parameter");
1775 assert(n_pot_offset==n_set+1);
1777 for (std::size_t i=0; i<n_pot_offset; i++) {
1780 eofCheck(fin,
"potential type array offset");
1783 geZeroCheck(
n_pot,
"number of potential types");
1785 for (std::size_t i=0; i<
n_pot; i++) {
1788 eofCheck(fin,
"potential type");
1792 assert(n_arg_offset==n_set+1);
1793 for (std::size_t i=0; i<n_arg_offset; i++) {
1796 eofCheck(fin,
"potential argument array offset");
1799 geZeroCheck(n_arg,
"number of potential arguments");
1801 for (std::size_t i=0; i<n_arg; i++) {
1804 eofCheck(fin,
"potential arguments");
1806 fin>>n_change_offset;
1808 assert(n_change_offset==n_set+1);
1809 for (std::size_t i=0; i<n_change_offset; i++) {
1812 eofCheck(fin,
"changing argument offset");
1815 geZeroCheck(n_change,
"number of changing arguments");
1817 for (std::size_t i=0; i<n_change; i++) {
1820 eofCheck(fin,
"changing arguments");
1824 #ifdef PARTICLE_SIMULATOR_MPI_PARALLEL
1845 double dt = _time -
time;
1847 if (_print_flag) std::cout<<
"Galpy update argument, time [Galpy unit]: "<<_time<<
" dt: "<<
dt<<std::endl;
1849 for (std::size_t i=0; i<n_set; i++) {
1852 double* change_arg_ptr = NULL;
1853 if (index_local==-1)
1857 change_arg_ptr = &(
pot_args[index]);
1861 if (_print_flag) std::cout<<
"Set "<<i+1<<
" Index: "<<
change_args[k].index<<
" "<<
" new_argument(linear): "<<*change_arg_ptr;
1865 if (_print_flag) std::cout<<
"Set "<<i+1<<
" Index: "<<
change_args[k].index<<
" "<<
" new_argument(exp): "<<*change_arg_ptr;
1867 if (_print_flag) std::cout<<std::endl;