From e9455c0a0e62396cf78103547e3a3b3945837946 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Wed, 4 Mar 2020 13:46:04 -0500 Subject: [PATCH 01/65] Started cleanup process --- Makefile | 14 +- phi-GRAPE.c | 7293 -------------------------------------------------- phigrape.cpp | 6934 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 6941 insertions(+), 7300 deletions(-) delete mode 100644 phi-GRAPE.c create mode 100644 phigrape.cpp diff --git a/Makefile b/Makefile index f8fe666..20340bf 100644 --- a/Makefile +++ b/Makefile @@ -13,18 +13,18 @@ yebisu: GRAPEHOME = ../yebisu yebisu: GRAPELIB = -L$(GRAPEHOME) -lyebisug6 GRAPEINC = -I$(GRAPEHOME) -CFLAGS ?= -mcmodel=large -CFLAGS += -O$(OPTIMIZATION) +CXXFLAGS ?= -mcmodel=medium +CFFFLAGS += -O$(OPTIMIZATION) INC = $(GRAPEINC) $(CUDAINC) -LIB = $(GRAPELIB) $(CUDALIB) -lm -lgcc -lgfortran -lstdc++ -MPICC ?= mpicc -EXECUTABLE ?= phi-GRAPE.exe +LIB = $(GRAPELIB) $(CUDALIB) -lm +MPICXX ?= mpic++ +EXECUTABLE ?= phigrape default: - $(MPICC) $(CPPFLAGS) $(CFLAGS) -DETICS_DTSCF=$(ETICS_DTSCF) $(INC) phi-GRAPE.c -o $(EXECUTABLE) $(LIB) + $(MPICXX) $(CPPFLAGS) $(CXXFLAGS) -DETICS_DTSCF=$(ETICS_DTSCF) $(INC) phigrape.cpp -o $(EXECUTABLE) $(LIB) yebisu: CPPFLAGS := $(filter-out -DETICS, $(CPPFLAGS)) yebisu: default clean: - rm -f *.o phi-GRAPE.exe + rm -f *.o phigrape diff --git a/phi-GRAPE.c b/phi-GRAPE.c deleted file mode 100644 index 236ee7e..0000000 --- a/phi-GRAPE.c +++ /dev/null @@ -1,7293 +0,0 @@ -/***************************************************************************** - File Name : "phi-GRAPE/GPU.c" // BH (1 || 2) + ACC + EJECT - : - Contents : N-body code with integration by individual block time step - : together with the parallel using of GRAPE6a board's. - : - : Added the GPU support via SAPPORO library. - : - : Normalization to the physical units!!! - : - : External Potential added - : Plummer-Kuzmin: Bulge, Disk, Halo - : Kharchenko+Andreas... - : - : SC extra POT for Bek SC test runs... - : - : Rebuced to the Single BH -> Plummer - : Andreas+Fazeel... - : - : Stellar evolution added - : Stellar lifetimes: Raiteri, Villata & Navarro (1996) - : IMS mass loss: van den Hoeg & Groenewegen (1997) - : - : STARDESTR_EXT: Tidal disruption of stars by external BH... - : Chingis, Denis & Maxim... - : - : STARDESTR: Tidal disruption of stars by BH... - : Jose, Li Shuo & Shiyan Zhong - : - : STARDISK: Drag force... - : Chingis, Denis & Maxim... - : - : STARDISK: variable hz = HZ*(R/R_crit) up to R_crit... - : Taras, Andreas... - : - : Live BH (1 || 2) + ACC + EJECT... - : Li Shuo & Shiyan Zhong - : - : dt_min for BH (1 || 2)... - : - : added the PN calculus for the BBH - : PN0, PN1, PN2, PN2.5 (coded on the base of - : Gabor Kupi original routine) - : - : added the "name" array... - : - : added the GMC's calculus (GMC on CPU; GMC2 on GPU) - : for Alexey SC runs... and also for Fazeel Zurich runs... - : - : CPU_TIMELIMIT added for the Julich MW cluster runs... - : - Coded by : Peter Berczik - Version number : 19.04 - Last redaction : 2019.04.16 12:55 -*****************************************************************************/ -//#define CPU_RUNLIMIT 28000 // 24h = 24*60*60 = 86400 -#define CPU_RUNLIMIT 255000 // 3 days = 3*24*60*60 = 259200 -//#define CPU_RUNLIMIT 100 // 9.5 min -//#define CPU_RUNLIMIT 100 // 9.5 min - -//#define GMC // add the GMC's to the run -//#define GMC2 // add the GMC's to the run - -//#define NORM // Physical normalization -//#define STEVOL // Stellar evolution Do not tuch! Defined inside the Makefiles !!! -//#define STEVOL_SSE // Stellar evolution with SSE Do not tuch! Defined inside the Makefiles !!! - -//#define ADD_BH1 // add the Single BH - -#define ADD_BH2 // add the Binary BH's -#define ADD_N_BH // eps_BH = 0.0, but added only the Newtonian forces -// #define ADD_PN_BH // extra - added also the Post-Newton forces -// #define ADD_SPIN_BH // extra - added the SPIN for the BH's - DEFAULT !!! - -// #define BH_OUT // extra output for BH's (live) -// #define BH_OUT_NB // extra output for the BH's neighbours (live) - -// #define BBH_INF // BBH influence sphere... -// #define R_INF 10.0 // Factor for the influence sphere... if( R < R_INF * DR_BBH ) -// #define R_INF2 (R_INF*R_INF) - -// #define DT_MIN_WARNING // dt < dt_min warning !!! - -//#define BH_OUT_NB_EXT // extra output for the BH's neighbours (external) - -//#define SAPPORO // Gaburov. Do not tuch! Defined inside the Makefiles !!! -//#define YEBISU // Nitadori. Do not tuch! Defined inside the Makefiles !!! -//#define GUINNESS // Nakasato. Do not tuch! Defined inside the Makefiles !!! - -//#define STARDESTR // disruption of stars by BH tidal forces -//#define R_TIDAL 1.0E-03 // Tidal radius of the BH's -//#define RMAX_OUT // extra data for def. r_max... - -//#define STARDESTR_EXT // disruption of stars by external BH tidal forces -//#define R_0 0.22 // Outer cut of the disk -//#define R_ACCR 0.0050 // Tidal Accr. rad of the BH's in units of R_0 -//#define R_TIDAL (R_0*R_ACCR) // Tidal radius of the BH's in NB units - -//#define STARDISK // analytic gas disk around BH + drag -//#define HZ (0.001*R_0) // Disk thickness... in NB units -//#define R_CRIT 0.0257314 // Critical radius of the disk (vert SG = vert BH force) -//#define R_CRIT 0.0 // i.e. hz=HZ=const... - -//#define SPH_GAS // SPH gas disk around BH + drag; experimental stuff !!! - -//#define EXTPOT // external potential (BH? or galactic?) -//#define EXTPOT_BH // BH - usually NB units - -//#define EXTPOT_GAL // Galactic B+D+H PK - usually physical units - -//#define EXTPOT_GAL_DEH // Dehnen Galactic - usually physical units -//#define EXTPOT_GAL_LOG // Log Galactic - usually physical units - -//#define EXTPOT_SC // SC extra POT for Bek test runs... -//#define DATAFILE eff0.05.tsf10.00.tab -//#define M_SC_DIM 100001 - -//#define CMCORR // CM correction in the zero step and in every dt_contr - -//#define DEBUG // debug information to files & screen -// #define DEBUG_extra // extra debug information to files & screen -//#define LAGR_RAD // write out lagr-rad.dat - -//#define LIMITS // for "0" mass particles !!! -//#define R_LIMITS 1.0E+03 // for "0" mass particles !!! -//#define COORDS 1010.0 // for "0" mass particles !!! - -//#define LIMITS_NEW // for "0" mass particles !!! - -//#define LIMITS_ALL_BEG // for ALL particles at the beginning... -//#define LIMITS_ALL // for ALL particles -//#define R_LIMITS_ALL 1.0E+03 // for ALL particles - -#ifdef ETICS -#include "grapite.h" -// why do we need CEP as a compilaion flag... just have it always on when ETICS is on. IF there is no CEP, there should be a graceful skipping of those operations. -//#define ETICS_CEP -#ifndef ETICS_DTSCF -#error "ETICS_DTSCF must be defined" -#endif -#endif - -#define TIMING - -#define ETA_S_CORR 4.0 -#define ETA_BH_CORR 4.0 - -#define DTMAXPOWER -3.0 -#define DTMINPOWER -36.0 - -/* - -3.0 0.125 - -4.0 0.0625 - -5.0 0.03125 - -7.0 ~1e-2 --10.0 ~1e-3 -............. --20.0 ~1e-6 --23.0 ~1e-7 --26.0 ~1e-8 --30.0 ~1e-9 -*/ - -//#define AMD - -// #define ACT_DEF_LL - -#if defined(ACT_DEF_LL) && defined(ACT_DEF_GRAPITE) -#error "Contradicting preprocessor flags!" -#endif - -/****************************************************************************/ -#include -#include -#include -#include -#include -#include -#include - -/* -double aaa; -double aaapars[5]; - -extern void qwerty_(double *aaa, double *aaapars); -*/ - -#ifdef SAPPORO -#include -#include -#define GPU_PIPE 256 -#else -# ifdef YEBISU -# define G6_NPIPE 2048 -# else -# define G6_NPIPE 48 -# endif -#include "grape6.h" -#endif - -#ifdef GUINNESS -#define GPU_PIPE 128 -#endif - -#include - -/* Some "good" functions and constants... */ -#define SIG(x) ( ((x)<0) ? (-1):(1) ) -#define ABS(x) ( ((x)<0) ? (-x):(x) ) -#define MAX(a,b) ( ((a)>(b)) ? (a):(b) ) -#define MIN(a,b) ( ((a)<(b)) ? (a):(b) ) -#define SQR(x) ( (x)*(x) ) -#define POW3(x) ( (x)*SQR(x) ) - -#define Pi 3.14159265358979323846 -#define TWOPi 6.283185307179 -#define sqrt_TWOPi 2.506628274631 - -#ifdef NORM -//http://pdg.lbl.gov/2015/reviews/rpp2015-rev-astrophysical-constants.pdf - -#define G 6.67388E-11 // (m/s^2) * (m^2/kg) -#define Msol 1.988489E+30 // kg -#define Rsol 6.957E+08 // m -#define AU 149597870700.0 // m -#define pc 3.08567758149E+16 // m -#define Year 31556925.2 // s -#define c_feny 299792458.0 // m/s - -#define kpc (1.0E+03*pc) // m -#define km 1.0E+03 // km -> m -#define cm3 1.0E-06 // cm^3 -> m^3 -#define Myr (1.0E+06*Year) // s -#define Gyr (1.0E+09*Year) // s -#define R_gas 8.31447215 // J/(K*mol) -#define k_gas 1.380650424E-23 // J/K -#define N_A 6.022141510E+23 // 1/mol -#define mu 1.6605388628E-27 // kg -#define mp 1.67262163783E-27 // kg -#define me 9.1093821545E-31 // kg - -#define pc2 (pc*pc) -#define pc3 (pc*pc*pc) -#define kpc2 (kpc*kpc) -#define kpc3 (kpc*kpc*kpc) -#endif - -/* - 1KB = 1024 - 2KB = 2048 - 4KB = 4096 - 8KB = 8192 - 16KB = 16384 - 32KB = 32768 - 64KB = 65536 - 128KB = 131072 - 256KB = 262144 - 512KB = 524288 - 1024KB = 1048576 -> 1MB -*/ - -#define KB 1024 -#define MB (KB*KB) - -#define N_MAX (6*MB) -#define N_MAX_loc (2*MB) - -//#define N_MAX (1200000) -//#define N_MAX_loc (1200000) - -//#define P_MAX 32 - -//#ifdef DEBUG - -/* extra code & data for DEBUG... */ - -#include "debug.h" - -//#ifdef DEBUG_extra -int ind_sort[N_MAX]; -double var_sort[N_MAX]; -//#endif - -//#endif - -#ifdef LAGR_RAD -int lagr_rad_N = 22; -double mass_frac[] = { 0.0001, 0.0003, 0.0005, 0.001, 0.003, 0.005, 0.01, 0.03, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.95, 0.99, 0.9999, 1.0 }; -double lagr_rad[22]; -double m_tot, m_cum, n_cum; -#endif - -int name_proc, n_proc=1, myRank=0, rootRank=0, cur_rank, - i, j, k, ni, nj, diskstep=0, power, jjj, iii, - skip_con=0, tmp_i; - -double dt_disk, dt_contr, t_disk=0.0, t_contr=0.0, - dt_bh, t_bh=0.0, dt_bh_tmp, - t_end, time_cur, dt_min, dt_max, min_t, min_t_loc, dt_new, min_dt, - eta_s, eta, eta_bh, - E_pot, E_pot_ext, E_kin, E_tot, E_tot_0, DE_tot, - E_tot_corr, E_tot_corr_0, DE_tot_corr, - E_tot_corr_sd, E_tot_corr_sd_0, DE_tot_corr_sd, - E_corr = 0.0, E_sd = 0.0, t_diss_on = 0.125, - e_kin_corr = 0.0, e_pot_corr = 0.0, e_pot_BH_corr = 0.0, - e_summ_corr = 0.0, - mcm, rcm_mod, vcm_mod, - rcm_sum=0.0, vcm_sum=0.0, - eps=0.0, eps2, - xcm[3], vcm[3], mom[3], - xdc[3], vdc[2], - over2=(1.0/2.0), over3=(1.0/3.0), over6=(1.0/6.0), - a2_mod, adot2_mod, - dt_tmp, dt2half, dt3over6, dt4over24, dt5over120, - dtinv, dt2inv, dt3inv, - a0mia1, ad04plad12, ad0plad1, - a2[3], a3[3], a2dot1[3], - a1abs, adot1abs, a2dot1abs, a3dot1abs, - Timesteps=0.0, n_act_sum=0.0, n_act_distr[N_MAX], g6_calls=0.0, g6_calls_sum=0.0, - tmp, tmp_r, tmp_v, tmp_rv, tmp_cpu, - tmp_pot, tmp_a, tmp_adot, - tmp_a_bh, tmp_adot_bh, - tmp_a_bh_pn0, tmp_a_bh_pn1, tmp_a_bh_pn2, tmp_a_bh_pn2_5, tmp_a_bh_pn3, tmp_a_bh_pn3_5, tmp_a_bh_spin, - tmp_adot_bh_pn0, tmp_adot_bh_pn1, tmp_adot_bh_pn2, tmp_adot_bh_pn2_5, tmp_adot_bh_pn3, tmp_adot_bh_pn3_5, tmp_adot_bh_spin; - -double R[3], V[3], L[3], mju, dr2, dr, dv2, dv, dl2, dl, pot_eff; - -char processor_name[MPI_MAX_PROCESSOR_NAME], - inp_fname[30], inp_fname_gmc[30], - out_fname[30], dbg_fname[30]; - -/* global variables */ - -int N, N_star, N_gmc, N_bh, - ind[N_MAX], name[N_MAX]; -double m[N_MAX], x[N_MAX][3], v[N_MAX][3], - pot[N_MAX], a[N_MAX][3], adot[N_MAX][3], - t[N_MAX], dt[N_MAX]; - -/* local variables */ - -int n_loc, ind_loc[N_MAX_loc]; -double m_loc[N_MAX_loc], x_loc[N_MAX_loc][3], v_loc[N_MAX_loc][3], - pot_loc[N_MAX_loc], a_loc[N_MAX_loc][3], adot_loc[N_MAX_loc][3], - t_loc[N_MAX_loc], dt_loc[N_MAX_loc]; - -/* data for active particles */ - -int n_act, ind_act[N_MAX]; -double m_act[N_MAX], - x_act[N_MAX][3], v_act[N_MAX][3], - pot_act[N_MAX], a_act[N_MAX][3], adot_act[N_MAX][3], - t_act[N_MAX], dt_act[N_MAX], - x_act_new[N_MAX][3], v_act_new[N_MAX][3], - pot_act_new[N_MAX], a_act_new[N_MAX][3], adot_act_new[N_MAX][3], - pot_act_tmp[N_MAX], a_act_tmp[N_MAX][3], adot_act_tmp[N_MAX][3], - pot_act_tmp_loc[N_MAX], a_act_tmp_loc[N_MAX][3], adot_act_tmp_loc[N_MAX][3]; - -FILE *inp, *out, *tmp_file, *dbg; - -double CPU_time_real0, CPU_time_user0, CPU_time_syst0; -double CPU_time_real, CPU_time_user, CPU_time_syst; - - -#ifdef TIMING - -double CPU_tmp_real0, CPU_tmp_user0, CPU_tmp_syst0; -double CPU_tmp_real, CPU_tmp_user, CPU_tmp_syst; - -double DT_TOT, - DT_ACT_DEF1, DT_ACT_DEF2, DT_ACT_DEF3, DT_ACT_PRED, - DT_ACT_GRAV, DT_EXT_GRAV, - DT_GMC_GRAV, DT_GMC_GMC_GRAV, DT_EXT_GMC_GRAV, - DT_ACT_CORR, DT_ACT_LOAD, - DT_STEVOL, DT_STARDISK, DT_STARDESTR; - -double DT_ACT_REDUCE; - -#endif - -/* some local settings for G6a board's */ - -int clusterid, ii, nn, numGPU; - -//#ifdef SAPPORO -#if defined(SAPPORO) || defined(GUINNESS) - -int npipe=GPU_PIPE, index_i[GPU_PIPE]; -double h2_i[GPU_PIPE], x_i[GPU_PIPE][3], v_i[GPU_PIPE][3], - p_i[GPU_PIPE], a_i[GPU_PIPE][3], jerk_i[GPU_PIPE][3]; -double new_tunit=51.0, new_xunit=51.0; - -#elif defined YEBISU - -int npipe=G6_NPIPE, index_i[G6_NPIPE]; -double h2_i[G6_NPIPE], x_i[G6_NPIPE][3], v_i[G6_NPIPE][3], - p_i[G6_NPIPE], a_i[G6_NPIPE][3], jerk_i[G6_NPIPE][3]; -int new_tunit=51, new_xunit=51; -#else - -int npipe=48, index_i[48]; -double h2_i[48], x_i[48][3], v_i[48][3], - p_i[48], a_i[48][3], jerk_i[48][3]; -int new_tunit=51, new_xunit=51; - -#endif - -int aflag=1, jflag=1, pflag=1; - -double ti=0.0, a2by18[3], a1by6[3], aby2[3]; - -/* normalization... */ - -#ifdef NORM -double m_norm, r_norm, v_norm, t_norm; -#endif - -double eps_BH=0.0; - -/* external potential... */ - -#ifdef EXTPOT - -#ifdef EXTPOT_GAL -double m_bulge, a_bulge, b_bulge, - m_disk, a_disk, b_disk, - m_halo, a_halo, b_halo, -// x_ext, y_ext, z_ext, -// vx_ext, vy_ext, vz_ext, -// x_ij, y_ij, z_ij, -// vx_ij, vy_ij, vz_ij, rv_ij, - x2_ij, y2_ij, z2_ij, - r_tmp, r2_tmp, z_tmp, z2_tmp; -#endif - -#ifdef EXTPOT_GAL_DEH -double m_ext, r_ext, g_ext, - tmp_r2, tmp_r3, dum, dum2, dum3, dum_g, tmp_g; -#endif - -#ifdef EXTPOT_GAL_LOG -double v_halo, r_halo, - v2_halo, r2_halo, r2_r2_halo, - x2_ij, y2_ij, z2_ij; -#endif - -#ifdef EXTPOT_BH -double r2, rv_ij, - m_bh, b_bh, eps_bh; -#endif - -#ifdef EXTPOT_SC -int M_SC=M_SC_DIM; -double r_sc[M_SC_DIM], m_sc[M_SC_DIM], p_sc[M_SC_DIM]; -double M_R, pot_out_R; -#endif - - -double pot_ext[N_MAX], pot_act_ext[N_MAX]; // for all EXTPOT - -#endif - - -int i_bh, i_bh1, i_bh2, - num_bh = 0, num_bh1 = 0, num_bh2 = 0; - -double m_bh, m_bh1, m_bh2, b_bh, - r, r2, - x_ij, y_ij, z_ij, - vx_ij, vy_ij, vz_ij, rv_ij; - -#ifdef STEVOL -int num_dead, event[N_MAX]; -double dt_stevol, t_stevol; -double m0[N_MAX], ZZZ[N_MAX], t0[N_MAX]; -#endif - - -#ifdef STEVOL_SSE - -int num_dead, event[N_MAX], event_old[N_MAX]; -double dt_stevol, t_stevol; -double m0[N_MAX], ZZZ[N_MAX], t0[N_MAX]; -double SSEMass[N_MAX], SSESpin[N_MAX], SSERad[N_MAX], - SSELum[N_MAX], SSETemp[N_MAX]; -double SSEMV[N_MAX], SSEBV[N_MAX]; - -double Rgal = 10000.0; //Distance of star from sun for artificial CMD with observational errors [pc] - -int van_kick=0; - -extern void zcnsts_(double *z, double *zpars); -extern void evolv1_(int *kw, double *mass, double *mt, double *r, double *lum, double *mc, double *rc, double *menv, double *renv, double *ospin, double *epoch, double *tms, double *tphys, double *tphysf, double *dtp, double *z, double *zpars, double *vkick, double *vs); -extern int cmd(int kstar, double rstar, double lstar, double Rgal, double *abvmag, double *vmag, double *BV, double *Teff, double *dvmag, double *dBV); - -struct{ - double neta; - double bwind; - double hewind; - double mxns; -} value1_; - -struct{ - double pts1; - double pts2; - double pts3; -} points_; - -struct{ - double sigma; - int bhflag; -} value4_; - -struct{ - int idum; -} value3_; - -struct{ - int ceflag; - int tflag; - int ifflag; - int nsflag; - int wdflag; -} flags_; - -struct{ - double beta; - double xi; - double acc2; - double epsnov; - double eddfac; - double gamma; -} value5_; - -struct{ - double alpha1; - double lambda; -} value2_; - -#include "cmd.c" - -#endif - - - -#ifdef BBH_INF -int inf_event[N_MAX]; -double x_bbhc[3], v_bbhc[3], DR2, tmp_r2; -double DV2, EB, SEMI_a, SEMI_a2; -#endif - - - -/* STARDISK Drag force... */ - -#ifdef STARDISK - -double a_drag[N_MAX][3], adot_drag[N_MAX][3]; -//double a_drag[N_MAX][3], adot_drag[N_MAX][3]; - -double z_new_drag, r_new_drag2, hz; - -#ifdef SPH_GAS - -#define N_GAS_MAX (128*KB) -#define NB 50 - -int N_GAS, ind_gas[N_GAS_MAX], sosed_gas[N_GAS_MAX][NB]; -double m_gas[N_GAS_MAX], x_gas[N_GAS_MAX][3], v_gas[N_GAS_MAX][3], h_gas[N_GAS_MAX], DEN_gas[N_GAS_MAX]; - -//int sosed[NB]; -double d[N_MAX]; // podrazumevajem chto: N_MAX > N_GAS_MAX vsegda ! -double x_star, y_star, z_star, DEN_star; -double h_min = 1.0E-04, h_max = 1.0; - -#include "def_H.c" -#include "def_DEN.c" -#include "def_DEN_STAR.c" - -#endif // SPH_GAS - -#include "drag_force.c" - -// calculate the SG for the set of active particles which is deepley INSIDE the EXT BH infl. rad. -// EXPERIMENTAL feature !!! - -//int SG_CALC = 0; -//double summ_tmp_r = 0.0, aver_tmp_r = 0.0, R_INT_CUT = 1.0E-03; - -#endif // STARDISK - - - -/* GMC data... */ - -#ifdef GMC - -double dt_gmc, E_pot_gmc, E_pot_gmc_gmc, E_pot_ext_gmc, E_kin_gmc; - -#define N_gmc_MAX (500) - -int N_gmc, ind_gmc[N_gmc_MAX], name_gmc[N_gmc_MAX]; - -double m_gmc[N_gmc_MAX], pot_gmc_gmc[N_gmc_MAX], pot_ext_gmc[N_gmc_MAX], - x_gmc[N_gmc_MAX][3], v_gmc[N_gmc_MAX][3], a_gmc[N_gmc_MAX][3], - eps_gmc[N_gmc_MAX]; - -double pot_gmc[N_MAX]; - -#endif // GMC - - -/****************************************************************************/ - -/****************************************************************************/ -#ifdef ADD_N_BH - -double x_bh1[3], x_bh2[3], v_bh1[3], v_bh2[3]; - -double pot_bh1, a_bh1[3], adot_bh1[3], - pot_bh2, a_bh2[3], adot_bh2[3]; - -//double eps_BH = 0.0; - -#include "n_bh.c" - -/* -int calc_force_n_BH(double m1, double xx1[], double vv1[], - double m2, double xx2[], double vv2[], - double eps_BH, - double pot_n1, double a_n1[], double adot_n1[], - double pot_n2, double a_n2[], double adot_n2[]) -*/ - -/* - INPUT - -m1 - mass of the 1 BH -xx1[0,1,2] - coordinate of the 1 BH -vv1[0,1,2] - velocity of the 1 BH - -m2 - mass of the 2 BH -xx2[0,1,2] - coordinate of the 2 BH -vv2[0,1,2] - velocity of the 2 BH - -eps_BH - force softening, can be even exactly 0.0 ! - - OUTPUT - -pot_n1 for the 1 BH -a_n1 [0,1,2] for the 1 BH -adot_n1 [0,1,2] for the 1 BH - -pot_n2 for the 2 BH -a_n2 [0,1,2] for the 2 BH -adot_n2 [0,1,2] for the 2 BH - -return - 0 if everything OK -*/ - -#endif -/****************************************************************************/ - -/****************************************************************************/ -#ifdef ADD_PN_BH - -double C_NB = 477.12; - -int usedOrNot[7] = {1, 1, 1, 1, 0, 0, 0}; - -double a_pn1[7][3], adot_pn1[7][3], - a_pn2[7][3], adot_pn2[7][3]; - -double s_bh1[3] = {0.0, 0.0, 1.0}; -double s_bh2[3] = {0.0, 0.0, 1.0}; - -#ifdef ADD_SPIN_BH // eto rabotajet vsegda !!! -#include "pn_bh_spin.c" -#else -#include "pn_bh.c" // eto staraja versija, bolshe ne rabotajet !!! -#endif - -/* -int calc_force_pn_BH(double m1, double xx1[], double vv1[], double ss1[], - double m2, double xx2[], double vv2[], double ss2[], - double CCC_NB, double dt_bh, - int usedOrNot[], - double a_pn1[][3], double adot_pn1[][3], - double a_pn2[][3], double adot_pn2[][3]) -*/ - -/* - INPUT - -m1 - mass of the 1 BH -xx1[0,1,2] - coordinate of the 1 BH -vv1[0,1,2] - velocity of the 1 BH -spin1[0,1,2] - normalized spin of the 1 BH - -m2 - mass of the 2 BH -xx2[0,1,2] - coordinate of the 2 BH -vv2[0,1,2] - velocity of the 2 BH -spin2[0,1,2] - normalized spin of the 2 BH - -CCC_NB - Speed of light "c" in internal units -dt_BH - timestep of the BH's, needed for the SPIN integration - -usedOrNot[PN0, PN1, PN2, PN2.5, PN3, PN3.5, SPIN] - different PN term usage: PN1, PN2, PN2.5, PN3, PN3.5, SPIN - 0 1 2 3 4 5 6 - - OUTPUT - -a_pn1 [0 - PN0; 1 - PN1; 2 - PN2; 3 - PN2.5, 4 - PN3, 5 - PN3.5, 6 - SPIN] [3] for the 1 BH -adot_pn1[0 - PN0; 1 - PN1; 2 - PN2; 3 - PN2.5, 4 - PN3, 5 - PN3.5, 6 - SPIN] [3] for the 1 BH - -a_pn2 [0 - PN0; 1 - PN1; 2 - PN2; 3 - PN2.5, 4 - PN3, 5 - PN3.5, 6 - SPIN] [3] for the 2 BH -adot_pn2[0 - PN0; 1 - PN1; 2 - PN2; 3 - PN2.5, 4 - PN3, 5 - PN3.5, 6 - SPIN] [3] for the 2 BH - -return - 0 if everything OK - - 505 if BH's separation < 4 x (RSwarch1 + RSwarch2) -*/ - -#endif - -/****************************************************************************/ - -/****************************************************************************/ -/* RAND_MAX = 2147483647 */ -/* my_rand : 0.0 - 1.0 */ -/* my_rand2 : -1.0 - 1.0 */ - -double my_rand(void) -{ -return( (double)(rand()/(double)RAND_MAX) ); -} - -double my_rand2(void) -{ -return (double)(2.0)*((rand() - RAND_MAX/2)/(double)RAND_MAX); -} -/****************************************************************************/ - -#ifdef STARDESTR -#include "star_destr.c" -#endif - -#ifdef STARDESTR_EXT -#include "star_destr_ext.c" -#endif - -#ifdef ACT_DEF_LL -#include "act_def_linklist.c" -#endif - -#ifdef ETICS -double t_exp, dt_exp=ETICS_DTSCF; // t_exp is just the initial value -#ifdef ETICS_CEP -int grapite_cep_index; -#endif -#endif - -/****************************************************************************/ -void get_CPU_time(double *time_real, double *time_user, double *time_syst) - { - struct rusage xxx; - double sec_u, microsec_u, sec_s, microsec_s; - struct timeval tv; - - - getrusage(RUSAGE_SELF,&xxx); - - sec_u = xxx.ru_utime.tv_sec; - sec_s = xxx.ru_stime.tv_sec; - - microsec_u = xxx.ru_utime.tv_usec; - microsec_s = xxx.ru_stime.tv_usec; - - *time_user = sec_u + microsec_u * 1.0E-06; - *time_syst = sec_s + microsec_s * 1.0E-06; - -// *time_real = time(NULL); - - gettimeofday(&tv, NULL); - *time_real = tv.tv_sec + 1.0E-06 * tv.tv_usec; - - *time_user = *time_real; - - } -/****************************************************************************/ - -#ifdef STEVOL -/****************************************************************************/ -double t_dead(double m, double Z) -/* -m - mass of the star (in Msol) -Z - metallicity (absolut values - i.e. Zsol = 0.0122) -t - return value of star lifetime (in Year) - -Raiteri, Villata & Navarro, 1996, A&A, 315, 105 -*/ -{ - double a0, a1, a2, lZ, lm, tmp=0.0; - - m *= (m_norm/Msol); - - lZ = log10(Z); - lm = log10(m); - - a0 = 10.130 + 0.07547*lZ - 0.008084*lZ*lZ; - a1 = -4.424 - 0.79390*lZ - 0.118700*lZ*lZ; - a2 = 1.262 + 0.33850*lZ + 0.054170*lZ*lZ; - - tmp = a0 + a1*lm + a2*lm*lm; - - tmp = pow(10.0,tmp); - - tmp *= (Year/t_norm); - - return(tmp); -} -/****************************************************************************/ - -/****************************************************************************/ -double m_loss_old(double m, double Z) -/* -m - initial mass of the star (in Msol) -Z - metallicity (e.g. Zsol = 0.02) -m_ret - returned maass to ISM from the star (in Msol) - -approx. from data of van den Hoek & Groenewegen, 1997, A&AS, 123, 305 -*/ -{ - double tmp=0.0; - - m *= (m_norm/Msol); - -// tmp = (-0.46168 + 0.912274 * m); // first approx. - - tmp = -0.420542*pow(Z, -0.0176601) + (0.901495 + 0.629441*Z) * m; - - tmp *= (Msol/m_norm); - - return(tmp); -} -/****************************************************************************/ - -/****************************************************************************/ -double m_curr_old(double m0, double Z, double t0, double t) -{ - double td, ml, tmp=0.0; - - td = t_dead(m0, Z); - ml = m_loss_old(m0, Z); - - if( (t-t0) < td ) - { - tmp = m0; // instant mass loss -// tmp = m0 - (t-t0)/(td-t0) * ml; // linear mass loss - } - else - { - tmp = m0 - ml; - - if(event[i] == 0) - { - num_dead++; - event[i] = 1; - } - - } /* if( (t-t0) < td ) */ - - return(tmp); -} -/****************************************************************************/ - -/****************************************************************************/ -double m_loss(double m, double Z) -/* -m - initial mass of the star (in norm. units) -Z - metallicity (absolut value - i.e. Zsol = 0.0122) -m_loss - returned maass to ISM from the star (in norm. units) -*/ -{ - double tmp=0.0; - - m *= (m_norm/Msol); - - if( m < 8.0) - { -// approx. from data of van den Hoek & Groenewegen, 1997, A&AS, 123, 305 - -// tmp = (-0.46168 + 0.912274 * m); // first approx. - tmp = -0.420542*pow(Z, -0.0176601) + (0.901495 + 0.629441*Z) * m; // second approx. - } - else - { -// approx. from data of Woosley & Weaver, 1995, ApJS, 110, 181 - -// tmp = 0.813956*pow(m, 1.04214); - tmp = 0.813956*pow(m, 1.04); - } - - tmp *= (Msol/m_norm); - - return(tmp); -} -/****************************************************************************/ - -/****************************************************************************/ -double m_curr(double m0, double Z, double t0, double t) -{ - double td, ml, tmp=0.0; - - tmp = m0; - - if( event[i] == 0 ) - { - - td = t_dead(m0, Z); - - if( (t-t0) > td ) - { - - ml = m_loss(m0, Z); - - tmp = m0 - ml; - - num_dead++; - -// wd http://en.wikipedia.org/wiki/Chandrasekhar_limit 1.38 - - if( tmp * (m_norm/Msol) < 1.38 ) - { - event[i] = 1; - } - else - { - -// ns http://en.wikipedia.org/wiki/Neutron_stars 1.38 - ~2.0 ??? - - if( tmp * (m_norm/Msol) > 1.38 ) event[i] = 2; - -// bh http://en.wikipedia.org/wiki/Tolman-Oppenheimer-Volkoff_limit ~1.5 - ~3.0 ??? - - if( tmp * (m_norm/Msol) > 2.00 ) event[i] = 3; - - } - - } /* if( (t-t0) > td ) */ - - } /* if( event[i] == 0 ) */ - - return(tmp); -} -/****************************************************************************/ -#endif - - -#ifdef STEVOL_SSE -/****************************************************************************/ -double m_curr(int ipart, double m0, double Z, double t0, double t) -{ - //set up parameters and variables for SSE (Hurley, Pols & Tout 2002) - int kw=0; //stellar type - double mass; //initial mass - double mt=0.0; //actual mass - double r=0.0; //radius - double lum=0.0; //luminosity - double mc=0.0; //core mass - double rc=0.0; //core radius - double menv=0.0; //envelope mass - double renv=0.0; //envelope radius - double ospin=0.0; //spin - double epoch=0.0; //time spent in current evolutionary state - double tms=0.0; //main-sequence lifetime - double tphys; //initial age - double tphysf; //final age - double dtp=0.0; //data store value, if dtp>tphys no data will be stored - double z; //metallicity - double zpars[20]; //metallicity parameters - double vkick=0.0; //kick velocity for compact remnants - double vs[3]; //kick velocity componets - - // M_V_[mag] V_[mag] B-V_[mag] T_eff_[K] dV_[mag] d(B-V) - double abvmag, vmag, BV, Teff, dvmag, dBV; - - mass = m0*(m_norm/Msol); // m0[i] initial mass of the stars Msol - mt = mass; // current mass for output in Msol - tphys = t0*(t_norm/Myr); // t0[i] time of the star formation Myr - tphysf = t*(t_norm/Myr); // t[i] current time for the star Myr - dtp = 0.0; // output parameter, just set to 0.0 !!! - z = Z; // ZZZ[i] of the star - -/* - if(ipart > 9995) - { - printf("Initial parameters: \n"); - printf("M = %g [Mo] \n", mass); - printf("Z = %g \n", z); - printf("kw = %d \n", kw); - printf("spin = %g \n", ospin); - printf("epoch = %g [Myr] \n", epoch); - printf("t_beg = %g [Myr] \n", tphys); - printf("t_end = %g [Myr] \n", tphysf); - printf("R = %g [R_o] \n", r); - printf("L = %g [L_o] \n", lum); - printf("V_kick = %g [km/s] \n", vkick); - } -*/ - - for (k=0; k<20; k++) zpars[k] = 0; - zcnsts_(&z,zpars); //get metallicity parameters - - evolv1_(&kw, &mass, &mt, &r, &lum, &mc, &rc, &menv, &renv, &ospin, &epoch, &tms, &tphys, &tphysf, &dtp, &z, zpars, &vkick, vs); - cmd(kw, r, lum, Rgal, &abvmag, &vmag, &BV, &Teff, &dvmag, &dBV); - -/* - if(ipart > 9995) - { - printf("Final parameters: \n"); - printf("M = %g [Mo] \n", mt); - printf("Z = %g \n", z); - printf("kw = %d \n", kw); - printf("spin = %g \n", ospin); - printf("epoch = %g [Myr] \n", epoch); - printf("t_beg = %g [Myr] \n", tphys); - printf("t_end = %g [Myr] \n", tphysf); - printf("R = %g [R_o] \n", r); - printf("L = %g [L_o] \n", lum); - printf("V_kick = %g [km/s] \n", vkick); - printf("M_V_[mag]\tV_[mag]\t\tB-V_[mag]\tT_eff_[K]\tdV_[mag]\td(B-V)\n"); - printf("%.3E\t%.3E\t%.3E\t%.3E\t%.3E\t%.3E\n", abvmag, vmag, BV, Teff, dvmag, dBV); -// printf("%g\t%g\t%g\t%g\t%g\t%g\n", abvmag, vmag, BV, Teff, dvmag, dBV); - } -*/ - - event[ipart] = kw; // Evolution type (0 - 15). - SSEMass[ipart] = mt; // Mass in Msol - SSESpin[ipart] = ospin; // Spin in SI ??? [kg*m*m/s] - SSERad[ipart] = r; // Radius in Rsol - SSELum[ipart] = lum; // Luminosity in Lsol - SSETemp[ipart] = Teff; // Temperature - - SSEMV[ipart] = abvmag; // M_V absolute V magnitude - SSEBV[ipart] = BV; // B-V color index - -/* -c STELLAR TYPES - KW -c -c 0 - deeply or fully convective low mass MS star -c 1 - Main Sequence star -c 2 - Hertzsprung Gap -c 3 - First Giant Branch -c 4 - Core Helium Burning -c 5 - First Asymptotic Giant Branch -c 6 - Second Asymptotic Giant Branch -c 7 - Main Sequence Naked Helium star -c 8 - Hertzsprung Gap Naked Helium star -c 9 - Giant Branch Naked Helium star -c 10 - Helium White Dwarf -c 11 - Carbon/Oxygen White Dwarf -c 12 - Oxygen/Neon White Dwarf -c 13 - Neutron Star -c 14 - Black Hole -c 15 - Massless Supernova -*/ - - if( van_kick == 1 ) // we have a kick ??? - { - - if( (event_old[ipart] < 10) && ( (event[ipart] == 13) || (event[ipart] == 14) ) ) // NS or BH - { - - if(myRank == rootRank) - { -// printf("KICK: %06d %.6E [Myr] %02d (%02d) %.6E [Mo] %.6E [km/s] [% .3E, % .3E, % .3E] OLD: [% .3E, % .3E, % .3E] %.6E [Mo] \n", ipart, tphysf, kw, event_old[ipart], mt, vkick, vs[0], vs[1], vs[2], v[ipart][0]*(v_norm/km), v[ipart][1]*(v_norm/km), v[ipart][2]*(v_norm/km), mass); - printf("KICK: %06d %.6E %02d %02d %.6E %.6E % .3E % .3E % .3E % .3E % .3E % .3E %.6E \n", ipart, tphysf, kw, event_old[ipart], mt, vkick, vs[0], vs[1], vs[2], v[ipart][0]*(v_norm/km), v[ipart][1]*(v_norm/km), v[ipart][2]*(v_norm/km), mass); - fflush(stdout); - } /* if(myRank == rootRank) */ - - v[ipart][0] += vs[0]*(km/v_norm); - v[ipart][1] += vs[1]*(km/v_norm); - v[ipart][2] += vs[2]*(km/v_norm); - } - - } // we have a kick ??? - - - event_old[ipart] = event[ipart]; - - - tmp = mt*(Msol/m_norm); // return the current mass(t-t0) of the star in NB units - - return(tmp); -} -/****************************************************************************/ -#endif - - -/****************************************************************************/ -void read_data() -{ - inp = fopen(inp_fname,"r"); - fscanf(inp,"%d \n", &diskstep); - -//#ifdef STEVOL -// fscanf(inp,"%d \n", &N); -//#endif -// fscanf(inp,"%d %d %d %d \n", &N, &N_bh, &N_gmc, &N_star); - - fscanf(inp,"%d \n", &N); - - fscanf(inp,"%lE \n", &time_cur); - - for(i=0; i= (mass_frac[k]*m_tot) ) - { - lagr_rad[k] = var_sort[j]; - k++; - } -#endif - } - - fclose(out); - -// write out lagr-rad.dat - -#ifdef LAGR_RAD - out = fopen("lagr-rad.dat","a"); - fprintf(out,"%.6E ", time_cur); - for(k=0; k 100.0) jerk_i[ii][0] = 100.0; - if(ABS(jerk_i[ii][1]) > 100.0) jerk_i[ii][1] = 100.0; - if(ABS(jerk_i[ii][2]) > 100.0) jerk_i[ii][2] = 100.0; - } - -#ifdef SAPPORO - g6calc_firsthalf_(&clusterid, &n_loc, &nn, index_i, x_i, v_i , a_i, jerk_i, p_i, &eps2, h2_i); - g6calc_lasthalf_(&clusterid, &n_loc, &nn, index_i, x_i, v_i, &eps2, h2_i, a_i, jerk_i, p_i); -#else - g6calc_firsthalf(clusterid, n_loc, nn, index_i, x_i, v_i , a_i, jerk_i, p_i, eps2, h2_i); - g6calc_lasthalf(clusterid, n_loc, nn, index_i, x_i, v_i, eps2, h2_i, a_i, jerk_i, p_i); -#endif - - for(ii=0; ii r) ) - { - r1 = r_sc[ii]; r2 = r_sc[ii+1]; - m1 = m_sc[ii]; m2 = m_sc[ii+1]; - p1 = p_sc[ii]; p2 = m_sc[ii+1]; - break; - } - } - - m_tmp = m1 + (r-r1)*(m2-m1)/(r2-r1); - p_tmp = p1 + (r-r1)*(p2-p1)/(r2-r1); - -// if(myRank == rootRank) -// { -// printf("\t \t \t %.6E %.6E \n", r1, r2); -// printf("\t \t \t %.6E %.6E \n", m1, m2); -// printf("\t \t \t %.6E %.6E \n", p1, p2); -// printf("\t \t \t %06d %.6E %.6E %.6E \n", ii, r, m_tmp, p_tmp); -// fflush(stdout); -// } /* if(myRank == rootRank) */ - - *M_R = m_tmp; - *pot_out_R = p_tmp; - -//exit(-1); - - } -#endif -/****************************************************************************/ - -/****************************************************************************/ -void calc_ext_grav_zero() -{ - -#ifdef EXTPOT - - /* Define the external potential for all particles on all nodes */ - - ni = n_act; - - for(i=0; i 100.0) jerk_i[ii][0] = 100.0; - if(ABS(jerk_i[ii][1]) > 100.0) jerk_i[ii][1] = 100.0; - if(ABS(jerk_i[ii][2]) > 100.0) jerk_i[ii][2] = 100.0; - } - - g6calc_firsthalf(clusterid, n_loc, nn, index_i, x_i, v_i , a_i, jerk_i, p_i, eps2, h2_i); - g6calc_lasthalf(clusterid, n_loc, nn, index_i, x_i, v_i, eps2, h2_i, a_i, jerk_i, p_i); - - g6_calls++; -*/ - - for(ii=0; ii R_LIMITS_ALL) && (m[i] != 0.0) ) - if( (tmp_r > R_LIMITS_ALL) && (tmp_rv > 0.0) ) - { - - for(k=0;k<3;k++) - { -// x[i][k] = R_LIMITS_ALL + 1.0*my_rand2(); - v[i][k] *= 1.0E-01; - } /* k */ - - } /* if */ - - } /* i */ - -#endif - - -#ifdef CMCORR - - /* possible CM correction of the initial datafile... */ - - if( (diskstep == 0) && (time_cur == 0.0) ) cm_corr(); -// if( (time_cur = 0.0) ) cm_corr(); - -#endif - - - printf("\n"); - printf("Begin the calculation of phi-GRAPE program on %03d processors\n", n_proc); - printf("\n"); -#ifdef GMC - printf("N = %06d \t N_GMC = %06d \t eps = %.6E \n", N, N_gmc, eps); -#else - printf("N = %07d \t eps = %.6E \n", N, eps); -#endif - printf("t_beg = %.6E \t t_end = %.6E \n", time_cur, t_end); - printf("dt_disk = %.6E \t dt_contr = %.6E \n", dt_disk, dt_contr); - printf("dt_bh = %.6E \n", dt_bh); - printf("eta = %.6E \n", eta); - printf("\n"); - -#ifdef NORM - printf("Normalization: \n"); - printf("\n"); - printf("m_norm = %.4E [Msol] r_norm = %.4E [pc] \n", m_norm/Msol, r_norm/pc); - printf("v_morm = %.4E [km/s] t_morm = %.4E [Myr] \n", v_norm/km, t_norm/Myr); - printf("\n"); -#endif - -#ifdef EXTPOT - printf("External Potential: \n"); - printf("\n"); - -#ifdef EXTPOT_GAL - printf("m_bulge = %.4E [Msol] a_bulge = %.4E b_bulge = %.4E [kpc] \n", m_bulge*m_norm/Msol, a_bulge*r_norm/kpc, b_bulge*r_norm/kpc); - printf("m_disk = %.4E [Msol] a_disk = %.4E b_disk = %.4E [kpc] \n", m_disk*m_norm/Msol, a_disk*r_norm/kpc, b_disk*r_norm/kpc); - printf("m_halo = %.4E [Msol] a_halo = %.4E b_halo = %.4E [kpc] \n", m_halo*m_norm/Msol, a_halo*r_norm/kpc, b_halo*r_norm/kpc); -#endif - -#ifdef EXTPOT_BH - printf("m_bh = %.4E b_bh = %.4E \n", m_bh, b_bh); -// printf("m_bh = %.4E [Msol] b_bh = %.4E [kpc] \n", m_bh*m_norm/Msol, b_bh*r_norm/kpc); -#endif - -#ifdef EXTPOT_GAL_DEH - printf("m_ext = %.6E r_ext = %.6E \t g_ext = %.3E \n", m_ext, r_ext, g_ext); -#endif - -#ifdef EXTPOT_GAL_LOG - printf("v_halo = %.6E r_halo = %.6E \n", v_halo, r_halo); -#endif - -#ifdef EXTPOT_SC - read_SC_mass(); - - printf("EXTPOT_SC: # of points %06d \t M_SC_TOT = %.6E \n", M_SC_DIM-1, m_sc[M_SC_DIM-1]); -// printf("EXTPOT_SC: %.6E \t %.6E \n", m_sc[0], m_sc[M_SC_DIM-1]); -// printf("EXTPOT_SC: %.6E \t %.6E \n", p_sc[0], p_sc[M_SC_DIM-1]); -#endif - - printf("\n"); -#endif - - - - fflush(stdout); - - - if( (diskstep == 0) && (time_cur == 0.0) ) -// if( (time_cur = 0.0) ) - { - -#ifdef SPH_GAS - write_data_SPH(); -#endif - -#ifdef GMC - write_snap_GMC(); - write_cont_GMC(); -#endif - -// write_snap_data(); -// write_cont_data(); - - out = fopen("contr.dat","w"); - fclose(out); - -#ifdef TIMING - out = fopen("timing.dat","w"); - fclose(out); -#endif - -#ifdef ADD_BH2 - -#ifdef BH_OUT - out = fopen("bh.dat","w"); - fclose(out); -#endif - -#ifdef BH_OUT_NB - out = fopen("bh_nb.dat","w"); - fclose(out); -#endif - -#else - -#ifdef ADD_BH1 - -#ifdef BH_OUT - out = fopen("bh.dat","w"); - fclose(out); -#endif - -#ifdef BH_OUT_NB - out = fopen("bh_nb.dat","w"); - fclose(out); -#endif - -#endif // ADD_BH1 - -#endif // ADD_BH2 - - -#ifdef STARDESTR - -#ifdef ADD_BH2 - - out = fopen("mass-bh.dat","w"); - m_bh1 = m[0]; - m_bh2 = m[1]; - num_bh1 = 0; - num_bh2 = 0; - fprintf(out,"%.8E \t %.8E %06d \t %.8E %06d \n", - time_cur, m_bh1, num_bh1, m_bh2, num_bh2); - fclose(out); - - out = fopen("mass-bh.con","w"); - m_bh1 = m[0]; - m_bh2 = m[1]; - num_bh1 = 0; - num_bh2 = 0; - fprintf(out,"%.8E \t %.8E %06d \t %.8E %06d \n", - time_cur, m_bh1, num_bh1, m_bh2, num_bh2); - fclose(out); - -#else - -#ifdef ADD_BH1 - - out = fopen("mass-bh.dat","w"); - m_bh1 = m[0]; - num_bh1 = 0; - fprintf(out,"%.8E \t %.8E %06d \n", - time_cur, m_bh1, num_bh1); - fclose(out); - - out = fopen("mass-bh.con","w"); - m_bh1 = m[0]; - num_bh1 = 0; - fprintf(out,"%.8E \t %.8E %06d \n", - time_cur, m_bh1, num_bh1); - fclose(out); - -#endif // ADD_BH1 - -#endif // ADD_BH2 - -#endif // STARDESTR - - -#ifdef STARDESTR_EXT - - num_bh = 0; - out = fopen("mass-bh.dat","w"); - fprintf(out,"%.8E \t %.8E \t %06d \n", time_cur, m_bh, num_bh); - fclose(out); - - num_bh = 0; - out = fopen("mass-bh.con","w"); - fprintf(out,"%.8E \t %.8E \t %06d \n", time_cur, m_bh, num_bh); - fclose(out); - -#ifdef BH_OUT_NB_EXT - out = fopen("bh_nb.dat","w"); - fclose(out); -#endif - -#endif // STARDESTR_EXT - - -#ifdef DEBUG_extra -#ifdef LAGR_RAD - out = fopen("lagr-rad.dat","w"); - fclose(out); -#endif -#endif - - -#ifdef BBH_INF - out = fopen("bbh.inf","w"); - fclose(out); -#endif - - - } - else // if(diskstep == 0) - { - -//#ifdef LAGR_RAD -// out = fopen("lagr-rad.dat","a"); -// fclose(out); -//#endif - -/* -#ifdef SPH_GAS - write_data_SPH(); -#endif - -#ifdef GMC - write_snap_GMC(); - write_cont_GMC(); -#endif - - write_snap_data(); - write_cont_data(); -*/ - -#ifdef STARDESTR - -#ifdef ADD_BH2 - -/* - inp = fopen("mass-bh.dat","r"); - while(feof(inp) == NULL) - { - fscanf(inp,"%lE %lE %d %lE %d", &tmp, &m_bh1, &num_bh1, &m_bh2, &num_bh2); - } - fclose(inp); - printf("%.8E \t %.8E %06d \t %.8E %06d \n", tmp, m_bh1, num_bh1, m_bh2, num_bh2); - fflush(stdout); -*/ - - inp = fopen("mass-bh.con","r"); - fscanf(inp,"%lE %lE %d %lE %d", &tmp, &m_bh1, &num_bh1, &m_bh2, &num_bh2); - fclose(inp); - printf("%.8E \t %.8E %06d \t %.8E %06d \n", tmp, m_bh1, num_bh1, m_bh2, num_bh2); - fflush(stdout); - -#else - -#ifdef ADD_BH1 - -/* - inp = fopen("mass-bh.dat","r"); - while(feof(inp) == NULL) - { - fscanf(inp,"%lE %lE %d", &tmp, &m_bh1, &num_bh1); - } - fclose(inp); - printf("%.8E \t %.8E \t %06d \n", tmp, m_bh1, num_bh1); - fflush(stdout); -*/ - - inp = fopen("mass-bh.con","r"); - fscanf(inp,"%lE %lE %d", &tmp, &m_bh1, &num_bh1); - fclose(inp); - printf("%.8E \t %.8E \t %06d \n", tmp, m_bh1, num_bh1); - fflush(stdout); - -#endif // ADD_BH1 - -#endif // ADD_BH2 - -#endif // STARDESTR - - -#ifdef STARDESTR_EXT - -/* - inp = fopen("mass-bh.dat","r"); - while(feof(inp) == NULL) - { - fscanf(inp,"%lE %lE %d", &tmp, &m_bh, &num_bh); - } - fclose(inp); - printf("%.8E \t %.8E \t %06d \n", tmp, m_bh, num_bh); - fflush(stdout); -*/ - - inp = fopen("mass-bh.con","r"); - fscanf(inp,"%lE %lE %d", &tmp, &m_bh, &num_bh); - fclose(inp); - printf("%.8E \t %.8E \t %06d \n", tmp, m_bh, num_bh); - fflush(stdout); - -#endif // STARDESTR_EXT - - - } // if(diskstep == 0) - - - get_CPU_time(&CPU_time_real0, &CPU_time_user0, &CPU_time_syst0); - - } /* if(myRank == rootRank) */ - - - - -#ifdef STEVOL_SSE -//SSE internal parameters (see Hurley, Pols & Tout 2000) - -value1_.neta = 0.5; //Reimers mass-loss coefficent (neta*4x10^-13; 0.5 normally) -value1_.bwind = 0.0; //Binary enhanced mass loss parameter (inactive for single) -value1_.hewind = 1.0; //Helium star mass loss factor (1.0 normally) -value1_.mxns = 3.0; //Maximum NS mass (1.8, nsflag=0; 3.0, nsflag=1) - -points_.pts1 = 0.05; //Time-step parameter in evolution phase: MS (0.05) -points_.pts2 = 0.01; //Time-step parameter in evolution phase: GB, CHeB, AGB, HeGB (0.01) -points_.pts3 = 0.02; //Time-step parameter in evolution phase: HG, HeMS (0.02) - -//value4_.sigma = 190.0; //Kick velocities - standard values... -value4_.sigma = 265.0; //Kick velocities - Hobbs++2005 values... -value4_.bhflag = 1; //bhflag > 0 allows velocity kick at BH formation - -value3_.idum = 19640916; // random number seed !!! - -//BSE internal parameters (see Hurley, Pols & Tout 2002) - -flags_.ceflag = 0; //ceflag > 0 activates spin-energy correction in common-envelope (0) #defunct# -flags_.tflag = 1; //tflag > 0 activates tidal circularisation (1) -flags_.ifflag = 0; //ifflag > 0 uses WD IFMR of HPE, 1995, MNRAS, 272, 800 (0) -flags_.nsflag = 1; //nsflag > 0 takes NS/BH mass from Belczynski et al. 2002, ApJ, 572, 407 (1) -flags_.wdflag = 1; //wdflag > 0 uses modified-Mestel cooling for WDs (0) - -value5_.beta = 0.125; //beta is wind velocity factor: proportional to vwind**2 (1/8) -value5_.xi = 1.0; //xi is the wind accretion efficiency factor (1.0) -value5_.acc2 = 1.5; //acc2 is the Bondi-Hoyle wind accretion factor (3/2) -value5_.epsnov = 0.001; //epsnov is the fraction of accreted matter retained in nova eruption (0.001) -value5_.eddfac = 1.0; //eddfac is Eddington limit factor for mass transfer (1.0) -value5_.gamma = -1.0; //gamma is the angular momentum factor for mass lost during Roche (-1.0) - -value2_.alpha1 = 1.0; //alpha1 is the common-envelope efficiency parameter (1.0) -value2_.lambda = 0.5; //lambda is the binding energy factor for common envelope evolution (0.5) - -#endif // STEVOL_SSE - - - /* Wait to all processors to finish his works... */ - MPI_Barrier(MPI_COMM_WORLD); - - /* Broadcast all useful values to all processors... */ - MPI_Bcast(&N, 1, MPI_INT, rootRank, MPI_COMM_WORLD); - MPI_Bcast(&eps, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Bcast(&eta, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Bcast(&t_end, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Bcast(&dt_disk, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Bcast(&dt_contr, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Bcast(&dt_bh, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Bcast(&time_cur, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - -#ifdef NORM - MPI_Bcast(&m_norm, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Bcast(&r_norm, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Bcast(&v_norm, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Bcast(&t_norm, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); -#endif // NORM - -#ifdef EXTPOT - -#ifdef EXTPOT_GAL - MPI_Bcast(&m_bulge, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Bcast(&a_bulge, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Bcast(&b_bulge, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - - MPI_Bcast(&m_disk, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Bcast(&a_disk, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Bcast(&b_disk, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - - MPI_Bcast(&m_halo, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Bcast(&a_halo, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Bcast(&b_halo, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - -/* - MPI_Bcast(&x_ext, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Bcast(&y_ext, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Bcast(&z_ext, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - - MPI_Bcast(&vx_ext, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Bcast(&vy_ext, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Bcast(&vz_ext, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); -*/ -#endif - -#ifdef EXTPOT_BH - MPI_Bcast(&m_bh, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Bcast(&b_bh, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); -#endif - -#ifdef EXTPOT_GAL_DEH - MPI_Bcast(&m_ext, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Bcast(&r_ext, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Bcast(&g_ext, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); -#endif - -#ifdef EXTPOT_GAL_LOG - MPI_Bcast(&v_halo, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Bcast(&r_halo, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - - MPI_Bcast(&v2_halo, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Bcast(&r2_halo, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); -#endif - -#endif // EXTPOT - - -#ifdef STARDESTR - MPI_Bcast(&m_bh1, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Bcast(&num_bh1, 1, MPI_INT, rootRank, MPI_COMM_WORLD); - - MPI_Bcast(&m_bh2, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Bcast(&num_bh2, 1, MPI_INT, rootRank, MPI_COMM_WORLD); -#endif // STARDESTR - - -#ifdef STARDESTR_EXT - MPI_Bcast(&num_bh, 1, MPI_INT, rootRank, MPI_COMM_WORLD); -#endif // STARDESTR_EXT - - - /* Wait to all processors to finish his works... */ - MPI_Barrier(MPI_COMM_WORLD); - - - - eta_s = eta/ETA_S_CORR; - eta_bh = eta/ETA_BH_CORR; - - eps2 = SQR(eps); - - dt_min = 1.0*pow(2.0, DTMINPOWER); - dt_max = 1.0*pow(2.0, DTMAXPOWER); - - if(dt_disk == dt_contr) - dt_max = dt_contr; - else - dt_max = MIN(dt_disk, dt_contr); - - if(dt_max > 1.0) dt_max = 1.0; - - t_disk = dt_disk*(1.0+floor(time_cur/dt_disk)); - t_contr = dt_contr*(1.0+floor(time_cur/dt_contr)); - t_bh = dt_bh*(1.0+floor(time_cur/dt_bh)); - - -if(myRank == rootRank) - { - printf("t_disk = %.6E t_contr = %.6E t_bh = %.6E \n", t_disk, t_contr, t_bh); - printf("\n"); - fflush(stdout); - } /* if(myRank == rootRank) */ - -/* - t_disk = time_cur + dt_disk; - t_contr = time_cur + dt_contr; - t_bh = time_cur + dt_bh; -*/ - -#ifdef STEVOL - dt_stevol = dt_max; - t_stevol = dt_stevol*(1.0 + floorl(time_cur/dt_stevol)); - -if(myRank == rootRank) - { - printf("t_stevol = %.6E dt_stevol = %.6E \n", t_stevol, dt_stevol); - printf("\n"); - fflush(stdout); - } /* if(myRank == rootRank) */ -#endif - -#ifdef STEVOL_SSE - dt_stevol = dt_max; - t_stevol = dt_stevol*(1.0 + floorl(time_cur/dt_stevol)); - -if(myRank == rootRank) - { - printf("t_stevol = %.6E dt_stevol = %.6E \n", t_stevol, dt_stevol); - printf("\n"); - fflush(stdout); - } /* if(myRank == rootRank) */ -#endif - - - for(i=0; i BH _softened_ pot, acc & jerk - - tmp_i = calc_force_n_BH(m_bh1, x_bh1, v_bh1, - m_bh2, x_bh2, v_bh2, - eps, - &pot_bh1, a_bh1, adot_bh1, - &pot_bh2, a_bh2, adot_bh2); - - pot[i_bh1] -= pot_bh1; - pot[i_bh2] -= pot_bh2; - - for(k=0;k<3;k++) - { - a[i_bh1][k] -= a_bh1[k]; - a[i_bh2][k] -= a_bh2[k]; - - adot[i_bh1][k] -= adot_bh1[k]; - adot[i_bh2][k] -= adot_bh2[k]; - } - -// calculate and "plus" the new BH <-> BH _unsoftened_ pot, acc, jerk - - tmp_i = calc_force_n_BH(m_bh1, x_bh1, v_bh1, - m_bh2, x_bh2, v_bh2, - eps_BH, - &pot_bh1, a_bh1, adot_bh1, - &pot_bh2, a_bh2, adot_bh2); - - pot[i_bh1] += pot_bh1; - pot[i_bh2] += pot_bh2; - - for(k=0;k<3;k++) - { - a[i_bh1][k] += a_bh1[k]; - a[i_bh2][k] += a_bh2[k]; - - adot[i_bh1][k] += adot_bh1[k]; - adot[i_bh2][k] += adot_bh2[k]; - } - -#endif // ADD_N_BH - - -#ifdef ADD_PN_BH - -// calculate and "plus" the new BH <-> BH : PN1, PN2, PN2.5, PN3, PN3.5 : acc, jerk - - -/* - printf("PN: % .8E \t % .8E \t % .8E \n", x_bh1[0], x_bh1[1], x_bh1[2]); - printf("PN: % .8E \t % .8E \t % .8E \n", x_bh2[0], x_bh2[1], x_bh2[2]); - fflush(stdout); -*/ - - dt_bh_tmp = dt[0]; - - tmp_i = calc_force_pn_BH(m_bh1, x_bh1, v_bh1, s_bh1, - m_bh2, x_bh2, v_bh2, s_bh2, - C_NB, dt_bh_tmp, usedOrNot, - a_pn1, adot_pn1, - a_pn2, adot_pn2); - - for(k=0;k<3;k++) - { - a[i_bh1][k] += a_pn1[1][k] + a_pn1[2][k] + a_pn1[3][k] + a_pn1[4][k] + a_pn1[5][k] + a_pn1[6][k]; - a[i_bh2][k] += a_pn2[1][k] + a_pn2[2][k] + a_pn2[3][k] + a_pn2[4][k] + a_pn2[5][k] + a_pn2[6][k]; - - adot[i_bh1][k] += adot_pn1[1][k] + adot_pn1[2][k] + adot_pn1[3][k] + adot_pn1[4][k] + adot_pn1[5][k] + adot_pn1[6][k]; - adot[i_bh2][k] += adot_pn2[1][k] + adot_pn2[2][k] + adot_pn2[3][k] + adot_pn2[4][k] + adot_pn2[5][k] + adot_pn2[6][k]; - } - - if(myRank == rootRank) - { - if(tmp_i == 505) - { - printf("PN RSDIST: %.8E \t %.8E \n", Timesteps, time_cur); - fflush(stdout); - exit(-1); - } - } - -#endif // ADD_PN_BH - -#endif // ADD_BH2 - - - -#if defined(EXTPOT) || defined(GMC) - calc_ext_grav_zero(); -#endif - -#ifdef GMC - calc_gmc_self_grav(); - calc_ext_gmc_grav(); -#endif - - - /* Wait to all processors to finish his works... */ - MPI_Barrier(MPI_COMM_WORLD); - - - -// sjuda stavim DRAG... - -#ifdef STARDISK - - for(i=0; i dt_max) dt_tmp = dt_max; - -// dt_tmp = dt_min; - - -#ifdef STARDESTR - if(m[i] == 0.0) dt_tmp = dt_max; -#endif - -#ifdef STARDESTR_EXT - if(m[i] == 0.0) dt_tmp = dt_max; -#endif - - dt[i] = dt_tmp; - - -#ifdef DT_MIN_WARNING - if(myRank == 0) - { - if(dt[i] == dt_min) - { - printf("!!! Warning0: dt = dt_min = %.6E \t ind = %07d \n", dt[i], ind[i]); - fflush(stdout); - } - } -#endif - - } /* i */ - - - - -#ifdef ADD_BH2 - -/* define the min. dt over all the part. and set it also for the BH... */ - - min_dt = dt[0]; - - for(i=1; i 0.1) dt[i] = min_dt; - } /* i */ - -#endif // GMC2 - - -#ifdef GMC2222 - -/* define the max. dt for the GMC... */ - - for(i=1; i 0.1) dt[i] = dt_max; - } /* i */ - -#endif // GMC2 - - - -#ifdef ACT_DEF_LL - CreateLinkList(); -#ifdef DEBUG111 - if( myRank == rootRank ) check_linklist(0); -#endif -#endif - - - - /* Wait to all processors to finish his works... */ - MPI_Barrier(MPI_COMM_WORLD); - - /* Scatter the "local" vectors from "global" */ - MPI_Scatter(dt, n_loc, MPI_DOUBLE, dt_loc, n_loc, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - - /* Wait to all processors to finish his works... */ - MPI_Barrier(MPI_COMM_WORLD); - - /* load the new values for particles to the local GRAPE's */ - - nj=n_loc; - - /* load the nj particles to the G6 */ - - for(j=0; j 0) - for(int i=0; i= t_contr) -// { - MPI_Allreduce(pot_act_tmp, pot_act_new, n_act, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); -// } /* if(min_t >= t_contr) */ - -// MPI_Allreduce(pot_act_tmp, pot_act_new, n_act, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - - MPI_Allreduce(a_act_tmp, a_act_new, 3*n_act, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - MPI_Allreduce(adot_act_tmp, adot_act_new, 3*n_act, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - - /* Wait to all processors to finish his works... */ - MPI_Barrier(MPI_COMM_WORLD); - -#ifdef TIMING - get_CPU_time(&CPU_tmp_real, &CPU_tmp_user, &CPU_tmp_syst); - DT_ACT_REDUCE += (CPU_tmp_user - CPU_tmp_user0); -#endif - - - -#ifdef ADD_BH2 - -#ifdef ADD_N_BH - - m_bh1 = m_act[i_bh1]; - m_bh2 = m_act[i_bh2]; - - for(k=0;k<3;k++) - { - x_bh1[k] = x_act_new[i_bh1][k]; - v_bh1[k] = v_act_new[i_bh1][k]; - - x_bh2[k] = x_act_new[i_bh2][k]; - v_bh2[k] = v_act_new[i_bh2][k]; - } - -// calculate and "minus" the BH <-> BH softened pot, acc & jerk - - tmp_i = calc_force_n_BH(m_bh1, x_bh1, v_bh1, - m_bh2, x_bh2, v_bh2, - eps, - &pot_bh1, a_bh1, adot_bh1, - &pot_bh2, a_bh2, adot_bh2); - - pot_act_new[i_bh1] -= pot_bh1; - pot_act_new[i_bh2] -= pot_bh2; - - for(k=0;k<3;k++) - { - a_act_new[i_bh1][k] -= a_bh1[k]; - a_act_new[i_bh2][k] -= a_bh2[k]; - - adot_act_new[i_bh1][k] -= adot_bh1[k]; - adot_act_new[i_bh2][k] -= adot_bh2[k]; - } - -// calculate and "plus" the new BH <-> BH unsoftened pot, acc, jerk - - tmp_i = calc_force_n_BH(m_bh1, x_bh1, v_bh1, - m_bh2, x_bh2, v_bh2, - eps_BH, - &pot_bh1, a_bh1, adot_bh1, - &pot_bh2, a_bh2, adot_bh2); - - pot_act_new[i_bh1] += pot_bh1; - pot_act_new[i_bh2] += pot_bh2; - - for(k=0;k<3;k++) - { - a_act_new[i_bh1][k] += a_bh1[k]; - a_act_new[i_bh2][k] += a_bh2[k]; - - adot_act_new[i_bh1][k] += adot_bh1[k]; - adot_act_new[i_bh2][k] += adot_bh2[k]; - } - -#endif // ADD_N_BH - - -#ifdef ADD_PN_BH - -// calculate and "plus" the new BH <-> BH : PN1, PN2, PN2.5, PN3, PN3.5 : acc, jerk - - dt_bh_tmp = dt[0]; - - tmp_i = calc_force_pn_BH(m_bh1, x_bh1, v_bh1, s_bh1, - m_bh2, x_bh2, v_bh2, s_bh2, - C_NB, dt_bh_tmp, usedOrNot, - a_pn1, adot_pn1, - a_pn2, adot_pn2); - - for(k=0;k<3;k++) - { - a_act_new[i_bh1][k] += a_pn1[1][k] + a_pn1[2][k] + a_pn1[3][k] + a_pn1[4][k] + a_pn1[5][k] + a_pn1[6][k]; - a_act_new[i_bh2][k] += a_pn2[1][k] + a_pn2[2][k] + a_pn2[3][k] + a_pn2[4][k] + a_pn2[5][k] + a_pn2[6][k]; - - adot_act_new[i_bh1][k] += adot_pn1[1][k] + adot_pn1[2][k] + adot_pn1[3][k] + adot_pn1[4][k] + adot_pn1[5][k] + adot_pn1[6][k]; - adot_act_new[i_bh2][k] += adot_pn2[1][k] + adot_pn2[2][k] + adot_pn2[3][k] + adot_pn2[4][k] + adot_pn2[5][k] + adot_pn2[6][k]; - } - - if(myRank == rootRank) - { - if(tmp_i == 505) - { - printf("PN RSDIST: TS = %.8E \t t = %.8E \n", Timesteps, time_cur); - fflush(stdout); - exit(-1); - } - } - -#endif // ADD_PN_BH - -#endif // ADD_BH2 - -#ifdef EXTPOT - calc_ext_grav(); -#endif - -#ifdef GMC - calc_gmc_self_grav(); - calc_ext_gmc_grav(); -#endif - - -// sjuda stavim DRAG... - -#ifdef STARDISK - -#ifdef TIMING - get_CPU_time(&CPU_tmp_real0, &CPU_tmp_user0, &CPU_tmp_syst0); -#endif - - calc_drag_force(); - - /* E_sd tut opjaty pljusujetsja... */ - - for(i=0; i dt_min) ) - { - power = log(dt_new)/log(2.0) - 1; -// power = log(dt_new)/log(2.0); - - dt_tmp = pow(2.0, (double)power); - } - - -#ifdef STARDISK - - // accretion disk criteria -// sjuda stavim izmenenija DT za schot DRAG pri priblizhenii k ploskosti Z=0 ... - - z_new_drag = x_act_new[i][2] + dt_tmp * v_act_new[i][2]; - r_new_drag2 = SQR(x_act_new[i][0]) + SQR(x_act_new[i][1]); - - if(r_new_drag2 > (R_CRIT*R_CRIT)) - { - hz = HZ; - } - else - { - hz = HZ*(sqrt(r_new_drag2)/R_CRIT); - } - -// if (fabs(x_act_new[i][2]) > HZ*2.2) - if (fabs(x_act_new[i][2]) > hz*2.2) - { - - if (z_new_drag * x_act_new[i][2] < 0.0) - { - dt_tmp *= 0.125; - } - else - { -// if (fabs(z_new_drag) < HZ*1.8) - if (fabs(z_new_drag) < hz*1.8) - { - dt_tmp *= 0.5; - } - } - - } - -#endif - - - if( (dt_new > 2.0*dt_tmp) && - (fmod(min_t, 2.0*dt_tmp) == 0.0) && - (2.0*dt_tmp <= dt_max) ) - { - dt_tmp *= 2.0; - } - - dt_act[i] = dt_tmp; - - t_act[i] = min_t; - - pot_act[i] = pot_act_new[i]; - - for(k=0; k<3; k++) - { - x_act[i][k] = x_act_new[i][k]; - v_act[i][k] = v_act_new[i][k]; - a_act[i][k] = a_act_new[i][k]; - adot_act[i][k] = adot_act_new[i][k]; - } /* k */ - -/* - if(myRank == rootRank) - { - tmp_r = sqrt( SQR(x_act_new[i][0]) + SQR(x_act_new[i][1]) + SQR(x_act_new[i][2]) ); - - if(ind_act[i] == 4232) - { - printf("SOS: TS = %.8E \t i = %06d \t n_act = %06d \t R = %.8E \n", Timesteps, ind_act[i], n_act, tmp_r); - printf(" x = % .6E % .6E % .6E \n", x_act_new[i][0], x_act_new[i][1], x_act_new[i][2]); - printf(" v = % .6E % .6E % .6E \n", v_act_new[i][0], v_act_new[i][1], v_act_new[i][2]); - printf(" a = % .6E % .6E % .6E \n", a_act_new[i][0], a_act_new[i][1], a_act_new[i][2]); - printf(" adot = % .6E % .6E % .6E \n", adot_act_new[i][0], adot_act_new[i][1], adot_act_new[i][2]); - printf(" t = %.6E %.6E \n", t_act[i], dt_act[i]); - fflush(stdout); -// exit(-1); - } - } -*/ - - -#ifdef DT_MIN_WARNING - if(myRank == 0) - { - if(dt_act[i] == dt_min) - { - printf("!!! Warning1: dt_act = dt_min = %.6E \t ind_act = %07d \n", dt[i], ind_act[i]); - fflush(stdout); - } - } -#endif - - - - } /* i */ - - - - -/* define the min. dt over all the act. part. and set it also for the BH... */ - -#ifdef ADD_BH2 - - min_dt = dt_act[0]; - - for(i=1; i 0.1) dt_act[i] = min_dt; - } /* i */ - - -#endif // GMC2 - - -#ifdef GMC2222 - -/* define the max. dt for the GMC... */ - - for(i=1; i 0.1) dt_act[i] = dt_max; - } /* i */ - -#endif // GMC2 - - - - - - -#ifdef BBH_INF - if(myRank == rootRank) - { - - out = fopen("bbh.inf","a"); - - m_bh1 = m_act[i_bh1]; - m_bh2 = m_act[i_bh2]; - - for(k=0;k<3;k++) - { - x_bh1[k] = x_act[i_bh1][k]; - x_bh2[k] = x_act[i_bh2][k]; - - v_bh1[k] = v_act[i_bh1][k]; - v_bh2[k] = v_act[i_bh2][k]; - } - - for(k=0;k<3;k++) - { - x_bbhc[k] = (m_bh1*x_bh1[k] + m_bh2*x_bh2[k])/(m_bh1 + m_bh2); - v_bbhc[k] = (m_bh1*v_bh1[k] + m_bh2*v_bh2[k])/(m_bh1 + m_bh2); - } - - DR2 = SQR(x_bh1[0] - x_bh2[0]) + SQR(x_bh1[1] - x_bh2[1]) + SQR(x_bh1[2] - x_bh2[2]); - DV2 = SQR(v_bh1[0] - v_bh2[0]) + SQR(v_bh1[1] - v_bh2[1]) + SQR(v_bh1[2] - v_bh2[2]); - -// mju = m_bh1*m_bh2/(m_bh1 + m_bh2); - - EB = -(m_bh1 + m_bh2) / sqrt(DR2) + 0.5 * DV2; - - SEMI_a = -0.5 * (m_bh1 + m_bh2)/EB; - SEMI_a2 = SQR(SEMI_a); - - -// printf("INF: %.6E %.16E %.6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E \n", -// Timesteps, time_cur, SEMI_a, -// sqrt(DR2), x_bbhc[0], x_bbhc[1], x_bbhc[2], v_bbhc[0], v_bbhc[1], v_bbhc[2], -// m_bh1, x_bh1[0], x_bh1[1], x_bh1[2], v_bh1[0], v_bh1[1], v_bh1[2], pot_act[0], -// m_bh2, x_bh2[0], x_bh2[1], x_bh2[2], v_bh2[0], v_bh2[1], v_bh2[2], pot_act[1]); -// fflush(stdout); - - - - for(i=2; i= t_stevol) - { - - /* Define the current mass of all star particles... */ - - for(i=0; i= t_stevol) */ - -#ifdef TIMING - get_CPU_time(&CPU_tmp_real, &CPU_tmp_user, &CPU_tmp_syst); - DT_STEVOL += (CPU_tmp_user - CPU_tmp_user0); -#endif - -#endif - - - /* STEVOL_SSE routine on all the nodes */ - -#ifdef STEVOL_SSE - - -#ifdef TIMING - get_CPU_time(&CPU_tmp_real0, &CPU_tmp_user0, &CPU_tmp_syst0); -#endif - - if(time_cur >= t_stevol) - { - - /* Define the current mass of all star particles... */ - - for(i=0; i= t_stevol) */ - -#ifdef TIMING - get_CPU_time(&CPU_tmp_real, &CPU_tmp_user, &CPU_tmp_syst); - DT_STEVOL += (CPU_tmp_user - CPU_tmp_user0); -#endif - - - - -/* Update ALL the new m,r,v "j" part. to the GRAPE/GPU memory */ - - - for(j=0; j= t_bh) - { - - if(myRank == rootRank) - { - -#ifdef BH_OUT - /* Write BH data... */ - write_bh_data(); -#endif - -#ifdef BH_OUT_NB - /* Write BH NB data... */ - write_bh_nb_data(); -#endif - -#ifdef BH_OUT_NB_EXT - /* Write BH NB data... */ - write_bh_nb_data_ext(); -#endif - - } /* if(myRank == rootRank) */ - - t_bh += dt_bh; - } /* if(time_cur >= t_bh) */ - - - - - - if(time_cur >= t_contr) - { - - if(myRank == rootRank) - { - -#ifdef STARDESTR - -/* - out = fopen("phi-GRAPE.ext","w"); - fprintf(out,"%.8E \t %.8E \n", m_bh, b_bh); - fclose(out); -*/ -/* - out = fopen("mass-bh.dat","a"); - fprintf(out,"%.8E \t %.8E \t %06d \n", time_cur, m_bh, num_bh); - fclose(out); -*/ - -#ifdef ADD_BH2 - - out = fopen("mass-bh.dat","a"); - fprintf(out,"%.8E \t %.8E %06d \t %.8E %06d \n", - time_cur, m_bh1, num_bh1, m_bh2, num_bh2); - fclose(out); - - out = fopen("mass-bh.con","w"); - fprintf(out,"%.8E \t %.8E %06d \t %.8E %06d \n", - time_cur, m_bh1, num_bh1, m_bh2, num_bh2); - fclose(out); - -#else - -#ifdef ADD_BH1 - - out = fopen("mass-bh.dat","a"); - fprintf(out,"%.8E \t %.8E %06d \n", - time_cur, m_bh1, num_bh1); - fclose(out); - - out = fopen("mass-bh.con","w"); - fprintf(out,"%.8E \t %.8E %06d \n", - time_cur, m_bh1, num_bh1); - fclose(out); - -#endif // ADD_BH1 - -#endif // ADD_BH2 - -#endif // STARDESTR - -#ifdef STARDESTR_EXT - - out = fopen("phi-GRAPE.ext","w"); - fprintf(out,"%.8E \t %.8E \n", m_bh, b_bh); - fclose(out); - - out = fopen("mass-bh.dat","a"); - fprintf(out,"%.8E \t %.8E \t %06d \n", time_cur, m_bh, num_bh); - fclose(out); - - out = fopen("mass-bh.con","w"); - fprintf(out,"%.8E \t %.8E \t %06d \n", time_cur, m_bh, num_bh); - fclose(out); - -#endif // STARDESTR_EXT - - - -#ifdef ACT_DEF_LL -#ifdef DEBUG111 - if(myRank == rootRank) check_linklist((int)Timesteps); -#endif -#endif - - - energy_contr(); - -#ifdef CMCORR111 - for(i=0; i R_LIMITS_ALL) && (m[i] != 0.0) ) - if( (tmp_r > R_LIMITS_ALL) && (tmp_rv > 0.0) ) - { - -// tmp_v = sqrt( SQR(v[i][0]) + SQR(v[i][1]) + SQR(v[i][2]) ); -// E_corr += 0.5*m[i]*SQR(tmp_v); - -// pot[i] = 0.0; - -#ifdef EXTPOT -// pot_ext[i] = 0.0; -#endif - - for(k=0;k<3;k++) - { -// x[i][k] = R_LIMITS_ALL + 1.0*my_rand2(); - v[i][k] *= 1.0E-01; -// a[i][k] = 1.0E-06*my_rand2(); -// adot[i][k] = 1.0E-06*my_rand2(); - } /* k */ - -// t[i] = min_t; -// dt[i] = 0.125; - - } /* if */ - - } /* i */ - - - - for(j=0; j= t_contr) */ - - - - - - - - - if(time_cur >= t_disk) - { - - - if(myRank == rootRank) - { - - diskstep++; - - write_snap_data(); -// write_cont_data(); - -#ifdef DEBUG_extra - write_snap_extra(); -#endif - -#ifdef SPH_GAS - write_data_SPH(); -#endif - -#ifdef GMC - write_snap_GMC(); -#endif - - } /* if(myRank == rootRank) */ - -#ifdef ETICS_DUMP - sprintf(out_fname, "coeffs.%06d.%02d.dat", diskstep, myRank); - grapite_dump(out_fname, 2); -#endif - - - - -#ifdef LIMITS_NEW - - for(i=0; i 900.0 ) - { - - m[i] = 0.0; - - pot[i] = 0.0; - -#ifdef EXTPOT - pot_ext[i] = 0.0; -#endif - - for(k=0;k<3;k++) - { - x[i][k] = 1000.0 + 1.0*my_rand2(); - v[i][k] = 1.0E-06*my_rand2(); - a[i][k] = 1.0E-06*my_rand2(); - adot[i][k] = 1.0E-06*my_rand2(); - } /* k */ - - t[i] = 2.0*t_end; - - dt[i] = 0.125; - - } /* if */ - - } /* i */ - - - - for(j=0; j= t_disk) */ - - - -#ifdef CPU_TIMELIMIT - if(myRank == rootRank) - { - get_CPU_time(&CPU_time_real, &CPU_time_user, &CPU_time_syst); - tmp_cpu = CPU_time_real-CPU_time_real0; - } /* if(myRank == rootRank) */ -#endif - - -#ifdef ACT_DEF_LL - //printf("At tsteps= %04d . t+dt for BH = % 08E\n", int(Timesteps), t[N-1]+dt[N-1]); - ModifyLinkList(); - -#ifdef DEBUG111 - if( (((int)Timesteps)%10000 == 0) && (myRank == rootRank) ) check_linklist((int)Timesteps); -#endif -#endif - - } /* while(time_cur < t_end) */ - - - - /* close the local GRAPE's */ - -#ifdef SAPPORO - g6_close_(&clusterid); -#else - g6_close(clusterid); -#endif - - - /* Wait to all processors to finish his works... */ - MPI_Barrier(MPI_COMM_WORLD); - - MPI_Reduce(&g6_calls, &g6_calls_sum, 1, MPI_DOUBLE, MPI_SUM, rootRank, MPI_COMM_WORLD); - - /* Wait to all processors to finish his works... */ - MPI_Barrier(MPI_COMM_WORLD); - - - if(myRank == rootRank) - { - - /* Write some output for the timestep annalize... */ - - printf("\n"); - printf("Timesteps = %.0f Total sum of integrated part. = %.0f g6_calls on all nodes = %.0f \n", Timesteps, n_act_sum, g6_calls); - printf("\n"); - printf("Real Speed = %.3f GFlops \n", 57.0*N*n_act_sum/(CPU_time_user-CPU_time_user0)/1.0E+09); - fflush(stdout); - - -#ifdef DEBUG111 - tmp_file = fopen("n_act_distr.dat","w"); - - fprintf(tmp_file,"\n"); - fprintf(tmp_file,"Total Timesteps = %.0f Total sum of integrated part. = %.0f g6_calls on all nodes = %.0f \n", Timesteps, n_act_sum, g6_calls); - fprintf(tmp_file,"\n"); - fprintf(tmp_file,"Real Speed = %.3f GFlops \n", 57.0*N*n_act_sum/(CPU_time_user-CPU_time_user0)/1.0E+09); - - for(i=1;i Plummer + : Andreas+Fazeel... + : + : Stellar evolution added + : Stellar lifetimes: Raiteri, Villata & Navarro (1996) + : IMS mass loss: van den Hoeg & Groenewegen (1997) + : + : STARDESTR_EXT: Tidal disruption of stars by external BH... + : Chingis, Denis & Maxim... + : + : STARDESTR: Tidal disruption of stars by BH... + : Jose, Li Shuo & Shiyan Zhong + : + : STARDISK: Drag force... + : Chingis, Denis & Maxim... + : + : STARDISK: variable hz = HZ*(R/R_crit) up to R_crit... + : Taras, Andreas... + : + : Live BH (1 || 2) + ACC + EJECT... + : Li Shuo & Shiyan Zhong + : + : dt_min for BH (1 || 2)... + : + : added the PN calculus for the BBH + : PN0, PN1, PN2, PN2.5 (coded on the base of + : Gabor Kupi original routine) + : + : added the "name" array... + : + : added the GMC's calculus (GMC on CPU; GMC2 on GPU) + : for Alexey SC runs... and also for Fazeel Zurich runs... + : + : CPU_TIMELIMIT added for the Julich MW cluster runs... + : +Coded by : Peter Berczik +Version number : 19.04 +Last redaction : 2019.04.16 12:55 +*****************************************************************************/ +//#define CPU_RUNLIMIT 28000 // 24h = 24*60*60 = 86400 +#define CPU_RUNLIMIT 255000 // 3 days = 3*24*60*60 = 259200 +//#define CPU_RUNLIMIT 100 // 9.5 min +//#define CPU_RUNLIMIT 100 // 9.5 min + +//#define GMC // add the GMC's to the run +//#define GMC2 // add the GMC's to the run + +//#define NORM // Physical normalization +//#define STEVOL // Stellar evolution Do not tuch! Defined inside the Makefiles !!! +//#define STEVOL_SSE // Stellar evolution with SSE Do not tuch! Defined inside the Makefiles !!! + +//#define ADD_BH1 // add the Single BH + +#define ADD_BH2 // add the Binary BH's +#define ADD_N_BH // eps_BH = 0.0, but added only the Newtonian forces +// #define ADD_PN_BH // extra - added also the Post-Newton forces +// #define ADD_SPIN_BH // extra - added the SPIN for the BH's - DEFAULT !!! + +// #define BH_OUT // extra output for BH's (live) +// #define BH_OUT_NB // extra output for the BH's neighbours (live) + +// #define BBH_INF // BBH influence sphere... +// #define R_INF 10.0 // Factor for the influence sphere... if ( R < R_INF * DR_BBH ) +// #define R_INF2 (R_INF*R_INF) + +// #define DT_MIN_WARNING // dt < dt_min warning !!! + +//#define BH_OUT_NB_EXT // extra output for the BH's neighbours (external) + +//#define SAPPORO // Gaburov. Do not tuch! Defined inside the Makefiles !!! +//#define YEBISU // Nitadori. Do not tuch! Defined inside the Makefiles !!! +//#define GUINNESS // Nakasato. Do not tuch! Defined inside the Makefiles !!! + +//#define STARDESTR // disruption of stars by BH tidal forces +//#define R_TIDAL 1.0E-03 // Tidal radius of the BH's +//#define RMAX_OUT // extra data for def. r_max... + +//#define STARDESTR_EXT // disruption of stars by external BH tidal forces +//#define R_0 0.22 // Outer cut of the disk +//#define R_ACCR 0.0050 // Tidal Accr. rad of the BH's in units of R_0 +//#define R_TIDAL (R_0*R_ACCR) // Tidal radius of the BH's in NB units + +//#define STARDISK // analytic gas disk around BH + drag +//#define HZ (0.001*R_0) // Disk thickness... in NB units +//#define R_CRIT 0.0257314 // Critical radius of the disk (vert SG = vert BH force) +//#define R_CRIT 0.0 // i.e. hz=HZ=const... + +//#define SPH_GAS // SPH gas disk around BH + drag; experimental stuff !!! + +//#define EXTPOT // external potential (BH? or galactic?) +//#define EXTPOT_BH // BH - usually NB units + +//#define EXTPOT_GAL // Galactic B+D+H PK - usually physical units + +//#define EXTPOT_GAL_DEH // Dehnen Galactic - usually physical units +//#define EXTPOT_GAL_LOG // Log Galactic - usually physical units + +//#define EXTPOT_SC // SC extra POT for Bek test runs... +//#define DATAFILE eff0.05.tsf10.00.tab +//#define M_SC_DIM 100001 + +//#define CMCORR // CM correction in the zero step and in every dt_contr + +//#define DEBUG // debug information to files & screen +// #define DEBUG_extra // extra debug information to files & screen +//#define LAGR_RAD // write out lagr-rad.dat + +//#define LIMITS // for "0" mass particles !!! +//#define R_LIMITS 1.0E+03 // for "0" mass particles !!! +//#define COORDS 1010.0 // for "0" mass particles !!! + +//#define LIMITS_NEW // for "0" mass particles !!! + +//#define LIMITS_ALL_BEG // for ALL particles at the beginning... +//#define LIMITS_ALL // for ALL particles +//#define R_LIMITS_ALL 1.0E+03 // for ALL particles + +#ifdef ETICS +#include "grapite.h" +// why do we need CEP as a compilaion flag... just have it always on when ETICS is on. IF there is no CEP, there should be a graceful skipping of those operations. +//#define ETICS_CEP +#ifndef ETICS_DTSCF +#error "ETICS_DTSCF must be defined" +#endif +#endif + +#define TIMING + +#define ETA_S_CORR 4.0 +#define ETA_BH_CORR 4.0 + +#define DTMAXPOWER -3.0 +#define DTMINPOWER -36.0 + +/* +-3.0 0.125 +-4.0 0.0625 +-5.0 0.03125 +-7.0 ~1e-2 +-10.0 ~1e-3 +............. +-20.0 ~1e-6 +-23.0 ~1e-7 +-26.0 ~1e-8 +-30.0 ~1e-9 +*/ + +//#define AMD + +// #define ACT_DEF_LL + +#if defined(ACT_DEF_LL) && defined(ACT_DEF_GRAPITE) +#error "Contradicting preprocessor flags!" +#endif + +/****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include + +/* +double aaa; +double aaapars[5]; + +extern void qwerty_(double *aaa, double *aaapars); +*/ + +#ifdef SAPPORO +#include +#include +#define GPU_PIPE 256 +#else +# ifdef YEBISU +# define G6_NPIPE 2048 +# else +# define G6_NPIPE 48 +# endif +#include "grape6.h" +#endif + +#ifdef GUINNESS +#define GPU_PIPE 128 +#endif + +#include + +/* Some "good" functions and constants... */ +#define SIG(x) ( ((x)<0) ? (-1):(1) ) +#define ABS(x) ( ((x)<0) ? (-x):(x) ) +#define MAX(a,b) ( ((a)>(b)) ? (a):(b) ) +#define MIN(a,b) ( ((a)<(b)) ? (a):(b) ) +#define SQR(x) ( (x)*(x) ) +#define POW3(x) ( (x)*SQR(x) ) + +#define Pi 3.14159265358979323846 +#define TWOPi 6.283185307179 +#define sqrt_TWOPi 2.506628274631 + +#ifdef NORM +//http://pdg.lbl.gov/2015/reviews/rpp2015-rev-astrophysical-constants.pdf + +#define G 6.67388E-11 // (m/s^2) * (m^2/kg) +#define Msol 1.988489E+30 // kg +#define Rsol 6.957E+08 // m +#define AU 149597870700.0 // m +#define pc 3.08567758149E+16 // m +#define Year 31556925.2 // s +#define c_feny 299792458.0 // m/s + +#define kpc (1.0E+03*pc) // m +#define km 1.0E+03 // km -> m +#define cm3 1.0E-06 // cm^3 -> m^3 +#define Myr (1.0E+06*Year) // s +#define Gyr (1.0E+09*Year) // s +#define R_gas 8.31447215 // J/(K*mol) +#define k_gas 1.380650424E-23 // J/K +#define N_A 6.022141510E+23 // 1/mol +#define mu 1.6605388628E-27 // kg +#define mp 1.67262163783E-27 // kg +#define me 9.1093821545E-31 // kg + +#define pc2 (pc*pc) +#define pc3 (pc*pc*pc) +#define kpc2 (kpc*kpc) +#define kpc3 (kpc*kpc*kpc) +#endif + +/* + 1KB = 1024 + 2KB = 2048 + 4KB = 4096 + 8KB = 8192 +16KB = 16384 +32KB = 32768 +64KB = 65536 +128KB = 131072 +256KB = 262144 +512KB = 524288 +1024KB = 1048576 -> 1MB +*/ + +#define KB 1024 +#define MB (KB*KB) + +#define N_MAX (6*MB) +#define N_MAX_loc (2*MB) + +//#define N_MAX (1200000) +//#define N_MAX_loc (1200000) + +//#define P_MAX 32 + +//#ifdef DEBUG + +/* extra code & data for DEBUG... */ + +#include "debug.h" + +//#ifdef DEBUG_extra +int ind_sort[N_MAX]; +double var_sort[N_MAX]; +//#endif + +//#endif + +#ifdef LAGR_RAD +int lagr_rad_N = 22; +double mass_frac[] = { 0.0001, 0.0003, 0.0005, 0.001, 0.003, 0.005, 0.01, 0.03, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.95, 0.99, 0.9999, 1.0 }; +double lagr_rad[22]; +double m_tot, m_cum, n_cum; +#endif + +int name_proc, n_proc=1, myRank=0, rootRank=0, cur_rank, + i, j, k, ni, nj, diskstep=0, power, jjj, iii, + skip_con=0, tmp_i; + +double dt_disk, dt_contr, t_disk=0.0, t_contr=0.0, + dt_bh, t_bh=0.0, dt_bh_tmp, + t_end, time_cur, dt_min, dt_max, min_t, min_t_loc, dt_new, min_dt, + eta_s, eta, eta_bh, + E_pot, E_pot_ext, E_kin, E_tot, E_tot_0, DE_tot, + E_tot_corr, E_tot_corr_0, DE_tot_corr, + E_tot_corr_sd, E_tot_corr_sd_0, DE_tot_corr_sd, + E_corr = 0.0, E_sd = 0.0, t_diss_on = 0.125, + e_kin_corr = 0.0, e_pot_corr = 0.0, e_pot_BH_corr = 0.0, + e_summ_corr = 0.0, + mcm, rcm_mod, vcm_mod, + rcm_sum=0.0, vcm_sum=0.0, + eps=0.0, eps2, + xcm[3], vcm[3], mom[3], + xdc[3], vdc[2], + over2=(1.0/2.0), over3=(1.0/3.0), over6=(1.0/6.0), + a2_mod, adot2_mod, + dt_tmp, dt2half, dt3over6, dt4over24, dt5over120, + dtinv, dt2inv, dt3inv, + a0mia1, ad04plad12, ad0plad1, + a2[3], a3[3], a2dot1[3], + a1abs, adot1abs, a2dot1abs, a3dot1abs, + Timesteps=0.0, n_act_sum=0.0, n_act_distr[N_MAX], g6_calls=0.0, g6_calls_sum=0.0, + tmp, tmp_r, tmp_v, tmp_rv, tmp_cpu, + tmp_pot, tmp_a, tmp_adot, + tmp_a_bh, tmp_adot_bh, + tmp_a_bh_pn0, tmp_a_bh_pn1, tmp_a_bh_pn2, tmp_a_bh_pn2_5, tmp_a_bh_pn3, tmp_a_bh_pn3_5, tmp_a_bh_spin, + tmp_adot_bh_pn0, tmp_adot_bh_pn1, tmp_adot_bh_pn2, tmp_adot_bh_pn2_5, tmp_adot_bh_pn3, tmp_adot_bh_pn3_5, tmp_adot_bh_spin; + +double R[3], V[3], L[3], mju, dr2, dr, dv2, dv, dl2, dl, pot_eff; + +char processor_name[MPI_MAX_PROCESSOR_NAME], + inp_fname[30], inp_fname_gmc[30], + out_fname[30], dbg_fname[30]; + +/* global variables */ + +int N, N_star, N_gmc, N_bh, + ind[N_MAX], name[N_MAX]; +double m[N_MAX], x[N_MAX][3], v[N_MAX][3], + pot[N_MAX], a[N_MAX][3], adot[N_MAX][3], + t[N_MAX], dt[N_MAX]; + +/* local variables */ + +int n_loc, ind_loc[N_MAX_loc]; +double m_loc[N_MAX_loc], x_loc[N_MAX_loc][3], v_loc[N_MAX_loc][3], + pot_loc[N_MAX_loc], a_loc[N_MAX_loc][3], adot_loc[N_MAX_loc][3], + t_loc[N_MAX_loc], dt_loc[N_MAX_loc]; + +/* data for active particles */ + +int n_act, ind_act[N_MAX]; +double m_act[N_MAX], + x_act[N_MAX][3], v_act[N_MAX][3], + pot_act[N_MAX], a_act[N_MAX][3], adot_act[N_MAX][3], + t_act[N_MAX], dt_act[N_MAX], + x_act_new[N_MAX][3], v_act_new[N_MAX][3], + pot_act_new[N_MAX], a_act_new[N_MAX][3], adot_act_new[N_MAX][3], + pot_act_tmp[N_MAX], a_act_tmp[N_MAX][3], adot_act_tmp[N_MAX][3], + pot_act_tmp_loc[N_MAX], a_act_tmp_loc[N_MAX][3], adot_act_tmp_loc[N_MAX][3]; + +FILE *inp, *out, *tmp_file, *dbg; + +double CPU_time_real0, CPU_time_user0, CPU_time_syst0; +double CPU_time_real, CPU_time_user, CPU_time_syst; + + +#ifdef TIMING + +double CPU_tmp_real0, CPU_tmp_user0, CPU_tmp_syst0; +double CPU_tmp_real, CPU_tmp_user, CPU_tmp_syst; + +double DT_TOT, + DT_ACT_DEF1, DT_ACT_DEF2, DT_ACT_DEF3, DT_ACT_PRED, + DT_ACT_GRAV, DT_EXT_GRAV, + DT_GMC_GRAV, DT_GMC_GMC_GRAV, DT_EXT_GMC_GRAV, + DT_ACT_CORR, DT_ACT_LOAD, + DT_STEVOL, DT_STARDISK, DT_STARDESTR; + +double DT_ACT_REDUCE; + +#endif + +/* some local settings for G6a board's */ + +int clusterid, ii, nn, numGPU; + +//#ifdef SAPPORO +#if defined(SAPPORO) || defined(GUINNESS) + +int npipe=GPU_PIPE, index_i[GPU_PIPE]; +double h2_i[GPU_PIPE], x_i[GPU_PIPE][3], v_i[GPU_PIPE][3], + p_i[GPU_PIPE], a_i[GPU_PIPE][3], jerk_i[GPU_PIPE][3]; +double new_tunit=51.0, new_xunit=51.0; + +#elif defined YEBISU + +int npipe=G6_NPIPE, index_i[G6_NPIPE]; +double h2_i[G6_NPIPE], x_i[G6_NPIPE][3], v_i[G6_NPIPE][3], + p_i[G6_NPIPE], a_i[G6_NPIPE][3], jerk_i[G6_NPIPE][3]; +int new_tunit=51, new_xunit=51; +#else + +int npipe=48, index_i[48]; +double h2_i[48], x_i[48][3], v_i[48][3], + p_i[48], a_i[48][3], jerk_i[48][3]; +int new_tunit=51, new_xunit=51; + +#endif + +int aflag=1, jflag=1, pflag=1; + +double ti=0.0, a2by18[3], a1by6[3], aby2[3]; + +/* normalization... */ + +#ifdef NORM +double m_norm, r_norm, v_norm, t_norm; +#endif + +double eps_BH=0.0; + +/* external potential... */ + +#ifdef EXTPOT + +#ifdef EXTPOT_GAL +double m_bulge, a_bulge, b_bulge, + m_disk, a_disk, b_disk, + m_halo, a_halo, b_halo, +// x_ext, y_ext, z_ext, +// vx_ext, vy_ext, vz_ext, +// x_ij, y_ij, z_ij, +// vx_ij, vy_ij, vz_ij, rv_ij, + x2_ij, y2_ij, z2_ij, + r_tmp, r2_tmp, z_tmp, z2_tmp; +#endif + +#ifdef EXTPOT_GAL_DEH +double m_ext, r_ext, g_ext, + tmp_r2, tmp_r3, dum, dum2, dum3, dum_g, tmp_g; +#endif + +#ifdef EXTPOT_GAL_LOG +double v_halo, r_halo, + v2_halo, r2_halo, r2_r2_halo, + x2_ij, y2_ij, z2_ij; +#endif + +#ifdef EXTPOT_BH +double r2, rv_ij, + m_bh, b_bh, eps_bh; +#endif + +#ifdef EXTPOT_SC +int M_SC=M_SC_DIM; +double r_sc[M_SC_DIM], m_sc[M_SC_DIM], p_sc[M_SC_DIM]; +double M_R, pot_out_R; +#endif + + +double pot_ext[N_MAX], pot_act_ext[N_MAX]; // for all EXTPOT + +#endif + + +int i_bh, i_bh1, i_bh2, + num_bh = 0, num_bh1 = 0, num_bh2 = 0; + +double m_bh, m_bh1, m_bh2, b_bh, + r, r2, + x_ij, y_ij, z_ij, + vx_ij, vy_ij, vz_ij, rv_ij; + +#ifdef STEVOL +int num_dead, event[N_MAX]; +double dt_stevol, t_stevol; +double m0[N_MAX], ZZZ[N_MAX], t0[N_MAX]; +#endif + + +#ifdef STEVOL_SSE + +int num_dead, event[N_MAX], event_old[N_MAX]; +double dt_stevol, t_stevol; +double m0[N_MAX], ZZZ[N_MAX], t0[N_MAX]; +double SSEMass[N_MAX], SSESpin[N_MAX], SSERad[N_MAX], + SSELum[N_MAX], SSETemp[N_MAX]; +double SSEMV[N_MAX], SSEBV[N_MAX]; + +double Rgal = 10000.0; //Distance of star from sun for artificial CMD with observational errors [pc] + +int van_kick=0; + +extern void zcnsts_(double *z, double *zpars); +extern void evolv1_(int *kw, double *mass, double *mt, double *r, double *lum, double *mc, double *rc, double *menv, double *renv, double *ospin, double *epoch, double *tms, double *tphys, double *tphysf, double *dtp, double *z, double *zpars, double *vkick, double *vs); +extern int cmd(int kstar, double rstar, double lstar, double Rgal, double *abvmag, double *vmag, double *BV, double *Teff, double *dvmag, double *dBV); + +struct{ + double neta; + double bwind; + double hewind; + double mxns; +} value1_; + +struct{ + double pts1; + double pts2; + double pts3; +} points_; + +struct{ + double sigma; + int bhflag; +} value4_; + +struct{ + int idum; +} value3_; + +struct{ + int ceflag; + int tflag; + int ifflag; + int nsflag; + int wdflag; +} flags_; + +struct{ + double beta; + double xi; + double acc2; + double epsnov; + double eddfac; + double gamma; +} value5_; + +struct{ + double alpha1; + double lambda; +} value2_; + +#include "cmd.c" + +#endif + + + +#ifdef BBH_INF +int inf_event[N_MAX]; +double x_bbhc[3], v_bbhc[3], DR2, tmp_r2; +double DV2, EB, SEMI_a, SEMI_a2; +#endif + + + +/* STARDISK Drag force... */ + +#ifdef STARDISK + +double a_drag[N_MAX][3], adot_drag[N_MAX][3]; +//double a_drag[N_MAX][3], adot_drag[N_MAX][3]; + +double z_new_drag, r_new_drag2, hz; + +#ifdef SPH_GAS + +#define N_GAS_MAX (128*KB) +#define NB 50 + +int N_GAS, ind_gas[N_GAS_MAX], sosed_gas[N_GAS_MAX][NB]; +double m_gas[N_GAS_MAX], x_gas[N_GAS_MAX][3], v_gas[N_GAS_MAX][3], h_gas[N_GAS_MAX], DEN_gas[N_GAS_MAX]; + +//int sosed[NB]; +double d[N_MAX]; // podrazumevajem chto: N_MAX > N_GAS_MAX vsegda ! +double x_star, y_star, z_star, DEN_star; +double h_min = 1.0E-04, h_max = 1.0; + +#include "def_H.c" +#include "def_DEN.c" +#include "def_DEN_STAR.c" + +#endif // SPH_GAS + +#include "drag_force.c" + +// calculate the SG for the set of active particles which is deepley INSIDE the EXT BH infl. rad. +// EXPERIMENTAL feature !!! + +//int SG_CALC = 0; +//double summ_tmp_r = 0.0, aver_tmp_r = 0.0, R_INT_CUT = 1.0E-03; + +#endif // STARDISK + + + +/* GMC data... */ + +#ifdef GMC + +double dt_gmc, E_pot_gmc, E_pot_gmc_gmc, E_pot_ext_gmc, E_kin_gmc; + +#define N_gmc_MAX (500) + +int N_gmc, ind_gmc[N_gmc_MAX], name_gmc[N_gmc_MAX]; + +double m_gmc[N_gmc_MAX], pot_gmc_gmc[N_gmc_MAX], pot_ext_gmc[N_gmc_MAX], + x_gmc[N_gmc_MAX][3], v_gmc[N_gmc_MAX][3], a_gmc[N_gmc_MAX][3], + eps_gmc[N_gmc_MAX]; + +double pot_gmc[N_MAX]; + +#endif // GMC + + +/****************************************************************************/ + +/****************************************************************************/ +#ifdef ADD_N_BH + +double x_bh1[3], x_bh2[3], v_bh1[3], v_bh2[3]; + +double pot_bh1, a_bh1[3], adot_bh1[3], + pot_bh2, a_bh2[3], adot_bh2[3]; + +//double eps_BH = 0.0; + +#include "n_bh.c" + +/* +int calc_force_n_BH(double m1, double xx1[], double vv1[], + double m2, double xx2[], double vv2[], + double eps_BH, + double pot_n1, double a_n1[], double adot_n1[], + double pot_n2, double a_n2[], double adot_n2[]) +*/ + +/* + INPUT + +m1 - mass of the 1 BH +xx1[0,1,2] - coordinate of the 1 BH +vv1[0,1,2] - velocity of the 1 BH + +m2 - mass of the 2 BH +xx2[0,1,2] - coordinate of the 2 BH +vv2[0,1,2] - velocity of the 2 BH + +eps_BH - force softening, can be even exactly 0.0 ! + + OUTPUT + +pot_n1 for the 1 BH +a_n1 [0,1,2] for the 1 BH +adot_n1 [0,1,2] for the 1 BH + +pot_n2 for the 2 BH +a_n2 [0,1,2] for the 2 BH +adot_n2 [0,1,2] for the 2 BH + +return - 0 if everything OK +*/ + +#endif +/****************************************************************************/ + +/****************************************************************************/ +#ifdef ADD_PN_BH + +double C_NB = 477.12; + +int usedOrNot[7] = {1, 1, 1, 1, 0, 0, 0}; + +double a_pn1[7][3], adot_pn1[7][3], + a_pn2[7][3], adot_pn2[7][3]; + +double s_bh1[3] = {0.0, 0.0, 1.0}; +double s_bh2[3] = {0.0, 0.0, 1.0}; + +#ifdef ADD_SPIN_BH // eto rabotajet vsegda !!! +#include "pn_bh_spin.c" +#else +#include "pn_bh.c" // eto staraja versija, bolshe ne rabotajet !!! +#endif + +/* +int calc_force_pn_BH(double m1, double xx1[], double vv1[], double ss1[], + double m2, double xx2[], double vv2[], double ss2[], + double CCC_NB, double dt_bh, + int usedOrNot[], + double a_pn1[][3], double adot_pn1[][3], + double a_pn2[][3], double adot_pn2[][3]) +*/ + +/* + INPUT + +m1 - mass of the 1 BH +xx1[0,1,2] - coordinate of the 1 BH +vv1[0,1,2] - velocity of the 1 BH +spin1[0,1,2] - normalized spin of the 1 BH + +m2 - mass of the 2 BH +xx2[0,1,2] - coordinate of the 2 BH +vv2[0,1,2] - velocity of the 2 BH +spin2[0,1,2] - normalized spin of the 2 BH + +CCC_NB - Speed of light "c" in internal units +dt_BH - timestep of the BH's, needed for the SPIN integration + +usedOrNot[PN0, PN1, PN2, PN2.5, PN3, PN3.5, SPIN] - different PN term usage: PN1, PN2, PN2.5, PN3, PN3.5, SPIN + 0 1 2 3 4 5 6 + + OUTPUT + +a_pn1 [0 - PN0; 1 - PN1; 2 - PN2; 3 - PN2.5, 4 - PN3, 5 - PN3.5, 6 - SPIN] [3] for the 1 BH +adot_pn1[0 - PN0; 1 - PN1; 2 - PN2; 3 - PN2.5, 4 - PN3, 5 - PN3.5, 6 - SPIN] [3] for the 1 BH + +a_pn2 [0 - PN0; 1 - PN1; 2 - PN2; 3 - PN2.5, 4 - PN3, 5 - PN3.5, 6 - SPIN] [3] for the 2 BH +adot_pn2[0 - PN0; 1 - PN1; 2 - PN2; 3 - PN2.5, 4 - PN3, 5 - PN3.5, 6 - SPIN] [3] for the 2 BH + +return - 0 if everything OK + - 505 if BH's separation < 4 x (RSwarch1 + RSwarch2) +*/ + +#endif + +/****************************************************************************/ + +/****************************************************************************/ +/* RAND_MAX = 2147483647 */ +/* my_rand : 0.0 - 1.0 */ +/* my_rand2 : -1.0 - 1.0 */ + +double my_rand(void) +{ +return( (double)(rand()/(double)RAND_MAX) ); +} + +double my_rand2(void) +{ +return (double)(2.0)*((rand() - RAND_MAX/2)/(double)RAND_MAX); +} +/****************************************************************************/ + +#ifdef STARDESTR +#include "star_destr.c" +#endif + +#ifdef STARDESTR_EXT +#include "star_destr_ext.c" +#endif + +#ifdef ACT_DEF_LL +#include "act_def_linklist.c" +#endif + +#ifdef ETICS +double t_exp, dt_exp=ETICS_DTSCF; // t_exp is just the initial value +#ifdef ETICS_CEP +int grapite_cep_index; +#endif +#endif + +/****************************************************************************/ +void get_CPU_time(double *time_real, double *time_user, double *time_syst) +{ +struct rusage xxx; +double sec_u, microsec_u, sec_s, microsec_s; +struct timeval tv; + + +getrusage(RUSAGE_SELF,&xxx); + +sec_u = xxx.ru_utime.tv_sec; +sec_s = xxx.ru_stime.tv_sec; + +microsec_u = xxx.ru_utime.tv_usec; +microsec_s = xxx.ru_stime.tv_usec; + +*time_user = sec_u + microsec_u * 1.0E-06; +*time_syst = sec_s + microsec_s * 1.0E-06; + +// *time_real = time(NULL); + +gettimeofday(&tv, NULL); +*time_real = tv.tv_sec + 1.0E-06 * tv.tv_usec; + +*time_user = *time_real; + +} +/****************************************************************************/ + +#ifdef STEVOL +/****************************************************************************/ +double t_dead(double m, double Z) +/* +m - mass of the star (in Msol) +Z - metallicity (absolut values - i.e. Zsol = 0.0122) +t - return value of star lifetime (in Year) + +Raiteri, Villata & Navarro, 1996, A&A, 315, 105 +*/ +{ +double a0, a1, a2, lZ, lm, tmp=0.0; + +m *= (m_norm/Msol); + +lZ = log10(Z); +lm = log10(m); + +a0 = 10.130 + 0.07547*lZ - 0.008084*lZ*lZ; +a1 = -4.424 - 0.79390*lZ - 0.118700*lZ*lZ; +a2 = 1.262 + 0.33850*lZ + 0.054170*lZ*lZ; + +tmp = a0 + a1*lm + a2*lm*lm; + +tmp = pow(10.0,tmp); + +tmp *= (Year/t_norm); + +return(tmp); +} +/****************************************************************************/ + +/****************************************************************************/ +double m_loss_old(double m, double Z) +/* +m - initial mass of the star (in Msol) +Z - metallicity (e.g. Zsol = 0.02) +m_ret - returned maass to ISM from the star (in Msol) + +approx. from data of van den Hoek & Groenewegen, 1997, A&AS, 123, 305 +*/ +{ +double tmp=0.0; + +m *= (m_norm/Msol); + +// tmp = (-0.46168 + 0.912274 * m); // first approx. + +tmp = -0.420542*pow(Z, -0.0176601) + (0.901495 + 0.629441*Z) * m; + +tmp *= (Msol/m_norm); + +return(tmp); +} +/****************************************************************************/ + +/****************************************************************************/ +double m_curr_old(double m0, double Z, double t0, double t) +{ +double td, ml, tmp=0.0; + +td = t_dead(m0, Z); +ml = m_loss_old(m0, Z); + +if ( (t-t0) < td ) + { + tmp = m0; // instant mass loss +// tmp = m0 - (t-t0)/(td-t0) * ml; // linear mass loss + } +else + { + tmp = m0 - ml; + + if (event[i] == 0) + { + num_dead++; + event[i] = 1; + } + + } /* if ( (t-t0) < td ) */ + +return(tmp); +} +/****************************************************************************/ + +/****************************************************************************/ +double m_loss(double m, double Z) +/* +m - initial mass of the star (in norm. units) +Z - metallicity (absolut value - i.e. Zsol = 0.0122) +m_loss - returned maass to ISM from the star (in norm. units) +*/ +{ +double tmp=0.0; + +m *= (m_norm/Msol); + +if ( m < 8.0) + { +// approx. from data of van den Hoek & Groenewegen, 1997, A&AS, 123, 305 + +// tmp = (-0.46168 + 0.912274 * m); // first approx. + tmp = -0.420542*pow(Z, -0.0176601) + (0.901495 + 0.629441*Z) * m; // second approx. + } +else + { +// approx. from data of Woosley & Weaver, 1995, ApJS, 110, 181 + +// tmp = 0.813956*pow(m, 1.04214); + tmp = 0.813956*pow(m, 1.04); + } + +tmp *= (Msol/m_norm); + +return(tmp); +} +/****************************************************************************/ + +/****************************************************************************/ +double m_curr(double m0, double Z, double t0, double t) +{ +double td, ml, tmp=0.0; + +tmp = m0; + +if ( event[i] == 0 ) + { + + td = t_dead(m0, Z); + + if ( (t-t0) > td ) + { + + ml = m_loss(m0, Z); + + tmp = m0 - ml; + + num_dead++; + +// wd http://en.wikipedia.org/wiki/Chandrasekhar_limit 1.38 + + if ( tmp * (m_norm/Msol) < 1.38 ) + { + event[i] = 1; + } + else + { + +// ns http://en.wikipedia.org/wiki/Neutron_stars 1.38 - ~2.0 ??? + + if ( tmp * (m_norm/Msol) > 1.38 ) event[i] = 2; + +// bh http://en.wikipedia.org/wiki/Tolman-Oppenheimer-Volkoff_limit ~1.5 - ~3.0 ??? + + if ( tmp * (m_norm/Msol) > 2.00 ) event[i] = 3; + + } + + } /* if ( (t-t0) > td ) */ + + } /* if ( event[i] == 0 ) */ + +return(tmp); +} +/****************************************************************************/ +#endif + + +#ifdef STEVOL_SSE +/****************************************************************************/ +double m_curr(int ipart, double m0, double Z, double t0, double t) +{ +//set up parameters and variables for SSE (Hurley, Pols & Tout 2002) +int kw=0; //stellar type +double mass; //initial mass +double mt=0.0; //actual mass +double r=0.0; //radius +double lum=0.0; //luminosity +double mc=0.0; //core mass +double rc=0.0; //core radius +double menv=0.0; //envelope mass +double renv=0.0; //envelope radius +double ospin=0.0; //spin +double epoch=0.0; //time spent in current evolutionary state +double tms=0.0; //main-sequence lifetime +double tphys; //initial age +double tphysf; //final age +double dtp=0.0; //data store value, if dtp>tphys no data will be stored +double z; //metallicity +double zpars[20]; //metallicity parameters +double vkick=0.0; //kick velocity for compact remnants +double vs[3]; //kick velocity componets + +// M_V_[mag] V_[mag] B-V_[mag] T_eff_[K] dV_[mag] d(B-V) +double abvmag, vmag, BV, Teff, dvmag, dBV; + +mass = m0*(m_norm/Msol); // m0[i] initial mass of the stars Msol +mt = mass; // current mass for output in Msol +tphys = t0*(t_norm/Myr); // t0[i] time of the star formation Myr +tphysf = t*(t_norm/Myr); // t[i] current time for the star Myr +dtp = 0.0; // output parameter, just set to 0.0 !!! +z = Z; // ZZZ[i] of the star + +/* +if (ipart > 9995) + { +printf("Initial parameters: \n"); +printf("M = %g [Mo] \n", mass); +printf("Z = %g \n", z); +printf("kw = %d \n", kw); +printf("spin = %g \n", ospin); +printf("epoch = %g [Myr] \n", epoch); +printf("t_beg = %g [Myr] \n", tphys); +printf("t_end = %g [Myr] \n", tphysf); +printf("R = %g [R_o] \n", r); +printf("L = %g [L_o] \n", lum); +printf("V_kick = %g [km/s] \n", vkick); + } +*/ + +for (k=0; k<20; k++) zpars[k] = 0; +zcnsts_(&z,zpars); //get metallicity parameters + +evolv1_(&kw, &mass, &mt, &r, &lum, &mc, &rc, &menv, &renv, &ospin, &epoch, &tms, &tphys, &tphysf, &dtp, &z, zpars, &vkick, vs); +cmd(kw, r, lum, Rgal, &abvmag, &vmag, &BV, &Teff, &dvmag, &dBV); + +/* +if (ipart > 9995) + { +printf("Final parameters: \n"); +printf("M = %g [Mo] \n", mt); +printf("Z = %g \n", z); +printf("kw = %d \n", kw); +printf("spin = %g \n", ospin); +printf("epoch = %g [Myr] \n", epoch); +printf("t_beg = %g [Myr] \n", tphys); +printf("t_end = %g [Myr] \n", tphysf); +printf("R = %g [R_o] \n", r); +printf("L = %g [L_o] \n", lum); +printf("V_kick = %g [km/s] \n", vkick); +printf("M_V_[mag]\tV_[mag]\t\tB-V_[mag]\tT_eff_[K]\tdV_[mag]\td(B-V)\n"); +printf("%.3E\t%.3E\t%.3E\t%.3E\t%.3E\t%.3E\n", abvmag, vmag, BV, Teff, dvmag, dBV); +// printf("%g\t%g\t%g\t%g\t%g\t%g\n", abvmag, vmag, BV, Teff, dvmag, dBV); + } +*/ + +event[ipart] = kw; // Evolution type (0 - 15). +SSEMass[ipart] = mt; // Mass in Msol +SSESpin[ipart] = ospin; // Spin in SI ??? [kg*m*m/s] +SSERad[ipart] = r; // Radius in Rsol +SSELum[ipart] = lum; // Luminosity in Lsol +SSETemp[ipart] = Teff; // Temperature + +SSEMV[ipart] = abvmag; // M_V absolute V magnitude +SSEBV[ipart] = BV; // B-V color index + +/* +c STELLAR TYPES - KW +c +c 0 - deeply or fully convective low mass MS star +c 1 - Main Sequence star +c 2 - Hertzsprung Gap +c 3 - First Giant Branch +c 4 - Core Helium Burning +c 5 - First Asymptotic Giant Branch +c 6 - Second Asymptotic Giant Branch +c 7 - Main Sequence Naked Helium star +c 8 - Hertzsprung Gap Naked Helium star +c 9 - Giant Branch Naked Helium star +c 10 - Helium White Dwarf +c 11 - Carbon/Oxygen White Dwarf +c 12 - Oxygen/Neon White Dwarf +c 13 - Neutron Star +c 14 - Black Hole +c 15 - Massless Supernova +*/ + +if ( van_kick == 1 ) // we have a kick ??? + { + +if ( (event_old[ipart] < 10) && ( (event[ipart] == 13) || (event[ipart] == 14) ) ) // NS or BH + { + + if (myRank == rootRank) + { +// printf("KICK: %06d %.6E [Myr] %02d (%02d) %.6E [Mo] %.6E [km/s] [% .3E, % .3E, % .3E] OLD: [% .3E, % .3E, % .3E] %.6E [Mo] \n", ipart, tphysf, kw, event_old[ipart], mt, vkick, vs[0], vs[1], vs[2], v[ipart][0]*(v_norm/km), v[ipart][1]*(v_norm/km), v[ipart][2]*(v_norm/km), mass); + printf("KICK: %06d %.6E %02d %02d %.6E %.6E % .3E % .3E % .3E % .3E % .3E % .3E %.6E \n", ipart, tphysf, kw, event_old[ipart], mt, vkick, vs[0], vs[1], vs[2], v[ipart][0]*(v_norm/km), v[ipart][1]*(v_norm/km), v[ipart][2]*(v_norm/km), mass); + fflush(stdout); + } /* if (myRank == rootRank) */ + + v[ipart][0] += vs[0]*(km/v_norm); + v[ipart][1] += vs[1]*(km/v_norm); + v[ipart][2] += vs[2]*(km/v_norm); + } + + } // we have a kick ??? + + +event_old[ipart] = event[ipart]; + + +tmp = mt*(Msol/m_norm); // return the current mass(t-t0) of the star in NB units + +return(tmp); +} +/****************************************************************************/ +#endif + + +/****************************************************************************/ +void read_data() +{ +inp = fopen(inp_fname,"r"); +fscanf(inp,"%d \n", &diskstep); + +//#ifdef STEVOL +// fscanf(inp,"%d \n", &N); +//#endif +// fscanf(inp,"%d %d %d %d \n", &N, &N_bh, &N_gmc, &N_star); + +fscanf(inp,"%d \n", &N); + +fscanf(inp,"%lE \n", &time_cur); + +for (i=0; i= (mass_frac[k]*m_tot) ) + { + lagr_rad[k] = var_sort[j]; + k++; + } +#endif + } + +fclose(out); + +// write out lagr-rad.dat + +#ifdef LAGR_RAD +out = fopen("lagr-rad.dat","a"); +fprintf(out,"%.6E ", time_cur); +for (k=0; k 100.0) jerk_i[ii][0] = 100.0; + if (ABS(jerk_i[ii][1]) > 100.0) jerk_i[ii][1] = 100.0; + if (ABS(jerk_i[ii][2]) > 100.0) jerk_i[ii][2] = 100.0; + } + +#ifdef SAPPORO + g6calc_firsthalf_(&clusterid, &n_loc, &nn, index_i, x_i, v_i , a_i, jerk_i, p_i, &eps2, h2_i); + g6calc_lasthalf_(&clusterid, &n_loc, &nn, index_i, x_i, v_i, &eps2, h2_i, a_i, jerk_i, p_i); +#else + g6calc_firsthalf(clusterid, n_loc, nn, index_i, x_i, v_i , a_i, jerk_i, p_i, eps2, h2_i); + g6calc_lasthalf(clusterid, n_loc, nn, index_i, x_i, v_i, eps2, h2_i, a_i, jerk_i, p_i); +#endif + + for (ii=0; ii r) ) + { + r1 = r_sc[ii]; r2 = r_sc[ii+1]; + m1 = m_sc[ii]; m2 = m_sc[ii+1]; + p1 = p_sc[ii]; p2 = m_sc[ii+1]; + break; + } + } + +m_tmp = m1 + (r-r1)*(m2-m1)/(r2-r1); +p_tmp = p1 + (r-r1)*(p2-p1)/(r2-r1); + +// if (myRank == rootRank) +// { +// printf("\t \t \t %.6E %.6E \n", r1, r2); +// printf("\t \t \t %.6E %.6E \n", m1, m2); +// printf("\t \t \t %.6E %.6E \n", p1, p2); +// printf("\t \t \t %06d %.6E %.6E %.6E \n", ii, r, m_tmp, p_tmp); +// fflush(stdout); +// } /* if (myRank == rootRank) */ + +*M_R = m_tmp; +*pot_out_R = p_tmp; + +//exit(-1); + +} +#endif +/****************************************************************************/ + +/****************************************************************************/ +void calc_ext_grav_zero() +{ + +#ifdef EXTPOT + +/* Define the external potential for all particles on all nodes */ + +ni = n_act; + +for (i=0; i 100.0) jerk_i[ii][0] = 100.0; + if (ABS(jerk_i[ii][1]) > 100.0) jerk_i[ii][1] = 100.0; + if (ABS(jerk_i[ii][2]) > 100.0) jerk_i[ii][2] = 100.0; + } + + g6calc_firsthalf(clusterid, n_loc, nn, index_i, x_i, v_i , a_i, jerk_i, p_i, eps2, h2_i); + g6calc_lasthalf(clusterid, n_loc, nn, index_i, x_i, v_i, eps2, h2_i, a_i, jerk_i, p_i); + + g6_calls++; +*/ + + for (ii=0; ii R_LIMITS_ALL) && (tmp_rv > 0.0) ) + { + + for (k=0;k<3;k++) + { + v[i][k] *= 1.0E-01; + } /* k */ + + } /* if */ + + } /* i */ + + #endif + + + #ifdef CMCORR + + /* possible CM correction of the initial datafile... */ + + if ( (diskstep == 0) && (time_cur == 0.0) ) cm_corr(); + + #endif + + + printf("\n"); + printf("Begin the calculation of phi-GRAPE program on %03d processors\n", n_proc); + printf("\n"); + #ifdef GMC + printf("N = %06d \t N_GMC = %06d \t eps = %.6E \n", N, N_gmc, eps); + #else + printf("N = %07d \t eps = %.6E \n", N, eps); + #endif + printf("t_beg = %.6E \t t_end = %.6E \n", time_cur, t_end); + printf("dt_disk = %.6E \t dt_contr = %.6E \n", dt_disk, dt_contr); + printf("dt_bh = %.6E \n", dt_bh); + printf("eta = %.6E \n", eta); + printf("\n"); + + #ifdef NORM + printf("Normalization: \n"); + printf("\n"); + printf("m_norm = %.4E [Msol] r_norm = %.4E [pc] \n", m_norm/Msol, r_norm/pc); + printf("v_morm = %.4E [km/s] t_morm = %.4E [Myr] \n", v_norm/km, t_norm/Myr); + printf("\n"); + #endif + + #ifdef EXTPOT + printf("External Potential: \n"); + printf("\n"); + + #ifdef EXTPOT_GAL + printf("m_bulge = %.4E [Msol] a_bulge = %.4E b_bulge = %.4E [kpc] \n", m_bulge*m_norm/Msol, a_bulge*r_norm/kpc, b_bulge*r_norm/kpc); + printf("m_disk = %.4E [Msol] a_disk = %.4E b_disk = %.4E [kpc] \n", m_disk*m_norm/Msol, a_disk*r_norm/kpc, b_disk*r_norm/kpc); + printf("m_halo = %.4E [Msol] a_halo = %.4E b_halo = %.4E [kpc] \n", m_halo*m_norm/Msol, a_halo*r_norm/kpc, b_halo*r_norm/kpc); + #endif + + #ifdef EXTPOT_BH + printf("m_bh = %.4E b_bh = %.4E \n", m_bh, b_bh); + #endif + + #ifdef EXTPOT_GAL_DEH + printf("m_ext = %.6E r_ext = %.6E \t g_ext = %.3E \n", m_ext, r_ext, g_ext); + #endif + + #ifdef EXTPOT_GAL_LOG + printf("v_halo = %.6E r_halo = %.6E \n", v_halo, r_halo); + #endif + + #ifdef EXTPOT_SC + read_SC_mass(); + + printf("EXTPOT_SC: # of points %06d \t M_SC_TOT = %.6E \n", M_SC_DIM-1, m_sc[M_SC_DIM-1]); + #endif + + printf("\n"); + #endif + + + + fflush(stdout); + + + if ( (diskstep == 0) && (time_cur == 0.0) ) + { + + #ifdef SPH_GAS + write_data_SPH(); + #endif + + #ifdef GMC + write_snap_GMC(); + write_cont_GMC(); + #endif + + + out = fopen("contr.dat","w"); + fclose(out); + + #ifdef TIMING + out = fopen("timing.dat","w"); + fclose(out); + #endif + + #ifdef ADD_BH2 + + #ifdef BH_OUT + out = fopen("bh.dat","w"); + fclose(out); + #endif + + #ifdef BH_OUT_NB + out = fopen("bh_nb.dat","w"); + fclose(out); + #endif + + #else + + #ifdef ADD_BH1 + + #ifdef BH_OUT + out = fopen("bh.dat","w"); + fclose(out); + #endif + + #ifdef BH_OUT_NB + out = fopen("bh_nb.dat","w"); + fclose(out); + #endif + + #endif // ADD_BH1 + + #endif // ADD_BH2 + + + #ifdef STARDESTR + + #ifdef ADD_BH2 + + out = fopen("mass-bh.dat","w"); + m_bh1 = m[0]; + m_bh2 = m[1]; + num_bh1 = 0; + num_bh2 = 0; + fprintf(out,"%.8E \t %.8E %06d \t %.8E %06d \n", + time_cur, m_bh1, num_bh1, m_bh2, num_bh2); + fclose(out); + + out = fopen("mass-bh.con","w"); + m_bh1 = m[0]; + m_bh2 = m[1]; + num_bh1 = 0; + num_bh2 = 0; + fprintf(out,"%.8E \t %.8E %06d \t %.8E %06d \n", + time_cur, m_bh1, num_bh1, m_bh2, num_bh2); + fclose(out); + + #else + + #ifdef ADD_BH1 + + out = fopen("mass-bh.dat","w"); + m_bh1 = m[0]; + num_bh1 = 0; + fprintf(out,"%.8E \t %.8E %06d \n", + time_cur, m_bh1, num_bh1); + fclose(out); + + out = fopen("mass-bh.con","w"); + m_bh1 = m[0]; + num_bh1 = 0; + fprintf(out,"%.8E \t %.8E %06d \n", + time_cur, m_bh1, num_bh1); + fclose(out); + + #endif // ADD_BH1 + + #endif // ADD_BH2 + + #endif // STARDESTR + + + #ifdef STARDESTR_EXT + + num_bh = 0; + out = fopen("mass-bh.dat","w"); + fprintf(out,"%.8E \t %.8E \t %06d \n", time_cur, m_bh, num_bh); + fclose(out); + + num_bh = 0; + out = fopen("mass-bh.con","w"); + fprintf(out,"%.8E \t %.8E \t %06d \n", time_cur, m_bh, num_bh); + fclose(out); + + #ifdef BH_OUT_NB_EXT + out = fopen("bh_nb.dat","w"); + fclose(out); + #endif + + #endif // STARDESTR_EXT + + + #ifdef DEBUG_extra + #ifdef LAGR_RAD + out = fopen("lagr-rad.dat","w"); + fclose(out); + #endif + #endif + + + #ifdef BBH_INF + out = fopen("bbh.inf","w"); + fclose(out); + #endif + + + } + else // if (diskstep == 0) + { + + #ifdef STARDESTR + + #ifdef ADD_BH2 + + inp = fopen("mass-bh.con","r"); + fscanf(inp,"%lE %lE %d %lE %d", &tmp, &m_bh1, &num_bh1, &m_bh2, &num_bh2); + fclose(inp); + printf("%.8E \t %.8E %06d \t %.8E %06d \n", tmp, m_bh1, num_bh1, m_bh2, num_bh2); + fflush(stdout); + + #else + + #ifdef ADD_BH1 + + inp = fopen("mass-bh.con","r"); + fscanf(inp,"%lE %lE %d", &tmp, &m_bh1, &num_bh1); + fclose(inp); + printf("%.8E \t %.8E \t %06d \n", tmp, m_bh1, num_bh1); + fflush(stdout); + + #endif // ADD_BH1 + + #endif // ADD_BH2 + + #endif // STARDESTR + + + #ifdef STARDESTR_EXT + + inp = fopen("mass-bh.con","r"); + fscanf(inp,"%lE %lE %d", &tmp, &m_bh, &num_bh); + fclose(inp); + printf("%.8E \t %.8E \t %06d \n", tmp, m_bh, num_bh); + fflush(stdout); + + #endif // STARDESTR_EXT + + + } // if (diskstep == 0) + + + get_CPU_time(&CPU_time_real0, &CPU_time_user0, &CPU_time_syst0); + + } /* if (myRank == rootRank) */ + + + + + #ifdef STEVOL_SSE + //SSE internal parameters (see Hurley, Pols & Tout 2000) + + value1_.neta = 0.5; //Reimers mass-loss coefficent (neta*4x10^-13; 0.5 normally) + value1_.bwind = 0.0; //Binary enhanced mass loss parameter (inactive for single) + value1_.hewind = 1.0; //Helium star mass loss factor (1.0 normally) + value1_.mxns = 3.0; //Maximum NS mass (1.8, nsflag=0; 3.0, nsflag=1) + + points_.pts1 = 0.05; //Time-step parameter in evolution phase: MS (0.05) + points_.pts2 = 0.01; //Time-step parameter in evolution phase: GB, CHeB, AGB, HeGB (0.01) + points_.pts3 = 0.02; //Time-step parameter in evolution phase: HG, HeMS (0.02) + + //value4_.sigma = 190.0; //Kick velocities - standard values... + value4_.sigma = 265.0; //Kick velocities - Hobbs++2005 values... + value4_.bhflag = 1; //bhflag > 0 allows velocity kick at BH formation + + value3_.idum = 19640916; // random number seed !!! + + //BSE internal parameters (see Hurley, Pols & Tout 2002) + + flags_.ceflag = 0; //ceflag > 0 activates spin-energy correction in common-envelope (0) #defunct# + flags_.tflag = 1; //tflag > 0 activates tidal circularisation (1) + flags_.ifflag = 0; //ifflag > 0 uses WD IFMR of HPE, 1995, MNRAS, 272, 800 (0) + flags_.nsflag = 1; //nsflag > 0 takes NS/BH mass from Belczynski et al. 2002, ApJ, 572, 407 (1) + flags_.wdflag = 1; //wdflag > 0 uses modified-Mestel cooling for WDs (0) + + value5_.beta = 0.125; //beta is wind velocity factor: proportional to vwind**2 (1/8) + value5_.xi = 1.0; //xi is the wind accretion efficiency factor (1.0) + value5_.acc2 = 1.5; //acc2 is the Bondi-Hoyle wind accretion factor (3/2) + value5_.epsnov = 0.001; //epsnov is the fraction of accreted matter retained in nova eruption (0.001) + value5_.eddfac = 1.0; //eddfac is Eddington limit factor for mass transfer (1.0) + value5_.gamma = -1.0; //gamma is the angular momentum factor for mass lost during Roche (-1.0) + + value2_.alpha1 = 1.0; //alpha1 is the common-envelope efficiency parameter (1.0) + value2_.lambda = 0.5; //lambda is the binding energy factor for common envelope evolution (0.5) + + #endif // STEVOL_SSE + + + /* Wait to all processors to finish his works... */ + MPI_Barrier(MPI_COMM_WORLD); + + /* Broadcast all useful values to all processors... */ + MPI_Bcast(&N, 1, MPI_INT, rootRank, MPI_COMM_WORLD); + MPI_Bcast(&eps, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + MPI_Bcast(&eta, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + MPI_Bcast(&t_end, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + MPI_Bcast(&dt_disk, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + MPI_Bcast(&dt_contr, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + MPI_Bcast(&dt_bh, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + MPI_Bcast(&time_cur, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + + #ifdef NORM + MPI_Bcast(&m_norm, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + MPI_Bcast(&r_norm, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + MPI_Bcast(&v_norm, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + MPI_Bcast(&t_norm, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + #endif // NORM + + #ifdef EXTPOT + + #ifdef EXTPOT_GAL + MPI_Bcast(&m_bulge, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + MPI_Bcast(&a_bulge, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + MPI_Bcast(&b_bulge, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + + MPI_Bcast(&m_disk, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + MPI_Bcast(&a_disk, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + MPI_Bcast(&b_disk, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + + MPI_Bcast(&m_halo, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + MPI_Bcast(&a_halo, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + MPI_Bcast(&b_halo, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + + #endif + + #ifdef EXTPOT_BH + MPI_Bcast(&m_bh, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + MPI_Bcast(&b_bh, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + #endif + + #ifdef EXTPOT_GAL_DEH + MPI_Bcast(&m_ext, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + MPI_Bcast(&r_ext, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + MPI_Bcast(&g_ext, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + #endif + + #ifdef EXTPOT_GAL_LOG + MPI_Bcast(&v_halo, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + MPI_Bcast(&r_halo, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + + MPI_Bcast(&v2_halo, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + MPI_Bcast(&r2_halo, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + #endif + + #endif // EXTPOT + + + #ifdef STARDESTR + MPI_Bcast(&m_bh1, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + MPI_Bcast(&num_bh1, 1, MPI_INT, rootRank, MPI_COMM_WORLD); + + MPI_Bcast(&m_bh2, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + MPI_Bcast(&num_bh2, 1, MPI_INT, rootRank, MPI_COMM_WORLD); + #endif // STARDESTR + + + #ifdef STARDESTR_EXT + MPI_Bcast(&num_bh, 1, MPI_INT, rootRank, MPI_COMM_WORLD); + #endif // STARDESTR_EXT + + + /* Wait to all processors to finish his works... */ + MPI_Barrier(MPI_COMM_WORLD); + + + + eta_s = eta/ETA_S_CORR; + eta_bh = eta/ETA_BH_CORR; + + eps2 = SQR(eps); + + dt_min = 1.0*pow(2.0, DTMINPOWER); + dt_max = 1.0*pow(2.0, DTMAXPOWER); + + if (dt_disk == dt_contr) + dt_max = dt_contr; + else + dt_max = MIN(dt_disk, dt_contr); + + if (dt_max > 1.0) dt_max = 1.0; + + t_disk = dt_disk*(1.0+floor(time_cur/dt_disk)); + t_contr = dt_contr*(1.0+floor(time_cur/dt_contr)); + t_bh = dt_bh*(1.0+floor(time_cur/dt_bh)); + + + if (myRank == rootRank) + { + printf("t_disk = %.6E t_contr = %.6E t_bh = %.6E \n", t_disk, t_contr, t_bh); + printf("\n"); + fflush(stdout); + } /* if (myRank == rootRank) */ + + #ifdef STEVOL + dt_stevol = dt_max; + t_stevol = dt_stevol*(1.0 + floorl(time_cur/dt_stevol)); + + if (myRank == rootRank) + { + printf("t_stevol = %.6E dt_stevol = %.6E \n", t_stevol, dt_stevol); + printf("\n"); + fflush(stdout); + } /* if (myRank == rootRank) */ + #endif + + #ifdef STEVOL_SSE + dt_stevol = dt_max; + t_stevol = dt_stevol*(1.0 + floorl(time_cur/dt_stevol)); + + if (myRank == rootRank) + { + printf("t_stevol = %.6E dt_stevol = %.6E \n", t_stevol, dt_stevol); + printf("\n"); + fflush(stdout); + } /* if (myRank == rootRank) */ + #endif + + + for (i=0; i BH _softened_ pot, acc & jerk + + tmp_i = calc_force_n_BH(m_bh1, x_bh1, v_bh1, + m_bh2, x_bh2, v_bh2, + eps, + &pot_bh1, a_bh1, adot_bh1, + &pot_bh2, a_bh2, adot_bh2); + + pot[i_bh1] -= pot_bh1; + pot[i_bh2] -= pot_bh2; + + for (k=0;k<3;k++) + { + a[i_bh1][k] -= a_bh1[k]; + a[i_bh2][k] -= a_bh2[k]; + + adot[i_bh1][k] -= adot_bh1[k]; + adot[i_bh2][k] -= adot_bh2[k]; + } + + // calculate and "plus" the new BH <-> BH _unsoftened_ pot, acc, jerk + + tmp_i = calc_force_n_BH(m_bh1, x_bh1, v_bh1, + m_bh2, x_bh2, v_bh2, + eps_BH, + &pot_bh1, a_bh1, adot_bh1, + &pot_bh2, a_bh2, adot_bh2); + + pot[i_bh1] += pot_bh1; + pot[i_bh2] += pot_bh2; + + for (k=0;k<3;k++) + { + a[i_bh1][k] += a_bh1[k]; + a[i_bh2][k] += a_bh2[k]; + + adot[i_bh1][k] += adot_bh1[k]; + adot[i_bh2][k] += adot_bh2[k]; + } + + #endif // ADD_N_BH + + + #ifdef ADD_PN_BH + + // calculate and "plus" the new BH <-> BH : PN1, PN2, PN2.5, PN3, PN3.5 : acc, jerk + + dt_bh_tmp = dt[0]; + + tmp_i = calc_force_pn_BH(m_bh1, x_bh1, v_bh1, s_bh1, + m_bh2, x_bh2, v_bh2, s_bh2, + C_NB, dt_bh_tmp, usedOrNot, + a_pn1, adot_pn1, + a_pn2, adot_pn2); + + for (k=0;k<3;k++) + { + a[i_bh1][k] += a_pn1[1][k] + a_pn1[2][k] + a_pn1[3][k] + a_pn1[4][k] + a_pn1[5][k] + a_pn1[6][k]; + a[i_bh2][k] += a_pn2[1][k] + a_pn2[2][k] + a_pn2[3][k] + a_pn2[4][k] + a_pn2[5][k] + a_pn2[6][k]; + + adot[i_bh1][k] += adot_pn1[1][k] + adot_pn1[2][k] + adot_pn1[3][k] + adot_pn1[4][k] + adot_pn1[5][k] + adot_pn1[6][k]; + adot[i_bh2][k] += adot_pn2[1][k] + adot_pn2[2][k] + adot_pn2[3][k] + adot_pn2[4][k] + adot_pn2[5][k] + adot_pn2[6][k]; + } + + if (myRank == rootRank) + { + if (tmp_i == 505) + { + printf("PN RSDIST: %.8E \t %.8E \n", Timesteps, time_cur); + fflush(stdout); + exit(-1); + } + } + + #endif // ADD_PN_BH + + #endif // ADD_BH2 + + + + #if defined(EXTPOT) || defined(GMC) + calc_ext_grav_zero(); + #endif + + #ifdef GMC + calc_gmc_self_grav(); + calc_ext_gmc_grav(); + #endif + + + /* Wait to all processors to finish his works... */ + MPI_Barrier(MPI_COMM_WORLD); + + + + // sjuda stavim DRAG... + + #ifdef STARDISK + + for (i=0; i dt_max) dt_tmp = dt_max; + + + #ifdef STARDESTR + if (m[i] == 0.0) dt_tmp = dt_max; + #endif + + #ifdef STARDESTR_EXT + if (m[i] == 0.0) dt_tmp = dt_max; + #endif + + dt[i] = dt_tmp; + + + #ifdef DT_MIN_WARNING + if (myRank == 0) + { + if (dt[i] == dt_min) + { + printf("!!! Warning0: dt = dt_min = %.6E \t ind = %07d \n", dt[i], ind[i]); + fflush(stdout); + } + } + #endif + + } /* i */ + + + + + #ifdef ADD_BH2 + + /* define the min. dt over all the part. and set it also for the BH... */ + + min_dt = dt[0]; + + for (i=1; i 0.1) dt[i] = min_dt; + } /* i */ + + #endif // GMC2 + + + #ifdef GMC2222 + + /* define the max. dt for the GMC... */ + + for (i=1; i 0.1) dt[i] = dt_max; + } /* i */ + + #endif // GMC2 + + + + #ifdef ACT_DEF_LL + CreateLinkList(); + #ifdef DEBUG111 + if ( myRank == rootRank ) check_linklist(0); + #endif + #endif + + + + /* Wait to all processors to finish his works... */ + MPI_Barrier(MPI_COMM_WORLD); + + /* Scatter the "local" vectors from "global" */ + MPI_Scatter(dt, n_loc, MPI_DOUBLE, dt_loc, n_loc, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); + + /* Wait to all processors to finish his works... */ + MPI_Barrier(MPI_COMM_WORLD); + + /* load the new values for particles to the local GRAPE's */ + + nj=n_loc; + + /* load the nj particles to the G6 */ + + for (j=0; j 0) + for (int i=0; i BH softened pot, acc & jerk + + tmp_i = calc_force_n_BH(m_bh1, x_bh1, v_bh1, + m_bh2, x_bh2, v_bh2, + eps, + &pot_bh1, a_bh1, adot_bh1, + &pot_bh2, a_bh2, adot_bh2); + + pot_act_new[i_bh1] -= pot_bh1; + pot_act_new[i_bh2] -= pot_bh2; + + for (k=0;k<3;k++) + { + a_act_new[i_bh1][k] -= a_bh1[k]; + a_act_new[i_bh2][k] -= a_bh2[k]; + + adot_act_new[i_bh1][k] -= adot_bh1[k]; + adot_act_new[i_bh2][k] -= adot_bh2[k]; + } + + // calculate and "plus" the new BH <-> BH unsoftened pot, acc, jerk + + tmp_i = calc_force_n_BH(m_bh1, x_bh1, v_bh1, + m_bh2, x_bh2, v_bh2, + eps_BH, + &pot_bh1, a_bh1, adot_bh1, + &pot_bh2, a_bh2, adot_bh2); + + pot_act_new[i_bh1] += pot_bh1; + pot_act_new[i_bh2] += pot_bh2; + + for (k=0;k<3;k++) + { + a_act_new[i_bh1][k] += a_bh1[k]; + a_act_new[i_bh2][k] += a_bh2[k]; + + adot_act_new[i_bh1][k] += adot_bh1[k]; + adot_act_new[i_bh2][k] += adot_bh2[k]; + } + + #endif // ADD_N_BH + + + #ifdef ADD_PN_BH + + // calculate and "plus" the new BH <-> BH : PN1, PN2, PN2.5, PN3, PN3.5 : acc, jerk + + dt_bh_tmp = dt[0]; + + tmp_i = calc_force_pn_BH(m_bh1, x_bh1, v_bh1, s_bh1, + m_bh2, x_bh2, v_bh2, s_bh2, + C_NB, dt_bh_tmp, usedOrNot, + a_pn1, adot_pn1, + a_pn2, adot_pn2); + + for (k=0;k<3;k++) + { + a_act_new[i_bh1][k] += a_pn1[1][k] + a_pn1[2][k] + a_pn1[3][k] + a_pn1[4][k] + a_pn1[5][k] + a_pn1[6][k]; + a_act_new[i_bh2][k] += a_pn2[1][k] + a_pn2[2][k] + a_pn2[3][k] + a_pn2[4][k] + a_pn2[5][k] + a_pn2[6][k]; + + adot_act_new[i_bh1][k] += adot_pn1[1][k] + adot_pn1[2][k] + adot_pn1[3][k] + adot_pn1[4][k] + adot_pn1[5][k] + adot_pn1[6][k]; + adot_act_new[i_bh2][k] += adot_pn2[1][k] + adot_pn2[2][k] + adot_pn2[3][k] + adot_pn2[4][k] + adot_pn2[5][k] + adot_pn2[6][k]; + } + + if (myRank == rootRank) + { + if (tmp_i == 505) + { + printf("PN RSDIST: TS = %.8E \t t = %.8E \n", Timesteps, time_cur); + fflush(stdout); + exit(-1); + } + } + + #endif // ADD_PN_BH + + #endif // ADD_BH2 + + #ifdef EXTPOT + calc_ext_grav(); + #endif + + #ifdef GMC + calc_gmc_self_grav(); + calc_ext_gmc_grav(); + #endif + + + // sjuda stavim DRAG... + + #ifdef STARDISK + + #ifdef TIMING + get_CPU_time(&CPU_tmp_real0, &CPU_tmp_user0, &CPU_tmp_syst0); + #endif + + calc_drag_force(); + + /* E_sd tut opjaty pljusujetsja... */ + + for (i=0; i dt_min) ) + { + power = log(dt_new)/log(2.0) - 1; + + dt_tmp = pow(2.0, (double)power); + } + + + #ifdef STARDISK + + // accretion disk criteria + // sjuda stavim izmenenija DT za schot DRAG pri priblizhenii k ploskosti Z=0 ... + + z_new_drag = x_act_new[i][2] + dt_tmp * v_act_new[i][2]; + r_new_drag2 = SQR(x_act_new[i][0]) + SQR(x_act_new[i][1]); + + if (r_new_drag2 > (R_CRIT*R_CRIT)) + { + hz = HZ; + } + else + { + hz = HZ*(sqrt(r_new_drag2)/R_CRIT); + } + + if (fabs(x_act_new[i][2]) > hz*2.2) + { + + if (z_new_drag * x_act_new[i][2] < 0.0) + { + dt_tmp *= 0.125; + } + else + { + if (fabs(z_new_drag) < hz*1.8) + { + dt_tmp *= 0.5; + } + } + + } + + #endif + + + if ( (dt_new > 2.0*dt_tmp) && + (fmod(min_t, 2.0*dt_tmp) == 0.0) && + (2.0*dt_tmp <= dt_max) ) + { + dt_tmp *= 2.0; + } + + dt_act[i] = dt_tmp; + + t_act[i] = min_t; + + pot_act[i] = pot_act_new[i]; + + for (k=0; k<3; k++) + { + x_act[i][k] = x_act_new[i][k]; + v_act[i][k] = v_act_new[i][k]; + a_act[i][k] = a_act_new[i][k]; + adot_act[i][k] = adot_act_new[i][k]; + } /* k */ + + + #ifdef DT_MIN_WARNING + if (myRank == 0) + { + if (dt_act[i] == dt_min) + { + printf("!!! Warning1: dt_act = dt_min = %.6E \t ind_act = %07d \n", dt[i], ind_act[i]); + fflush(stdout); + } + } + #endif + + + + } /* i */ + + + + + /* define the min. dt over all the act. part. and set it also for the BH... */ + + #ifdef ADD_BH2 + + min_dt = dt_act[0]; + + for (i=1; i 0.1) dt_act[i] = min_dt; + } /* i */ + + + #endif // GMC2 + + + #ifdef GMC2222 + + /* define the max. dt for the GMC... */ + + for (i=1; i 0.1) dt_act[i] = dt_max; + } /* i */ + + #endif // GMC2 + + + + + + + #ifdef BBH_INF + if (myRank == rootRank) + { + + out = fopen("bbh.inf","a"); + + m_bh1 = m_act[i_bh1]; + m_bh2 = m_act[i_bh2]; + + for (k=0;k<3;k++) + { + x_bh1[k] = x_act[i_bh1][k]; + x_bh2[k] = x_act[i_bh2][k]; + + v_bh1[k] = v_act[i_bh1][k]; + v_bh2[k] = v_act[i_bh2][k]; + } + + for (k=0;k<3;k++) + { + x_bbhc[k] = (m_bh1*x_bh1[k] + m_bh2*x_bh2[k])/(m_bh1 + m_bh2); + v_bbhc[k] = (m_bh1*v_bh1[k] + m_bh2*v_bh2[k])/(m_bh1 + m_bh2); + } + + DR2 = SQR(x_bh1[0] - x_bh2[0]) + SQR(x_bh1[1] - x_bh2[1]) + SQR(x_bh1[2] - x_bh2[2]); + DV2 = SQR(v_bh1[0] - v_bh2[0]) + SQR(v_bh1[1] - v_bh2[1]) + SQR(v_bh1[2] - v_bh2[2]); + + EB = -(m_bh1 + m_bh2) / sqrt(DR2) + 0.5 * DV2; + + SEMI_a = -0.5 * (m_bh1 + m_bh2)/EB; + SEMI_a2 = SQR(SEMI_a); + + for (i=2; i= t_stevol) + { + + /* Define the current mass of all star particles... */ + + for (i=0; i= t_stevol) */ + + #ifdef TIMING + get_CPU_time(&CPU_tmp_real, &CPU_tmp_user, &CPU_tmp_syst); + DT_STEVOL += (CPU_tmp_user - CPU_tmp_user0); + #endif + + #endif + + + /* STEVOL_SSE routine on all the nodes */ + + #ifdef STEVOL_SSE + + + #ifdef TIMING + get_CPU_time(&CPU_tmp_real0, &CPU_tmp_user0, &CPU_tmp_syst0); + #endif + + if (time_cur >= t_stevol) + { + + /* Define the current mass of all star particles... */ + + for (i=0; i= t_stevol) */ + + #ifdef TIMING + get_CPU_time(&CPU_tmp_real, &CPU_tmp_user, &CPU_tmp_syst); + DT_STEVOL += (CPU_tmp_user - CPU_tmp_user0); + #endif + + + + + /* Update ALL the new m,r,v "j" part. to the GRAPE/GPU memory */ + + + for (j=0; j= t_bh) + { + + if (myRank == rootRank) + { + + #ifdef BH_OUT + /* Write BH data... */ + write_bh_data(); + #endif + + #ifdef BH_OUT_NB + /* Write BH NB data... */ + write_bh_nb_data(); + #endif + + #ifdef BH_OUT_NB_EXT + /* Write BH NB data... */ + write_bh_nb_data_ext(); + #endif + + } /* if (myRank == rootRank) */ + + t_bh += dt_bh; + } /* if (time_cur >= t_bh) */ + + + + + + if (time_cur >= t_contr) + { + + if (myRank == rootRank) + { + + #ifdef STARDESTR + + #ifdef ADD_BH2 + + out = fopen("mass-bh.dat","a"); + fprintf(out,"%.8E \t %.8E %06d \t %.8E %06d \n", + time_cur, m_bh1, num_bh1, m_bh2, num_bh2); + fclose(out); + + out = fopen("mass-bh.con","w"); + fprintf(out,"%.8E \t %.8E %06d \t %.8E %06d \n", + time_cur, m_bh1, num_bh1, m_bh2, num_bh2); + fclose(out); + + #else + + #ifdef ADD_BH1 + + out = fopen("mass-bh.dat","a"); + fprintf(out,"%.8E \t %.8E %06d \n", + time_cur, m_bh1, num_bh1); + fclose(out); + + out = fopen("mass-bh.con","w"); + fprintf(out,"%.8E \t %.8E %06d \n", + time_cur, m_bh1, num_bh1); + fclose(out); + + #endif // ADD_BH1 + + #endif // ADD_BH2 + + #endif // STARDESTR + + #ifdef STARDESTR_EXT + + out = fopen("phi-GRAPE.ext","w"); + fprintf(out,"%.8E \t %.8E \n", m_bh, b_bh); + fclose(out); + + out = fopen("mass-bh.dat","a"); + fprintf(out,"%.8E \t %.8E \t %06d \n", time_cur, m_bh, num_bh); + fclose(out); + + out = fopen("mass-bh.con","w"); + fprintf(out,"%.8E \t %.8E \t %06d \n", time_cur, m_bh, num_bh); + fclose(out); + + #endif // STARDESTR_EXT + + + + #ifdef ACT_DEF_LL + #ifdef DEBUG111 + if (myRank == rootRank) check_linklist((int)Timesteps); + #endif + #endif + + + energy_contr(); + + #ifdef CMCORR111 + for (i=0; i R_LIMITS_ALL) && (tmp_rv > 0.0) ) + { + + #ifdef EXTPOT + #endif + + for (k=0;k<3;k++) + { + v[i][k] *= 1.0E-01; + } /* k */ + + } /* if */ + + } /* i */ + + + + for (j=0; j= t_contr) */ + + + + + + + + + if (time_cur >= t_disk) + { + + + if (myRank == rootRank) + { + + diskstep++; + + write_snap_data(); + + #ifdef DEBUG_extra + write_snap_extra(); + #endif + + #ifdef SPH_GAS + write_data_SPH(); + #endif + + #ifdef GMC + write_snap_GMC(); + #endif + + } /* if (myRank == rootRank) */ + + #ifdef ETICS_DUMP + sprintf(out_fname, "coeffs.%06d.%02d.dat", diskstep, myRank); + grapite_dump(out_fname, 2); + #endif + + + + + #ifdef LIMITS_NEW + + for (i=0; i 900.0 ) + { + + m[i] = 0.0; + + pot[i] = 0.0; + + #ifdef EXTPOT + pot_ext[i] = 0.0; + #endif + + for (k=0;k<3;k++) + { + x[i][k] = 1000.0 + 1.0*my_rand2(); + v[i][k] = 1.0E-06*my_rand2(); + a[i][k] = 1.0E-06*my_rand2(); + adot[i][k] = 1.0E-06*my_rand2(); + } /* k */ + + t[i] = 2.0*t_end; + + dt[i] = 0.125; + + } /* if */ + + } /* i */ + + + + for (j=0; j= t_disk) */ + + + + #ifdef CPU_TIMELIMIT + if (myRank == rootRank) + { + get_CPU_time(&CPU_time_real, &CPU_time_user, &CPU_time_syst); + tmp_cpu = CPU_time_real-CPU_time_real0; + } /* if (myRank == rootRank) */ + #endif + + + #ifdef ACT_DEF_LL + ModifyLinkList(); + + #ifdef DEBUG111 + if ( (((int)Timesteps)%10000 == 0) && (myRank == rootRank) ) check_linklist((int)Timesteps); + #endif + #endif + + } /* while (time_cur < t_end) */ + + + + /* close the local GRAPE's */ + + #ifdef SAPPORO + g6_close_(&clusterid); + #else + g6_close(clusterid); + #endif + + + /* Wait to all processors to finish his works... */ + MPI_Barrier(MPI_COMM_WORLD); + + MPI_Reduce(&g6_calls, &g6_calls_sum, 1, MPI_DOUBLE, MPI_SUM, rootRank, MPI_COMM_WORLD); + + /* Wait to all processors to finish his works... */ + MPI_Barrier(MPI_COMM_WORLD); + + + if (myRank == rootRank) + { + + /* Write some output for the timestep annalize... */ + + printf("\n"); + printf("Timesteps = %.0f Total sum of integrated part. = %.0f g6_calls on all nodes = %.0f \n", Timesteps, n_act_sum, g6_calls); + printf("\n"); + printf("Real Speed = %.3f GFlops \n", 57.0*N*n_act_sum/(CPU_time_user-CPU_time_user0)/1.0E+09); + fflush(stdout); + + + #ifdef DEBUG111 + tmp_file = fopen("n_act_distr.dat","w"); + + fprintf(tmp_file,"\n"); + fprintf(tmp_file,"Total Timesteps = %.0f Total sum of integrated part. = %.0f g6_calls on all nodes = %.0f \n", Timesteps, n_act_sum, g6_calls); + fprintf(tmp_file,"\n"); + fprintf(tmp_file,"Real Speed = %.3f GFlops \n", 57.0*N*n_act_sum/(CPU_time_user-CPU_time_user0)/1.0E+09); + + for (i=1;i Date: Thu, 5 Mar 2020 17:00:13 -0500 Subject: [PATCH 02/65] removed many ifdefs blocks and associated included c files --- cmd.c | 76 -- def_DEN.c | 38 - def_DEN_STAR.c | 74 -- def_H.c | 85 -- drag_force.c | 185 ---- phigrape.cpp | 2442 +----------------------------------------------- 6 files changed, 5 insertions(+), 2895 deletions(-) delete mode 100644 cmd.c delete mode 100644 def_DEN.c delete mode 100644 def_DEN_STAR.c delete mode 100644 def_H.c delete mode 100644 drag_force.c diff --git a/cmd.c b/cmd.c deleted file mode 100644 index 8d99a68..0000000 --- a/cmd.c +++ /dev/null @@ -1,76 +0,0 @@ - -int cmd(int kstar, double rstar, double lstar, double Rgal, double *abvmag, double *vmag, double *BV, double *Teff, double *dvmag, double *dBV) - { - - double lTeff, BC, kb; - double bvc[8], bcc[8]; - double dbmag; - double BCsun, abvmagsun; - double rand1, rand2, prand; - - kb = 5.6704E-08*0.5*1.3914E9*0.5*1.3914E9/3.846E26; //Stefan-Boltzmann constant in Lsun Rsun^-2 K^-4 - - bvc[0] = -654597.405559323; - bvc[1] = 1099118.61158915; - bvc[2] = -789665.995692672; - bvc[3] = 314714.220932623; - bvc[4] = -75148.4728506455; - bvc[5] = 10751.803394526; - bvc[6] = -853.487897283685; - bvc[7] = 28.9988730655392; - - bcc[0] = -4222907.80590972; - bcc[1] = 7209333.13326442; - bcc[2] = -5267167.04593882; - bcc[3] = 2134724.55938336; - bcc[4] = -518317.954642773; - bcc[5] = 75392.2372207101; - bcc[6] = -6082.7301194776; - bcc[7] = 209.990478646363; - - BCsun = 0.11; //sun's bolometric correction - abvmagsun = 4.83; //sun's absolute V magnitude - - if( rstar && (kstar<14) ) - { - *Teff = pow(lstar/(4.0*Pi*rstar*rstar*kb),0.25); - - if( (*Teff>3000.0) && (*Teff<55000.0) ) - { - lTeff = log10(*Teff); - *BV = bvc[0] + bvc[1]*lTeff + bvc[2]*pow(lTeff,2) + bvc[3]*pow(lTeff,3) + bvc[4]*pow(lTeff,4) + bvc[5]*pow(lTeff,5) + bvc[6]*pow(lTeff,6) + bvc[7]*pow(lTeff,7); - BC = bcc[0] + bcc[1]*lTeff + bcc[2]*pow(lTeff,2) + bcc[3]*pow(lTeff,3) + bcc[4]*pow(lTeff,4) + bcc[5]*pow(lTeff,5) + bcc[6]*pow(lTeff,6) + bcc[7]*pow(lTeff,7); - if(lstar) *abvmag = -2.5*log10(lstar)-BC+BCsun+abvmagsun; - *vmag = *abvmag + 5.0*log10(Rgal) - 5.0; - - do{ - rand1 = 2.0*drand48()-1.0; - rand2 = 2.0*drand48()-1.0; - } while (rand1*rand1+rand2*rand2 > 1.0); - - prand = sqrt(-2.0*log(rand1*rand1+rand2*rand2)/(rand1*rand1+rand2*rand2)); - *dvmag = rand1*prand*sqrt(pow(0.02,2) + pow(0.07*pow(10.0, 0.4*(*vmag-25.0)),2)); - dbmag = rand2*prand*sqrt(pow(0.02,2) + pow(0.07*pow(10.0, 0.4*(*vmag-25.0)),2)); - *dBV = *dvmag + dbmag; - } - else - { - *vmag = 9999.9; - *abvmag = 9999.9; - *BV = 9999.9; - *dvmag = 0.0; - *dBV = 0.0; - } - } - else - { - *Teff = 0.0; - *vmag = 9999.9; - *abvmag = 9999.9; - *BV = 9999.9; - *dvmag = 0.0; - *dBV = 0.0; - } - - return(0); -} diff --git a/def_DEN.c b/def_DEN.c deleted file mode 100644 index 7cb217b..0000000 --- a/def_DEN.c +++ /dev/null @@ -1,38 +0,0 @@ - -/*************************************************************************/ -/*************************************************************************/ -/*************************************************************************/ - -void DEF_DEN(double x_gas[][3], double m_gas[], double h_gas[], int sosed_gas[][NB], double DEN_gas[]) -{ - -double Xij, Yij, Zij, Rij, tmp; - -/* SPH style */ - -for(i=0;i= 0.0) && (v <= 1.0) ) - { - tmp = 1.0 - 1.5*v2 + 0.75*v3; - } - else - { - if( (v > 1.0) && (v < 2.0) ) - { - tmp = 0.25*(2.0-v)*(2.0-v)*(2.0-v); - } - else - { - tmp = 0.0; /* if ( v >= 2.0 ) */ - } - } - - tmp = 1.0/(Pi*h*h*h)*tmp; - - return(tmp); - -} - -/*************************************************************************/ - -void DEF_H(double x_gas[][3], double h_gas[], int sosed_gas[][NB]) -{ - -int sosed_tmp[N_GAS_MAX]; -double Xij, Yij, Zij; - -for(i=0;i N_GAS_MAX vsegda ! -double x_star, y_star, z_star, DEN_star; -double h_min = 1.0E-04, h_max = 1.0; - -#include "def_H.c" -#include "def_DEN.c" -#include "def_DEN_STAR.c" - -#endif // SPH_GAS - -#include "drag_force.c" - -// calculate the SG for the set of active particles which is deepley INSIDE the EXT BH infl. rad. -// EXPERIMENTAL feature !!! - -//int SG_CALC = 0; -//double summ_tmp_r = 0.0, aver_tmp_r = 0.0, R_INT_CUT = 1.0E-03; - -#endif // STARDISK - - - -/* GMC data... */ - -#ifdef GMC - -double dt_gmc, E_pot_gmc, E_pot_gmc_gmc, E_pot_ext_gmc, E_kin_gmc; - -#define N_gmc_MAX (500) - -int N_gmc, ind_gmc[N_gmc_MAX], name_gmc[N_gmc_MAX]; - -double m_gmc[N_gmc_MAX], pot_gmc_gmc[N_gmc_MAX], pot_ext_gmc[N_gmc_MAX], - x_gmc[N_gmc_MAX][3], v_gmc[N_gmc_MAX][3], a_gmc[N_gmc_MAX][3], - eps_gmc[N_gmc_MAX]; - -double pot_gmc[N_MAX]; - -#endif // GMC - - /****************************************************************************/ /****************************************************************************/ @@ -788,349 +603,18 @@ gettimeofday(&tv, NULL); } /****************************************************************************/ -#ifdef STEVOL -/****************************************************************************/ -double t_dead(double m, double Z) -/* -m - mass of the star (in Msol) -Z - metallicity (absolut values - i.e. Zsol = 0.0122) -t - return value of star lifetime (in Year) - -Raiteri, Villata & Navarro, 1996, A&A, 315, 105 -*/ -{ -double a0, a1, a2, lZ, lm, tmp=0.0; - -m *= (m_norm/Msol); - -lZ = log10(Z); -lm = log10(m); - -a0 = 10.130 + 0.07547*lZ - 0.008084*lZ*lZ; -a1 = -4.424 - 0.79390*lZ - 0.118700*lZ*lZ; -a2 = 1.262 + 0.33850*lZ + 0.054170*lZ*lZ; - -tmp = a0 + a1*lm + a2*lm*lm; - -tmp = pow(10.0,tmp); - -tmp *= (Year/t_norm); - -return(tmp); -} -/****************************************************************************/ - -/****************************************************************************/ -double m_loss_old(double m, double Z) -/* -m - initial mass of the star (in Msol) -Z - metallicity (e.g. Zsol = 0.02) -m_ret - returned maass to ISM from the star (in Msol) - -approx. from data of van den Hoek & Groenewegen, 1997, A&AS, 123, 305 -*/ -{ -double tmp=0.0; - -m *= (m_norm/Msol); - -// tmp = (-0.46168 + 0.912274 * m); // first approx. - -tmp = -0.420542*pow(Z, -0.0176601) + (0.901495 + 0.629441*Z) * m; - -tmp *= (Msol/m_norm); - -return(tmp); -} -/****************************************************************************/ - -/****************************************************************************/ -double m_curr_old(double m0, double Z, double t0, double t) -{ -double td, ml, tmp=0.0; - -td = t_dead(m0, Z); -ml = m_loss_old(m0, Z); - -if ( (t-t0) < td ) - { - tmp = m0; // instant mass loss -// tmp = m0 - (t-t0)/(td-t0) * ml; // linear mass loss - } -else - { - tmp = m0 - ml; - - if (event[i] == 0) - { - num_dead++; - event[i] = 1; - } - - } /* if ( (t-t0) < td ) */ - -return(tmp); -} -/****************************************************************************/ - -/****************************************************************************/ -double m_loss(double m, double Z) -/* -m - initial mass of the star (in norm. units) -Z - metallicity (absolut value - i.e. Zsol = 0.0122) -m_loss - returned maass to ISM from the star (in norm. units) -*/ -{ -double tmp=0.0; - -m *= (m_norm/Msol); - -if ( m < 8.0) - { -// approx. from data of van den Hoek & Groenewegen, 1997, A&AS, 123, 305 - -// tmp = (-0.46168 + 0.912274 * m); // first approx. - tmp = -0.420542*pow(Z, -0.0176601) + (0.901495 + 0.629441*Z) * m; // second approx. - } -else - { -// approx. from data of Woosley & Weaver, 1995, ApJS, 110, 181 - -// tmp = 0.813956*pow(m, 1.04214); - tmp = 0.813956*pow(m, 1.04); - } - -tmp *= (Msol/m_norm); - -return(tmp); -} -/****************************************************************************/ - -/****************************************************************************/ -double m_curr(double m0, double Z, double t0, double t) -{ -double td, ml, tmp=0.0; - -tmp = m0; - -if ( event[i] == 0 ) - { - - td = t_dead(m0, Z); - - if ( (t-t0) > td ) - { - - ml = m_loss(m0, Z); - - tmp = m0 - ml; - - num_dead++; - -// wd http://en.wikipedia.org/wiki/Chandrasekhar_limit 1.38 - - if ( tmp * (m_norm/Msol) < 1.38 ) - { - event[i] = 1; - } - else - { - -// ns http://en.wikipedia.org/wiki/Neutron_stars 1.38 - ~2.0 ??? - - if ( tmp * (m_norm/Msol) > 1.38 ) event[i] = 2; - -// bh http://en.wikipedia.org/wiki/Tolman-Oppenheimer-Volkoff_limit ~1.5 - ~3.0 ??? - - if ( tmp * (m_norm/Msol) > 2.00 ) event[i] = 3; - - } - - } /* if ( (t-t0) > td ) */ - - } /* if ( event[i] == 0 ) */ - -return(tmp); -} -/****************************************************************************/ -#endif - - -#ifdef STEVOL_SSE -/****************************************************************************/ -double m_curr(int ipart, double m0, double Z, double t0, double t) -{ -//set up parameters and variables for SSE (Hurley, Pols & Tout 2002) -int kw=0; //stellar type -double mass; //initial mass -double mt=0.0; //actual mass -double r=0.0; //radius -double lum=0.0; //luminosity -double mc=0.0; //core mass -double rc=0.0; //core radius -double menv=0.0; //envelope mass -double renv=0.0; //envelope radius -double ospin=0.0; //spin -double epoch=0.0; //time spent in current evolutionary state -double tms=0.0; //main-sequence lifetime -double tphys; //initial age -double tphysf; //final age -double dtp=0.0; //data store value, if dtp>tphys no data will be stored -double z; //metallicity -double zpars[20]; //metallicity parameters -double vkick=0.0; //kick velocity for compact remnants -double vs[3]; //kick velocity componets - -// M_V_[mag] V_[mag] B-V_[mag] T_eff_[K] dV_[mag] d(B-V) -double abvmag, vmag, BV, Teff, dvmag, dBV; - -mass = m0*(m_norm/Msol); // m0[i] initial mass of the stars Msol -mt = mass; // current mass for output in Msol -tphys = t0*(t_norm/Myr); // t0[i] time of the star formation Myr -tphysf = t*(t_norm/Myr); // t[i] current time for the star Myr -dtp = 0.0; // output parameter, just set to 0.0 !!! -z = Z; // ZZZ[i] of the star - -/* -if (ipart > 9995) - { -printf("Initial parameters: \n"); -printf("M = %g [Mo] \n", mass); -printf("Z = %g \n", z); -printf("kw = %d \n", kw); -printf("spin = %g \n", ospin); -printf("epoch = %g [Myr] \n", epoch); -printf("t_beg = %g [Myr] \n", tphys); -printf("t_end = %g [Myr] \n", tphysf); -printf("R = %g [R_o] \n", r); -printf("L = %g [L_o] \n", lum); -printf("V_kick = %g [km/s] \n", vkick); - } -*/ - -for (k=0; k<20; k++) zpars[k] = 0; -zcnsts_(&z,zpars); //get metallicity parameters - -evolv1_(&kw, &mass, &mt, &r, &lum, &mc, &rc, &menv, &renv, &ospin, &epoch, &tms, &tphys, &tphysf, &dtp, &z, zpars, &vkick, vs); -cmd(kw, r, lum, Rgal, &abvmag, &vmag, &BV, &Teff, &dvmag, &dBV); - -/* -if (ipart > 9995) - { -printf("Final parameters: \n"); -printf("M = %g [Mo] \n", mt); -printf("Z = %g \n", z); -printf("kw = %d \n", kw); -printf("spin = %g \n", ospin); -printf("epoch = %g [Myr] \n", epoch); -printf("t_beg = %g [Myr] \n", tphys); -printf("t_end = %g [Myr] \n", tphysf); -printf("R = %g [R_o] \n", r); -printf("L = %g [L_o] \n", lum); -printf("V_kick = %g [km/s] \n", vkick); -printf("M_V_[mag]\tV_[mag]\t\tB-V_[mag]\tT_eff_[K]\tdV_[mag]\td(B-V)\n"); -printf("%.3E\t%.3E\t%.3E\t%.3E\t%.3E\t%.3E\n", abvmag, vmag, BV, Teff, dvmag, dBV); -// printf("%g\t%g\t%g\t%g\t%g\t%g\n", abvmag, vmag, BV, Teff, dvmag, dBV); - } -*/ - -event[ipart] = kw; // Evolution type (0 - 15). -SSEMass[ipart] = mt; // Mass in Msol -SSESpin[ipart] = ospin; // Spin in SI ??? [kg*m*m/s] -SSERad[ipart] = r; // Radius in Rsol -SSELum[ipart] = lum; // Luminosity in Lsol -SSETemp[ipart] = Teff; // Temperature - -SSEMV[ipart] = abvmag; // M_V absolute V magnitude -SSEBV[ipart] = BV; // B-V color index - -/* -c STELLAR TYPES - KW -c -c 0 - deeply or fully convective low mass MS star -c 1 - Main Sequence star -c 2 - Hertzsprung Gap -c 3 - First Giant Branch -c 4 - Core Helium Burning -c 5 - First Asymptotic Giant Branch -c 6 - Second Asymptotic Giant Branch -c 7 - Main Sequence Naked Helium star -c 8 - Hertzsprung Gap Naked Helium star -c 9 - Giant Branch Naked Helium star -c 10 - Helium White Dwarf -c 11 - Carbon/Oxygen White Dwarf -c 12 - Oxygen/Neon White Dwarf -c 13 - Neutron Star -c 14 - Black Hole -c 15 - Massless Supernova -*/ - -if ( van_kick == 1 ) // we have a kick ??? - { - -if ( (event_old[ipart] < 10) && ( (event[ipart] == 13) || (event[ipart] == 14) ) ) // NS or BH - { - - if (myRank == rootRank) - { -// printf("KICK: %06d %.6E [Myr] %02d (%02d) %.6E [Mo] %.6E [km/s] [% .3E, % .3E, % .3E] OLD: [% .3E, % .3E, % .3E] %.6E [Mo] \n", ipart, tphysf, kw, event_old[ipart], mt, vkick, vs[0], vs[1], vs[2], v[ipart][0]*(v_norm/km), v[ipart][1]*(v_norm/km), v[ipart][2]*(v_norm/km), mass); - printf("KICK: %06d %.6E %02d %02d %.6E %.6E % .3E % .3E % .3E % .3E % .3E % .3E %.6E \n", ipart, tphysf, kw, event_old[ipart], mt, vkick, vs[0], vs[1], vs[2], v[ipart][0]*(v_norm/km), v[ipart][1]*(v_norm/km), v[ipart][2]*(v_norm/km), mass); - fflush(stdout); - } /* if (myRank == rootRank) */ - - v[ipart][0] += vs[0]*(km/v_norm); - v[ipart][1] += vs[1]*(km/v_norm); - v[ipart][2] += vs[2]*(km/v_norm); - } - - } // we have a kick ??? - - -event_old[ipart] = event[ipart]; - - -tmp = mt*(Msol/m_norm); // return the current mass(t-t0) of the star in NB units - -return(tmp); -} -/****************************************************************************/ -#endif - - /****************************************************************************/ void read_data() { inp = fopen(inp_fname,"r"); fscanf(inp,"%d \n", &diskstep); -//#ifdef STEVOL -// fscanf(inp,"%d \n", &N); -//#endif -// fscanf(inp,"%d %d %d %d \n", &N, &N_bh, &N_gmc, &N_star); - fscanf(inp,"%d \n", &N); fscanf(inp,"%lE \n", &time_cur); for (i=0; i= (mass_frac[k]*m_tot) ) - { - lagr_rad[k] = var_sort[j]; - k++; - } -#endif - } - -fclose(out); - -// write out lagr-rad.dat - -#ifdef LAGR_RAD -out = fopen("lagr-rad.dat","a"); -fprintf(out,"%.6E ", time_cur); -for (k=0; k 0 allows velocity kick at BH formation - - value3_.idum = 19640916; // random number seed !!! - - //BSE internal parameters (see Hurley, Pols & Tout 2002) - - flags_.ceflag = 0; //ceflag > 0 activates spin-energy correction in common-envelope (0) #defunct# - flags_.tflag = 1; //tflag > 0 activates tidal circularisation (1) - flags_.ifflag = 0; //ifflag > 0 uses WD IFMR of HPE, 1995, MNRAS, 272, 800 (0) - flags_.nsflag = 1; //nsflag > 0 takes NS/BH mass from Belczynski et al. 2002, ApJ, 572, 407 (1) - flags_.wdflag = 1; //wdflag > 0 uses modified-Mestel cooling for WDs (0) - - value5_.beta = 0.125; //beta is wind velocity factor: proportional to vwind**2 (1/8) - value5_.xi = 1.0; //xi is the wind accretion efficiency factor (1.0) - value5_.acc2 = 1.5; //acc2 is the Bondi-Hoyle wind accretion factor (3/2) - value5_.epsnov = 0.001; //epsnov is the fraction of accreted matter retained in nova eruption (0.001) - value5_.eddfac = 1.0; //eddfac is Eddington limit factor for mass transfer (1.0) - value5_.gamma = -1.0; //gamma is the angular momentum factor for mass lost during Roche (-1.0) - - value2_.alpha1 = 1.0; //alpha1 is the common-envelope efficiency parameter (1.0) - value2_.lambda = 0.5; //lambda is the binding energy factor for common envelope evolution (0.5) - - #endif // STEVOL_SSE - - /* Wait to all processors to finish his works... */ MPI_Barrier(MPI_COMM_WORLD); @@ -4655,31 +2778,6 @@ int main(int argc, char *argv[]) fflush(stdout); } /* if (myRank == rootRank) */ - #ifdef STEVOL - dt_stevol = dt_max; - t_stevol = dt_stevol*(1.0 + floorl(time_cur/dt_stevol)); - - if (myRank == rootRank) - { - printf("t_stevol = %.6E dt_stevol = %.6E \n", t_stevol, dt_stevol); - printf("\n"); - fflush(stdout); - } /* if (myRank == rootRank) */ - #endif - - #ifdef STEVOL_SSE - dt_stevol = dt_max; - t_stevol = dt_stevol*(1.0 + floorl(time_cur/dt_stevol)); - - if (myRank == rootRank) - { - printf("t_stevol = %.6E dt_stevol = %.6E \n", t_stevol, dt_stevol); - printf("\n"); - fflush(stdout); - } /* if (myRank == rootRank) */ - #endif - - for (i=0; i 0.1) dt[i] = min_dt; - } /* i */ - - #endif // GMC2 - - - #ifdef GMC2222 - - /* define the max. dt for the GMC... */ - - for (i=1; i 0.1) dt[i] = dt_max; - } /* i */ - - #endif // GMC2 - - - #ifdef ACT_DEF_LL CreateLinkList(); - #ifdef DEBUG111 - if ( myRank == rootRank ) check_linklist(0); - #endif #endif @@ -5311,45 +3236,6 @@ int main(int argc, char *argv[]) g6_flush_jp_buffer(clusterid); #endif - - - #ifdef STEVOL_SSE - /* Define the current mass of all star particles... */ - - for (i=0; i (R_CRIT*R_CRIT)) - { - hz = HZ; - } - else - { - hz = HZ*(sqrt(r_new_drag2)/R_CRIT); - } - - if (fabs(x_act_new[i][2]) > hz*2.2) - { - - if (z_new_drag * x_act_new[i][2] < 0.0) - { - dt_tmp *= 0.125; - } - else - { - if (fabs(z_new_drag) < hz*1.8) - { - dt_tmp *= 0.5; - } - } - - } - - #endif - - if ( (dt_new > 2.0*dt_tmp) && (fmod(min_t, 2.0*dt_tmp) == 0.0) && (2.0*dt_tmp <= dt_max) ) @@ -5989,55 +3778,6 @@ int main(int argc, char *argv[]) - #ifdef GMC - - min_dt = dt_act[0]; - - for (i=1; i 0.1) dt_act[i] = min_dt; - } /* i */ - - - #endif // GMC2 - - - #ifdef GMC2222 - - /* define the max. dt for the GMC... */ - - for (i=1; i 0.1) dt_act[i] = dt_max; - } /* i */ - - #endif // GMC2 - - - - - - #ifdef BBH_INF if (myRank == rootRank) { @@ -6354,113 +4094,6 @@ int main(int argc, char *argv[]) n_act_sum += n_act; n_act_distr[n_act-1]++; - - /* STEVOL routine on all the nodes */ - - #ifdef STEVOL - - #ifdef TIMING - get_CPU_time(&CPU_tmp_real0, &CPU_tmp_user0, &CPU_tmp_syst0); - #endif - - if (time_cur >= t_stevol) - { - - /* Define the current mass of all star particles... */ - - for (i=0; i= t_stevol) */ - - #ifdef TIMING - get_CPU_time(&CPU_tmp_real, &CPU_tmp_user, &CPU_tmp_syst); - DT_STEVOL += (CPU_tmp_user - CPU_tmp_user0); - #endif - - #endif - - - /* STEVOL_SSE routine on all the nodes */ - - #ifdef STEVOL_SSE - - - #ifdef TIMING - get_CPU_time(&CPU_tmp_real0, &CPU_tmp_user0, &CPU_tmp_syst0); - #endif - - if (time_cur >= t_stevol) - { - - /* Define the current mass of all star particles... */ - - for (i=0; i= t_stevol) */ - - #ifdef TIMING - get_CPU_time(&CPU_tmp_real, &CPU_tmp_user, &CPU_tmp_syst); - DT_STEVOL += (CPU_tmp_user - CPU_tmp_user0); - #endif - - - - - /* Update ALL the new m,r,v "j" part. to the GRAPE/GPU memory */ - - - for (j=0; j= t_bh) { @@ -6547,15 +4180,6 @@ int main(int argc, char *argv[]) #endif // STARDESTR_EXT - - - #ifdef ACT_DEF_LL - #ifdef DEBUG111 - if (myRank == rootRank) check_linklist((int)Timesteps); - #endif - #endif - - energy_contr(); #ifdef CMCORR111 @@ -6576,12 +4200,6 @@ int main(int argc, char *argv[]) write_cont_data(); - #ifdef GMC - write_cont_GMC(); - #endif - - - /* possible OUT for timing !!! */ #ifdef TIMING @@ -6608,24 +4226,6 @@ int main(int argc, char *argv[]) fclose(out); #endif - - - #ifdef DEBUG111 - tmp_file = fopen("n_act_distr.dat","w"); - - fprintf(tmp_file,"\n"); - fprintf(tmp_file,"Total Timesteps = %.0f Total sum of integrated part. = %.0f g6_calls on all nodes = %.0f \n", Timesteps, n_act_sum, g6_calls); - fprintf(tmp_file,"\n"); - fprintf(tmp_file,"Real Speed = %.3f GFlops \n", 57.0*N*n_act_sum/(CPU_time_user-CPU_time_user0)/1.0E+09); - - for (i=1;i Date: Thu, 5 Mar 2020 23:48:08 -0500 Subject: [PATCH 03/65] mostly fixed indentation in main --- phigrape.cpp | 2644 +++++++++++++++++++++----------------------------- 1 file changed, 1126 insertions(+), 1518 deletions(-) diff --git a/phigrape.cpp b/phigrape.cpp index c747a9e..33c243f 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -58,19 +58,19 @@ Last redaction : 2019.04.16 12:55 //#define ADD_BH1 // add the Single BH -// #define ADD_BH2 // add the Binary BH's -// #define ADD_N_BH // eps_BH = 0.0, but added only the Newtonian forces -// #define ADD_PN_BH // extra - added also the Post-Newton forces -// #define ADD_SPIN_BH // extra - added the SPIN for the BH's - DEFAULT !!! +//#define ADD_BH2 // add the Binary BH's +//#define ADD_N_BH // eps_BH = 0.0, but added only the Newtonian forces +//#define ADD_PN_BH // extra - added also the Post-Newton forces +//#define ADD_SPIN_BH // extra - added the SPIN for the BH's - DEFAULT !!! -// #define BH_OUT // extra output for BH's (live) -// #define BH_OUT_NB // extra output for the BH's neighbours (live) +//#define BH_OUT // extra output for BH's (live) +//#define BH_OUT_NB // extra output for the BH's neighbours (live) -// #define BBH_INF // BBH influence sphere... -// #define R_INF 10.0 // Factor for the influence sphere... if ( R < R_INF * DR_BBH ) -// #define R_INF2 (R_INF*R_INF) +//#define BBH_INF // BBH influence sphere... +//#define R_INF 10.0 // Factor for the influence sphere... if ( R < R_INF * DR_BBH ) +//#define R_INF2 (R_INF*R_INF) -// #define DT_MIN_WARNING // dt < dt_min warning !!! +//#define DT_MIN_WARNING // dt < dt_min warning !!! //#define BH_OUT_NB_EXT // extra output for the BH's neighbours (external) @@ -137,7 +137,7 @@ Last redaction : 2019.04.16 12:55 //#define AMD -// #define ACT_DEF_LL +//#define ACT_DEF_LL #if defined(ACT_DEF_LL) && defined(ACT_DEF_GRAPITE) #error "Contradicting preprocessor flags!" @@ -310,7 +310,6 @@ FILE *inp, *out, *tmp_file, *dbg; double CPU_time_real0, CPU_time_user0, CPU_time_syst0; double CPU_time_real, CPU_time_user, CPU_time_syst; - #ifdef TIMING double CPU_tmp_real0, CPU_tmp_user0, CPU_tmp_syst0; @@ -404,12 +403,10 @@ double r_sc[M_SC_DIM], m_sc[M_SC_DIM], p_sc[M_SC_DIM]; double M_R, pot_out_R; #endif - double pot_ext[N_MAX], pot_act_ext[N_MAX]; // for all EXTPOT #endif - int i_bh, i_bh1, i_bh2, num_bh = 0, num_bh1 = 0, num_bh2 = 0; @@ -418,7 +415,6 @@ double m_bh, m_bh1, m_bh2, b_bh, x_ij, y_ij, z_ij, vx_ij, vy_ij, vz_ij, rv_ij; - #ifdef BBH_INF int inf_event[N_MAX]; double x_bbhc[3], v_bbhc[3], DR2, tmp_r2; @@ -581,7 +577,6 @@ struct rusage xxx; double sec_u, microsec_u, sec_s, microsec_s; struct timeval tv; - getrusage(RUSAGE_SELF,&xxx); sec_u = xxx.ru_utime.tv_sec; @@ -666,7 +661,6 @@ fclose(out); } /****************************************************************************/ - /****************************************************************************/ void write_bh_data() { @@ -764,7 +758,6 @@ fprintf(out,"%.16E \t %.8E \t % .16E % .16E % .16E \t %.16E \t % .16E % .16E % . #endif // ADD_N_BH - /* 2nd BH */ // i=N-1; @@ -860,7 +853,6 @@ fclose(out); #else - #ifdef ADD_BH1 out = fopen("bh.dat","a"); @@ -1111,8 +1103,6 @@ fclose(out); #endif /****************************************************************************/ - - /****************************************************************************/ void calc_self_grav_zero() { @@ -1198,7 +1188,6 @@ for (i=0; i r) ) @@ -1327,7 +1313,6 @@ for (i=0; i R_LIMITS_ALL) && (tmp_rv > 0.0) ) - { - - for (k=0;k<3;k++) - { - v[i][k] *= 1.0E-01; - } /* k */ + /* possible coordinate & velocity limits for ALL particles !!! */ +#ifdef LIMITS_ALL_BEG + for (i=0; i R_LIMITS_ALL) && (tmp_rv > 0.0) ) { + for (k=0;k<3;k++) { + v[i][k] *= 1.0E-01; + } /* k */ } /* if */ - } /* i */ +#endif - #endif - - - #ifdef CMCORR - +#ifdef CMCORR /* possible CM correction of the initial datafile... */ - if ( (diskstep == 0) && (time_cur == 0.0) ) cm_corr(); - - #endif - - +#endif printf("\n"); printf("Begin the calculation of phi-GRAPE program on %03d processors\n", n_proc); printf("\n"); @@ -2466,212 +2358,189 @@ int main(int argc, char *argv[]) printf("eta = %.6E \n", eta); printf("\n"); - #ifdef NORM +#ifdef NORM printf("Normalization: \n"); printf("\n"); printf("m_norm = %.4E [Msol] r_norm = %.4E [pc] \n", m_norm/Msol, r_norm/pc); printf("v_morm = %.4E [km/s] t_morm = %.4E [Myr] \n", v_norm/km, t_norm/Myr); printf("\n"); - #endif +#endif - #ifdef EXTPOT +#ifdef EXTPOT printf("External Potential: \n"); printf("\n"); - #ifdef EXTPOT_GAL +#ifdef EXTPOT_GAL printf("m_bulge = %.4E [Msol] a_bulge = %.4E b_bulge = %.4E [kpc] \n", m_bulge*m_norm/Msol, a_bulge*r_norm/kpc, b_bulge*r_norm/kpc); printf("m_disk = %.4E [Msol] a_disk = %.4E b_disk = %.4E [kpc] \n", m_disk*m_norm/Msol, a_disk*r_norm/kpc, b_disk*r_norm/kpc); printf("m_halo = %.4E [Msol] a_halo = %.4E b_halo = %.4E [kpc] \n", m_halo*m_norm/Msol, a_halo*r_norm/kpc, b_halo*r_norm/kpc); - #endif +#endif - #ifdef EXTPOT_BH +#ifdef EXTPOT_BH printf("m_bh = %.4E b_bh = %.4E \n", m_bh, b_bh); - #endif +#endif - #ifdef EXTPOT_GAL_DEH +#ifdef EXTPOT_GAL_DEH printf("m_ext = %.6E r_ext = %.6E \t g_ext = %.3E \n", m_ext, r_ext, g_ext); - #endif +#endif - #ifdef EXTPOT_GAL_LOG +#ifdef EXTPOT_GAL_LOG printf("v_halo = %.6E r_halo = %.6E \n", v_halo, r_halo); - #endif +#endif - #ifdef EXTPOT_SC +#ifdef EXTPOT_SC read_SC_mass(); - printf("EXTPOT_SC: # of points %06d \t M_SC_TOT = %.6E \n", M_SC_DIM-1, m_sc[M_SC_DIM-1]); - #endif + printf("EXTPOT_SC:# of points %06d \t M_SC_TOT = %.6E \n", M_SC_DIM-1, m_sc[M_SC_DIM-1]); +#endif printf("\n"); - #endif - - +#endif fflush(stdout); + if ( (diskstep == 0) && (time_cur == 0.0) ) { + out = fopen("contr.dat","w"); + fclose(out); - if ( (diskstep == 0) && (time_cur == 0.0) ) - { +#ifdef TIMING + out = fopen("timing.dat","w"); + fclose(out); +#endif - out = fopen("contr.dat","w"); - fclose(out); +#ifdef ADD_BH2 - #ifdef TIMING - out = fopen("timing.dat","w"); - fclose(out); - #endif +#ifdef BH_OUT + out = fopen("bh.dat","w"); + fclose(out); +#endif - #ifdef ADD_BH2 +#ifdef BH_OUT_NB + out = fopen("bh_nb.dat","w"); + fclose(out); +#endif - #ifdef BH_OUT - out = fopen("bh.dat","w"); - fclose(out); - #endif +#else - #ifdef BH_OUT_NB - out = fopen("bh_nb.dat","w"); - fclose(out); - #endif +#ifdef ADD_BH1 - #else +#ifdef BH_OUT + out = fopen("bh.dat","w"); + fclose(out); +#endif - #ifdef ADD_BH1 +#ifdef BH_OUT_NB + out = fopen("bh_nb.dat","w"); + fclose(out); +#endif - #ifdef BH_OUT - out = fopen("bh.dat","w"); - fclose(out); - #endif +#endif // ADD_BH1 - #ifdef BH_OUT_NB - out = fopen("bh_nb.dat","w"); - fclose(out); - #endif +#endif // ADD_BH2 - #endif // ADD_BH1 +#ifdef STARDESTR - #endif // ADD_BH2 +#ifdef ADD_BH2 + out = fopen("mass-bh.dat","w"); + m_bh1 = m[0]; + m_bh2 = m[1]; + num_bh1 = 0; + num_bh2 = 0; + fprintf(out,"%.8E \t %.8E %06d \t %.8E %06d \n", + time_cur, m_bh1, num_bh1, m_bh2, num_bh2); + fclose(out); + out = fopen("mass-bh.con","w"); + m_bh1 = m[0]; + m_bh2 = m[1]; + num_bh1 = 0; + num_bh2 = 0; + fprintf(out,"%.8E \t %.8E %06d \t %.8E %06d \n", + time_cur, m_bh1, num_bh1, m_bh2, num_bh2); + fclose(out); +#else - #ifdef STARDESTR +#ifdef ADD_BH1 - #ifdef ADD_BH2 + out = fopen("mass-bh.dat","w"); + m_bh1 = m[0]; + num_bh1 = 0; + fprintf(out,"%.8E \t %.8E %06d \n", + time_cur, m_bh1, num_bh1); + fclose(out); - out = fopen("mass-bh.dat","w"); - m_bh1 = m[0]; - m_bh2 = m[1]; - num_bh1 = 0; - num_bh2 = 0; - fprintf(out,"%.8E \t %.8E %06d \t %.8E %06d \n", - time_cur, m_bh1, num_bh1, m_bh2, num_bh2); - fclose(out); + out = fopen("mass-bh.con","w"); + m_bh1 = m[0]; + num_bh1 = 0; + fprintf(out,"%.8E \t %.8E %06d \n", + time_cur, m_bh1, num_bh1); + fclose(out); - out = fopen("mass-bh.con","w"); - m_bh1 = m[0]; - m_bh2 = m[1]; - num_bh1 = 0; - num_bh2 = 0; - fprintf(out,"%.8E \t %.8E %06d \t %.8E %06d \n", - time_cur, m_bh1, num_bh1, m_bh2, num_bh2); - fclose(out); +#endif // ADD_BH1 - #else +#endif // ADD_BH2 - #ifdef ADD_BH1 +#endif // STARDESTR - out = fopen("mass-bh.dat","w"); - m_bh1 = m[0]; - num_bh1 = 0; - fprintf(out,"%.8E \t %.8E %06d \n", - time_cur, m_bh1, num_bh1); - fclose(out); +#ifdef STARDESTR_EXT + num_bh = 0; + out = fopen("mass-bh.dat","w"); + fprintf(out,"%.8E \t %.8E \t %06d \n", time_cur, m_bh, num_bh); + fclose(out); - out = fopen("mass-bh.con","w"); - m_bh1 = m[0]; - num_bh1 = 0; - fprintf(out,"%.8E \t %.8E %06d \n", - time_cur, m_bh1, num_bh1); - fclose(out); + num_bh = 0; + out = fopen("mass-bh.con","w"); + fprintf(out,"%.8E \t %.8E \t %06d \n", time_cur, m_bh, num_bh); + fclose(out); - #endif // ADD_BH1 +#ifdef BH_OUT_NB_EXT + out = fopen("bh_nb.dat","w"); + fclose(out); +#endif - #endif // ADD_BH2 +#endif // STARDESTR_EXT - #endif // STARDESTR +#ifdef BBH_INF + out = fopen("bbh.inf","w"); + fclose(out); +#endif + } else { // if (diskstep == 0) +#ifdef STARDESTR - #ifdef STARDESTR_EXT +#ifdef ADD_BH2 + inp = fopen("mass-bh.con","r"); + fscanf(inp,"%lE %lE %d %lE %d", &tmp, &m_bh1, &num_bh1, &m_bh2, &num_bh2); + fclose(inp); + printf("%.8E \t %.8E %06d \t %.8E %06d \n", tmp, m_bh1, num_bh1, m_bh2, num_bh2); + fflush(stdout); +#else - num_bh = 0; - out = fopen("mass-bh.dat","w"); - fprintf(out,"%.8E \t %.8E \t %06d \n", time_cur, m_bh, num_bh); - fclose(out); +#ifdef ADD_BH1 + inp = fopen("mass-bh.con","r"); + fscanf(inp,"%lE %lE %d", &tmp, &m_bh1, &num_bh1); + fclose(inp); + printf("%.8E \t %.8E \t %06d \n", tmp, m_bh1, num_bh1); + fflush(stdout); +#endif // ADD_BH1 - num_bh = 0; - out = fopen("mass-bh.con","w"); - fprintf(out,"%.8E \t %.8E \t %06d \n", time_cur, m_bh, num_bh); - fclose(out); +#endif // ADD_BH2 - #ifdef BH_OUT_NB_EXT - out = fopen("bh_nb.dat","w"); - fclose(out); - #endif - - #endif // STARDESTR_EXT - - #ifdef BBH_INF - out = fopen("bbh.inf","w"); - fclose(out); - #endif - - - } - else // if (diskstep == 0) - { - - #ifdef STARDESTR - - #ifdef ADD_BH2 - - inp = fopen("mass-bh.con","r"); - fscanf(inp,"%lE %lE %d %lE %d", &tmp, &m_bh1, &num_bh1, &m_bh2, &num_bh2); - fclose(inp); - printf("%.8E \t %.8E %06d \t %.8E %06d \n", tmp, m_bh1, num_bh1, m_bh2, num_bh2); - fflush(stdout); - - #else - - #ifdef ADD_BH1 - - inp = fopen("mass-bh.con","r"); - fscanf(inp,"%lE %lE %d", &tmp, &m_bh1, &num_bh1); - fclose(inp); - printf("%.8E \t %.8E \t %06d \n", tmp, m_bh1, num_bh1); - fflush(stdout); - - #endif // ADD_BH1 - - #endif // ADD_BH2 - - #endif // STARDESTR - - - #ifdef STARDESTR_EXT - - inp = fopen("mass-bh.con","r"); - fscanf(inp,"%lE %lE %d", &tmp, &m_bh, &num_bh); - fclose(inp); - printf("%.8E \t %.8E \t %06d \n", tmp, m_bh, num_bh); - fflush(stdout); - - #endif // STARDESTR_EXT +#endif // STARDESTR +#ifdef STARDESTR_EXT + inp = fopen("mass-bh.con","r"); + fscanf(inp,"%lE %lE %d", &tmp, &m_bh, &num_bh); + fclose(inp); + printf("%.8E \t %.8E \t %06d \n", tmp, m_bh, num_bh); + fflush(stdout); +#endif // STARDESTR_EXT } // if (diskstep == 0) - get_CPU_time(&CPU_time_real0, &CPU_time_user0, &CPU_time_syst0); - } /* if (myRank == rootRank) */ + } /* if (myRank == rootRank) */ /* Wait to all processors to finish his works... */ MPI_Barrier(MPI_COMM_WORLD); @@ -2686,16 +2555,16 @@ int main(int argc, char *argv[]) MPI_Bcast(&dt_bh, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); MPI_Bcast(&time_cur, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - #ifdef NORM +#ifdef NORM MPI_Bcast(&m_norm, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); MPI_Bcast(&r_norm, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); MPI_Bcast(&v_norm, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); MPI_Bcast(&t_norm, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - #endif // NORM +#endif // NORM - #ifdef EXTPOT +#ifdef EXTPOT - #ifdef EXTPOT_GAL +#ifdef EXTPOT_GAL MPI_Bcast(&m_bulge, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); MPI_Bcast(&a_bulge, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); MPI_Bcast(&b_bulge, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); @@ -2708,49 +2577,44 @@ int main(int argc, char *argv[]) MPI_Bcast(&a_halo, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); MPI_Bcast(&b_halo, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - #endif +#endif - #ifdef EXTPOT_BH +#ifdef EXTPOT_BH MPI_Bcast(&m_bh, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); MPI_Bcast(&b_bh, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - #endif +#endif - #ifdef EXTPOT_GAL_DEH +#ifdef EXTPOT_GAL_DEH MPI_Bcast(&m_ext, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); MPI_Bcast(&r_ext, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); MPI_Bcast(&g_ext, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - #endif +#endif - #ifdef EXTPOT_GAL_LOG +#ifdef EXTPOT_GAL_LOG MPI_Bcast(&v_halo, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); MPI_Bcast(&r_halo, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); MPI_Bcast(&v2_halo, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); MPI_Bcast(&r2_halo, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - #endif +#endif - #endif // EXTPOT +#endif // EXTPOT - - #ifdef STARDESTR +#ifdef STARDESTR MPI_Bcast(&m_bh1, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); MPI_Bcast(&num_bh1, 1, MPI_INT, rootRank, MPI_COMM_WORLD); MPI_Bcast(&m_bh2, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); MPI_Bcast(&num_bh2, 1, MPI_INT, rootRank, MPI_COMM_WORLD); - #endif // STARDESTR +#endif // STARDESTR - - #ifdef STARDESTR_EXT +#ifdef STARDESTR_EXT MPI_Bcast(&num_bh, 1, MPI_INT, rootRank, MPI_COMM_WORLD); - #endif // STARDESTR_EXT - +#endif // STARDESTR_EXT /* Wait to all processors to finish his works... */ MPI_Barrier(MPI_COMM_WORLD); - - eta_s = eta/ETA_S_CORR; eta_bh = eta/ETA_BH_CORR; @@ -2770,24 +2634,19 @@ int main(int argc, char *argv[]) t_contr = dt_contr*(1.0+floor(time_cur/dt_contr)); t_bh = dt_bh*(1.0+floor(time_cur/dt_bh)); - - if (myRank == rootRank) - { - printf("t_disk = %.6E t_contr = %.6E t_bh = %.6E \n", t_disk, t_contr, t_bh); - printf("\n"); - fflush(stdout); + if (myRank == rootRank) { + printf("t_disk = %.6E t_contr = %.6E t_bh = %.6E \n", t_disk, t_contr, t_bh); + printf("\n"); + fflush(stdout); } /* if (myRank == rootRank) */ - for (i=0; i BH _softened_ pot, acc & jerk @@ -2987,14 +2831,13 @@ int main(int argc, char *argv[]) pot[i_bh1] -= pot_bh1; pot[i_bh2] -= pot_bh2; - for (k=0;k<3;k++) - { + for (k=0;k<3;k++) { a[i_bh1][k] -= a_bh1[k]; a[i_bh2][k] -= a_bh2[k]; adot[i_bh1][k] -= adot_bh1[k]; adot[i_bh2][k] -= adot_bh2[k]; - } + } // calculate and "plus" the new BH <-> BH _unsoftened_ pot, acc, jerk @@ -3007,58 +2850,51 @@ int main(int argc, char *argv[]) pot[i_bh1] += pot_bh1; pot[i_bh2] += pot_bh2; - for (k=0;k<3;k++) - { + for (k=0;k<3;k++) { a[i_bh1][k] += a_bh1[k]; a[i_bh2][k] += a_bh2[k]; adot[i_bh1][k] += adot_bh1[k]; adot[i_bh2][k] += adot_bh2[k]; - } + } - #endif // ADD_N_BH +#endif // ADD_N_BH - - #ifdef ADD_PN_BH +#ifdef ADD_PN_BH // calculate and "plus" the new BH <-> BH : PN1, PN2, PN2.5, PN3, PN3.5 : acc, jerk dt_bh_tmp = dt[0]; tmp_i = calc_force_pn_BH(m_bh1, x_bh1, v_bh1, s_bh1, - m_bh2, x_bh2, v_bh2, s_bh2, - C_NB, dt_bh_tmp, usedOrNot, - a_pn1, adot_pn1, - a_pn2, adot_pn2); + m_bh2, x_bh2, v_bh2, s_bh2, + C_NB, dt_bh_tmp, usedOrNot, + a_pn1, adot_pn1, + a_pn2, adot_pn2); - for (k=0;k<3;k++) - { + for (k=0;k<3;k++) { a[i_bh1][k] += a_pn1[1][k] + a_pn1[2][k] + a_pn1[3][k] + a_pn1[4][k] + a_pn1[5][k] + a_pn1[6][k]; a[i_bh2][k] += a_pn2[1][k] + a_pn2[2][k] + a_pn2[3][k] + a_pn2[4][k] + a_pn2[5][k] + a_pn2[6][k]; adot[i_bh1][k] += adot_pn1[1][k] + adot_pn1[2][k] + adot_pn1[3][k] + adot_pn1[4][k] + adot_pn1[5][k] + adot_pn1[6][k]; adot[i_bh2][k] += adot_pn2[1][k] + adot_pn2[2][k] + adot_pn2[3][k] + adot_pn2[4][k] + adot_pn2[5][k] + adot_pn2[6][k]; + } + + if (myRank == rootRank) { + if (tmp_i == 505) { + printf("PN RSDIST: %.8E \t %.8E \n", Timesteps, time_cur); + fflush(stdout); + exit(-1); } + } - if (myRank == rootRank) - { - if (tmp_i == 505) - { - printf("PN RSDIST: %.8E \t %.8E \n", Timesteps, time_cur); - fflush(stdout); - exit(-1); - } - } +#endif // ADD_PN_BH - #endif // ADD_PN_BH +#endif // ADD_BH2 - #endif // ADD_BH2 - - - - #ifdef EXTPOT +#ifdef EXTPOT calc_ext_grav_zero(); - #endif +#endif /* Wait to all processors to finish his works... */ MPI_Barrier(MPI_COMM_WORLD); @@ -3066,22 +2902,17 @@ int main(int argc, char *argv[]) /* Wait to all processors to finish his works... */ MPI_Barrier(MPI_COMM_WORLD); - /* Energy control... */ - if (myRank == rootRank) - { - + if (myRank == rootRank) { energy_contr(); + } /* if (myRank == rootRank) */ - } /* if (myRank == rootRank) */ - - #ifdef ETICS_DUMP - if (diskstep==0) { +#ifdef ETICS_DUMP + if (diskstep==0) { sprintf(out_fname, "coeffs.%06d.%02d.dat", 0, myRank); grapite_dump(out_fname, 2); - } - #endif - + } +#endif /* Wait to all processors to finish his works... */ MPI_Barrier(MPI_COMM_WORLD); @@ -3091,7 +2922,7 @@ int main(int argc, char *argv[]) MPI_Scatter(a, 3*n_loc, MPI_DOUBLE, a_loc, 3*n_loc, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); MPI_Scatter(adot, 3*n_loc, MPI_DOUBLE, adot_loc, 3*n_loc, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - #ifdef ETICS_CEP +#ifdef ETICS_CEP // First calculate the DC grapite_calc_center(N, m, x, v, xcm, vcm, xdc, vdc); @@ -3106,26 +2937,21 @@ int main(int argc, char *argv[]) } grapite_update_cep(time_cur, xdc, vdc, a[grapite_cep_index], adot[grapite_cep_index]); - #endif +#endif /* Wait to all processors to finish his works... */ MPI_Barrier(MPI_COMM_WORLD); - - - - /* Define initial timestep for all particles on all nodes */ - for (i=0; i dt_max) dt_tmp = dt_max; - - #ifdef STARDESTR +#ifdef STARDESTR if (m[i] == 0.0) dt_tmp = dt_max; - #endif +#endif - #ifdef STARDESTR_EXT +#ifdef STARDESTR_EXT if (m[i] == 0.0) dt_tmp = dt_max; - #endif +#endif dt[i] = dt_tmp; - - #ifdef DT_MIN_WARNING - if (myRank == 0) - { - if (dt[i] == dt_min) - { - printf("!!! Warning0: dt = dt_min = %.6E \t ind = %07d \n", dt[i], ind[i]); - fflush(stdout); +#ifdef DT_MIN_WARNING + if (myRank == 0) { + if (dt[i] == dt_min) { + printf("!!! Warning0: dt = dt_min = %.6E \t ind = %07d \n", dt[i], ind[i]); + fflush(stdout); } } - #endif +#endif - } /* i */ + } /* i */ - - - - #ifdef ADD_BH2 +#ifdef ADD_BH2 /* define the min. dt over all the part. and set it also for the BH... */ - min_dt = dt[0]; + min_dt = dt[0]; - for (i=1; i 0) - for (int i=0; i 0) + for (int i=0; i BH softened pot, acc & jerk - - tmp_i = calc_force_n_BH(m_bh1, x_bh1, v_bh1, - m_bh2, x_bh2, v_bh2, - eps, - &pot_bh1, a_bh1, adot_bh1, - &pot_bh2, a_bh2, adot_bh2); - - pot_act_new[i_bh1] -= pot_bh1; - pot_act_new[i_bh2] -= pot_bh2; - - for (k=0;k<3;k++) - { - a_act_new[i_bh1][k] -= a_bh1[k]; - a_act_new[i_bh2][k] -= a_bh2[k]; - - adot_act_new[i_bh1][k] -= adot_bh1[k]; - adot_act_new[i_bh2][k] -= adot_bh2[k]; - } - - // calculate and "plus" the new BH <-> BH unsoftened pot, acc, jerk - - tmp_i = calc_force_n_BH(m_bh1, x_bh1, v_bh1, - m_bh2, x_bh2, v_bh2, - eps_BH, - &pot_bh1, a_bh1, adot_bh1, - &pot_bh2, a_bh2, adot_bh2); - - pot_act_new[i_bh1] += pot_bh1; - pot_act_new[i_bh2] += pot_bh2; - - for (k=0;k<3;k++) - { - a_act_new[i_bh1][k] += a_bh1[k]; - a_act_new[i_bh2][k] += a_bh2[k]; - - adot_act_new[i_bh1][k] += adot_bh1[k]; - adot_act_new[i_bh2][k] += adot_bh2[k]; - } - - #endif // ADD_N_BH - - - #ifdef ADD_PN_BH - - // calculate and "plus" the new BH <-> BH : PN1, PN2, PN2.5, PN3, PN3.5 : acc, jerk - - dt_bh_tmp = dt[0]; - - tmp_i = calc_force_pn_BH(m_bh1, x_bh1, v_bh1, s_bh1, - m_bh2, x_bh2, v_bh2, s_bh2, - C_NB, dt_bh_tmp, usedOrNot, - a_pn1, adot_pn1, - a_pn2, adot_pn2); - - for (k=0;k<3;k++) - { - a_act_new[i_bh1][k] += a_pn1[1][k] + a_pn1[2][k] + a_pn1[3][k] + a_pn1[4][k] + a_pn1[5][k] + a_pn1[6][k]; - a_act_new[i_bh2][k] += a_pn2[1][k] + a_pn2[2][k] + a_pn2[3][k] + a_pn2[4][k] + a_pn2[5][k] + a_pn2[6][k]; - - adot_act_new[i_bh1][k] += adot_pn1[1][k] + adot_pn1[2][k] + adot_pn1[3][k] + adot_pn1[4][k] + adot_pn1[5][k] + adot_pn1[6][k]; - adot_act_new[i_bh2][k] += adot_pn2[1][k] + adot_pn2[2][k] + adot_pn2[3][k] + adot_pn2[4][k] + adot_pn2[5][k] + adot_pn2[6][k]; - } - - if (myRank == rootRank) - { - if (tmp_i == 505) - { - printf("PN RSDIST: TS = %.8E \t t = %.8E \n", Timesteps, time_cur); - fflush(stdout); - exit(-1); - } - } - - #endif // ADD_PN_BH - - #endif // ADD_BH2 - - #ifdef EXTPOT - calc_ext_grav(); - #endif - - /* correct the active particles positions etc... on all the nodes */ - - #ifdef TIMING - get_CPU_time(&CPU_tmp_real0, &CPU_tmp_user0, &CPU_tmp_syst0); - #endif - - for (i=0; i dt_min) ) - { - power = log(dt_new)/log(2.0) - 1; - - dt_tmp = pow(2.0, (double)power); - } - - if ( (dt_new > 2.0*dt_tmp) && - (fmod(min_t, 2.0*dt_tmp) == 0.0) && - (2.0*dt_tmp <= dt_max) ) - { - dt_tmp *= 2.0; - } - - dt_act[i] = dt_tmp; - - t_act[i] = min_t; - - pot_act[i] = pot_act_new[i]; - - for (k=0; k<3; k++) - { - x_act[i][k] = x_act_new[i][k]; - v_act[i][k] = v_act_new[i][k]; - a_act[i][k] = a_act_new[i][k]; - adot_act[i][k] = adot_act_new[i][k]; - } /* k */ - - - #ifdef DT_MIN_WARNING - if (myRank == 0) - { - if (dt_act[i] == dt_min) - { - printf("!!! Warning1: dt_act = dt_min = %.6E \t ind_act = %07d \n", dt[i], ind_act[i]); - fflush(stdout); - } - } - #endif - - - - } /* i */ - - - - - /* define the min. dt over all the act. part. and set it also for the BH... */ - - #ifdef ADD_BH2 - - min_dt = dt_act[0]; - - for (i=1; i BH softened pot, acc & jerk + + tmp_i = calc_force_n_BH(m_bh1, x_bh1, v_bh1, + m_bh2, x_bh2, v_bh2, + eps, + &pot_bh1, a_bh1, adot_bh1, + &pot_bh2, a_bh2, adot_bh2); + + pot_act_new[i_bh1] -= pot_bh1; + pot_act_new[i_bh2] -= pot_bh2; + + for (k=0;k<3;k++) { + a_act_new[i_bh1][k] -= a_bh1[k]; + a_act_new[i_bh2][k] -= a_bh2[k]; + + adot_act_new[i_bh1][k] -= adot_bh1[k]; + adot_act_new[i_bh2][k] -= adot_bh2[k]; } - DR2 = SQR(x_bh1[0] - x_bh2[0]) + SQR(x_bh1[1] - x_bh2[1]) + SQR(x_bh1[2] - x_bh2[2]); - DV2 = SQR(v_bh1[0] - v_bh2[0]) + SQR(v_bh1[1] - v_bh2[1]) + SQR(v_bh1[2] - v_bh2[2]); + // calculate and "plus" the new BH <-> BH unsoftened pot, acc, jerk - EB = -(m_bh1 + m_bh2) / sqrt(DR2) + 0.5 * DV2; + tmp_i = calc_force_n_BH(m_bh1, x_bh1, v_bh1, + m_bh2, x_bh2, v_bh2, + eps_BH, + &pot_bh1, a_bh1, adot_bh1, + &pot_bh2, a_bh2, adot_bh2); - SEMI_a = -0.5 * (m_bh1 + m_bh2)/EB; - SEMI_a2 = SQR(SEMI_a); + pot_act_new[i_bh1] += pot_bh1; + pot_act_new[i_bh2] += pot_bh2; - for (i=2; i BH : PN1, PN2, PN2.5, PN3, PN3.5 : acc, jerk - fprintf(out,"INF1 %.6E %.16E %07d %07d %.6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E \n", - Timesteps, time_cur, i, ind_act[i], - sqrt(DR2), x_bbhc[0], x_bbhc[1], x_bbhc[2], v_bbhc[0], v_bbhc[1], v_bbhc[2], - m_bh1, x_bh1[0], x_bh1[1], x_bh1[2], v_bh1[0], v_bh1[1], v_bh1[2], pot_act[0], - m_bh2, x_bh2[0], x_bh2[1], x_bh2[2], v_bh2[0], v_bh2[1], v_bh2[2], pot_act[1], - sqrt(tmp_r2), - m_act[i], x_act[i][0], x_act[i][1], x_act[i][2], v_act[i][0], v_act[i][1], v_act[i][2], pot_act[i], - dt_act[i]); + dt_bh_tmp = dt[0]; - inf_event[iii] = 1; + tmp_i = calc_force_pn_BH(m_bh1, x_bh1, v_bh1, s_bh1, + m_bh2, x_bh2, v_bh2, s_bh2, + C_NB, dt_bh_tmp, usedOrNot, + a_pn1, adot_pn1, + a_pn2, adot_pn2); + + for (k=0;k<3;k++) { + a_act_new[i_bh1][k] += a_pn1[1][k] + a_pn1[2][k] + a_pn1[3][k] + a_pn1[4][k] + a_pn1[5][k] + a_pn1[6][k]; + a_act_new[i_bh2][k] += a_pn2[1][k] + a_pn2[2][k] + a_pn2[3][k] + a_pn2[4][k] + a_pn2[5][k] + a_pn2[6][k]; + + adot_act_new[i_bh1][k] += adot_pn1[1][k] + adot_pn1[2][k] + adot_pn1[3][k] + adot_pn1[4][k] + adot_pn1[5][k] + adot_pn1[6][k]; + adot_act_new[i_bh2][k] += adot_pn2[1][k] + adot_pn2[2][k] + adot_pn2[3][k] + adot_pn2[4][k] + adot_pn2[5][k] + adot_pn2[6][k]; + } + + if (myRank == rootRank) { + if (tmp_i == 505) { + printf("PN RSDIST: TS = %.8E \t t = %.8E \n", Timesteps, time_cur); + fflush(stdout); + exit(-1); } - - } - else - { - - if ( (inf_event[iii] == 1) ) - { - - fprintf(out,"INF2 %.6E %.16E %07d %07d %.6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E \n", - Timesteps, time_cur, i, ind_act[i], - sqrt(DR2), x_bbhc[0], x_bbhc[1], x_bbhc[2], v_bbhc[0], v_bbhc[1], v_bbhc[2], - m_bh1, x_bh1[0], x_bh1[1], x_bh1[2], v_bh1[0], v_bh1[1], v_bh1[2], pot_act[0], - m_bh2, x_bh2[0], x_bh2[1], x_bh2[2], v_bh2[0], v_bh2[1], v_bh2[2], pot_act[1], - sqrt(tmp_r2), - m_act[i], x_act[i][0], x_act[i][1], x_act[i][2], v_act[i][0], v_act[i][1], v_act[i][2], pot_act[i], - dt_act[i]); - } - - inf_event[iii] = 0; - - } /* if (tmp_r2 < DR2*R_INF2) */ - - } /* i */ - - fclose(out); - - } /* if (myRank == rootRank) */ - #endif - - - - - /* Return back the new coordinates + etc... of active part. to the global data... */ - - for (i=0; i= t_bh) - { + if ( (dt_new < dt_tmp) && (dt_new > dt_min) ) { + power = log(dt_new)/log(2.0) - 1; - if (myRank == rootRank) - { + dt_tmp = pow(2.0, (double)power); + } - #ifdef BH_OUT - /* Write BH data... */ - write_bh_data(); - #endif + if ((dt_new > 2.0*dt_tmp) && (fmod(min_t, 2.0*dt_tmp) == 0.0) && (2.0*dt_tmp <= dt_max)) { + dt_tmp *= 2.0; + } - #ifdef BH_OUT_NB - /* Write BH NB data... */ - write_bh_nb_data(); - #endif + dt_act[i] = dt_tmp; - #ifdef BH_OUT_NB_EXT - /* Write BH NB data... */ - write_bh_nb_data_ext(); - #endif + t_act[i] = min_t; - } /* if (myRank == rootRank) */ + pot_act[i] = pot_act_new[i]; - t_bh += dt_bh; - } /* if (time_cur >= t_bh) */ - - - - - - if (time_cur >= t_contr) - { - - if (myRank == rootRank) - { - - #ifdef STARDESTR - - #ifdef ADD_BH2 - - out = fopen("mass-bh.dat","a"); - fprintf(out,"%.8E \t %.8E %06d \t %.8E %06d \n", - time_cur, m_bh1, num_bh1, m_bh2, num_bh2); - fclose(out); - - out = fopen("mass-bh.con","w"); - fprintf(out,"%.8E \t %.8E %06d \t %.8E %06d \n", - time_cur, m_bh1, num_bh1, m_bh2, num_bh2); - fclose(out); - - #else - - #ifdef ADD_BH1 - - out = fopen("mass-bh.dat","a"); - fprintf(out,"%.8E \t %.8E %06d \n", - time_cur, m_bh1, num_bh1); - fclose(out); - - out = fopen("mass-bh.con","w"); - fprintf(out,"%.8E \t %.8E %06d \n", - time_cur, m_bh1, num_bh1); - fclose(out); - - #endif // ADD_BH1 - - #endif // ADD_BH2 - - #endif // STARDESTR - - #ifdef STARDESTR_EXT - - out = fopen("phi-GRAPE.ext","w"); - fprintf(out,"%.8E \t %.8E \n", m_bh, b_bh); - fclose(out); - - out = fopen("mass-bh.dat","a"); - fprintf(out,"%.8E \t %.8E \t %06d \n", time_cur, m_bh, num_bh); - fclose(out); - - out = fopen("mass-bh.con","w"); - fprintf(out,"%.8E \t %.8E \t %06d \n", time_cur, m_bh, num_bh); - fclose(out); - - #endif // STARDESTR_EXT - - energy_contr(); - - #ifdef CMCORR111 - for (i=0; i R_LIMITS_ALL) && (tmp_rv > 0.0) ) - { - - #ifdef EXTPOT - #endif - - for (k=0;k<3;k++) - { - v[i][k] *= 1.0E-01; + for (k=0;k<3;k++) { + x[iii][k] = x_act[i][k]; + v[iii][k] = v_act[i][k]; } /* k */ - } /* if */ + t[iii] = t_act[i]; + dt[iii] = dt_act[i]; + pot[iii] = pot_act[i]; + +#ifdef EXTPOT + pot_ext[iii] = pot_act_ext[i]; +#endif + + for (k=0;k<3;k++) { + a[iii][k] = a_act[i][k]; + adot[iii][k] = adot_act[i][k]; + } /* k */ } /* i */ +#ifdef TIMING + get_CPU_time(&CPU_tmp_real, &CPU_tmp_user, &CPU_tmp_syst); + DT_ACT_CORR += (CPU_tmp_user - CPU_tmp_user0); +#endif + /* STARDESTR routine on all the nodes */ - for (j=0; j= t_contr) */ - - - - - - - - - if (time_cur >= t_disk) - { - - - if (myRank == rootRank) - { - - diskstep++; - - write_snap_data(); - - } /* if (myRank == rootRank) */ - - #ifdef ETICS_DUMP - sprintf(out_fname, "coeffs.%06d.%02d.dat", diskstep, myRank); - grapite_dump(out_fname, 2); - #endif - - - - - #ifdef LIMITS_NEW - - for (i=0; i 900.0 ) +#ifdef LIMITS + for (i=0; i= t_bh) { + if (myRank == rootRank) { +#ifdef BH_OUT + /* Write BH data... */ + write_bh_data(); +#endif + +#ifdef BH_OUT_NB + /* Write BH NB data... */ + write_bh_nb_data(); +#endif + +#ifdef BH_OUT_NB_EXT + /* Write BH NB data... */ + write_bh_nb_data_ext(); +#endif + } /* if (myRank == rootRank) */ + + t_bh += dt_bh; + } /* if (time_cur >= t_bh) */ + + if (time_cur >= t_contr) { + if (myRank == rootRank) { +#ifdef STARDESTR + +#ifdef ADD_BH2 + + out = fopen("mass-bh.dat","a"); + fprintf(out,"%.8E \t %.8E %06d \t %.8E %06d \n", + time_cur, m_bh1, num_bh1, m_bh2, num_bh2); + fclose(out); + + out = fopen("mass-bh.con","w"); + fprintf(out,"%.8E \t %.8E %06d \t %.8E %06d \n", + time_cur, m_bh1, num_bh1, m_bh2, num_bh2); + fclose(out); + +#else + +#ifdef ADD_BH1 + + out = fopen("mass-bh.dat","a"); + fprintf(out,"%.8E \t %.8E %06d \n", + time_cur, m_bh1, num_bh1); + fclose(out); + + out = fopen("mass-bh.con","w"); + fprintf(out,"%.8E \t %.8E %06d \n", + time_cur, m_bh1, num_bh1); + fclose(out); + +#endif // ADD_BH1 + +#endif // ADD_BH2 + +#endif // STARDESTR + +#ifdef STARDESTR_EXT + + out = fopen("phi-GRAPE.ext","w"); + fprintf(out,"%.8E \t %.8E \n", m_bh, b_bh); + fclose(out); + + out = fopen("mass-bh.dat","a"); + fprintf(out,"%.8E \t %.8E \t %06d \n", time_cur, m_bh, num_bh); + fclose(out); + + out = fopen("mass-bh.con","w"); + fprintf(out,"%.8E \t %.8E \t %06d \n", time_cur, m_bh, num_bh); + fclose(out); + +#endif // STARDESTR_EXT + + energy_contr(); + +#ifdef CMCORR111 + for (i=0; i R_LIMITS_ALL) && (tmp_rv > 0.0) ) { + for (k=0;k<3;k++) { + v[i][k] *= 1.0E-01; + } /* k */ + } /* if */ + } /* i */ + + for (j=0; j= t_contr) */ + + if (time_cur >= t_disk) { + if (myRank == rootRank) { + diskstep++; + write_snap_data(); + } /* if (myRank == rootRank) */ + +#ifdef ETICS_DUMP + sprintf(out_fname, "coeffs.%06d.%02d.dat", diskstep, myRank); + grapite_dump(out_fname, 2); +#endif + +#ifdef LIMITS_NEW + + for (i=0; i 900.0 ) + { + + m[i] = 0.0; + + pot[i] = 0.0; + +#ifdef EXTPOT + pot_ext[i] = 0.0; +#endif + + for (k=0;k<3;k++) + { + x[i][k] = 1000.0 + 1.0*my_rand2(); + v[i][k] = 1.0E-06*my_rand2(); + a[i][k] = 1.0E-06*my_rand2(); + adot[i][k] = 1.0E-06*my_rand2(); + } /* k */ + + t[i] = 2.0*t_end; + + dt[i] = 0.125; + + } /* if */ + + } /* i */ + + for (j=0; j= t_disk) */ - - - #ifdef CPU_TIMELIMIT - if (myRank == rootRank) - { - get_CPU_time(&CPU_time_real, &CPU_time_user, &CPU_time_syst); - tmp_cpu = CPU_time_real-CPU_time_real0; +#ifdef CPU_TIMELIMIT + if (myRank == rootRank) { + get_CPU_time(&CPU_time_real, &CPU_time_user, &CPU_time_syst); + tmp_cpu = CPU_time_real-CPU_time_real0; } /* if (myRank == rootRank) */ - #endif - - - #ifdef ACT_DEF_LL - ModifyLinkList(); - - #endif +#endif +#ifdef ACT_DEF_LL + ModifyLinkList(); +#endif } /* while (time_cur < t_end) */ - - /* close the local GRAPE's */ - #ifdef SAPPORO +#ifdef SAPPORO g6_close_(&clusterid); - #else +#else g6_close(clusterid); - #endif - +#endif /* Wait to all processors to finish his works... */ MPI_Barrier(MPI_COMM_WORLD); @@ -4471,9 +4087,7 @@ int main(int argc, char *argv[]) /* Wait to all processors to finish his works... */ MPI_Barrier(MPI_COMM_WORLD); - - if (myRank == rootRank) - { + if (myRank == rootRank) { /* Write some output for the timestep annalize... */ @@ -4485,18 +4099,12 @@ int main(int argc, char *argv[]) } /* if (myRank == rootRank) */ - - /* Wait to all processors to finish his works... */ MPI_Barrier(MPI_COMM_WORLD); /* Finalize the MPI work */ MPI_Finalize(); - return(0); + return 0; } - -/****************************************************************************/ -/****************************************************************************/ -/****************************************************************************/ From b5071b792e53648f531b0239e1dc5528575f0e70 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Fri, 6 Mar 2020 10:37:41 -0500 Subject: [PATCH 04/65] Added TODO --- TODO.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 TODO.md diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..a81190a --- /dev/null +++ b/TODO.md @@ -0,0 +1,16 @@ +TODO +==== + +* Get rid of all global variables. + +* Break main() into smaller chunks; operations that are timed should become independent functions. + +* Dynamically allocate the big arrays. + +* Create a key-value config file reader to replace the external parameter files. + +* Remove all ifdef blocks, options should be selected in the config file. + +* Optional HDF5 output. + +* In the config file let choose number of digits for ASCII output and 32 or 64-bit floats for HDF5. From 63a39cc9c8da17183f612c8a341738d25a997d80 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Fri, 6 Mar 2020 15:18:32 -0500 Subject: [PATCH 05/65] Removed ifdef blocks specific to non-Yebisu libraries --- phigrape.cpp | 131 +-------------------------------------------------- 1 file changed, 1 insertion(+), 130 deletions(-) diff --git a/phigrape.cpp b/phigrape.cpp index 33c243f..d258c08 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -74,10 +74,6 @@ Last redaction : 2019.04.16 12:55 //#define BH_OUT_NB_EXT // extra output for the BH's neighbours (external) -//#define SAPPORO // Gaburov. Do not tuch! Defined inside the Makefiles !!! -//#define YEBISU // Nitadori. Do not tuch! Defined inside the Makefiles !!! -//#define GUINNESS // Nakasato. Do not tuch! Defined inside the Makefiles !!! - //#define STARDESTR // disruption of stars by BH tidal forces //#define STARDESTR_EXT // disruption of stars by external BH tidal forces @@ -135,8 +131,6 @@ Last redaction : 2019.04.16 12:55 -30.0 ~1e-9 */ -//#define AMD - //#define ACT_DEF_LL #if defined(ACT_DEF_LL) && defined(ACT_DEF_GRAPITE) @@ -159,22 +153,8 @@ double aaapars[5]; extern void qwerty_(double *aaa, double *aaapars); */ -#ifdef SAPPORO -#include -#include -#define GPU_PIPE 256 -#else -# ifdef YEBISU -# define G6_NPIPE 2048 -# else -# define G6_NPIPE 48 -# endif +#define G6_NPIPE 2048 #include "grape6.h" -#endif - -#ifdef GUINNESS -#define GPU_PIPE 128 -#endif #include @@ -330,28 +310,10 @@ double DT_ACT_REDUCE; int clusterid, ii, nn, numGPU; -//#ifdef SAPPORO -#if defined(SAPPORO) || defined(GUINNESS) - -int npipe=GPU_PIPE, index_i[GPU_PIPE]; -double h2_i[GPU_PIPE], x_i[GPU_PIPE][3], v_i[GPU_PIPE][3], - p_i[GPU_PIPE], a_i[GPU_PIPE][3], jerk_i[GPU_PIPE][3]; -double new_tunit=51.0, new_xunit=51.0; - -#elif defined YEBISU - int npipe=G6_NPIPE, index_i[G6_NPIPE]; double h2_i[G6_NPIPE], x_i[G6_NPIPE][3], v_i[G6_NPIPE][3], p_i[G6_NPIPE], a_i[G6_NPIPE][3], jerk_i[G6_NPIPE][3]; int new_tunit=51, new_xunit=51; -#else - -int npipe=48, index_i[48]; -double h2_i[48], x_i[48][3], v_i[48][3], - p_i[48], a_i[48][3], jerk_i[48][3]; -int new_tunit=51, new_xunit=51; - -#endif int aflag=1, jflag=1, pflag=1; @@ -1109,11 +1071,7 @@ void calc_self_grav_zero() /* calc the grav for the active particles */ -#ifdef SAPPORO -g6_set_ti_(&clusterid, &time_cur); -#else g6_set_ti(clusterid, time_cur); -#endif ni = n_act; @@ -1146,13 +1104,8 @@ for (i=0; i 100.0) jerk_i[ii][2] = 100.0; } -#ifdef SAPPORO - g6calc_firsthalf_(&clusterid, &n_loc, &nn, index_i, x_i, v_i , a_i, jerk_i, p_i, &eps2, h2_i); - g6calc_lasthalf_(&clusterid, &n_loc, &nn, index_i, x_i, v_i, &eps2, h2_i, a_i, jerk_i, p_i); -#else g6calc_firsthalf(clusterid, n_loc, nn, index_i, x_i, v_i , a_i, jerk_i, p_i, eps2, h2_i); g6calc_lasthalf(clusterid, n_loc, nn, index_i, x_i, v_i, eps2, h2_i, a_i, jerk_i, p_i); -#endif for (ii=0; ii Date: Sun, 8 Mar 2020 00:59:44 -0500 Subject: [PATCH 06/65] started working on simple config file parser --- io.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 io.cpp diff --git a/io.cpp b/io.cpp new file mode 100644 index 0000000..b7894e6 --- /dev/null +++ b/io.cpp @@ -0,0 +1,40 @@ +#include +#include +#include +#include +#include + +int main() +{ + std::unordered_map dictionary; + std::string file_name = "phigrape.conf"; + std::ifstream file(file_name); + if (!file.good()) { + std::cout << "Not found!" << std::endl; + exit(1); + } + std::string str; + int line_number = 0; + while (std::getline(file, str)) { + line_number++; + auto pos = str.find('#'); + if (pos != std::string::npos) str = str.substr(0, pos); + pos = str.find_first_not_of(" \t"); + if (pos != std::string::npos) str = str.substr(pos, str.size()); + else continue; + pos = str.find_last_not_of(" \t"); + if (pos != std::string::npos) str = str.substr(0, pos+1); + if (str.size() == 0) continue; + pos = str.find_first_of(" \t"); + if (pos == std::string::npos) { + std::cerr << "Error: expected a key-value pair in line " << line_number << " of file " << file_name << std::endl; + exit(1); + } + std::string key = str.substr(0, pos); + pos = str.find_first_not_of(" \t", pos+1); + std::string val = str.substr(pos, str.size()); + dictionary[key] = val; + } + + printf("dictionary[\"more\"] = %s\n", dictionary["eps"].c_str()); +} From 2c05355eaab505a003b94aa4891a193b93e41183 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Fri, 13 Mar 2020 16:58:41 -0400 Subject: [PATCH 07/65] Removed more ifdef blocks --- act_def_linklist.c | 376 ------------------- phigrape.cpp | 889 +++------------------------------------------ pn_bh.c | 765 -------------------------------------- star_destr.c | 275 -------------- star_destr_ext.c | 286 --------------- 5 files changed, 56 insertions(+), 2535 deletions(-) delete mode 100644 act_def_linklist.c delete mode 100644 pn_bh.c delete mode 100644 star_destr.c delete mode 100644 star_destr_ext.c diff --git a/act_def_linklist.c b/act_def_linklist.c deleted file mode 100644 index b879bc3..0000000 --- a/act_def_linklist.c +++ /dev/null @@ -1,376 +0,0 @@ -/************************************************************** - File : act_def_linklist.c - Func. : provide linear linking list functions - : for active particle def. - CODED BY : Zhong Shiyan - START : 2014-03-28, 12:30 -**************************************************************/ - -//***********************************************************// -/* Definition of T/P-node */ -//***********************************************************// -typedef struct PNODE -{ - int Pid; // Particle's real ID - struct PNODE *NextPNODE; -} PNODE; - -typedef struct TNODE -{ - double t_node; // t_node = t + dt - int n_node; // number of P-nodes under this node - - struct PNODE *PartList, *PartListEnd; - struct TNODE *NextTNODE; -} TNODE; - -struct TNODE *CurrT=NULL; - -//***********************************************************// -/* Operations on T/P-node */ -//***********************************************************// -struct TNODE *CreateTNODE( double t ){ - - struct TNODE *ptr; - - ptr = (TNODE*)malloc(sizeof(*ptr)); - if( ptr == NULL ){ - printf("Fail to create a node."); - exit(-1); - } - - ptr->t_node = t; - ptr->n_node = 0; - - ptr->NextTNODE = NULL; - - ptr->PartList = NULL; - ptr->PartListEnd = NULL; - - return ptr; -} -//***********************************************************// -struct PNODE *DeletePNODE( struct PNODE *ptr ){ - struct PNODE *next; - - next = ptr->NextPNODE; - free(ptr); - - return next; -} -//***********************************************************// -void DeleteTNODE( struct TNODE *Tptr ){ - - struct PNODE *Pptr; - - Pptr = Tptr->PartList; - - while( Pptr != NULL ){ - Pptr = DeletePNODE( Pptr ); - } - - free(Tptr); - return; -} -//***********************************************************// -struct PNODE *CreatePNODE( int id ){ - struct PNODE *ptr; - - ptr = (PNODE*)malloc(sizeof(*ptr)); - if( ptr == NULL ){ - printf("Fail to create a P-node."); - return NULL; - } - - ptr->Pid = id; - ptr->NextPNODE = NULL; - - return ptr; - -} -//***********************************************************// -void InsertTNODE( struct TNODE *front, - struct TNODE *rear, - struct TNODE *ptr ) -{ - front->NextTNODE = ptr; - ptr->NextTNODE = rear; - -} -//***********************************************************// - - - - -//***********************************************************// -/* Functions about act_def */ -//***********************************************************// -/************************************************************** -This function only called 1 time, at beginning of simulation. -After all particle's dt are computed -**************************************************************/ - -void CreateLinkList(){ - - struct TNODE *head,*tail,*Tp1,*Tp2,*newTNODE,*Tptr; - struct PNODE *Pptr,*Ptail; - - int i, iii; - double ttmp, t1, t2; - - head = CreateTNODE( -1.0 ); // will be discarded at the end of this routine - tail = CreateTNODE( 2.0*t_end ); - - head->NextTNODE = tail; - tail->NextTNODE = NULL; - - // building link list - -for(i=0;iNextTNODE; - t1 = Tp1->t_node; - t2 = Tp2->t_node; - - Pptr = CreatePNODE( iii ); - - while( Tp1->NextTNODE != NULL ){ - if( ttmp == t1 ){ // if T-node exist, add a P-node - - if( Tp1->PartListEnd == NULL ){ // This is the first P-node under current T-node - Tp1->PartList = Pptr; - Tp1->PartListEnd = Pptr; - Tp1->n_node = Tp1->n_node + 1; - } - else{ // There are already many P-nodes under this T-node - Ptail = Tp1->PartListEnd; - Ptail->NextPNODE = Pptr; - Tp1->PartListEnd = Pptr; - Tp1->n_node = Tp1->n_node + 1; - } - break; // jump out of this "while" loop - } - - if( ttmp > t1 && ttmp < t2 ){ // Create a new T-node and insert between *Tp1 and *Tp2, then add P-node to it - - newTNODE = CreateTNODE(ttmp); - InsertTNODE( Tp1, Tp2, newTNODE); - - newTNODE->n_node = 1; - newTNODE->PartList = Pptr; - newTNODE->PartListEnd = Pptr; - break; // jump out of this "while" loop - } - - // move to next T-node - Tp1 = Tp1->NextTNODE; - t1 = Tp1->t_node; - - if(Tp2->NextTNODE != NULL){ - Tp2 = Tp2->NextTNODE; - t2 = Tp2->t_node; - } - else{ break; } - - }// while( Tp1->NextTNODE != NULL ) - -}//for(i=0;iNextTNODE; - free(head); - -} - -//End of CreateLinkList() -/**************************************************************/ - - -/************************************************************** -This Function is used to modify the link list, -after get new dt for active particles. Then point *CurrT to next -T-node. -**************************************************************/ - -void ModifyLinkList(){ - - struct TNODE *Tp1,*Tp2,*newTNODE; - struct PNODE *Pptr,*Ptail; - - int i, iii; - double ttmp, t1, t2; - - for(i=0;iNextTNODE; - t1 = Tp1->t_node; - t2 = Tp2->t_node; - - Pptr = CreatePNODE( iii ); - - while( Tp1->NextTNODE != NULL ){ - if( ttmp == t1 ){ // if T-node exist, add a P-node - - if( Tp1->PartListEnd == NULL ){ // This is the first P-node under current T-node - Tp1->PartList = Pptr; - Tp1->PartListEnd = Pptr; - Tp1->n_node = Tp1->n_node + 1; - } - else{ // There are already many P-nodes under this T-node - Ptail = Tp1->PartListEnd; - Ptail->NextPNODE = Pptr; - Tp1->PartListEnd = Pptr; - Tp1->n_node = Tp1->n_node + 1; - } - break; // jump out of this "while" loop - } - - if( ttmp > t1 && ttmp < t2 ){ // Create a new T-node and insert between *Tp1 and *Tp2, then add P-node to it - - newTNODE = CreateTNODE(ttmp); - InsertTNODE( Tp1, Tp2, newTNODE); - - newTNODE->n_node = 1; - newTNODE->PartList = Pptr; - newTNODE->PartListEnd = Pptr; - - break; // jump out of this "while" loop - } - - // move to next T-node - Tp1 = Tp1->NextTNODE; - t1 = Tp1->t_node; - - if(Tp2->NextTNODE != NULL){ - Tp2 = Tp2->NextTNODE; - t2 = Tp2->t_node; - } - else{ break; } - - }//while( Tp1->NextTNODE != NULL ) - - }//for(i=0;iNextTNODE; - DeleteTNODE( Tp1 ); -} - -//End of ModifyLinkList() -/***************************************************************/ - - -/***************************************************************/ -/* -void i_swap(int *a, int *b) -{ -register int tmp; -tmp = *a; *a = *b; *b = tmp; -} -*/ -/***************************************************************/ -/***************************************************************/ -void ind_act_sort(int l, int r) -{ - -int i, j, cikl, tmp; - -i = l; j = r; -tmp = ind_act[(l+r)/2]; - -cikl = 1; - -while(cikl) - { - while (ind_act[i]PartList; - n_act = 0; - - min_t = CurrT->t_node; // IMPORTANT !! - - flag = 0; - - while(Pptr != NULL) - { - iii = Pptr->Pid; - Pptr = Pptr->NextPNODE; - if( m[iii] != 0.0 ) // Do not put zero mass part. in active plist - { - ind_act[i] = iii; -// if(ind_act[i]==N-1) flag=1; - i++; n_act++; - } - } - - if( n_act > 2 ) ind_act_sort( 0, n_act-1 ); - -// printf("last pid: %06d\n", ind_act_ll[n_act-1]); -// if( flag == 0 ) printf("Warning: BH not in the ind_act array!\n"); -// if( ind_act[n_act-1]!= N-1) printf("Warning: BH not in the last of ind_act array!\n"); - - }// End of get_act_plist() -/**************************************************************/ - - -#ifdef DEBUG_extra -/************************************************************** -Check link list -**************************************************************/ -void check_linklist(int Tstep) - { - FILE *listf; - struct TNODE *Tptr; - - listf = fopen("Check_linklist.dat","a"); - Tptr = CurrT; - fprintf(listf,"Timesteps = %04d\n", Tstep); - while(Tptr != NULL) - { - fprintf(listf,"% 8E %04d\n", Tptr->t_node, Tptr->n_node); - Tptr = Tptr->NextTNODE; - } - - fprintf(listf,"========================\n\n"); - - fclose(listf); - } -/**************************************************************/ -#endif - diff --git a/phigrape.cpp b/phigrape.cpp index d258c08..70804df 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -137,7 +137,6 @@ Last redaction : 2019.04.16 12:55 #error "Contradicting preprocessor flags!" #endif -/****************************************************************************/ #include #include #include @@ -231,8 +230,6 @@ double dt_disk, dt_contr, t_disk=0.0, t_contr=0.0, E_tot_corr, E_tot_corr_0, DE_tot_corr, E_tot_corr_sd, E_tot_corr_sd_0, DE_tot_corr_sd, E_corr = 0.0, E_sd = 0.0, t_diss_on = 0.125, - e_kin_corr = 0.0, e_pot_corr = 0.0, e_pot_BH_corr = 0.0, - e_summ_corr = 0.0, mcm, rcm_mod, vcm_mod, rcm_sum=0.0, vcm_sum=0.0, eps=0.0, eps2, @@ -252,8 +249,6 @@ double dt_disk, dt_contr, t_disk=0.0, t_contr=0.0, tmp_a_bh_pn0, tmp_a_bh_pn1, tmp_a_bh_pn2, tmp_a_bh_pn2_5, tmp_a_bh_pn3, tmp_a_bh_pn3_5, tmp_a_bh_spin, tmp_adot_bh_pn0, tmp_adot_bh_pn1, tmp_adot_bh_pn2, tmp_adot_bh_pn2_5, tmp_adot_bh_pn3, tmp_adot_bh_pn3_5, tmp_adot_bh_spin; -double R[3], V[3], L[3], mju, dr2, dr, dv2, dv, dl2, dl, pot_eff; - char processor_name[MPI_MAX_PROCESSOR_NAME], inp_fname[30], out_fname[30], dbg_fname[30]; @@ -335,10 +330,6 @@ double eps_BH=0.0; double m_bulge, a_bulge, b_bulge, m_disk, a_disk, b_disk, m_halo, a_halo, b_halo, -// x_ext, y_ext, z_ext, -// vx_ext, vy_ext, vz_ext, -// x_ij, y_ij, z_ij, -// vx_ij, vy_ij, vz_ij, rv_ij, x2_ij, y2_ij, z2_ij, r_tmp, r2_tmp, z_tmp, z2_tmp; #endif @@ -359,12 +350,6 @@ double r2, rv_ij, m_bh, b_bh, eps_bh; #endif -#ifdef EXTPOT_SC -int M_SC=M_SC_DIM; -double r_sc[M_SC_DIM], m_sc[M_SC_DIM], p_sc[M_SC_DIM]; -double M_R, pot_out_R; -#endif - double pot_ext[N_MAX], pot_act_ext[N_MAX]; // for all EXTPOT #endif @@ -383,9 +368,6 @@ double x_bbhc[3], v_bbhc[3], DR2, tmp_r2; double DV2, EB, SEMI_a, SEMI_a2; #endif -/****************************************************************************/ - -/****************************************************************************/ #ifdef ADD_N_BH double x_bh1[3], x_bh2[3], v_bh1[3], v_bh2[3]; @@ -432,9 +414,7 @@ return - 0 if everything OK */ #endif -/****************************************************************************/ -/****************************************************************************/ #ifdef ADD_PN_BH double C_NB = 477.12; @@ -447,11 +427,7 @@ double a_pn1[7][3], adot_pn1[7][3], double s_bh1[3] = {0.0, 0.0, 1.0}; double s_bh2[3] = {0.0, 0.0, 1.0}; -#ifdef ADD_SPIN_BH // eto rabotajet vsegda !!! #include "pn_bh_spin.c" -#else -#include "pn_bh.c" // eto staraja versija, bolshe ne rabotajet !!! -#endif /* int calc_force_pn_BH(double m1, double xx1[], double vv1[], double ss1[], @@ -495,9 +471,6 @@ return - 0 if everything OK #endif -/****************************************************************************/ - -/****************************************************************************/ /* RAND_MAX = 2147483647 */ /* my_rand : 0.0 - 1.0 */ /* my_rand2 : -1.0 - 1.0 */ @@ -511,19 +484,6 @@ double my_rand2(void) { return (double)(2.0)*((rand() - RAND_MAX/2)/(double)RAND_MAX); } -/****************************************************************************/ - -#ifdef STARDESTR -#include "star_destr.c" -#endif - -#ifdef STARDESTR_EXT -#include "star_destr_ext.c" -#endif - -#ifdef ACT_DEF_LL -#include "act_def_linklist.c" -#endif #ifdef ETICS double t_exp, dt_exp=ETICS_DTSCF; // t_exp is just the initial value @@ -532,7 +492,6 @@ int grapite_cep_index; #endif #endif -/****************************************************************************/ void get_CPU_time(double *time_real, double *time_user, double *time_syst) { struct rusage xxx; @@ -558,9 +517,7 @@ gettimeofday(&tv, NULL); *time_user = *time_real; } -/****************************************************************************/ -/****************************************************************************/ void read_data() { inp = fopen(inp_fname,"r"); @@ -574,34 +531,25 @@ for (i=0; i r) ) - { - r1 = r_sc[ii]; r2 = r_sc[ii+1]; - m1 = m_sc[ii]; m2 = m_sc[ii+1]; - p1 = p_sc[ii]; p2 = m_sc[ii+1]; - break; - } - } - -m_tmp = m1 + (r-r1)*(m2-m1)/(r2-r1); -p_tmp = p1 + (r-r1)*(p2-p1)/(r2-r1); - -// if (myRank == rootRank) -// { -// printf("\t \t \t %.6E %.6E \n", r1, r2); -// printf("\t \t \t %.6E %.6E \n", m1, m2); -// printf("\t \t \t %.6E %.6E \n", p1, p2); -// printf("\t \t \t %06d %.6E %.6E %.6E \n", ii, r, m_tmp, p_tmp); -// fflush(stdout); -// } /* if (myRank == rootRank) */ - -*M_R = m_tmp; -*pot_out_R = p_tmp; - -//exit(-1); - -} -#endif -/****************************************************************************/ - -/****************************************************************************/ void calc_ext_grav_zero() { @@ -1492,171 +1292,73 @@ for (i=0; i 100.0) jerk_i[ii][0] = 100.0; - if (ABS(jerk_i[ii][1]) > 100.0) jerk_i[ii][1] = 100.0; - if (ABS(jerk_i[ii][2]) > 100.0) jerk_i[ii][2] = 100.0; - } - - g6calc_firsthalf(clusterid, n_loc, nn, index_i, x_i, v_i , a_i, jerk_i, p_i, eps2, h2_i); - g6calc_lasthalf(clusterid, n_loc, nn, index_i, x_i, v_i, eps2, h2_i, a_i, jerk_i, p_i); - - g6_calls++; -*/ - - for (ii=0; ii R_LIMITS_ALL) && (tmp_rv > 0.0) ) { - for (k=0;k<3;k++) { - v[i][k] *= 1.0E-01; - } /* k */ - } /* if */ - } /* i */ -#endif - -#ifdef CMCORR - /* possible CM correction of the initial datafile... */ - if ( (diskstep == 0) && (time_cur == 0.0) ) cm_corr(); -#endif printf("\n"); printf("Begin the calculation of phi-GRAPE program on %03d processors\n", n_proc); printf("\n"); @@ -2327,12 +1992,6 @@ int main(int argc, char *argv[]) printf("v_halo = %.6E r_halo = %.6E \n", v_halo, r_halo); #endif -#ifdef EXTPOT_SC - read_SC_mass(); - - printf("EXTPOT_SC:# of points %06d \t M_SC_TOT = %.6E \n", M_SC_DIM-1, m_sc[M_SC_DIM-1]); -#endif - printf("\n"); #endif @@ -2377,104 +2036,12 @@ int main(int argc, char *argv[]) #endif // ADD_BH2 -#ifdef STARDESTR - -#ifdef ADD_BH2 - out = fopen("mass-bh.dat","w"); - m_bh1 = m[0]; - m_bh2 = m[1]; - num_bh1 = 0; - num_bh2 = 0; - fprintf(out,"%.8E \t %.8E %06d \t %.8E %06d \n", - time_cur, m_bh1, num_bh1, m_bh2, num_bh2); - fclose(out); - - out = fopen("mass-bh.con","w"); - m_bh1 = m[0]; - m_bh2 = m[1]; - num_bh1 = 0; - num_bh2 = 0; - fprintf(out,"%.8E \t %.8E %06d \t %.8E %06d \n", - time_cur, m_bh1, num_bh1, m_bh2, num_bh2); - fclose(out); -#else - -#ifdef ADD_BH1 - - out = fopen("mass-bh.dat","w"); - m_bh1 = m[0]; - num_bh1 = 0; - fprintf(out,"%.8E \t %.8E %06d \n", - time_cur, m_bh1, num_bh1); - fclose(out); - - out = fopen("mass-bh.con","w"); - m_bh1 = m[0]; - num_bh1 = 0; - fprintf(out,"%.8E \t %.8E %06d \n", - time_cur, m_bh1, num_bh1); - fclose(out); - -#endif // ADD_BH1 - -#endif // ADD_BH2 - -#endif // STARDESTR - -#ifdef STARDESTR_EXT - num_bh = 0; - out = fopen("mass-bh.dat","w"); - fprintf(out,"%.8E \t %.8E \t %06d \n", time_cur, m_bh, num_bh); - fclose(out); - - num_bh = 0; - out = fopen("mass-bh.con","w"); - fprintf(out,"%.8E \t %.8E \t %06d \n", time_cur, m_bh, num_bh); - fclose(out); - -#ifdef BH_OUT_NB_EXT - out = fopen("bh_nb.dat","w"); - fclose(out); -#endif - -#endif // STARDESTR_EXT - #ifdef BBH_INF out = fopen("bbh.inf","w"); fclose(out); #endif } else { // if (diskstep == 0) -#ifdef STARDESTR - -#ifdef ADD_BH2 - inp = fopen("mass-bh.con","r"); - fscanf(inp,"%lE %lE %d %lE %d", &tmp, &m_bh1, &num_bh1, &m_bh2, &num_bh2); - fclose(inp); - printf("%.8E \t %.8E %06d \t %.8E %06d \n", tmp, m_bh1, num_bh1, m_bh2, num_bh2); - fflush(stdout); -#else - -#ifdef ADD_BH1 - inp = fopen("mass-bh.con","r"); - fscanf(inp,"%lE %lE %d", &tmp, &m_bh1, &num_bh1); - fclose(inp); - printf("%.8E \t %.8E \t %06d \n", tmp, m_bh1, num_bh1); - fflush(stdout); -#endif // ADD_BH1 - -#endif // ADD_BH2 - -#endif // STARDESTR - -#ifdef STARDESTR_EXT - inp = fopen("mass-bh.con","r"); - fscanf(inp,"%lE %lE %d", &tmp, &m_bh, &num_bh); - fclose(inp); - printf("%.8E \t %.8E \t %06d \n", tmp, m_bh, num_bh); - fflush(stdout); -#endif // STARDESTR_EXT - } // if (diskstep == 0) get_CPU_time(&CPU_time_real0, &CPU_time_user0, &CPU_time_syst0); @@ -2539,18 +2106,6 @@ int main(int argc, char *argv[]) #endif // EXTPOT -#ifdef STARDESTR - MPI_Bcast(&m_bh1, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Bcast(&num_bh1, 1, MPI_INT, rootRank, MPI_COMM_WORLD); - - MPI_Bcast(&m_bh2, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Bcast(&num_bh2, 1, MPI_INT, rootRank, MPI_COMM_WORLD); -#endif // STARDESTR - -#ifdef STARDESTR_EXT - MPI_Bcast(&num_bh, 1, MPI_INT, rootRank, MPI_COMM_WORLD); -#endif // STARDESTR_EXT - /* Wait to all processors to finish his works... */ MPI_Barrier(MPI_COMM_WORLD); @@ -2867,14 +2422,6 @@ int main(int argc, char *argv[]) if (dt_tmp < dt_min) dt_tmp = dt_min; if (dt_tmp > dt_max) dt_tmp = dt_max; -#ifdef STARDESTR - if (m[i] == 0.0) dt_tmp = dt_max; -#endif - -#ifdef STARDESTR_EXT - if (m[i] == 0.0) dt_tmp = dt_max; -#endif - dt[i] = dt_tmp; #ifdef DT_MIN_WARNING @@ -2919,10 +2466,6 @@ int main(int argc, char *argv[]) #endif // ADD_BH2 -#ifdef ACT_DEF_LL - CreateLinkList(); -#endif - /* Wait to all processors to finish his works... */ MPI_Barrier(MPI_COMM_WORLD); @@ -3008,21 +2551,6 @@ int main(int argc, char *argv[]) /* Define the minimal time and the active particles on all the nodes (exclude the ZERO masses!!!) */ -#ifdef ACT_DEF_LL - -#ifdef TIMING - get_CPU_time(&CPU_tmp_real0, &CPU_tmp_user0, &CPU_tmp_syst0); -#endif - - get_act_plist(); - -#ifdef TIMING - get_CPU_time(&CPU_tmp_real, &CPU_tmp_user, &CPU_tmp_syst); - DT_ACT_DEF1 += (CPU_tmp_user - CPU_tmp_user0); -#endif - -#else - #ifdef TIMING get_CPU_time(&CPU_tmp_real0, &CPU_tmp_user0, &CPU_tmp_syst0); #endif @@ -3117,8 +2645,6 @@ int main(int argc, char *argv[]) DT_ACT_DEF2 += (CPU_tmp_user - CPU_tmp_user0); #endif -#endif // ACT_DEF_LL - #ifdef TIMING get_CPU_time(&CPU_tmp_real0, &CPU_tmp_user0, &CPU_tmp_syst0); #endif @@ -3344,14 +2870,6 @@ int main(int argc, char *argv[]) #endif // ADD_BH2 -#ifdef STARDESTR - if (m_act[i] == 0.0) dt_new = dt_max; -#endif - -#ifdef STARDESTR_EXT - if (m_act[i] == 0.0) dt_new = dt_max; -#endif - if (dt_new < dt_min) dt_tmp = dt_min; if ( (dt_new < dt_tmp) && (dt_new > dt_min) ) { @@ -3519,126 +3037,6 @@ int main(int argc, char *argv[]) DT_ACT_CORR += (CPU_tmp_user - CPU_tmp_user0); #endif - /* STARDESTR routine on all the nodes */ - -#ifdef STARDESTR - -#ifdef TIMING - get_CPU_time(&CPU_tmp_real0, &CPU_tmp_user0, &CPU_tmp_syst0); -#endif - -#ifdef ADD_BH2 - - star_destr(min_t, n_act, ind_act, m_act, x_act, v_act, pot_act, a_act, adot_act, t_act, dt_act, - N, ind, m, x, v, pot, a, adot, t, &m_bh1, &num_bh1, i_bh1); - - m_act[i_bh1] = m_bh1; - - star_destr(min_t, n_act, ind_act, m_act, x_act, v_act, pot_act, a_act, adot_act, t_act, dt_act, - N, ind, m, x, v, pot, a, adot, t, &m_bh2, &num_bh2, i_bh2); - - m_act[i_bh2] = m_bh2; - -#else - -#ifdef ADD_BH1 - - star_destr(min_t, n_act, ind_act, m_act, x_act, v_act, pot_act, a_act, adot_act, t_act, dt_act, - N, ind, m, x, v, pot, a, adot, t, &m_bh1, &num_bh1, i_bh1); - - m_act[i_bh1] = m_bh1; - -#endif // ADD_BH1 - -#endif // ADD_BH2 - -#ifdef LIMITS - for (i=0; i= t_contr) { if (myRank == rootRank) { -#ifdef STARDESTR - -#ifdef ADD_BH2 - - out = fopen("mass-bh.dat","a"); - fprintf(out,"%.8E \t %.8E %06d \t %.8E %06d \n", - time_cur, m_bh1, num_bh1, m_bh2, num_bh2); - fclose(out); - - out = fopen("mass-bh.con","w"); - fprintf(out,"%.8E \t %.8E %06d \t %.8E %06d \n", - time_cur, m_bh1, num_bh1, m_bh2, num_bh2); - fclose(out); - -#else - -#ifdef ADD_BH1 - - out = fopen("mass-bh.dat","a"); - fprintf(out,"%.8E \t %.8E %06d \n", - time_cur, m_bh1, num_bh1); - fclose(out); - - out = fopen("mass-bh.con","w"); - fprintf(out,"%.8E \t %.8E %06d \n", - time_cur, m_bh1, num_bh1); - fclose(out); - -#endif // ADD_BH1 - -#endif // ADD_BH2 - -#endif // STARDESTR - -#ifdef STARDESTR_EXT - - out = fopen("phi-GRAPE.ext","w"); - fprintf(out,"%.8E \t %.8E \n", m_bh, b_bh); - fclose(out); - - out = fopen("mass-bh.dat","a"); - fprintf(out,"%.8E \t %.8E \t %06d \n", time_cur, m_bh, num_bh); - fclose(out); - - out = fopen("mass-bh.con","w"); - fprintf(out,"%.8E \t %.8E \t %06d \n", time_cur, m_bh, num_bh); - fclose(out); - -#endif // STARDESTR_EXT energy_contr(); -#ifdef CMCORR111 - for (i=0; i R_LIMITS_ALL) && (tmp_rv > 0.0) ) { - for (k=0;k<3;k++) { - v[i][k] *= 1.0E-01; - } /* k */ - } /* if */ - } /* i */ - - for (j=0; j 900.0 ) - { - - m[i] = 0.0; - - pot[i] = 0.0; - -#ifdef EXTPOT - pot_ext[i] = 0.0; -#endif - - for (k=0;k<3;k++) - { - x[i][k] = 1000.0 + 1.0*my_rand2(); - v[i][k] = 1.0E-06*my_rand2(); - a[i][k] = 1.0E-06*my_rand2(); - adot[i][k] = 1.0E-06*my_rand2(); - } /* k */ - - t[i] = 2.0*t_end; - - dt[i] = 0.125; - - } /* if */ - - } /* i */ - - for (j=0; j= t_disk) */ -#ifdef CPU_TIMELIMIT - if (myRank == rootRank) { - get_CPU_time(&CPU_time_real, &CPU_time_user, &CPU_time_syst); - tmp_cpu = CPU_time_real-CPU_time_real0; - } /* if (myRank == rootRank) */ -#endif - -#ifdef ACT_DEF_LL - ModifyLinkList(); -#endif } /* while (time_cur < t_end) */ /* close the local GRAPE's */ diff --git a/pn_bh.c b/pn_bh.c deleted file mode 100644 index 54822f3..0000000 --- a/pn_bh.c +++ /dev/null @@ -1,765 +0,0 @@ -/***************************************************************************/ -/* - Coded by : Peter Berczik (on the base of Gabor Kupi original PN code) - Version number : 2.0 SPIN - Last redaction : 2012.V.07. 11:16 -*/ - -int calc_force_pn_BH(double m1, double xx1[], double vv1[], double spin1[], - double m2, double xx2[], double vv2[], double spin2[], - double CCC_NB, double dt_bh, - int usedOrNot[], - double a_pn1[][3], double adot_pn1[][3], - double a_pn2[][3], double adot_pn2[][3]) -{ - -/* - INPUT - -m1 - mass of the 1 BH -xx1[0,1,2] - coordinate of the 1 BH -vv1[0,1,2] - velocity of the 1 BH -spin1[0,1,2] - normalized spin of the 1 BH - -m2 - mass of the 2 BH -xx2[0,1,2] - coordinate of the 2 BH -vv2[0,1,2] - velocity of the 2 BH -spin2[0,1,2] - normalized spin of the 2 BH - -CCC_NB - Speed of light "c" in internal units -dt_BH - timestep of the BH's, needed for the SPIN integration - -usedOrNot[PN0, PN1, PN2, PN2.5, PN3, PN3.5, SPIN] - different PN term usage: PN1, PN2, PN2.5, PN3, PN3.5, SPIN - 0 1 2 3 4 5 6 - - OUTPUT - -a_pn1 [0 - PN0; 1 - PN1; 2 - PN2; 3 - PN2.5, 4 - PN3, 5 - PN3.5, 6 - SPIN] [3] for the 1 BH -adot_pn1[0 - PN0; 1 - PN1; 2 - PN2; 3 - PN2.5, 4 - PN3, 5 - PN3.5, 6 - SPIN] [3] for the 1 BH - -a_pn2 [0 - PN0; 1 - PN1; 2 - PN2; 3 - PN2.5, 4 - PN3, 5 - PN3.5, 6 - SPIN] [3] for the 2 BH -adot_pn2[0 - PN0; 1 - PN1; 2 - PN2; 3 - PN2.5, 4 - PN3, 5 - PN3.5, 6 - SPIN] [3] for the 2 BH - -return - 0 if everything OK - - 505 if BH's separation < 4 x (RSwarch1 + RSwarch2) -*/ - - - -int j, k; -double PI2 = 9.86960440108935; - -double c_1, c_2, c_4, c_5, c_6, c_7, RS_DIST; - -double M, eta, r, r2, r3, MOR; -double V1_V22,VWHOLE, RP, RPP, VA; -double N[3], x[3], v[3], A[3]; -double A1, B1, A2, B2, A2_5, B2_5, AK2, BK2, AK4, BK4, AK5, BK5; -double A1D, A2D, A2_5D, B1D, B2D, B2_5D, ADK2, BDK2, ADK4, BDK4, ADK5, BDK5; - -double A3, B3, A3_5, B3_5, AK6, BK6, AK7, BK7; -double A3D, A3_5D, B3D, B3_5D, ADK6, BDK6, ADK7, BDK7; - -int Van_Spin=0; -int Van_QM=0; - -double DM, S1[3], SPIN[3][2], S2[3], KSS[3], KSSIG[3], XS[3], XA[3], NCV[3], NCS[3], NCSIG[3], - VCS[3], VCSIG[3], SDNCV, SIGDNCV, NDV, XS2, XA2, NXA, NXS, VDS, VDSIG, NDS, NDSIG, - C1_5[3], C2[3], C2_5[3]; -double LABS, LU[3], S1DLU, S2DLU, SU1[3], SV1[3], SS1[3], SS2[3], SU2[3], SV2[3]; -double AT[3], NDOT[3], NVDOT, NDOTCV[3], NCA[3]; -double SS1aux[3],SS2aux[3],SU[3],SV[3],XAD[3],XSD[3]; -double NDOTCS[3], NCSU[3], NDOTCSIG[3], NCSV[3], ACS[3], VCSU[3], ACSIG[3], VCSV[3], SNVDOT, - SIGNVDOT, NSDOT, NSIGDOT, VSDOT, VSIGDOT, NXSDOT, NXADOT; -double C1_5D[3],C2D[3], C2_5D[3]; -double ADK, BDK, AD[3], KSAK, KSBK; -double nu, Spin1Abs2, Spin2Abs2, rS1, rS2, S1Dir[3], S2Dir[3], QM[3]; -double Spin1Abs, Spin2Abs, QMAux2_1[3], QMAux2_2[3], QMAux1[3] , QMD[3], SPINPrev[3][2], SpinPrev2_1, - SpinPrev2_2, SPSPP1, SPSPP2, Spin1AbsNew2, Spin2AbsNew2, Spin1AbsNew, Spin2AbsNew, S1DirNew[3], - S2DirNew[3], rS1p, rS2p, S1p[3], S2p[3], Np[3]; - - -Van_Spin = usedOrNot[6]; // Van vagy nincs SPIN szamolas... - - -for(k=0;k<3;k++) - { - SPIN[k][0] = spin1[k]; - SPIN[k][1] = spin2[k]; - } - - -for(j=0;j<7;j++) - { -for(k=0;k<3;k++) - { - a_pn1[j][k] = 0.0; adot_pn1[j][k] = 0.0; - a_pn2[j][k] = 0.0; adot_pn2[j][k] = 0.0; - } - } - - -// Speed of light "c" and its powers - -c_1 = CCC_NB; - -c_2 = SQR(c_1); -c_4 = SQR(c_2); -c_5 = c_4*c_1; -c_6 = c_5*c_1; -c_7 = c_6*c_1; - - -// Mass parameters - -M = m1+m2; -eta = m1*m2/(M*M); -nu = m1/m2; - -for(k=0;k<3;k++) - { - x[k] = xx1[k] - xx2[k]; - v[k] = vv1[k] - vv2[k]; - } - - -r2 = SQR(x[0]) + SQR(x[1]) + SQR(x[2]); -r = sqrt(r2); -r3 = r2*r; - -MOR = M/r; -V1_V22 = v[0]*v[0]+v[1]*v[1]+v[2]*v[2]; -VWHOLE = sqrt(V1_V22); -RP = (x[0]*v[0]+x[1]*v[1]+x[2]*v[2])/r; - - -// Newton accelerations - -for(k=0;k<3;k++) N[k] = x[k]/r; - -// PN accelerations - -AK2 = 0.0; BK2 = 0.0; -AK4 = 0.0; BK4 = 0.0; -AK5 = 0.0; BK5 = 0.0; -AK6 = 0.0; BK6 = 0.0; -AK7 = 0.0; BK7 = 0.0; - -for(k=0;k<3;k++) - { - C1_5[k] = 0.0; - C2[k] = 0.0; - C2_5[k] = 0.0; - QM[k] = 0.0; - } - - -if(usedOrNot[1] == 1) // PN1 ~1/c^2 - { - A1 = 2.0*(2.0+eta)*MOR-(1.0+3.0*eta)*V1_V22 +1.5*eta*RP*RP; - B1 = 2.0*(2.0-eta)*RP; - - AK2 = A1/c_2; - BK2 = B1/c_2; - } - -if(usedOrNot[2] == 1) // PN2 ~1/c^4 - { - A2 = -0.75*(12.0+29.0*eta)*MOR*MOR-eta*(3.0-4.0*eta)*V1_V22*V1_V22-1.875*eta*(1.0-3.0*eta)*RP*RP*RP*RP+0.5*eta*(13.0-4.0*eta)*MOR*V1_V22+(2.0+25.0*eta+2.0*eta*eta)*MOR*RP*RP+1.5*eta*(3.0-4.0*eta)*V1_V22*RP*RP; - B2 = -0.5*RP*((4.0+41.0*eta+8.0*eta*eta)*MOR-eta*(15.0+4.0*eta)*V1_V22+3.0*eta*(3.0+2.0*eta)*RP*RP); - - AK4 = A2/c_4; - BK4 = B2/c_4; - } - -if(usedOrNot[3] == 1) // PN2.5 ~1/c^5 - { - A2_5 = 1.6*eta*MOR*RP*(17.0*MOR/3.0+3.0*V1_V22); - B2_5 = -1.6*eta*MOR*(3.0*MOR+V1_V22); - - AK5 = A2_5/c_5; - BK5 = B2_5/c_5; - } - -if(usedOrNot[4] == 1) // PN3 ~1/c^6 - { - A3 = MOR*MOR*MOR*(16.0+(1399.0/12.0-41.0*PI2/16.0)*eta+ - 71.0*eta*eta/2.0)+eta*(20827.0/840.0+123.0*PI2/64.0-eta*eta) - *MOR*MOR*V1_V22-(1.0+(22717.0/168.0+615.0*PI2/64.0)*eta+ - 11.0*eta*eta/8.0-7.0*eta*eta*eta)*MOR*MOR*RP*RP- - 0.25*eta*(11.0-49.0*eta+52.0*eta*eta)*V1_V22*V1_V22*V1_V22+ - 35.0*eta*(1.0-5.0*eta+5.0*eta*eta)*RP*RP*RP*RP*RP*RP/16.0- - 0.25*eta*(75.0+32.0*eta-40.0*eta*eta)*MOR*V1_V22*V1_V22- - 0.5*eta*(158.0-69.0*eta-60.0*eta*eta)*MOR*RP*RP*RP*RP+ - eta*(121.0-16.0*eta-20.0*eta*eta)*MOR*V1_V22*RP*RP+ - 3.0*eta*(20.0-79.0*eta+60.0*eta*eta)*V1_V22*V1_V22*RP*RP/8.0- - 15.0*eta*(4.0-18.0*eta+17.0*eta*eta)*V1_V22*RP*RP*RP*RP/8.0; - - B3 = RP*((4.0+(5849.0/840.0+123.0*PI2/32.0)*eta-25.0*eta*eta- - 8.0*eta*eta*eta)*MOR*MOR+eta*(65.0-152.0*eta-48.0*eta*eta)* - V1_V22*V1_V22/8.0+15.0*eta*(3.0-8.0*eta-2.0*eta*eta)*RP*RP*RP*RP/8.0+ - eta*(15.0+27.0*eta+10.0*eta*eta)*MOR*V1_V22-eta*(329.0+177.0*eta+ - 108.0*eta*eta)*MOR*RP*RP/6.0- - 3.0*eta*(16.0-37.0*eta-16.0*eta*eta)*V1_V22*RP*RP/4.0); - - AK6 = A3/c_6; - BK6 = B3/c_6; - } - -if(usedOrNot[5] == 1) // PN3.5 ~1/c^7 - { - A3_5 = MOR*eta*(V1_V22*V1_V22*(-366.0/35.0-12.0*eta)+V1_V22*RP*RP*(114.0+12.0*eta)-112.0*RP*RP*RP*RP+MOR*(V1_V22*(-692.0/35.0+724.0*eta/15.0)+RP*RP*(-294.0/5.0-376.0*eta/5.0)+MOR*(-3956.0/35.0-184.0*eta/5.0))); - B3_5 = 8.0*eta*MOR*((1325.0+546.0*eta)*MOR*MOR/42.0+(313.0+42.0*eta)*V1_V22*V1_V22/28.0+75.0*RP*RP*RP*RP-(205.0+777.0*eta)*MOR*V1_V22/42.0+(205.0+424.0*eta)*MOR*RP*RP/12.0-3.0*(113.0+2.0*eta)*V1_V22*RP*RP/4.0)/5.0; - - AK7 = A3_5/c_7; - BK7 = B3_5/c_7; - } - - -// Spin accelerations - - if(Van_Spin==1) - { - DM = m1 - m2; - - Spin1Abs2 = 0.0; - Spin2Abs2 = 0.0; - rS1 = 0.0; - rS2 = 0.0; - - for(k=0;k<3;k++) - { - Spin1Abs2 += SPIN[k][0]*SPIN[k][0]; // normalizalt spin - Spin2Abs2 += SPIN[k][1]*SPIN[k][1]; - rS1 += N[k]*S1Dir[k]; - rS2 += N[k]*S2Dir[k]; - - S1[k] = SPIN[k][0]*m1*m1/c_1; // fizikai spin - S2[k] = SPIN[k][1]*m2*m2/c_1; - KSS[k] = S1[k]+S2[k]; - KSSIG[k] = M*(S2[k]/m2-S1[k]/m1); - XS[k] = 0.5*(SPIN[k][0]+SPIN[k][1]); - XA[k] = 0.5*(SPIN[k][0]-SPIN[k][1]); - } - - Spin1Abs = sqrt(Spin1Abs2); - Spin2Abs = sqrt(Spin2Abs2); - - for(k=0;k<3;k++) - { - S1Dir[k] = SPIN[k][0]/Spin1Abs; - S2Dir[k] = SPIN[k][1]/Spin2Abs; - } - - - //NCV crossproduct of N[k] and relative v = N[k]Xv[j] - NCV[0] = N[1]*v[2] - N[2]*v[1]; - NCV[1] = N[2]*v[0] - N[0]*v[2]; - NCV[2] = N[0]*v[1] - N[1]*v[0]; - - //NCS crossproduct of N[k] and KSS = N[k]XKSS - NCS[0] = N[1]*KSS[2] - N[2]*KSS[1]; - NCS[1] = N[2]*KSS[0] - N[0]*KSS[2]; - NCS[2] = N[0]*KSS[1] - N[1]*KSS[0]; - - //NCSIG crossproduct of N[k] and KSSIG = N[k]XKSSIG - NCSIG[0] = N[1]*KSSIG[2] - N[2]*KSSIG[1]; - NCSIG[1] = N[2]*KSSIG[0] - N[0]*KSSIG[2]; - NCSIG[2] = N[0]*KSSIG[1] - N[1]*KSSIG[0]; - - //VCS crossproduct of v[k] and KSS = v[k]XKSS - VCS[0] = v[1]*KSS[2] - v[2]*KSS[1]; - VCS[1] = v[2]*KSS[0] - v[0]*KSS[2]; - VCS[2] = v[0]*KSS[1] - v[1]*KSS[0]; - - //VCSIG crossproduct of v[k] and KSSIG = v[k]XKSSIG - VCSIG[0] = v[1]*KSSIG[2] - v[2]*KSSIG[1]; - VCSIG[1] = v[2]*KSSIG[0] - v[0]*KSSIG[2]; - VCSIG[2] = v[0]*KSSIG[1] - v[1]*KSSIG[0]; - - SDNCV = KSS[0]*NCV[0]+KSS[1]*NCV[1]+KSS[2]*NCV[2]; - - SIGDNCV = KSSIG[0]*NCV[0]+KSSIG[1]*NCV[1]+KSSIG[2]*NCV[2]; - - NDV = N[0]*v[0] + N[1]*v[1] + N[2]*v[2]; - - XS2 = XS[0]*XS[0]+XS[1]*XS[1]+XS[2]*XS[2]; - XA2 = XA[0]*XA[0]+XA[1]*XA[1]+XA[2]*XA[2]; - - NXA = N[0]*XA[0]+N[1]*XA[1]+N[2]*XA[2]; - NXS = N[0]*XS[0]+N[1]*XS[1]+N[2]*XS[2]; - - VDS = v[0]*KSS[0]+v[1]*KSS[1]+v[2]*KSS[2]; - VDSIG = v[0]*KSSIG[0]+v[1]*KSSIG[1]+v[2]*KSSIG[2]; - - NDS = N[0]*KSS[0]+N[1]*KSS[1]+N[2]*KSS[2]; - NDSIG = N[0]*KSSIG[0]+N[1]*KSSIG[1]+N[2]*KSSIG[2]; - - for(k=0;k<3;k++) - { - C1_5[k] = (N[k]*(12.0*SDNCV+6.0*DM*SIGDNCV/M)+9.0*NDV*NCS[k]+3.0*DM*NDV*NCSIG[k]/M -7.0*VCS[k]-3.0*DM*VCSIG[k]/M)/r3; - C2[k] = -MOR*MOR*MOR/r*3.0*eta*(N[k]*(XS2-XA2-5.0*NXS*NXS+5.0*NXA*NXA)+2.0*(XS[k]*NXS-XA[k]*NXA)); - C2_5[k] = (N[k]*(SDNCV*(-30.0*eta*NDV*NDV+24.0*eta*V1_V22-MOR*(38.0+25.0*eta))+DM/M*SIGDNCV*(-15.0*eta*NDV*NDV+12.0*eta*V1_V22 - -MOR*(18.0+14.5*eta)))+NDV*v[k]*(SDNCV*(-9.0+9.0*eta)+DM/M* SIGDNCV*(-3.0+6.0*eta))+NCV[k]*(NDV*VDS*(-3.0+3.0*eta) - -8.0*MOR*eta*NDS-DM/M*(4.0*MOR*eta*NDSIG+3.0*NDV*VDSIG))+NDV*NCS[k]*(-22.5*eta*NDV*NDV+21.0*eta*V1_V22-MOR*(25.0+15.0*eta)) - +DM/M*NDV*NCSIG[k]*(-15.0*eta*NDV*NDV+12.0*eta*V1_V22-MOR*(9.0+8.5*eta))+VCS[k]*(16.5*eta*NDV*NDV+MOR*(21.0+9.0*eta) - -14.0*eta*V1_V22)+DM/M*VCSIG[k]*(9.0*eta*NDV*NDV-7.0*eta*V1_V22+MOR*(9.0+4.5*eta)))/r3; - - if(Van_QM==1) - { - - if(m1>m2) - { - QMAux2_1[k] = (1.0-5.0*rS1*rS1)*N[k]+2.0*rS1*S1Dir[k]; - QMAux2_2[k] = (1.0-5.0*rS2*rS2)*N[k]+2.0*rS2*S2Dir[k]; - QMAux1[k] = Spin1Abs2*QMAux2_1[k]/nu+Spin2Abs2*QMAux2_2[k]*nu; - QM[k] = -1.5*MOR*MOR*MOR*eta*QMAux1[k]/r; - } - else - { - QMAux2_1[k] = (1.0-5.0*rS2*rS2)*N[k]+2.0*rS2*S2Dir[k]; - QMAux2_2[k] = (1.0-5.0*rS1*rS1)*N[k]+2.0*rS1*S1Dir[k]; - QMAux1[k] = Spin2Abs2*QMAux2_1[k]/nu+Spin1Abs2*QMAux2_2[k]*nu; - QM[k] = -1.5*MOR*MOR*MOR*eta*QMAux1[k]/r; - } - - } /* if(Van_QM==1) */ - - } /* k */ - - } /* if(Van_Spin==1) */ - - - - - -for(k=0;k<3;k++) - { - -if(usedOrNot[0] == 1) // PN0 (Newton) ~1/c^0 - { - a_pn1[0][k] = -m2*x[k]/r3; - a_pn2[0][k] = m1*x[k]/r3; - } - -if(usedOrNot[1] == 1) // PN1 ~1/c^2 - { - a_pn1[1][k] = ((AK2*N[k] + BK2*v[k])/r2)*m2; - a_pn2[1][k] = -((AK2*N[k] + BK2*v[k])/r2)*m1; - } - -if(usedOrNot[2] == 1) // PN2 ~1/c^4 - { - a_pn1[2][k] = ((AK4*N[k] + BK4*v[k])/r2)*m2; - a_pn2[2][k] = -((AK4*N[k] + BK4*v[k])/r2)*m1; - } - -if(usedOrNot[3] == 1) // PN2.5 ~1/c^5 - { - a_pn1[3][k] = ((AK5*N[k] + BK5*v[k])/r2)*m2; - a_pn2[3][k] = -((AK5*N[k] + BK5*v[k])/r2)*m1; - } - -if(usedOrNot[4] == 1) // PN3 ~1/c^6 - { - a_pn1[4][k] = ((AK6*N[k] + BK6*v[k])/r2)*m2; - a_pn2[4][k] = -((AK6*N[k] + BK6*v[k])/r2)*m1; - } - -if(usedOrNot[5] == 1) // PN3.5 ~1/c^7 - { - a_pn1[5][k] = ((AK7*N[k] + BK7*v[k])/r2)*m2; - a_pn2[5][k] = -((AK7*N[k] + BK7*v[k])/r2)*m1; - } - -if(Van_Spin == 1) // All the SPIN terms - { - a_pn1[6][k] += (C1_5[k]/c_2 + C2[k]/c_4 + C2_5[k]/c_4 + QM[k]/c_4)*m2/M; - a_pn2[6][k] += -(C1_5[k]/c_2 + C2[k]/c_4 + C2_5[k]/c_4 + QM[k]/c_4)*m1/M; - } - - A[k] = MOR*((AK2+AK4+AK5+AK6+AK7)*N[k] + (BK2+BK4+BK5+BK6+BK7)*v[k])/r + C1_5[k]/c_2 + C2[k]/c_4 + C2_5[k]/c_4 + QM[k]/c_4; - } - -// PN accelerations - - - - -// PN jerks - -for(k=0;k<3;k++) - { - AT[k] = A[k] - MOR*N[k]/r; // miert van AT - ? - } - -/* -AT[0] = A[0]; -AT[1] = A[1]; -AT[2] = A[2]; -*/ - -RPP = V1_V22/r + AT[0]*N[0]+AT[1]*N[1] + AT[2]*N[2] - RP*RP/r; -VA = AT[0]*v[0] + AT[1]*v[1] + AT[2]*v[2]; - -for(k=0;k<3;k++) NDOT[k] = (v[k]-N[k]*RP)/r; - -NVDOT = NDOT[0]*v[0]+NDOT[1]*v[1]+NDOT[2]*v[2]+N[0]*AT[0]+N[1]*AT[1]+N[2]*AT[2]; - -//NDOTCV crossproduct of NDOT[k] and relative v = NDOT[k]Xv[j] -NDOTCV[0] = NDOT[1]*v[2] - NDOT[2]*v[1]; -NDOTCV[1] = NDOT[2]*v[0] - NDOT[0]*v[2]; -NDOTCV[2] = NDOT[0]*v[1] - NDOT[1]*v[0]; - -//NCA crossproduct of N and AT = N[k]XAT[j] -NCA[0] = N[1]*AT[2] - N[2]*AT[1]; -NCA[1] = N[2]*AT[0] - N[0]*AT[2]; -NCA[2] = N[0]*AT[1] - N[1]*AT[0]; - -ADK2 = 0.0; BDK2 = 0.0; -ADK4 = 0.0; BDK4 = 0.0; -ADK5 = 0.0; BDK5 = 0.0; -ADK6 = 0.0; BDK6 = 0.0; -ADK7 = 0.0; BDK7 = 0.0; - - -for(k=0;k<3;k++) - { - C1_5D[k] = 0.0; - C2D[k] = 0.0; - C2_5D[k] = 0.0; - QMD[k] = 0.0; - } - -if(usedOrNot[1] == 1) // PN1 ~1/c^2 - { - A1D = -2.0*(2.0+eta)*MOR*RP/r - 2.0*(1.0+3.0*eta)*VA + 3.0*eta*RP*RPP; - B1D = 2.0*(2.0-eta)*RPP; - - ADK2 = A1D/c_2; - BDK2 = B1D/c_2; - } - -if(usedOrNot[2] == 1) // PN2 ~1/c^4 - { - A2D = 1.5*(12.0+29.0*eta)*MOR*MOR*RP/r -eta*(3.0-4.0*eta)*4.0*V1_V22*VA - 7.5*eta*(1.0-3.0*eta)*RPP -0.5*eta*(13.0-4.0*eta)*MOR*RP*V1_V22/r+eta*(13.0-4.0*eta)*MOR*VA -(2.0+25.0*eta+2.0*eta*eta)*MOR*RP*RP*RP/r+2.0*(2.0+25.0*eta+2.0*eta*eta)*MOR*RP*RPP + 3.0*eta*(3.0-4.0*eta)*VA*RP*RP + 3.0*eta*(3.0-4.0*eta)*V1_V22*RP*RPP; - B2D = -0.5*RPP*((4.0+41.0*eta+8.0*eta*eta)*MOR - eta*(15.0+4.0*eta)*V1_V22+3.0*eta*(3.0+2.0*eta)*RP*RP) - 0.5*RP*(-(4.0+41.0*eta+8.0*eta*eta)*MOR*RP/r - 2.0*eta*(15.0+4.0*eta)*VA + 6.0*eta*(3.0+2.0*eta)*RP*RPP); - - ADK4 = A2D/c_4; - BDK4 = B2D/c_4; - } - -if(usedOrNot[3] == 1) // PN2.5 ~1/c^5 - { - A2_5D = -1.6*eta*MOR*RP*RP*(17.0/3.0*MOR+3.0*V1_V22)/r +1.6*eta*MOR*RPP*(17.0/3.0*MOR+3.0*V1_V22)+1.6*eta*MOR*RP*(-17.0*MOR*RP/3.0/r+6.0*VA); - B2_5D = 1.6*eta*MOR*RP*(3.0*MOR+V1_V22)/r - 1.6*eta*MOR*(-3.0*MOR*RP/r+2.0*VA); - - ADK5 = A2_5D/c_5; - BDK5 = B2_5D/c_5; - } - -if(usedOrNot[4] == 1) // PN3 ~1/c^6 - { - A3D = 6.0*eta*RP*RP*RP*RP*RP*RPP*(35.0-175.0*eta+175.0*eta*eta)/16.0 + eta*(4.0*RP*RP*RP*RPP*V1_V22 + 2.0*RP*RP*RP*RP*VA)*(-15.0+135.0*eta/2.0-255.0*eta*eta/4.0)/2.0 + eta*(2.0*RP*RPP*V1_V22*V1_V22+4.0*RP*RP*V1_V22*VA)/2.0*(15.0-237.0*eta/2.0+45.0*eta*eta) + 6.0*V1_V22*V1_V22*VA*eta*(-11.0/4.0-49.0*eta/4.0-13.0*eta*eta) + MOR*(4.0*RP*RP*RP*RPP*eta*(-79.0+69.0/2.0*eta+30.0*eta*eta) + eta*(2.0*RP*RPP*V1_V22+2.0*RP*RP*VA)*(121.0-16.0*eta-20.0*eta*eta)+4.0*V1_V22*VA*eta*(-75.0/4.0-8.0*eta+10.0*eta*eta)) - MOR*RP*((-79.0+69.0*eta/2.0+30.0*eta*eta)*RP*RP*RP*RP*eta+eta*RP*RP*V1_V22*(121.0-16.0*eta-20.0*eta*eta)+eta*V1_V22*V1_V22*(-75.0/4.0-8.0*eta+10.0*eta*eta))/r - 2.0*MOR*MOR*RP*(RP*RP*((-1.0-615.0*PI2*eta/64.0)-22717.0*eta/168.0-11.0*eta*eta/8.0+7.0*eta*eta*eta)+eta*V1_V22*((20827.0/840.0+123.0*PI2/64.0)-eta*eta))/r + MOR*MOR*(2.0*RP*RPP*((-1.0-615*PI2*eta/64.0)-22717.0*eta/168.0-11.0*eta*eta/8.0+7*eta*eta*eta)+2.0*eta*VA*((20827.0/840.0 +123.0*PI2/64.0)-eta*eta)) - 3.0*MOR*MOR*MOR*RP*(16.0+(1399.0/12.0-41.0*PI2/16.0)*eta+71.0*eta*eta/2.0)/r; - B3D = 75.0*RP*RP*RP*RP*RPP*eta*(3.0/8.0-eta-.25*eta*eta)+eta*(3.0*RP*RP*RPP*V1_V22+2.0*RP*RP*RP*VA)*(-12.0+111.0*eta/4.0+12.0*eta*eta)+eta*(RPP*V1_V22*V1_V22+4.0*RP*V1_V22*VA)*(65.0/8.0-19.0*eta-6.0*eta*eta)-MOR*RP*(RP*RP*RP*eta*(-329.0/6.0-59.0*eta/2.0-18.0*eta*eta)+RP*V1_V22*eta*(15.0+27.0*eta+10.0*eta*eta))/r+MOR*(3.0*RP*RP*RPP*eta*(-329.0/6.0-59.0*eta/2.0-18.0*eta*eta)+eta*(RPP*V1_V22+2.0*RP*VA)*(15.0+27.0*eta+10.0*eta*eta))-2.0*MOR*MOR*RP*(RP*((4.0+123.0*PI2*eta/32.0)+5849.0*eta/840.0-25.0*eta*eta-8.0*eta*eta*eta))/r+MOR*MOR*(RPP*((4.0+123.0*PI2*eta/32.0)+5849.0/840.0*eta-25.0*eta*eta-8.0*eta*eta*eta)); - - ADK6 = A3D/c_6; - BDK6 = B3D/c_6; - } - -if(usedOrNot[5] == 1) // PN3.5 ~1/c^7 - { - A3_5D = MOR*eta*(-RP*(V1_V22*V1_V22*(-366.0/35.0-12.0*eta)+V1_V22*RP*RP*(114.0+12.0*eta)+RP*RP*RP*RP*(-112.0))/r+4.0*V1_V22*VA*(-366.0/35.0-12.0*eta)+2.0*(VA*RP*RP+RP*RPP*V1_V22)*(114.0+12.0*eta)+4.0*RP*RP*RP*RPP*(-112.0)+MOR*(2.0*VA*(-692.0/35.0+724.0*eta/15.0)+2.0*RP*RPP*(-294.0/5.0-376.0*eta/5.0)-2.0*RP*(V1_V22*(-692.0/35.0+724.0*eta/15.0)+RP*RP*(-294.0/5.0-376.0*eta/5.0))/r-3.0*MOR*RP*(-3956.0/35.0-184.0*eta/5.0)/r)); - B3_5D = MOR*eta*(4.0*V1_V22*VA*(626.0/35.0+12.0*eta/5.0)+2.0*(VA*RP*RP+V1_V22*RP*RPP)*(-678.0/5.0-12.0*eta/5.0)+4.0*RP*RP*RP*RPP*120.0-RP*(V1_V22*V1_V22*(626.0/35.0+12.0*eta/5.0)+V1_V22*RP*RP*(-678.0/5.0-12.0*eta/5.0)+120.0*RP*RP*RP*RP)/r+MOR*(2.0*VA*(-164.0/21.0-148.0*eta/5.0)+2*RP*RPP*(82.0/3.0+848.0*eta/15.0)-2.0*RP*(V1_V22*(-164.0/21-148.0*eta/5.0)+RP*RP*(82.0/3.0+848.0*eta/15.0))/r-3.0*MOR*RP*(1060.0/21.0+104.0*eta/5.0)/r)); - - ADK7 = A3_5D/c_7; - BDK7 = B3_5D/c_7; - } - - - - - - if(Van_Spin==1) - { - - //L crossproduct of x[k] and relative v = x[k]Xv[j] - L[0] = x[1]*v[2] - x[2]*v[1]; - L[1] = x[2]*v[0] - x[0]*v[2]; - L[2] = x[0]*v[1] - x[1]*v[0]; - - LABS = sqrt(L[0]*L[0]+L[1]*L[1]+L[2]*L[2]); - - LU[0] = L[0]/LABS; - LU[1] = L[1]/LABS; - LU[2] = L[2]/LABS; - - S1DLU = S1[0]*LU[0]+S1[1]*LU[1]+S1[2]*LU[2]; - S2DLU = S2[0]*LU[0]+S2[1]*LU[1]+S2[2]*LU[2]; - - for(k=0;k<3;k++) - { - SU1[k] = MOR*eta*(N[k]*(-4.0*VDS-2.0*DM/M*VDSIG)+ v[k]*(3.0*NDS+DM/M*NDSIG)+NDV*(2.0*KSS[k]+DM/M*KSSIG[k])) /r; - SV1[k] = MOR*(N[k]*(VDSIG*(-2.0+4.0*eta)-2.0*DM/M*VDS)+ v[k]*(NDSIG*(1.0-eta)+DM/M*NDS)+NDV*(KSSIG[k]*(1.0- 2.0*eta)+ DM/M*KSS[k]))/r; - - SS1[k] = 0.5*(L[k]*(4.0+3.0*(m2/m1))+ (S2[k]-3.0*S2DLU*LU[k]))/r3; - SS2[k] = 0.5*(L[k]*(4.0+3.0*(m1/m2))+ (S1[k]-3.0*S1DLU*LU[k]))/r3; - - SU2[k] = MOR*eta/r*(N[k]*(VDS*(-2.0*V1_V22+3.0*NDV*NDV- 6.0*eta*NDV*NDV+7.0*MOR-8.0*eta*MOR)-14.0*MOR*NDS*NDV+ DM/M*VDSIG*eta*(-3.0*NDV*NDV-4.0*MOR)+DM/M*MOR*NDSIG*NDV* (2.0-eta/2.))+v[k]*(NDS*(2.0*V1_V22-4.0*eta*V1_V22-3.0*NDV* NDV+7.5*eta*NDV*NDV+4.0*MOR-6.0*eta*MOR)+VDS*NDV*(2.0- 6.0*eta)+ DM/M*NDSIG*(-1.5*eta*V1_V22+3.0*eta*NDV*NDV-MOR-3.5*eta* MOR)-3.0*DM/M*VDSIG*NDV*eta)+KSS[k]*NDV*(V1_V22-2.0*eta* V1_V22-1.5*NDV*NDV+3.0*eta*NDV*NDV-MOR+2.0*eta*MOR)+ DM/M*KSSIG[k]*NDV*(-eta*V1_V22+1.5*eta*NDV*NDV+ (eta-1.)*MOR)); - SV2[k] = MOR/r*(N[k]*(VDSIG*eta*(-2.0*V1_V22+6.0*eta*NDV* NDV+(3.0+8.0*eta)*MOR)+MOR*NDSIG*NDV*(2.0-22.5*eta+2.0* eta*eta)+ DM/M*VDS*eta*(-3.0*NDV*NDV-4.0*MOR)+DM/M*MOR*NDS*NDV*(2.0- 0.5*eta))+v[k]*(NDSIG*(0.5*eta*V1_V22+2.0*eta*eta*V1_V22- 4.5*eta*eta*NDV*NDV+(4.5*eta-1.0+8.0*eta*eta)*MOR)+VDSIG*NDV* eta*(6.0*eta-1.)-3.0*DM/M*VDS*NDV*eta+DM/M*NDS*(-1.5* eta*V1_V22+ 3.0*eta*NDV*NDV-(1.0+3.5*eta)*MOR))+KSSIG[k]*NDV*(2.0*eta*eta* V1_V22-3.0*eta*eta*NDV*NDV+(-1.0+4.0*eta-2.0*eta*eta)*MOR)+ DM/M*KSS[k]*NDV*(-eta*V1_V22+1.5*eta*NDV*NDV+(-1.0+eta)* MOR)); - } - - //SS1 crossproduct of SS1 and S1 = SS1[k]XS1[j] - SS1aux[0] = SS1[1]*S1[2] - SS1[2]*S1[1]; - SS1aux[1] = SS1[2]*S1[0] - SS1[0]*S1[2]; - SS1aux[2] = SS1[0]*S1[1] - SS1[1]*S1[0]; - - SS1[0] = SS1aux[0]; - SS1[1] = SS1aux[1]; - SS1[2] = SS1aux[2]; - - //SS2 crossproduct of SS2 and S2 = SS2[k]XS2[j] - SS2aux[0] = SS2[1]*S2[2] - SS2[2]*S2[1]; - SS2aux[1] = SS2[2]*S2[0] - SS2[0]*S2[2]; - SS2aux[2] = SS2[0]*S2[1] - SS2[1]*S2[0]; - - SS2[0] = SS2aux[0]; - SS2[1] = SS2aux[1]; - SS2[2] = SS2aux[2]; - - SPINPrev[0][0] = SPIN[0][0]; - SPINPrev[1][0] = SPIN[1][0]; - SPINPrev[2][0] = SPIN[2][0]; - - SPINPrev[0][1] = SPIN[0][1]; - SPINPrev[1][1] = SPIN[1][1]; - SPINPrev[2][1] = SPIN[2][1]; - - SpinPrev2_1 = SPINPrev[0][0]*SPINPrev[0][0] + SPINPrev[1][0]*SPINPrev[1][0] + SPINPrev[2][0]*SPINPrev[2][0]; - SpinPrev2_2 = SPINPrev[0][1]*SPINPrev[0][1] + SPINPrev[1][1]*SPINPrev[1][1] + SPINPrev[2][1]*SPINPrev[2][1]; - - SPSPP1 = 0.0; - SPSPP2 = 0.0; - - Spin1AbsNew2 = 0.0; - Spin2AbsNew2 = 0.0; - - for(k=0;k<3;k++) - { - SU[k] = SU1[k]/c_2 + SU2[k]/c_4 + (SS1[k] + SS2[k])/c_2; - SV[k] = SV1[k]/c_2 + SV2[k]/c_4+M*(SS2[k]/m2-SS1[k]/ m1)/c_2; - - KSS[k] = KSS[k] + SU[k]*dt_bh; // integrate for dt_bh timestep - KSSIG[k] = KSSIG[k] + SV[k]*dt_bh; - - SPIN[k][0] = m1*(M*KSS[k]-m2*KSSIG[k])/M/M/m1/m1*c_1; - SPIN[k][1] = m2*(M*KSS[k]+m1*KSSIG[k])/M/M/m2/m2*c_1; - Spin1AbsNew2 += SPIN[k][0]*SPIN[k][0]; - Spin2AbsNew2 += SPIN[k][1]*SPIN[k][1]; - XAD[k] = 0.5/(M*M*m1*m2)*(-SU[k]*M*DM-SV[k]*(m1*m1+m2*m2)); - XSD[k] = 0.5/(M*M*m1*m2)*(SU[k]*M*M+SV[k]*(m1*m1-m2*m2)); - - if(m1>m2) - { - SPSPP1 += SPINPrev[k][0]*(SPIN[k][0]-SPINPrev[k][0])/dt_bh; - SPSPP2 += SPINPrev[k][1]*(SPIN[k][1]-SPINPrev[k][1])/dt_bh; - } - else - { - SPSPP1 += SPINPrev[k][1]*(SPIN[k][1]-SPINPrev[k][1])/dt_bh; - SPSPP2 += SPINPrev[k][0]*(SPIN[k][0]-SPINPrev[k][0])/dt_bh; - } - } - - Spin1AbsNew = sqrt(Spin1AbsNew2); - Spin2AbsNew = sqrt(Spin2AbsNew2); - - for(k=0;k<3;k++) - { - S1DirNew[k] = SPIN[k][0]/Spin1AbsNew; - S2DirNew[k] = SPIN[k][1]/Spin2AbsNew; - } - - - //NDOTCS crossproduct of NDOT and KSS = NDOT[k]XKSS[j] - NDOTCS[0] = NDOT[1]*KSS[2] - NDOT[2]*KSS[1]; - NDOTCS[1] = NDOT[2]*KSS[0] - NDOT[0]*KSS[2]; - NDOTCS[2] = NDOT[0]*KSS[1] - NDOT[1]*KSS[0]; - //NCSU crossproduct of N and SU = N[k]XSU[j] - NCSU[0] = N[1]*SU[2] - N[2]*SU[1]; - NCSU[1] = N[2]*SU[0] - N[0]*SU[2]; - NCSU[2] = N[0]*SU[1] - N[1]*SU[0]; - //NDOTCSIG crossproduct of NDOT and KSSIG = NDOT[k]XKSSIG[j] - NDOTCSIG[0] = NDOT[1]*KSSIG[2] - NDOT[2]*KSSIG[1]; - NDOTCSIG[1] = NDOT[2]*KSSIG[0] - NDOT[0]*KSSIG[2]; - NDOTCSIG[2] = NDOT[0]*KSSIG[1] - NDOT[1]*KSSIG[0]; - //NCSV crossproduct of N and SV = N[k]XSV[j] - NCSV[0] = N[1]*SV[2] - N[2]*SV[1]; - NCSV[1] = N[2]*SV[0] - N[0]*SV[2]; - NCSV[2] = N[0]*SV[1] - N[1]*SV[0]; - //ACS crossproduct of AT and KSS = AT[k]XKSS[j] - ACS[0] = AT[1]*KSS[2] - AT[2]*KSS[1]; - ACS[1] = AT[2]*KSS[0] - AT[0]*KSS[2]; - ACS[2] = AT[0]*KSS[1] - AT[1]*KSS[0]; - //VCSU crossproduct of relative v and SU = v[k]XSU[j] - VCSU[0] = v[1]*SU[2] - v[2]*SU[1]; - VCSU[1] = v[2]*SU[0] - v[0]*SU[2]; - VCSU[2] = v[0]*SU[1] - v[1]*SU[0]; - //ACSIG crossproduct of AT and KSSIG = AT[k]XKSSIG[j] - ACSIG[0] = AT[1]*KSSIG[2] - AT[2]*KSSIG[1]; - ACSIG[1] = AT[2]*KSSIG[0] - AT[0]*KSSIG[2]; - ACSIG[2] = AT[0]*KSSIG[1] - AT[1]*KSSIG[0]; - //VCSV crossproduct of relative v and SV = v[k]XSV[j] - VCSV[0] = v[1]*SV[2] - v[2]*SV[1]; - VCSV[1] = v[2]*SV[0] - v[0]*SV[2]; - VCSV[2] = v[0]*SV[1] - v[1]*SV[0]; - - SNVDOT = SU[0]*NCV[0]+SU[1]*NCV[1]+SU[2]*NCV[2]+ KSS[0]*NDOTCV[0]+KSS[1]*NDOTCV[1]+KSS[2]*NDOTCV[2]+ KSS[0]*NCA[0]+KSS[1]*NCA[1]+KSS[2]*NCA[2]; - - SIGNVDOT = SV[0]*NCV[0]+SV[1]*NCV[1]+SV[2]*NCV[2]+ KSSIG[0]*NDOTCV[0]+KSSIG[1]*NDOTCV[1]+KSSIG[2]*NDOTCV[2]+ KSSIG[0]*NCA[0]+KSSIG[1]*NCA[1]+KSSIG[2]*NCA[2]; - - NSDOT = NDOT[0]*KSS[0]+NDOT[1]*KSS[1]+NDOT[2]*KSS[2]+ N[0]*SU[0]+N[1]*SU[1]+N[2]*SU[2]; - NSIGDOT = NDOT[0]*KSSIG[0]+NDOT[1]*KSSIG[1]+NDOT[2]*KSSIG[2]+ N[0]*SV[0]+N[1]*SV[1]+N[2]*SV[2]; - VSDOT = AT[0]*KSS[0]+AT[1]*KSS[1]+AT[2]*KSS[2]+ v[0]*SU[0]+v[1]*SU[1]+v[2]*SU[2]; - VSIGDOT = AT[0]*KSSIG[0]+AT[1]*KSSIG[1]+AT[2]*KSSIG[2]+ v[0]*SV[0]+v[1]*SV[1]+v[2]*SV[2]; - - NXSDOT = NDOT[0]*XS[0]+NDOT[1]*XS[1]+NDOT[2]*XS[2]+ N[0]*XSD[0]+N[1]*XSD[1]+N[2]*XSD[2]; - NXADOT = NDOT[0]*XA[0]+NDOT[1]*XA[1]+NDOT[2]*XA[2]+ N[0]*XAD[0]+N[1]*XAD[1]+N[2]*XAD[2]; - - rS1p = -rS1*NDV/r; - rS2p = -rS2*NDV/r; - - for(k=0;k<3;k++) - { - S1p[k] = (S1DirNew[k] - S1Dir[k])/dt_bh; - S2p[k] = (S2DirNew[k] - S2Dir[k])/dt_bh; - - rS1p += v[k]*S1Dir[k]/r + N[k]*S1p[k]; - rS2p += v[k]*S2Dir[k]/r + N[k]*S2p[k]; - - Np[k] = (v[k] - N[k]*NDV)/r; - } - - for(k=0;k<3;k++) - { - C1_5D[k] = -3.0*RP/r*C1_5[k]+(NDOT[k]*(12.0*SDNCV+6.0*DM/M* SIGDNCV)+N[k]*(12.0*SNVDOT+6.0*DM/M*SIGNVDOT)+9.0*NVDOT* NCS[k]+9.0*NDV*(NDOTCS[k]+NCSU[k])+3.0*DM/M*(NVDOT*NCSIG[k]+ NDV*(NDOTCSIG[k]+NCSV[k]))-7.0*(ACS[k]+VCSU[k])-3.0*DM/M* (ACSIG[k]+VCSV[k]))/(r3); - C2D[k] = -4.0*RP/r*C2[k]-MOR*MOR*MOR*3.0*eta/r*(NDOT[k]* (XS2-XA2-5.0*NXS*NXS+5.0*NXA*NXA)+N[k]*(2.0*(XS[0]*XSD[0]+ XS[1]*XSD[1]+XS[2]*XSD[2]-XA[0]*XAD[0]-XA[1]*XAD[1]- XA[2]*XAD[2])-10.0*NXS*NXSDOT+10.0*NXA*NXADOT)+2.0*(XSD[k]* NXS+XS[k]*NXSDOT-XAD[k]*NXA-XA[k]*NXADOT)); - C2_5D[k] = -3.0*RP/r*C2_5[k]+(NDOT[k]*(SDNCV*(-30.0*eta* NDV*NDV+24.0*eta*V1_V22-MOR*(38.0+25.0*eta))+DM/M*SIGDNCV* (-15.0*eta*NDV*NDV+12.0*eta*V1_V22-MOR*(18.0+14.5*eta)))+ N[k]*(SNVDOT*(-30.0*eta*NDV*NDV+24.0*eta*V1_V22-MOR* (38.0+25.0*eta))+SDNCV*(-60.0*eta*NDV*NVDOT+48.0*eta*VA+ MOR*RP/r*(38.0+25.0*eta))+DM/M*SIGNVDOT*(-15.0*eta*NDV* NDV+12.0*eta*V1_V22-MOR*(18.0+14.5*eta))+DM/M*SIGDNCV* (-30.0*eta*NDV*NVDOT+24.0*eta*VA+MOR*RP/r*(18.0+14.5*eta)))+ (NVDOT*v[k]+NDV*AT[k])*(SDNCV*(-9.0+9.0*eta)+DM/M*SIGDNCV* (-3.0+6.0*eta))+NDV*v[k]*(SNVDOT*(-9.0+9.0*eta)+DM/M* SIGNVDOT*(-3.0+6.0*eta))+(NDOTCV[k]+NCA[k])*(NDV*VDS*(-3.0+ 3.0*eta)-8.0*MOR*eta*NDS-DM/M*(4.0*MOR*eta*NDSIG+3.0*NDV*VDSIG) )+NCV[k]*((NVDOT*VDS+NDV*VSDOT)*(-3.0+3.0*eta)-8.0*eta*MOR* (NSDOT-RP/r*NDS)-DM/M*(4.0*eta*MOR*(NSIGDOT-RP/r*NDSIG)+ 3.0*(NVDOT*VDSIG+NDV*VSIGDOT)))+(NVDOT*NCS[k]+NDV* (NDOTCS[k]+NCSU[k]))*(-22.5*eta*NDV*NDV+21.0*eta*V1_V22- MOR*(25.0+15.0*eta))+NDV*NCS[k]*(-45.0*eta*NDV*NVDOT+42.0*eta* VA+MOR*RP/r*(25.0+15.0*eta))+DM/M*(NVDOT*NCSIG[k]+NDV* (NDOTCSIG[k]+NCSV[k]))*(-15.0*eta*NDV*NDV+12.0*eta*V1_V22- MOR*(9.0+8.5*eta))+DM/M*NDV*NCSIG[k]*(-30.0*eta*NDV*NVDOT+ 24.0*eta*VA+MOR*RP/r*(9.0+8.5*eta))+(ACS[k]+VCSU[k])* (16.5*eta*NDV*NDV+MOR*(21.0+9.0*eta)-14.0*eta*V1_V22)+ VCS[k]*(33.0*eta*NDV*NVDOT-MOR*RP/r*(21.0+9.0*eta)- 28.0*eta*VA)+DM/M*(ACSIG[k]+VCSV[k])*(9.0*eta*NDV*NDV- 7.0*eta*V1_V22+MOR*(9.0+4.5*eta))+DM/M*VCSIG[k]*(18.0* eta*NDV*NVDOT-14.0*eta*VA-MOR*RP/r*(9.0+4.5*eta)))/ (r3); - - - if(Van_QM==1) - { - - if(m1>m2) - { - QMD[k] = -1.5*MOR*MOR*MOR*eta*(-4.0*RP*QMAux1[k]/r2+( 2.0*(SPSPP1*QMAux2_1[k]/nu+SPSPP2*QMAux2_2[k]*nu) + SpinPrev2_1*(-10.0*rS1*rS1p*N[k]+(1.0-5.0*rS1*rS1)*Np[k]+2.0*rS1p*S1Dir[k]+2.0*rS1*S1p[k])/nu + SpinPrev2_2*(-10.0*rS2*rS2p*N[k]+(1.0-5.0*rS2*rS2)*Np[k]+2.0*rS2p*S2Dir[k]+2.0*rS2*S2p[k])*nu )/r); - } - else - { - QMD[k] = -1.5*MOR*MOR*MOR*eta*(-4.0*RP*QMAux1[k]/r2+( 2.0*(SPSPP2*QMAux2_1[k]/nu+SPSPP1*QMAux2_2[k]*nu) + SpinPrev2_2*(-10.0*rS2*rS2p*N[k]+(1.0-5.0*rS2*rS2)*Np[k]+2.0*rS2p*S2Dir[k]+2.0*rS2*S2p[k])/nu + SpinPrev2_1*(-10.0*rS1*rS1p*N[k]+(1.0-5.0*rS1*rS1)*Np[k]+2.0*rS1p*S1Dir[k]+2.0*rS1*S1p[k])*nu )/r); - } - - } /* if(Van_QM==1) */ - - } /* k */ - - - } /* if(Van_Spin==1) */ - - - ADK = ADK2+ADK4+ADK5+ADK6+ADK7; - BDK = BDK2+BDK4+BDK5+BDK6+BDK7; - - KSAK = AK2+AK4+AK5+AK6+AK7; - KSBK = BK2+BK4+BK5+BK6+BK7; - - for(k=0;k<3;k++) AD[k] = -2.0*MOR*RP*(KSAK*N[k]+KSBK*v[k])/r2 + MOR*(ADK*N[k]+BDK*v[k])/r + MOR*(KSAK*(v[k]-N[k]*RP)/r+KSBK*AT[k])/r + C1_5D[k]/c_2 + C2D[k]/c_4 +C2_5D[k]/c_4 + QMD[k]/c_4; - - -for(k=0;k<3;k++) // new values of the BH's spins, returned back to the main program... - { - spin1[k] = SPIN[k][0]; - spin2[k] = SPIN[k][1]; - } - - - - - - - -for(k=0;k<3;k++) - { - -if(usedOrNot[0] == 1) // PN0 (Newton) ~1/c^0 - { - adot_pn1[0][k] = -m2*(v[k]/r3 - 3.0*RP*x[k]/r2/r2); - adot_pn2[0][k] = m1*(v[k]/r3 - 3.0*RP*x[k]/r2/r2); - } - -if(usedOrNot[1] == 1) // PN1 ~1/c^2 - { - adot_pn1[1][k] = (-2.0*MOR*RP*(AK2*N[k]+BK2*v[k])/r2 + MOR*(ADK2*N[k]+BDK2*v[k])/r + MOR*(AK2*(v[k]-N[k]*RP)/r+BK2*A[k])/r)*m2/M; - adot_pn2[1][k] = -(-2.0*MOR*RP*(AK2*N[k]+BK2*v[k])/r2 + MOR*(ADK2*N[k]+BDK2*v[k])/r + MOR*(AK2*(v[k]-N[k]*RP)/r+BK2*A[k])/r)*m1/M; - } - -if(usedOrNot[2] == 1) // PN2 ~1/c^4 - { - adot_pn1[2][k] = (-2.0*MOR*RP*(AK4*N[k]+BK4*v[k])/r2 + MOR*(ADK4*N[k]+BDK4*v[k])/r + MOR*(AK4*(v[k]-N[k]*RP)/r+BK4*A[k])/r)*m2/M; - adot_pn2[2][k] = -(-2.0*MOR*RP*(AK4*N[k]+BK4*v[k])/r2 + MOR*(ADK4*N[k]+BDK4*v[k])/r + MOR*(AK4*(v[k]-N[k]*RP)/r+BK4*A[k])/r)*m1/M; - } - -if(usedOrNot[3] == 1) // PN2.5 ~1/c^5 - { - adot_pn1[3][k] = (-2.0*MOR*RP*(AK5*N[k]+BK5*v[k])/r2 + MOR*(ADK5*N[k]+BDK5*v[k])/r + MOR*(AK5*(v[k]-N[k]*RP)/r+BK5*A[k])/r)*m2/M; - adot_pn2[3][k] = -(-2.0*MOR*RP*(AK5*N[k]+BK5*v[k])/r2 + MOR*(ADK5*N[k]+BDK5*v[k])/r + MOR*(AK5*(v[k]-N[k]*RP)/r+BK5*A[k])/r)*m1/M; - } - -if(usedOrNot[4] == 1) // PN3 ~1/c^6 - { - adot_pn1[4][k] = (-2.0*MOR*RP*(AK6*N[k]+BK6*v[k])/r2 + MOR*(ADK6*N[k]+BDK6*v[k])/r + MOR*(AK6*(v[k]-N[k]*RP)/r+BK6*A[k])/r)*m2/M; - adot_pn2[4][k] = -(-2.0*MOR*RP*(AK6*N[k]+BK6*v[k])/r2 + MOR*(ADK6*N[k]+BDK6*v[k])/r + MOR*(AK6*(v[k]-N[k]*RP)/r+BK6*A[k])/r)*m1/M; - } - -if(usedOrNot[5] == 1) // PN3.5 ~1/c^7 - { - adot_pn1[5][k] = (-2.0*MOR*RP*(AK7*N[k]+BK7*v[k])/r2 + MOR*(ADK7*N[k]+BDK7*v[k])/r + MOR*(AK7*(v[k]-N[k]*RP)/r+BK7*A[k])/r)*m2/M; - adot_pn2[5][k] = -(-2.0*MOR*RP*(AK7*N[k]+BK7*v[k])/r2 + MOR*(ADK7*N[k]+BDK7*v[k])/r + MOR*(AK7*(v[k]-N[k]*RP)/r+BK7*A[k])/r)*m1/M; - } - - -if(Van_Spin == 1) // All the SPIN terms - { - adot_pn1[6][k] += (C1_5D[k]/c_2 + C2D[k]/c_4 +C2_5D[k]/c_4 + QMD[k]/c_4)*m2/M; - adot_pn2[6][k] += -(C1_5D[k]/c_2 + C2D[k]/c_4 +C2_5D[k]/c_4 + QMD[k]/c_4)*m1/M; - } - - - } - -// PN jerks - - - - -// Check RS_DIST conditions !!! - -RS_DIST = 4.0*(2.0*m1/c_2 + 2.0*m2/c_2); - -if(r < RS_DIST) - { - if(myRank == rootRank) - { - fprintf(stdout,"PN RSDIST: r = %.8E \t RS = %.8E \n", r, RS_DIST); - fflush(stdout); - } - return(505); - } -else - { - return(0); - } - - -} -/***************************************************************************/ diff --git a/star_destr.c b/star_destr.c deleted file mode 100644 index 612d765..0000000 --- a/star_destr.c +++ /dev/null @@ -1,275 +0,0 @@ -/***************************************************************************** - File Name : "Star Destr.c" - Contents : star "destruction" by tidal field of "live" BH (1 or 2) - Coded by : Peter Berczik - Last redaction : 2010.IX.14 1:43PM -*****************************************************************************/ - -void star_destr(double time, - int n, - int ind[], - double m[], - double x[][3], - double v[][3], - double pot[], - double a[][3], - double adot[][3], - double t[], - double dt[], - int N, - double m_N[], - double x_N[][3], - double v_N[][3], - double a_N[][3], - double adot_N[][3], - double t_N[], - double *m_bh, - int *num_bh, - int i_bh) -{ - -int n_end, k_act, N_end; - -double R_t, e_kin=0.0, e_pot_BH=0.0, e_pot=0.0, e_corr=0.0; - -double eps_bh, eps2, eps_bh2, rsb, rkb2, rks2, xp[3], v_bh[3]; - -//double vir = 0.6, gamma = 1000.0; - -double x_max = 1.0E+03, v_max = 1.0E-08, - a_max = 1.0E-08, adot_max = 1.0E-08; - - -if( time < t_diss_on ) return; - - -eps_bh = eps; - -eps2 = SQR(eps); -eps_bh2 = SQR(eps_bh); - -/* -m_s = 1.0/N; -R_s = 2.52E-08/2.507328103; -R_t = gamma * R_s * pow( 2.0*(*m_bh/m_s), over3 ); -*/ - -R_t = R_TIDAL; - -/* -if(myRank == rootRank) - { - printf("%.6E \t %06d %06d %06d \t %.6E \t %.6E %06d \n", time, n, i_bh, ind[i_bh], R_t, *m_bh, *num_bh); - fflush(stdout); - } -*/ - -#ifdef ADD_BH2 - n_end = n-2; - N_end = N-2; -#else -#ifdef ADD_BH1 - n_end = n-1; - N_end = N-1; -#endif // ADD_BH1 -#endif // ADD_BH2 - -/* -if(myRank == rootRank) - { - printf("%.6E \t %06d %06d %06d %06d \t %.6E \t %.6E %06d \n", time, n, n_end, i_bh, ind[i_bh], R_t, *m_bh, *num_bh); - fflush(stdout); - } -*/ - -for(i=0; i Date: Fri, 13 Mar 2020 19:36:18 -0400 Subject: [PATCH 08/65] Removed redundant copying from calc_self_grav and got rid of calc_self_grav_zero --- phigrape.cpp | 183 ++++++++++----------------------------------------- 1 file changed, 36 insertions(+), 147 deletions(-) diff --git a/phigrape.cpp b/phigrape.cpp index 70804df..a919f70 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -145,6 +145,8 @@ Last redaction : 2019.04.16 12:55 #include #include +#include + /* double aaa; double aaapars[5]; @@ -158,12 +160,12 @@ extern void qwerty_(double *aaa, double *aaapars); #include /* Some "good" functions and constants... */ -#define SIG(x) ( ((x)<0) ? (-1):(1) ) -#define ABS(x) ( ((x)<0) ? (-x):(x) ) -#define MAX(a,b) ( ((a)>(b)) ? (a):(b) ) -#define MIN(a,b) ( ((a)<(b)) ? (a):(b) ) -#define SQR(x) ( (x)*(x) ) -#define POW3(x) ( (x)*SQR(x) ) +#define SIG(x) (((x)<0) ? (-1):(1) ) +#define ABS(x) (((x)<0) ? (-x):(x) ) +#define MAX(a,b) (((a)>(b)) ? (a):(b) ) +#define MIN(a,b) (((a)<(b)) ? (a):(b) ) +#define SQR(x) ((x)*(x) ) +#define POW3(x) ((x)*SQR(x) ) #define Pi 3.14159265358979323846 #define TWOPi 6.283185307179 @@ -477,7 +479,7 @@ return - 0 if everything OK double my_rand(void) { -return( (double)(rand()/(double)RAND_MAX) ); +return((double)(rand()/(double)RAND_MAX) ); } double my_rand2(void) @@ -952,101 +954,6 @@ fclose(out); #endif - - - -void calc_self_grav_zero() -{ - -/* calc the grav for the active particles */ - -g6_set_ti(clusterid, time_cur); - -ni = n_act; - -/* define the local phi, a, adot for these active particles */ - -for (i=0; i 100.0) jerk_i[ii][0] = 100.0; - if (ABS(jerk_i[ii][1]) > 100.0) jerk_i[ii][1] = 100.0; - if (ABS(jerk_i[ii][2]) > 100.0) jerk_i[ii][2] = 100.0; - } - - g6calc_firsthalf(clusterid, n_loc, nn, index_i, x_i, v_i , a_i, jerk_i, p_i, eps2, h2_i); - g6calc_lasthalf(clusterid, n_loc, nn, index_i, x_i, v_i, eps2, h2_i, a_i, jerk_i, p_i); - - for (ii=0; ii dt_min) ) { + if ((dt_new < dt_tmp) && (dt_new > dt_min)) { power = log(dt_new)/log(2.0) - 1; dt_tmp = pow(2.0, (double)power); @@ -2965,9 +2854,9 @@ int main(int argc, char *argv[]) iii = ind_act[i]; - if ( (tmp_r2 < SEMI_a2*R_INF2) ) { + if (tmp_r2 < SEMI_a2*R_INF2) { - if ( (inf_event[iii] == 0) ) { + if (inf_event[iii] == 0) { fprintf(out,"INF1 %.6E %.16E %07d %07d %.6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E \n", Timesteps, time_cur, i, ind_act[i], @@ -2982,7 +2871,7 @@ int main(int argc, char *argv[]) } } else { - if ( (inf_event[iii] == 1) ) { + if (inf_event[iii] == 1) { fprintf(out,"INF2 %.6E %.16E %07d %07d %.6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E \n", Timesteps, time_cur, i, ind_act[i], sqrt(DR2), x_bbhc[0], x_bbhc[1], x_bbhc[2], v_bbhc[0], v_bbhc[1], v_bbhc[2], From 34030c06d0e03153392ae8731a21c15e5288a8b5 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Fri, 13 Mar 2020 20:42:09 -0400 Subject: [PATCH 09/65] Introduced double3 structure in preparation of dynamic allocation and getting rid of k-loops --- phigrape.cpp | 64 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/phigrape.cpp b/phigrape.cpp index a919f70..09a8bd0 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -220,6 +220,12 @@ extern void qwerty_(double *aaa, double *aaapars); #define N_MAX (6*MB) #define N_MAX_loc (2*MB) +struct double3 { + double data[3]; + double& operator[](int i) {return data[i];} + operator double*() {return data;} +}; + int name_proc, n_proc=1, myRank=0, rootRank=0, cur_rank, i, j, k, ni, nj, diskstep=0, power, jjj, iii, skip_con=0, tmp_i; @@ -235,14 +241,10 @@ double dt_disk, dt_contr, t_disk=0.0, t_contr=0.0, mcm, rcm_mod, vcm_mod, rcm_sum=0.0, vcm_sum=0.0, eps=0.0, eps2, - xcm[3], vcm[3], mom[3], - xdc[3], vdc[2], - over2=(1.0/2.0), over3=(1.0/3.0), over6=(1.0/6.0), a2_mod, adot2_mod, dt_tmp, dt2half, dt3over6, dt4over24, dt5over120, dtinv, dt2inv, dt3inv, a0mia1, ad04plad12, ad0plad1, - a2[3], a3[3], a2dot1[3], a1abs, adot1abs, a2dot1abs, a3dot1abs, Timesteps=0.0, n_act_sum=0.0, n_act_distr[N_MAX], g6_calls=0.0, g6_calls_sum=0.0, tmp, tmp_r, tmp_v, tmp_rv, tmp_cpu, @@ -251,6 +253,10 @@ double dt_disk, dt_contr, t_disk=0.0, t_contr=0.0, tmp_a_bh_pn0, tmp_a_bh_pn1, tmp_a_bh_pn2, tmp_a_bh_pn2_5, tmp_a_bh_pn3, tmp_a_bh_pn3_5, tmp_a_bh_spin, tmp_adot_bh_pn0, tmp_adot_bh_pn1, tmp_adot_bh_pn2, tmp_adot_bh_pn2_5, tmp_adot_bh_pn3, tmp_adot_bh_pn3_5, tmp_adot_bh_spin; +double3 xcm, vcm, mom, + xdc, vdc, + a2, a3, a2dot1; + char processor_name[MPI_MAX_PROCESSOR_NAME], inp_fname[30], out_fname[30], dbg_fname[30]; @@ -259,28 +265,31 @@ char processor_name[MPI_MAX_PROCESSOR_NAME], int N, N_star, N_bh, ind[N_MAX], name[N_MAX]; -double m[N_MAX], x[N_MAX][3], v[N_MAX][3], - pot[N_MAX], a[N_MAX][3], adot[N_MAX][3], - t[N_MAX], dt[N_MAX]; +double m[N_MAX], pot[N_MAX], t[N_MAX], dt[N_MAX]; +double3 x[N_MAX], v[N_MAX], a[N_MAX], adot[N_MAX]; /* local variables */ int n_loc, ind_loc[N_MAX_loc]; -double m_loc[N_MAX_loc], x_loc[N_MAX_loc][3], v_loc[N_MAX_loc][3], - pot_loc[N_MAX_loc], a_loc[N_MAX_loc][3], adot_loc[N_MAX_loc][3], - t_loc[N_MAX_loc], dt_loc[N_MAX_loc]; +double m_loc[N_MAX_loc], pot_loc[N_MAX_loc], t_loc[N_MAX_loc], dt_loc[N_MAX_loc]; +double3 x_loc[N_MAX_loc], v_loc[N_MAX_loc], + a_loc[N_MAX_loc], adot_loc[N_MAX_loc]; /* data for active particles */ int n_act, ind_act[N_MAX]; double m_act[N_MAX], - x_act[N_MAX][3], v_act[N_MAX][3], - pot_act[N_MAX], a_act[N_MAX][3], adot_act[N_MAX][3], - t_act[N_MAX], dt_act[N_MAX], - x_act_new[N_MAX][3], v_act_new[N_MAX][3], - pot_act_new[N_MAX], a_act_new[N_MAX][3], adot_act_new[N_MAX][3], - pot_act_tmp[N_MAX], a_act_tmp[N_MAX][3], adot_act_tmp[N_MAX][3], - pot_act_tmp_loc[N_MAX], a_act_tmp_loc[N_MAX][3], adot_act_tmp_loc[N_MAX][3]; + pot_act[N_MAX], t_act[N_MAX], dt_act[N_MAX], + pot_act_new[N_MAX], + pot_act_tmp[N_MAX], + pot_act_tmp_loc[N_MAX]; + +double3 x_act[N_MAX], v_act[N_MAX], + a_act[N_MAX], adot_act[N_MAX], + x_act_new[N_MAX], v_act_new[N_MAX], + a_act_new[N_MAX], adot_act_new[N_MAX], + a_act_tmp[N_MAX], adot_act_tmp[N_MAX], + a_act_tmp_loc[N_MAX], adot_act_tmp_loc[N_MAX]; FILE *inp, *out, *tmp_file, *dbg; @@ -308,13 +317,15 @@ double DT_ACT_REDUCE; int clusterid, ii, nn, numGPU; int npipe=G6_NPIPE, index_i[G6_NPIPE]; -double h2_i[G6_NPIPE], x_i[G6_NPIPE][3], v_i[G6_NPIPE][3], - p_i[G6_NPIPE], a_i[G6_NPIPE][3], jerk_i[G6_NPIPE][3]; +double h2_i[G6_NPIPE], p_i[G6_NPIPE]; +double3 x_i[G6_NPIPE], v_i[G6_NPIPE], + a_i[G6_NPIPE], jerk_i[G6_NPIPE]; int new_tunit=51, new_xunit=51; int aflag=1, jflag=1, pflag=1; -double ti=0.0, a2by18[3], a1by6[3], aby2[3]; +double ti=0.0; +double3 a2by18, a1by6, aby2; /* normalization... */ @@ -1223,8 +1234,9 @@ void calc_self_grav(double t) for (ii=0; ii Date: Fri, 13 Mar 2020 20:59:53 -0400 Subject: [PATCH 10/65] Fixed typo in Makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 20340bf..1739015 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ yebisu: GRAPELIB = -L$(GRAPEHOME) -lyebisug6 GRAPEINC = -I$(GRAPEHOME) CXXFLAGS ?= -mcmodel=medium -CFFFLAGS += -O$(OPTIMIZATION) +CXXFLAGS += -O$(OPTIMIZATION) INC = $(GRAPEINC) $(CUDAINC) LIB = $(GRAPELIB) $(CUDALIB) -lm MPICXX ?= mpic++ From fd33819a7aba0fdbe9b8c4997ad20fcd2308d13b Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Sat, 14 Mar 2020 16:29:00 -0400 Subject: [PATCH 11/65] Got rid of most k-loops --- phigrape.cpp | 406 +++++++++++++++++++++++---------------------------- 1 file changed, 181 insertions(+), 225 deletions(-) diff --git a/phigrape.cpp b/phigrape.cpp index 09a8bd0..82547ad 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -222,10 +222,63 @@ extern void qwerty_(double *aaa, double *aaapars); struct double3 { double data[3]; + double3() {} + double3(const double x, const double y, const double z) + { + data[0] = x; + data[1] = y; + data[2] = z; + } double& operator[](int i) {return data[i];} + double3& operator=(const double3& a) + { + data[0] = a.data[0]; + data[1] = a.data[1]; + data[2] = a.data[2]; + return *this; + } + double3& operator+=(const double3& a) + { + data[0] += a.data[0]; + data[1] += a.data[1]; + data[2] += a.data[2]; + return *this; + } + double3& operator/=(const double& c) + { + data[0] /= c; + data[1] /= c; + data[2] /= c; + return *this; + } + double norm() + { + return sqrt(data[0]*data[0]+data[1]*data[1]+data[2]*data[2]); + } operator double*() {return data;} }; +double3 operator*(const double& c, const double3& a) +{ + return double3(a.data[0]*c, a.data[1]*c, a.data[2]*c); +} + +double3 operator*(const double3& a, const double& c) +{ + return double3(a.data[0]*c, a.data[1]*c, a.data[2]*c); +} + +double3 operator+(const double3& a, const double3& b) +{ + return double3(a.data[0]+b.data[0], a.data[1]+b.data[1], a.data[2]+b.data[2]); +} + +double3 operator-(const double3& a, const double3& b) +{ + return double3(a.data[0]-b.data[0], a.data[1]-b.data[1], a.data[2]-b.data[2]); +} + + int name_proc, n_proc=1, myRank=0, rootRank=0, cur_rank, i, j, k, ni, nj, diskstep=0, power, jjj, iii, skip_con=0, tmp_i; @@ -1245,10 +1298,8 @@ void calc_self_grav(double t) for (i=0; i Date: Sat, 14 Mar 2020 16:50:40 -0400 Subject: [PATCH 12/65] Minor edits --- phigrape.cpp | 96 ++++++++-------------------------------------------- 1 file changed, 15 insertions(+), 81 deletions(-) diff --git a/phigrape.cpp b/phigrape.cpp index 82547ad..905655e 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -299,7 +299,7 @@ double dt_disk, dt_contr, t_disk=0.0, t_contr=0.0, dtinv, dt2inv, dt3inv, a0mia1, ad04plad12, ad0plad1, a1abs, adot1abs, a2dot1abs, a3dot1abs, - Timesteps=0.0, n_act_sum=0.0, n_act_distr[N_MAX], g6_calls=0.0, g6_calls_sum=0.0, + timesteps=0.0, n_act_sum=0.0, n_act_distr[N_MAX], g6_calls=0.0, g6_calls_sum=0.0, tmp, tmp_r, tmp_v, tmp_rv, tmp_cpu, tmp_pot, tmp_a, tmp_adot, tmp_a_bh, tmp_adot_bh, @@ -537,20 +537,6 @@ return - 0 if everything OK #endif -/* RAND_MAX = 2147483647 */ -/* my_rand : 0.0 - 1.0 */ -/* my_rand2 : -1.0 - 1.0 */ - -double my_rand(void) -{ -return((double)(rand()/(double)RAND_MAX) ); -} - -double my_rand2(void) -{ -return (double)(2.0)*((rand() - RAND_MAX/2)/(double)RAND_MAX); -} - #ifdef ETICS double t_exp, dt_exp=ETICS_DTSCF; // t_exp is just the initial value #ifdef ETICS_CEP @@ -1557,53 +1543,6 @@ for (i=0; i Date: Sun, 15 Mar 2020 18:34:18 -0400 Subject: [PATCH 13/65] Moved much of the black hole stuff from ifdef blocks to regular if clauses --- phigrape.cpp | 1114 ++++++++++++++++++-------------------------------- 1 file changed, 408 insertions(+), 706 deletions(-) diff --git a/phigrape.cpp b/phigrape.cpp index 905655e..6c1e805 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -54,23 +54,36 @@ Version number : 19.04 Last redaction : 2019.04.16 12:55 *****************************************************************************/ +struct Parameters { + int live_smbh_count = 2; // ADD_BH1 or ADD_BH2 + double live_smbh_custom_eps = 0; // ADD_N_BH + bool live_smbh_output = true; // BH_OUT + bool live_smbh_neighbor_output = true; // BH_OUT_NB // NOTE needs `live_smbh_neighbor_number` + bool binary_smbh_influence_sphere_output = true; // BBH_INF // NOTE needs `binary_smbh_influence_radius_factor` + double binary_smbh_influence_radius_factor = 3.162277660168379497918067e+03; // R_INF + int live_smbh_neighbor_number = 10; // TODO make sure it's smaller than N? or just warn if it's not + bool binary_smbh_pn = true; // ADD_PN_BH + bool binary_smbh_spin = true; // ADD_SPIN_BH + bool dt_min_warning = true; // DT_MIN_WARNING +} parameters; + //#define NORM // Physical normalization -//#define ADD_BH1 // add the Single BH +// // // //#define ADD_BH1 // add the Single BH -//#define ADD_BH2 // add the Binary BH's -//#define ADD_N_BH // eps_BH = 0.0, but added only the Newtonian forces -//#define ADD_PN_BH // extra - added also the Post-Newton forces -//#define ADD_SPIN_BH // extra - added the SPIN for the BH's - DEFAULT !!! +// // // // #define ADD_BH2 // add the Binary BH's +// // // // #define ADD_N_BH // eps_BH = 0.0, but added only the Newtonian forces +// // // // #define ADD_PN_BH // extra - added also the Post-Newton forces +// // // // #define ADD_SPIN_BH // extra - added the SPIN for the BH's - DEFAULT !!! -//#define BH_OUT // extra output for BH's (live) -//#define BH_OUT_NB // extra output for the BH's neighbours (live) +// // // // #define BH_OUT // extra output for BH's (live) +// // // // #define BH_OUT_NB // extra output for the BH's neighbours (live) -//#define BBH_INF // BBH influence sphere... -//#define R_INF 10.0 // Factor for the influence sphere... if ( R < R_INF * DR_BBH ) -//#define R_INF2 (R_INF*R_INF) +// // // // #define BBH_INF // BBH influence sphere... +// // // // #define R_INF 3.162277660168379497918067e+03 // Factor for the influence sphere... if ( R < R_INF * DR_BBH ) +// // // // #define R_INF2 (R_INF*R_INF) -//#define DT_MIN_WARNING // dt < dt_min warning !!! +// // // // #define DT_MIN_WARNING // dt < dt_min warning !!! //#define BH_OUT_NB_EXT // extra output for the BH's neighbours (external) @@ -146,13 +159,7 @@ Last redaction : 2019.04.16 12:55 #include #include - -/* -double aaa; -double aaapars[5]; - -extern void qwerty_(double *aaa, double *aaapars); -*/ +#include #define G6_NPIPE 2048 #include "grape6.h" @@ -244,6 +251,13 @@ struct double3 { data[2] += a.data[2]; return *this; } + double3& operator-=(const double3& a) + { + data[0] -= a.data[0]; + data[1] -= a.data[1]; + data[2] -= a.data[2]; + return *this; + } double3& operator/=(const double& c) { data[0] /= c; @@ -268,6 +282,11 @@ double3 operator*(const double3& a, const double& c) return double3(a.data[0]*c, a.data[1]*c, a.data[2]*c); } +double3 operator/(const double3& a, const double& c) +{ + return double3(a.data[0]/c, a.data[1]/c, a.data[2]/c); +} + double3 operator+(const double3& a, const double3& b) { return double3(a.data[0]+b.data[0], a.data[1]+b.data[1], a.data[2]+b.data[2]); @@ -306,13 +325,21 @@ double dt_disk, dt_contr, t_disk=0.0, t_contr=0.0, tmp_a_bh_pn0, tmp_a_bh_pn1, tmp_a_bh_pn2, tmp_a_bh_pn2_5, tmp_a_bh_pn3, tmp_a_bh_pn3_5, tmp_a_bh_spin, tmp_adot_bh_pn0, tmp_adot_bh_pn1, tmp_adot_bh_pn2, tmp_adot_bh_pn2_5, tmp_adot_bh_pn3, tmp_adot_bh_pn3_5, tmp_adot_bh_spin; + +double L[3]; // needed in pn_bh_spin.c +// Needed for things related to BHs +#include "debug.h" +int ind_sort[N_MAX]; +double var_sort[N_MAX]; + + double3 xcm, vcm, mom, xdc, vdc, a2, a3, a2dot1; char processor_name[MPI_MAX_PROCESSOR_NAME], inp_fname[30], - out_fname[30], dbg_fname[30]; + out_fname[30]; /* global variables */ @@ -344,7 +371,7 @@ double3 x_act[N_MAX], v_act[N_MAX], a_act_tmp[N_MAX], adot_act_tmp[N_MAX], a_act_tmp_loc[N_MAX], adot_act_tmp_loc[N_MAX]; -FILE *inp, *out, *tmp_file, *dbg; +FILE *inp, *out; double CPU_time_real0, CPU_time_user0, CPU_time_syst0; double CPU_time_real, CPU_time_user, CPU_time_syst; @@ -375,8 +402,6 @@ double3 x_i[G6_NPIPE], v_i[G6_NPIPE], a_i[G6_NPIPE], jerk_i[G6_NPIPE]; int new_tunit=51, new_xunit=51; -int aflag=1, jflag=1, pflag=1; - double ti=0.0; double3 a2by18, a1by6, aby2; @@ -395,8 +420,8 @@ double eps_BH=0.0; #ifdef EXTPOT_GAL double m_bulge, a_bulge, b_bulge, m_disk, a_disk, b_disk, - m_halo, a_halo, b_halo, - x2_ij, y2_ij, z2_ij, + m_halo, a_halo, b_halo, // NOTE there are other "halo" variables in EXTPOT_GAL_LOG + x2_ij, y2_ij, z2_ij, // NOTE this variable exist also in EXTPOT_GAL_LOG r_tmp, r2_tmp, z_tmp, z2_tmp; #endif @@ -413,7 +438,9 @@ double v_halo, r_halo, #ifdef EXTPOT_BH double r2, rv_ij, - m_bh, b_bh, eps_bh; + m_bh, b_bh, eps_bh; // NOTE different from eps_BH + // NOTE there are other m_bh and b_bh defined outside this ifdef block + // NOTE this is a mess. Looks like eps_bh is never used, and the m_bh from outside the block is never used. #endif double pot_ext[N_MAX], pot_act_ext[N_MAX]; // for all EXTPOT @@ -428,18 +455,23 @@ double m_bh, m_bh1, m_bh2, b_bh, x_ij, y_ij, z_ij, vx_ij, vy_ij, vz_ij, rv_ij; -#ifdef BBH_INF +// #ifdef BBH_INF int inf_event[N_MAX]; -double x_bbhc[3], v_bbhc[3], DR2, tmp_r2; +double DR2, tmp_r2; +double3 x_bbhc, v_bbhc; double DV2, EB, SEMI_a, SEMI_a2; -#endif +// #endif // BBH_INF -#ifdef ADD_N_BH +// #ifdef ADD_N_BH -double x_bh1[3], x_bh2[3], v_bh1[3], v_bh2[3]; +// double x_bh1[3], x_bh2[3], v_bh1[3], v_bh2[3]; +double3 x_bh1, x_bh2, v_bh1, v_bh2; + +// double pot_bh1, a_bh1[3], adot_bh1[3], +// pot_bh2, a_bh2[3], adot_bh2[3]; +double pot_bh1, pot_bh2; +double3 a_bh1, adot_bh1, a_bh2, adot_bh2; -double pot_bh1, a_bh1[3], adot_bh1[3], - pot_bh2, a_bh2[3], adot_bh2[3]; //double eps_BH = 0.0; @@ -479,16 +511,17 @@ adot_n2 [0,1,2] for the 2 BH return - 0 if everything OK */ -#endif +// #endif // ADD_N_BH -#ifdef ADD_PN_BH +// #ifdef ADD_PN_BH double C_NB = 477.12; int usedOrNot[7] = {1, 1, 1, 1, 0, 0, 0}; -double a_pn1[7][3], adot_pn1[7][3], - a_pn2[7][3], adot_pn2[7][3]; +// double a_pn1[7][3], adot_pn1[7][3], +// a_pn2[7][3], adot_pn2[7][3]; +double3 a_pn1[7], adot_pn1[7], a_pn2[7], adot_pn2[7]; double s_bh1[3] = {0.0, 0.0, 1.0}; double s_bh2[3] = {0.0, 0.0, 1.0}; @@ -535,7 +568,7 @@ return - 0 if everything OK - 505 if BH's separation < 4 x (RSwarch1 + RSwarch2) */ -#endif +// #endif // ADD_N_BH #ifdef ETICS double t_exp, dt_exp=ETICS_DTSCF; // t_exp is just the initial value @@ -624,386 +657,164 @@ fclose(out); void write_bh_data() { + if (parameters.live_smbh_count == 2) { -#ifdef ADD_BH2 + out = fopen("bh.dat","a"); -out = fopen("bh.dat","a"); + for (int i=0; i < 2; i++) { +// double (*a_pn)[3], (*adot_pn)[3], pot_bh, *a_bh, *adot_bh; + double3 *a_pn, *adot_pn, a_bh, adot_bh; + double pot_bh; + if (i==0) { + a_pn = a_pn1; + adot_pn = adot_pn1; + pot_bh = pot_bh1; + a_bh = a_bh1; + adot_bh = adot_bh1; + } else { + a_pn = a_pn2; + adot_pn = adot_pn2; + pot_bh = pot_bh2; + a_bh = a_bh2; + adot_bh = adot_bh2; + } -/* 1st BH */ + tmp_r = sqrt( SQR(x[i][0]) + SQR(x[i][1]) + SQR(x[i][2]) ); + tmp_v = sqrt( SQR(v[i][0]) + SQR(v[i][1]) + SQR(v[i][2]) ); -// i=N-2; -i=0; + tmp_a = sqrt( SQR(a[i][0]) + SQR(a[i][1]) + SQR(a[i][2]) ); + tmp_adot = sqrt( SQR(adot[i][0]) + SQR(adot[i][1]) + SQR(adot[i][2]) ); -tmp_r = sqrt( SQR(x[i][0]) + SQR(x[i][1]) + SQR(x[i][2]) ); -tmp_v = sqrt( SQR(v[i][0]) + SQR(v[i][1]) + SQR(v[i][2]) ); + if (parameters.live_smbh_custom_eps >= 0) { -tmp_a = sqrt( SQR(a[i][0]) + SQR(a[i][1]) + SQR(a[i][2]) ); -tmp_adot = sqrt( SQR(adot[i][0]) + SQR(adot[i][1]) + SQR(adot[i][2]) ); + tmp_a_bh = sqrt( SQR(a_bh[0]) + SQR(a_bh[1]) + SQR(a_bh[2]) ); + tmp_adot_bh = sqrt( SQR(adot_bh[0]) + SQR(adot_bh[1]) + SQR(adot_bh[2]) ); -#ifdef ADD_N_BH + if (parameters.binary_smbh_spin) { + tmp_a_bh_pn0 = sqrt( SQR(a_pn[0][0]) + SQR(a_pn[0][1]) + SQR(a_pn[0][2]) ); + tmp_a_bh_pn1 = sqrt( SQR(a_pn[1][0]) + SQR(a_pn[1][1]) + SQR(a_pn[1][2]) ); + tmp_a_bh_pn2 = sqrt( SQR(a_pn[2][0]) + SQR(a_pn[2][1]) + SQR(a_pn[2][2]) ); + tmp_a_bh_pn2_5 = sqrt( SQR(a_pn[3][0]) + SQR(a_pn[3][1]) + SQR(a_pn[3][2]) ); + tmp_a_bh_pn3 = sqrt( SQR(a_pn[4][0]) + SQR(a_pn[4][1]) + SQR(a_pn[4][2]) ); + tmp_a_bh_pn3_5 = sqrt( SQR(a_pn[5][0]) + SQR(a_pn[5][1]) + SQR(a_pn[5][2]) ); + tmp_a_bh_spin = sqrt( SQR(a_pn[6][0]) + SQR(a_pn[6][1]) + SQR(a_pn[6][2]) ); -tmp_a_bh = sqrt( SQR(a_bh1[0]) + SQR(a_bh1[1]) + SQR(a_bh1[2]) ); -tmp_adot_bh = sqrt( SQR(adot_bh1[0]) + SQR(adot_bh1[1]) + SQR(adot_bh1[2]) ); - -#ifdef ADD_PN_BH - -tmp_a_bh_pn0 = sqrt( SQR(a_pn1[0][0]) + SQR(a_pn1[0][1]) + SQR(a_pn1[0][2]) ); -tmp_a_bh_pn1 = sqrt( SQR(a_pn1[1][0]) + SQR(a_pn1[1][1]) + SQR(a_pn1[1][2]) ); -tmp_a_bh_pn2 = sqrt( SQR(a_pn1[2][0]) + SQR(a_pn1[2][1]) + SQR(a_pn1[2][2]) ); -tmp_a_bh_pn2_5 = sqrt( SQR(a_pn1[3][0]) + SQR(a_pn1[3][1]) + SQR(a_pn1[3][2]) ); -tmp_a_bh_pn3 = sqrt( SQR(a_pn1[4][0]) + SQR(a_pn1[4][1]) + SQR(a_pn1[4][2]) ); -tmp_a_bh_pn3_5 = sqrt( SQR(a_pn1[5][0]) + SQR(a_pn1[5][1]) + SQR(a_pn1[5][2]) ); -tmp_a_bh_spin = sqrt( SQR(a_pn1[6][0]) + SQR(a_pn1[6][1]) + SQR(a_pn1[6][2]) ); - -tmp_adot_bh_pn0 = sqrt( SQR(adot_pn1[0][0]) + SQR(adot_pn1[0][1]) + SQR(adot_pn1[0][2]) ); -tmp_adot_bh_pn1 = sqrt( SQR(adot_pn1[1][0]) + SQR(adot_pn1[1][1]) + SQR(adot_pn1[1][2]) ); -tmp_adot_bh_pn2 = sqrt( SQR(adot_pn1[2][0]) + SQR(adot_pn1[2][1]) + SQR(adot_pn1[2][2]) ); -tmp_adot_bh_pn2_5 = sqrt( SQR(adot_pn1[3][0]) + SQR(adot_pn1[3][1]) + SQR(adot_pn1[3][2]) ); -tmp_adot_bh_pn3 = sqrt( SQR(adot_pn1[4][0]) + SQR(adot_pn1[4][1]) + SQR(adot_pn1[4][2]) ); -tmp_adot_bh_pn3_5 = sqrt( SQR(adot_pn1[5][0]) + SQR(adot_pn1[5][1]) + SQR(adot_pn1[5][2]) ); -tmp_adot_bh_spin = sqrt( SQR(adot_pn1[6][0]) + SQR(adot_pn1[6][1]) + SQR(adot_pn1[6][2]) ); - -fprintf(out,"%.16E \t %.8E \t % .16E % .16E % .16E \t %.16E \t % .16E % .16E % .16E \t %.16E \t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t %.8E \t\t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t\t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \n", - time_cur, m[i], - x[i][0], x[i][1], x[i][2], tmp_r, - v[i][0], v[i][1], v[i][2], tmp_v, - pot[i], - a[i][0], a[i][1], a[i][2], tmp_a, - adot[i][0], adot[i][1], adot[i][2], tmp_adot, - dt[i], - pot_bh1, - a_bh1[0], a_bh1[1], a_bh1[2], tmp_a_bh, - adot_bh1[0], adot_bh1[1], adot_bh1[2], tmp_adot_bh, - a_pn1[0][0], a_pn1[0][1], a_pn1[0][2], tmp_a_bh_pn0, - adot_pn1[0][0], adot_pn1[0][1], adot_pn1[0][2], tmp_adot_bh_pn0, - a_pn1[1][0], a_pn1[1][1], a_pn1[1][2], tmp_a_bh_pn1, - adot_pn1[1][0], adot_pn1[1][1], adot_pn1[1][2], tmp_adot_bh_pn1, - a_pn1[2][0], a_pn1[2][1], a_pn1[2][2], tmp_a_bh_pn2, - adot_pn1[2][0], adot_pn1[2][1], adot_pn1[2][2], tmp_adot_bh_pn2, - a_pn1[3][0], a_pn1[3][1], a_pn1[3][2], tmp_a_bh_pn2_5, - adot_pn1[3][0], adot_pn1[3][1], adot_pn1[3][2], tmp_adot_bh_pn2_5, - a_pn1[4][0], a_pn1[4][1], a_pn1[4][2], tmp_a_bh_pn3, - adot_pn1[4][0], adot_pn1[4][1], adot_pn1[4][2], tmp_adot_bh_pn3, - a_pn1[5][0], a_pn1[5][1], a_pn1[5][2], tmp_a_bh_pn3_5, - adot_pn1[5][0], adot_pn1[5][1], adot_pn1[5][2], tmp_adot_bh_pn3_5, - a_pn1[6][0], a_pn1[6][1], a_pn1[6][2], tmp_a_bh_spin, - adot_pn1[6][0], adot_pn1[6][1], adot_pn1[6][2], tmp_adot_bh_spin); - -#else - -fprintf(out,"%.16E \t %.8E \t % .16E % .16E % .16E \t %.16E \t % .16E % .16E % .16E \t %.16E \t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t %.8E \t\t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \n", - time_cur, m[i], - x[i][0], x[i][1], x[i][2], tmp_r, - v[i][0], v[i][1], v[i][2], tmp_v, - pot[i], - a[i][0], a[i][1], a[i][2], tmp_a, - adot[i][0], adot[i][1], adot[i][2], tmp_adot, - dt[i], - pot_bh1, - a_bh1[0], a_bh1[1], a_bh1[2], tmp_a_bh, - adot_bh1[0], adot_bh1[1], adot_bh1[2], tmp_adot_bh); - -#endif // ADD_PN_BH - -#else - -fprintf(out,"%.16E \t %.8E \t % .16E % .16E % .16E \t %.16E \t % .16E % .16E % .16E \t %.16E \t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t %.8E \n", - time_cur, m[i], - x[i][0], x[i][1], x[i][2], tmp_r, - v[i][0], v[i][1], v[i][2], tmp_v, - pot[i], - a[i][0], a[i][1], a[i][2], tmp_a, - adot[i][0], adot[i][1], adot[i][2], tmp_adot, - dt[i]); - -#endif // ADD_N_BH - -/* 2nd BH */ - -// i=N-1; -i=1; - -tmp_r = sqrt( SQR(x[i][0]) + SQR(x[i][1]) + SQR(x[i][2]) ); -tmp_v = sqrt( SQR(v[i][0]) + SQR(v[i][1]) + SQR(v[i][2]) ); - -tmp_a = sqrt( SQR(a[i][0]) + SQR(a[i][1]) + SQR(a[i][2]) ); -tmp_adot = sqrt( SQR(adot[i][0]) + SQR(adot[i][1]) + SQR(adot[i][2]) ); - -#ifdef ADD_N_BH - -tmp_a_bh = sqrt( SQR(a_bh2[0]) + SQR(a_bh2[1]) + SQR(a_bh2[2]) ); -tmp_adot_bh = sqrt( SQR(adot_bh2[0]) + SQR(adot_bh2[1]) + SQR(adot_bh2[2]) ); - -#ifdef ADD_PN_BH - -tmp_a_bh_pn0 = sqrt( SQR(a_pn2[0][0]) + SQR(a_pn2[0][1]) + SQR(a_pn2[0][2]) ); -tmp_a_bh_pn1 = sqrt( SQR(a_pn2[1][0]) + SQR(a_pn2[1][1]) + SQR(a_pn2[1][2]) ); -tmp_a_bh_pn2 = sqrt( SQR(a_pn2[2][0]) + SQR(a_pn2[2][1]) + SQR(a_pn2[2][2]) ); -tmp_a_bh_pn2_5 = sqrt( SQR(a_pn2[3][0]) + SQR(a_pn2[3][1]) + SQR(a_pn2[3][2]) ); -tmp_a_bh_pn3 = sqrt( SQR(a_pn2[4][0]) + SQR(a_pn2[4][1]) + SQR(a_pn2[4][2]) ); -tmp_a_bh_pn3_5 = sqrt( SQR(a_pn2[5][0]) + SQR(a_pn2[5][1]) + SQR(a_pn2[5][2]) ); -tmp_a_bh_spin = sqrt( SQR(a_pn2[6][0]) + SQR(a_pn2[6][1]) + SQR(a_pn2[6][2]) ); - -tmp_adot_bh_pn0 = sqrt( SQR(adot_pn2[0][0]) + SQR(adot_pn2[0][1]) + SQR(adot_pn2[0][2]) ); -tmp_adot_bh_pn1 = sqrt( SQR(adot_pn2[1][0]) + SQR(adot_pn2[1][1]) + SQR(adot_pn2[1][2]) ); -tmp_adot_bh_pn2 = sqrt( SQR(adot_pn2[2][0]) + SQR(adot_pn2[2][1]) + SQR(adot_pn2[2][2]) ); -tmp_adot_bh_pn2_5 = sqrt( SQR(adot_pn2[3][0]) + SQR(adot_pn2[3][1]) + SQR(adot_pn2[3][2]) ); -tmp_adot_bh_pn3 = sqrt( SQR(adot_pn2[4][0]) + SQR(adot_pn2[4][1]) + SQR(adot_pn2[4][2]) ); -tmp_adot_bh_pn3_5 = sqrt( SQR(adot_pn2[5][0]) + SQR(adot_pn2[5][1]) + SQR(adot_pn2[5][2]) ); -tmp_adot_bh_spin = sqrt( SQR(adot_pn2[6][0]) + SQR(adot_pn2[6][1]) + SQR(adot_pn2[6][2]) ); - -fprintf(out,"%.16E \t %.8E \t % .16E % .16E % .16E \t %.16E \t % .16E % .16E % .16E \t %.16E \t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t %.8E \t\t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t\t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \n", - time_cur, m[i], - x[i][0], x[i][1], x[i][2], tmp_r, - v[i][0], v[i][1], v[i][2], tmp_v, - pot[i], - a[i][0], a[i][1], a[i][2], tmp_a, - adot[i][0], adot[i][1], adot[i][2], tmp_adot, - dt[i], - pot_bh2, - a_bh2[0], a_bh2[1], a_bh2[2], tmp_a_bh, - adot_bh2[0], adot_bh2[1], adot_bh2[2], tmp_adot_bh, - a_pn2[0][0], a_pn2[0][1], a_pn2[0][2], tmp_a_bh_pn0, - adot_pn2[0][0], adot_pn2[0][1], adot_pn2[0][2], tmp_adot_bh_pn0, - a_pn2[1][0], a_pn2[1][1], a_pn2[1][2], tmp_a_bh_pn1, - adot_pn2[1][0], adot_pn2[1][1], adot_pn2[1][2], tmp_adot_bh_pn1, - a_pn2[2][0], a_pn2[2][1], a_pn2[2][2], tmp_a_bh_pn2, - adot_pn2[2][0], adot_pn2[2][1], adot_pn2[2][2], tmp_adot_bh_pn2, - a_pn2[3][0], a_pn2[3][1], a_pn2[3][2], tmp_a_bh_pn2_5, - adot_pn2[3][0], adot_pn2[3][1], adot_pn2[3][2], tmp_adot_bh_pn2_5, - a_pn2[4][0], a_pn2[4][1], a_pn2[4][2], tmp_a_bh_pn3, - adot_pn2[4][0], adot_pn2[4][1], adot_pn2[4][2], tmp_adot_bh_pn3, - a_pn2[5][0], a_pn2[5][1], a_pn2[5][2], tmp_a_bh_pn3_5, - adot_pn2[5][0], adot_pn2[5][1], adot_pn2[5][2], tmp_adot_bh_pn3_5, - a_pn2[6][0], a_pn2[6][1], a_pn2[6][2], tmp_a_bh_spin, - adot_pn2[6][0], adot_pn2[6][1], adot_pn2[6][2], tmp_adot_bh_spin); - -#else - -fprintf(out,"%.16E \t %.8E \t % .16E % .16E % .16E \t %.16E \t % .16E % .16E % .16E \t %.16E \t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t %.8E \t\t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \n", - time_cur, m[i], - x[i][0], x[i][1], x[i][2], tmp_r, - v[i][0], v[i][1], v[i][2], tmp_v, - pot[i], - a[i][0], a[i][1], a[i][2], tmp_a, - adot[i][0], adot[i][1], adot[i][2], tmp_adot, - dt[i], - pot_bh2, - a_bh2[0], a_bh2[1], a_bh2[2], tmp_a_bh, - adot_bh2[0], adot_bh2[1], adot_bh2[2], tmp_adot_bh); - -#endif // ADD_PN_BH - -#else - -fprintf(out,"%.16E \t %.8E \t % .16E % .16E % .16E \t %.16E \t % .16E % .16E % .16E \t %.16E \t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t %.8E \n", - time_cur, m[i], - x[i][0], x[i][1], x[i][2], tmp_r, - v[i][0], v[i][1], v[i][2], tmp_v, - pot[i], - a[i][0], a[i][1], a[i][2], tmp_a, - adot[i][0], adot[i][1], adot[i][2], tmp_adot, - dt[i]); - -#endif // ADD_N_BH - -fprintf(out,"\n"); - -fclose(out); - -#else - -#ifdef ADD_BH1 - -out = fopen("bh.dat","a"); - -// i=N-1; -i=0; - -tmp_r = sqrt( SQR(x[i][0]) + SQR(x[i][1]) + SQR(x[i][2]) ); -tmp_v = sqrt( SQR(v[i][0]) + SQR(v[i][1]) + SQR(v[i][2]) ); - -tmp_a = sqrt( SQR(a[i][0]) + SQR(a[i][1]) + SQR(a[i][2]) ); -tmp_adot = sqrt( SQR(adot[i][0]) + SQR(adot[i][1]) + SQR(adot[i][2]) ); - -fprintf(out,"%.16E \t %.8E \t % .16E % .16E % .16E \t %.16E \t % .16E % .16E % .16E \t %.16E \t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t %.8E \n", - time_cur, m[i], - x[i][0], x[i][1], x[i][2], tmp_r, - v[i][0], v[i][1], v[i][2], tmp_v, - pot[i], - a[i][0], a[i][1], a[i][2], tmp_a, - adot[i][0], adot[i][1], adot[i][2], tmp_adot, - dt[i]); - -fprintf(out,"\n"); - -fclose(out); - -#endif // ADD_BH1 - -#endif // ADD_BH2 + tmp_adot_bh_pn0 = sqrt( SQR(adot_pn[0][0]) + SQR(adot_pn[0][1]) + SQR(adot_pn[0][2]) ); + tmp_adot_bh_pn1 = sqrt( SQR(adot_pn[1][0]) + SQR(adot_pn[1][1]) + SQR(adot_pn[1][2]) ); + tmp_adot_bh_pn2 = sqrt( SQR(adot_pn[2][0]) + SQR(adot_pn[2][1]) + SQR(adot_pn[2][2]) ); + tmp_adot_bh_pn2_5 = sqrt( SQR(adot_pn[3][0]) + SQR(adot_pn[3][1]) + SQR(adot_pn[3][2]) ); + tmp_adot_bh_pn3 = sqrt( SQR(adot_pn[4][0]) + SQR(adot_pn[4][1]) + SQR(adot_pn[4][2]) ); + tmp_adot_bh_pn3_5 = sqrt( SQR(adot_pn[5][0]) + SQR(adot_pn[5][1]) + SQR(adot_pn[5][2]) ); + tmp_adot_bh_spin = sqrt( SQR(adot_pn[6][0]) + SQR(adot_pn[6][1]) + SQR(adot_pn[6][2]) ); + fprintf(out,"%.16E \t %.8E \t % .16E % .16E % .16E \t %.16E \t % .16E % .16E % .16E \t %.16E \t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t %.8E \t\t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t\t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \n", + time_cur, m[i], + x[i][0], x[i][1], x[i][2], tmp_r, + v[i][0], v[i][1], v[i][2], tmp_v, + pot[i], + a[i][0], a[i][1], a[i][2], tmp_a, + adot[i][0], adot[i][1], adot[i][2], tmp_adot, + dt[i], + pot_bh, + a_bh[0], a_bh[1], a_bh[2], tmp_a_bh, + adot_bh[0], adot_bh[1], adot_bh[2], tmp_adot_bh, + a_pn[0][0], a_pn[0][1], a_pn[0][2], tmp_a_bh_pn0, + adot_pn[0][0], adot_pn[0][1], adot_pn[0][2], tmp_adot_bh_pn0, + a_pn[1][0], a_pn[1][1], a_pn[1][2], tmp_a_bh_pn1, + adot_pn[1][0], adot_pn[1][1], adot_pn[1][2], tmp_adot_bh_pn1, + a_pn[2][0], a_pn[2][1], a_pn[2][2], tmp_a_bh_pn2, + adot_pn[2][0], adot_pn[2][1], adot_pn[2][2], tmp_adot_bh_pn2, + a_pn[3][0], a_pn[3][1], a_pn[3][2], tmp_a_bh_pn2_5, + adot_pn[3][0], adot_pn[3][1], adot_pn[3][2], tmp_adot_bh_pn2_5, + a_pn[4][0], a_pn[4][1], a_pn[4][2], tmp_a_bh_pn3, + adot_pn[4][0], adot_pn[4][1], adot_pn[4][2], tmp_adot_bh_pn3, + a_pn[5][0], a_pn[5][1], a_pn[5][2], tmp_a_bh_pn3_5, + adot_pn[5][0], adot_pn[5][1], adot_pn[5][2], tmp_adot_bh_pn3_5, + a_pn[6][0], a_pn[6][1], a_pn[6][2], tmp_a_bh_spin, + adot_pn[6][0], adot_pn[6][1], adot_pn[6][2], tmp_adot_bh_spin); + } else { + fprintf(out,"%.16E \t %.8E \t % .16E % .16E % .16E \t %.16E \t % .16E % .16E % .16E \t %.16E \t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t %.8E \t\t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \n", + time_cur, m[i], + x[i][0], x[i][1], x[i][2], tmp_r, + v[i][0], v[i][1], v[i][2], tmp_v, + pot[i], + a[i][0], a[i][1], a[i][2], tmp_a, + adot[i][0], adot[i][1], adot[i][2], tmp_adot, + dt[i], + pot_bh, + a_bh[0], a_bh[1], a_bh[2], tmp_a_bh, + adot_bh[0], adot_bh[1], adot_bh[2], tmp_adot_bh); + } + } else { + fprintf(out,"%.16E \t %.8E \t % .16E % .16E % .16E \t %.16E \t % .16E % .16E % .16E \t %.16E \t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t %.8E \n", + time_cur, m[i], + x[i][0], x[i][1], x[i][2], tmp_r, + v[i][0], v[i][1], v[i][2], tmp_v, + pot[i], + a[i][0], a[i][1], a[i][2], tmp_a, + adot[i][0], adot[i][1], adot[i][2], tmp_adot, + dt[i]); + } + } + fprintf(out,"\n"); + fclose(out); + } else if (parameters.live_smbh_count == 1) { + out = fopen("bh.dat","a"); + tmp_r = sqrt( SQR(x[0][0]) + SQR(x[0][1]) + SQR(x[0][2]) ); + tmp_v = sqrt( SQR(v[0][0]) + SQR(v[0][1]) + SQR(v[0][2]) ); + tmp_a = sqrt( SQR(a[0][0]) + SQR(a[0][1]) + SQR(a[0][2]) ); + tmp_adot = sqrt( SQR(adot[0][0]) + SQR(adot[0][1]) + SQR(adot[0][2]) ); + fprintf(out,"%.16E \t %.8E \t % .16E % .16E % .16E \t %.16E \t % .16E % .16E % .16E \t %.16E \t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t %.8E \n", + time_cur, m[0], + x[0][0], x[0][1], x[0][2], tmp_r, + v[0][0], v[0][1], v[0][2], tmp_v, + pot[0], + a[0][0], a[0][1], a[0][2], tmp_a, + adot[0][0], adot[0][1], adot[0][2], tmp_adot, + dt[0]); + fprintf(out,"\n"); + fclose(out); + } } -#ifdef BH_OUT_NB - void write_bh_nb_data() { + int i_bh, nb = parameters.live_smbh_neighbor_number; + double tmp, tmp_r, tmp_v; -#ifdef ADD_BH2 + out = fopen("bh_nb.dat", "a"); -int i_bh, nb = 10; -double tmp, tmp_r, tmp_v; + /* 1st BH */ -out = fopen("bh_nb.dat","a"); + i_bh = 0; -/* 1st BH */ + for (int i_bh=0; i_bh < parameters.live_smbh_count; i_bh++) { + for (i=0; i 0)) { + out = fopen("bh.dat", "w"); + fclose(out); + } + if ((parameters.live_smbh_neighbor_output) && (parameters.live_smbh_count > 0)) { + out = fopen("bh_nb.dat", "w"); + fclose(out); + } + if (parameters.binary_smbh_influence_sphere_output) { + out = fopen("bbh.inf","w"); + fclose(out); + } -#ifdef BH_OUT - out = fopen("bh.dat","w"); - fclose(out); -#endif - -#ifdef BH_OUT_NB - out = fopen("bh_nb.dat","w"); - fclose(out); -#endif - -#else - -#ifdef ADD_BH1 - -#ifdef BH_OUT - out = fopen("bh.dat","w"); - fclose(out); -#endif - -#ifdef BH_OUT_NB - out = fopen("bh_nb.dat","w"); - fclose(out); -#endif - -#endif // ADD_BH1 - -#endif // ADD_BH2 - -#ifdef BBH_INF - out = fopen("bbh.inf","w"); - fclose(out); -#endif } else { // if (diskstep == 0) } // if (diskstep == 0) @@ -2076,96 +1864,92 @@ int main(int argc, char *argv[]) /* Wait to all processors to finish his works... */ MPI_Barrier(MPI_COMM_WORLD); -#ifdef ADD_BH2 + if (parameters.live_smbh_count == 2) { + i_bh1 = 0; + i_bh2 = 1; - i_bh1 = 0; - i_bh2 = 1; + if (parameters.live_smbh_custom_eps >= 0) { -#ifdef ADD_N_BH + m_bh1 = m[i_bh1]; + m_bh2 = m[i_bh2]; - m_bh1 = m[i_bh1]; - m_bh2 = m[i_bh2]; + for (k=0;k<3;k++) { + x_bh1[k] = x[i_bh1][k]; + v_bh1[k] = v[i_bh1][k]; - for (k=0;k<3;k++) { - x_bh1[k] = x[i_bh1][k]; - v_bh1[k] = v[i_bh1][k]; + x_bh2[k] = x[i_bh2][k]; + v_bh2[k] = v[i_bh2][k]; + } - x_bh2[k] = x[i_bh2][k]; - v_bh2[k] = v[i_bh2][k]; - } + // calculate and "minus" the BH <-> BH _softened_ pot, acc & jerk - // calculate and "minus" the BH <-> BH _softened_ pot, acc & jerk + tmp_i = calc_force_n_BH(m_bh1, x_bh1, v_bh1, + m_bh2, x_bh2, v_bh2, + eps, + &pot_bh1, a_bh1, adot_bh1, + &pot_bh2, a_bh2, adot_bh2); - tmp_i = calc_force_n_BH(m_bh1, x_bh1, v_bh1, - m_bh2, x_bh2, v_bh2, - eps, - &pot_bh1, a_bh1, adot_bh1, - &pot_bh2, a_bh2, adot_bh2); + pot[i_bh1] -= pot_bh1; + pot[i_bh2] -= pot_bh2; - pot[i_bh1] -= pot_bh1; - pot[i_bh2] -= pot_bh2; + for (k=0;k<3;k++) { + a[i_bh1][k] -= a_bh1[k]; + a[i_bh2][k] -= a_bh2[k]; - for (k=0;k<3;k++) { - a[i_bh1][k] -= a_bh1[k]; - a[i_bh2][k] -= a_bh2[k]; + adot[i_bh1][k] -= adot_bh1[k]; + adot[i_bh2][k] -= adot_bh2[k]; + } - adot[i_bh1][k] -= adot_bh1[k]; - adot[i_bh2][k] -= adot_bh2[k]; - } + // calculate and "plus" the new BH <-> BH _unsoftened_ pot, acc, jerk - // calculate and "plus" the new BH <-> BH _unsoftened_ pot, acc, jerk + tmp_i = calc_force_n_BH(m_bh1, x_bh1, v_bh1, + m_bh2, x_bh2, v_bh2, + parameters.live_smbh_custom_eps, + &pot_bh1, a_bh1, adot_bh1, + &pot_bh2, a_bh2, adot_bh2); - tmp_i = calc_force_n_BH(m_bh1, x_bh1, v_bh1, - m_bh2, x_bh2, v_bh2, - eps_BH, - &pot_bh1, a_bh1, adot_bh1, - &pot_bh2, a_bh2, adot_bh2); + pot[i_bh1] += pot_bh1; + pot[i_bh2] += pot_bh2; - pot[i_bh1] += pot_bh1; - pot[i_bh2] += pot_bh2; + for (k=0;k<3;k++) { + a[i_bh1][k] += a_bh1[k]; + a[i_bh2][k] += a_bh2[k]; - for (k=0;k<3;k++) { - a[i_bh1][k] += a_bh1[k]; - a[i_bh2][k] += a_bh2[k]; + adot[i_bh1][k] += adot_bh1[k]; + adot[i_bh2][k] += adot_bh2[k]; + } + } - adot[i_bh1][k] += adot_bh1[k]; - adot[i_bh2][k] += adot_bh2[k]; - } + if (parameters.binary_smbh_pn) { -#endif // ADD_N_BH + // calculate and "plus" the new BH <-> BH : PN1, PN2, PN2.5, PN3, PN3.5 : acc, jerk -#ifdef ADD_PN_BH + dt_bh_tmp = dt[0]; - // calculate and "plus" the new BH <-> BH : PN1, PN2, PN2.5, PN3, PN3.5 : acc, jerk + tmp_i = calc_force_pn_BH(m_bh1, x_bh1, v_bh1, s_bh1, + m_bh2, x_bh2, v_bh2, s_bh2, + C_NB, dt_bh_tmp, usedOrNot, + (double(*)[3])a_pn1, (double(*)[3])adot_pn1, + (double(*)[3])a_pn2, (double(*)[3])adot_pn2); - dt_bh_tmp = dt[0]; + for (k=0;k<3;k++) { + a[i_bh1][k] += a_pn1[1][k] + a_pn1[2][k] + a_pn1[3][k] + a_pn1[4][k] + a_pn1[5][k] + a_pn1[6][k]; + a[i_bh2][k] += a_pn2[1][k] + a_pn2[2][k] + a_pn2[3][k] + a_pn2[4][k] + a_pn2[5][k] + a_pn2[6][k]; - tmp_i = calc_force_pn_BH(m_bh1, x_bh1, v_bh1, s_bh1, - m_bh2, x_bh2, v_bh2, s_bh2, - C_NB, dt_bh_tmp, usedOrNot, - a_pn1, adot_pn1, - a_pn2, adot_pn2); + adot[i_bh1][k] += adot_pn1[1][k] + adot_pn1[2][k] + adot_pn1[3][k] + adot_pn1[4][k] + adot_pn1[5][k] + adot_pn1[6][k]; + adot[i_bh2][k] += adot_pn2[1][k] + adot_pn2[2][k] + adot_pn2[3][k] + adot_pn2[4][k] + adot_pn2[5][k] + adot_pn2[6][k]; + } - for (k=0;k<3;k++) { - a[i_bh1][k] += a_pn1[1][k] + a_pn1[2][k] + a_pn1[3][k] + a_pn1[4][k] + a_pn1[5][k] + a_pn1[6][k]; - a[i_bh2][k] += a_pn2[1][k] + a_pn2[2][k] + a_pn2[3][k] + a_pn2[4][k] + a_pn2[5][k] + a_pn2[6][k]; - - adot[i_bh1][k] += adot_pn1[1][k] + adot_pn1[2][k] + adot_pn1[3][k] + adot_pn1[4][k] + adot_pn1[5][k] + adot_pn1[6][k]; - adot[i_bh2][k] += adot_pn2[1][k] + adot_pn2[2][k] + adot_pn2[3][k] + adot_pn2[4][k] + adot_pn2[5][k] + adot_pn2[6][k]; - } - - if (myRank == rootRank) { - if (tmp_i == 505) { - printf("PN RSDIST: %.8E \t %.8E \n", timesteps, time_cur); - fflush(stdout); - exit(-1); + if (myRank == rootRank) { + if (tmp_i == 505) { + printf("PN RSDIST: %.8E \t %.8E \n", timesteps, time_cur); + fflush(stdout); + exit(-1); + } + } } } -#endif // ADD_PN_BH - -#endif // ADD_BH2 - #ifdef EXTPOT calc_ext_grav_zero(); #endif @@ -2236,47 +2020,19 @@ int main(int argc, char *argv[]) dt[i] = dt_tmp; -#ifdef DT_MIN_WARNING - if (myRank == 0) { + if (parameters.dt_min_warning && (myRank == 0)) { if (dt[i] == dt_min) { printf("!!! Warning0: dt = dt_min = %.6E \t ind = %07d \n", dt[i], ind[i]); fflush(stdout); } } -#endif } /* i */ -#ifdef ADD_BH2 - - /* define the min. dt over all the part. and set it also for the BH... */ - - min_dt = dt[0]; - - for (i=1; i 0) { + double min_dt = *std::min_element(dt, dt+N); + for (int i=0; i 0) { + i_bh1 = 0; + i_bh2 = 1; + } #endif #ifdef TIMING @@ -2522,91 +2280,78 @@ int main(int argc, char *argv[]) DT_ACT_REDUCE += (CPU_tmp_user - CPU_tmp_user0); #endif -#ifdef ADD_BH2 + if (parameters.live_smbh_count == 2) { + if (parameters.live_smbh_custom_eps >= 0) { + m_bh1 = m_act[i_bh1]; + m_bh2 = m_act[i_bh2]; -#ifdef ADD_N_BH + x_bh1 = x_act_new[i_bh1]; + v_bh1 = v_act_new[i_bh1]; - m_bh1 = m_act[i_bh1]; - m_bh2 = m_act[i_bh2]; + x_bh2 = x_act_new[i_bh2]; + v_bh2 = v_act_new[i_bh2]; - for (k=0;k<3;k++) { - x_bh1[k] = x_act_new[i_bh1][k]; - v_bh1[k] = v_act_new[i_bh1][k]; + // calculate and "minus" the BH <-> BH softened pot, acc & jerk - x_bh2[k] = x_act_new[i_bh2][k]; - v_bh2[k] = v_act_new[i_bh2][k]; - } + tmp_i = calc_force_n_BH(m_bh1, x_bh1, v_bh1, + m_bh2, x_bh2, v_bh2, + eps, + &pot_bh1, a_bh1, adot_bh1, + &pot_bh2, a_bh2, adot_bh2); - // calculate and "minus" the BH <-> BH softened pot, acc & jerk + pot_act_new[i_bh1] -= pot_bh1; + pot_act_new[i_bh2] -= pot_bh2; - tmp_i = calc_force_n_BH(m_bh1, x_bh1, v_bh1, - m_bh2, x_bh2, v_bh2, - eps, - &pot_bh1, a_bh1, adot_bh1, - &pot_bh2, a_bh2, adot_bh2); + a_act_new[i_bh1] -= a_bh1; + a_act_new[i_bh2] -= a_bh2; - pot_act_new[i_bh1] -= pot_bh1; - pot_act_new[i_bh2] -= pot_bh2; + adot_act_new[i_bh1] -= adot_bh1; + adot_act_new[i_bh2] -= adot_bh2; - for (k=0;k<3;k++) { - a_act_new[i_bh1][k] -= a_bh1[k]; - a_act_new[i_bh2][k] -= a_bh2[k]; + // calculate and "plus" the new BH <-> BH unsoftened pot, acc, jerk - adot_act_new[i_bh1][k] -= adot_bh1[k]; - adot_act_new[i_bh2][k] -= adot_bh2[k]; - } + tmp_i = calc_force_n_BH(m_bh1, x_bh1, v_bh1, + m_bh2, x_bh2, v_bh2, + parameters.live_smbh_custom_eps, + &pot_bh1, a_bh1, adot_bh1, + &pot_bh2, a_bh2, adot_bh2); - // calculate and "plus" the new BH <-> BH unsoftened pot, acc, jerk + pot_act_new[i_bh1] += pot_bh1; + pot_act_new[i_bh2] += pot_bh2; - tmp_i = calc_force_n_BH(m_bh1, x_bh1, v_bh1, - m_bh2, x_bh2, v_bh2, - eps_BH, - &pot_bh1, a_bh1, adot_bh1, - &pot_bh2, a_bh2, adot_bh2); + a_act_new[i_bh1] += a_bh1; + a_act_new[i_bh2] += a_bh2; - pot_act_new[i_bh1] += pot_bh1; - pot_act_new[i_bh2] += pot_bh2; + adot_act_new[i_bh1] += adot_bh1; + adot_act_new[i_bh2] += adot_bh2; + } - for (k=0;k<3;k++) { - a_act_new[i_bh1][k] += a_bh1[k]; - a_act_new[i_bh2][k] += a_bh2[k]; + if (parameters.binary_smbh_pn) { + // calculate and "plus" the new BH <-> BH : PN1, PN2, PN2.5, PN3, PN3.5 : acc, jerk - adot_act_new[i_bh1][k] += adot_bh1[k]; - adot_act_new[i_bh2][k] += adot_bh2[k]; - } + dt_bh_tmp = dt[0]; -#endif // ADD_N_BH + tmp_i = calc_force_pn_BH(m_bh1, x_bh1, v_bh1, s_bh1, + m_bh2, x_bh2, v_bh2, s_bh2, + C_NB, dt_bh_tmp, usedOrNot, + (double(*)[3])a_pn1, (double(*)[3])adot_pn1, + (double(*)[3])a_pn2, (double(*)[3])adot_pn2); -#ifdef ADD_PN_BH + a_act_new[i_bh1] += a_pn1[1] + a_pn1[2] + a_pn1[3] + a_pn1[4] + a_pn1[5] + a_pn1[6]; + a_act_new[i_bh2] += a_pn2[1] + a_pn2[2] + a_pn2[3] + a_pn2[4] + a_pn2[5] + a_pn2[6]; - // calculate and "plus" the new BH <-> BH : PN1, PN2, PN2.5, PN3, PN3.5 : acc, jerk + adot_act_new[i_bh1] += adot_pn1[1] + adot_pn1[2] + adot_pn1[3] + adot_pn1[4] + adot_pn1[5] + adot_pn1[6]; + adot_act_new[i_bh2] += adot_pn2[1] + adot_pn2[2] + adot_pn2[3] + adot_pn2[4] + adot_pn2[5] + adot_pn2[6]; - dt_bh_tmp = dt[0]; - - tmp_i = calc_force_pn_BH(m_bh1, x_bh1, v_bh1, s_bh1, - m_bh2, x_bh2, v_bh2, s_bh2, - C_NB, dt_bh_tmp, usedOrNot, - a_pn1, adot_pn1, - a_pn2, adot_pn2); - - for (k=0;k<3;k++) { - a_act_new[i_bh1][k] += a_pn1[1][k] + a_pn1[2][k] + a_pn1[3][k] + a_pn1[4][k] + a_pn1[5][k] + a_pn1[6][k]; - a_act_new[i_bh2][k] += a_pn2[1][k] + a_pn2[2][k] + a_pn2[3][k] + a_pn2[4][k] + a_pn2[5][k] + a_pn2[6][k]; - - adot_act_new[i_bh1][k] += adot_pn1[1][k] + adot_pn1[2][k] + adot_pn1[3][k] + adot_pn1[4][k] + adot_pn1[5][k] + adot_pn1[6][k]; - adot_act_new[i_bh2][k] += adot_pn2[1][k] + adot_pn2[2][k] + adot_pn2[3][k] + adot_pn2[4][k] + adot_pn2[5][k] + adot_pn2[6][k]; - } - - if (myRank == rootRank) { - if (tmp_i == 505) { - printf("PN RSDIST: TS = %.8E \t t = %.8E \n", timesteps, time_cur); - fflush(stdout); - exit(-1); + if (myRank == rootRank) { + if (tmp_i == 505) { + printf("PN RSDIST: TS = %.8E \t t = %.8E \n", timesteps, time_cur); + fflush(stdout); + exit(-1); + } + } } } -#endif // ADD_PN_BH - -#endif // ADD_BH2 #ifdef EXTPOT calc_ext_grav(); @@ -2647,25 +2392,10 @@ int main(int argc, char *argv[]) a2dot1abs = a2dot1.norm(); a3dot1abs = a3.norm(); -#ifdef ADD_BH2 - if ((ind_act[i] == 0) || (ind_act[i] == 1)) { + if ((parameters.live_smbh_count > 0) && (ind_act[i] < parameters.live_smbh_count)) dt_new = sqrt(eta_bh*(a1abs*a2dot1abs+adot1abs*adot1abs)/(adot1abs*a3dot1abs+a2dot1abs*a2dot1abs)); - } else { + else dt_new = sqrt(eta*(a1abs*a2dot1abs+adot1abs*adot1abs)/(adot1abs*a3dot1abs+a2dot1abs*a2dot1abs)); - } -#else - -#ifdef ADD_BH1 - if (ind_act[i] == 0) { - dt_new = sqrt(eta_bh*(a1abs*a2dot1abs+adot1abs*adot1abs)/(adot1abs*a3dot1abs+a2dot1abs*a2dot1abs)); - } else { - dt_new = sqrt(eta*(a1abs*a2dot1abs+adot1abs*adot1abs)/(adot1abs*a3dot1abs+a2dot1abs*a2dot1abs)); - } -#endif // ADD_BH1 - - dt_new = sqrt(eta*(a1abs*a2dot1abs+adot1abs*adot1abs)/(adot1abs*a3dot1abs+a2dot1abs*a2dot1abs)); - -#endif // ADD_BH2 if (dt_new < dt_min) dt_tmp = dt_min; @@ -2690,114 +2420,92 @@ int main(int argc, char *argv[]) a_act[i] = a_act_new[i]; adot_act[i] = adot_act_new[i]; -#ifdef DT_MIN_WARNING - if (myRank == 0) { + if (parameters.dt_min_warning && (myRank == 0)) { if (dt_act[i] == dt_min) { printf("!!! Warning1: dt_act = dt_min = %.6E \t ind_act = %07d \n", dt[i], ind_act[i]); fflush(stdout); } } -#endif + } /* i */ /* define the min. dt over all the act. part. and set it also for the BH... */ -#ifdef ADD_BH2 - min_dt = dt_act[0]; + if (parameters.live_smbh_count > 0) { + double min_dt = *std::min_element(dt_act, dt_act+n_act); + if (parameters.live_smbh_count>=1) dt_act[i_bh1] = min_dt; + if (parameters.live_smbh_count==2) dt_act[i_bh2] = min_dt; + } - for (i=1; i= t_bh) { if (myRank == rootRank) { -#ifdef BH_OUT /* Write BH data... */ - write_bh_data(); -#endif + if (parameters.live_smbh_output) write_bh_data(); -#ifdef BH_OUT_NB /* Write BH NB data... */ - write_bh_nb_data(); -#endif + if (parameters.live_smbh_neighbor_output) write_bh_nb_data(); } /* if (myRank == rootRank) */ @@ -2921,8 +2625,6 @@ int main(int argc, char *argv[]) } /* if (myRank == rootRank) */ - /* possible coordinate & velocity limits for ALL particles !!! */ - #ifdef ETICS_CEP // We are /inside/ a control step, so all particles must be synchronized; we can safely calculate their density centre. The acceleration and jerk currently in the memory are for the predicted position of the CEP, by calling grapite_calc_center we "correct" the position and velocity, but not the gravity at that point. @@ -2960,7 +2662,7 @@ int main(int argc, char *argv[]) } /* while (time_cur < t_end) */ - /* close the local GRAPE's */ + /* close the local GRAPEs */ g6_close(clusterid); From cd282cc4065b7241626d83585378a39ebd40d9c2 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Sun, 15 Mar 2020 21:35:53 -0400 Subject: [PATCH 14/65] Improved the new-style config file and its reader --- io.cpp | 28 ++++++++++------ phigrape.conf | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++ phigrape.cpp | 23 +++++++------ 3 files changed, 119 insertions(+), 21 deletions(-) create mode 100644 phigrape.conf diff --git a/io.cpp b/io.cpp index b7894e6..b0a5641 100644 --- a/io.cpp +++ b/io.cpp @@ -4,6 +4,16 @@ #include #include +std::string strip(const std::string str) +{ + std::string str_new = str; + auto pos = str_new.find_first_not_of(" \t"); + if (pos != std::string::npos) str_new = str_new.substr(pos, str_new.size()); + pos = str_new.find_last_not_of(" \t"); + if (pos != std::string::npos) str_new = str_new.substr(0, pos+1); + return str_new; +} + int main() { std::unordered_map dictionary; @@ -19,22 +29,22 @@ int main() line_number++; auto pos = str.find('#'); if (pos != std::string::npos) str = str.substr(0, pos); - pos = str.find_first_not_of(" \t"); - if (pos != std::string::npos) str = str.substr(pos, str.size()); - else continue; - pos = str.find_last_not_of(" \t"); - if (pos != std::string::npos) str = str.substr(0, pos+1); + str = strip(str); if (str.size() == 0) continue; - pos = str.find_first_of(" \t"); + pos = str.find_first_of("="); if (pos == std::string::npos) { std::cerr << "Error: expected a key-value pair in line " << line_number << " of file " << file_name << std::endl; exit(1); } - std::string key = str.substr(0, pos); + std::string key = strip(str.substr(0, pos)); pos = str.find_first_not_of(" \t", pos+1); - std::string val = str.substr(pos, str.size()); + std::string val = strip(str.substr(pos, str.size())); dictionary[key] = val; } - printf("dictionary[\"more\"] = %s\n", dictionary["eps"].c_str()); + for (auto key_value : dictionary) { + auto key = key_value.first; + auto value = key_value.second; + printf("dictionary[\"%s\"] = \"%s\"\n", key.c_str(), value.c_str()); + } } diff --git a/phigrape.conf b/phigrape.conf new file mode 100644 index 0000000..34ef7ce --- /dev/null +++ b/phigrape.conf @@ -0,0 +1,89 @@ +###################### +# GENERAL PARAMETERS # +###################### + + +# Plummer softening parameter (can be even 0) +eps = 1E-4 + +# End time of the calculation +t_end = 4.0 + +# Interval of snapshot files output (xxxxxx.dat) +dt_disk = 1.0 + +# Interval for the energy control output (contr.dat) +dt_contr = 0.125 + +# Interval for SMBH output (bh.dat, bh_neighbors.dat, and bh_inf.dat) +dt_bh = 0.125 + +# Parameter for timestep determination +eta = 0.01 + +# Name of the input file; use "data.con" in most cases +inp_data = data.con + + +##### NOT IMPLEMENTED ####################### +output_format = HDF5 +dt_min_warning = true +############################################# + +################################### +# LIVE SUPERMASSIVE BLACK HOLE(S) # +################################### + +# There is special treatment for particles representing supermassive black holes (SMBHs): they are integrated at every time step, they can have custom softening in SMBH-SMBH interactions, and post Newtonian terms can be added to the gravity. + +# The number of SMBH particles. Can be 0 (no SMBH), 1, or 2. [default: 0] +live_smbh_count = 2 + +# Custom softening length for SMBH-SMBH interactions (can also be zero). If non-negative, the custom softening is applied. [default: -1] +live_smbh_custom_eps = 0 + +# Output additional diagnostics about live SMBHs. [default: false] +#TODO# dt_bh +live_smbh_output = true + +# Output additional diagnostics about the SMBH's (or SMBHs') nearest neighbours (number could be set as shown below). [default: false] +live_smbh_neighbor_output = true + +# Number of nearest neighbours to the SMBH (or SMBHs) to include in output. [default: 10] +live_smbh_neighbor_number = 10 + +################################## +# BINARY SUPERMASSIVE BLACK HOLE # +################################## + +# The following parameters can be set when `live_smbh_count` is 2. + +# Output additional diagnostics about the SMBH's sphere of influence (size could be set as shown below). [default: false] +binary_smbh_influence_sphere_output = true + +# The influence sphere is centred at the binary SMBH's centre of mass, and its radius is the semi-major axis of the binary times the factor below. [default: 10.0] +binary_smbh_influence_radius_factor = 3.162277660168379497918067e+03 + +# Add post Newtonian terms to SMBH-SMBH gravity. [default: false] +binary_smbh_pn = true + +#################################### +# Negative powers of two # +#################################### +# -1 1/2 0.5 # +# -2 1/4 0.25 # +# -3 1/8 0.125 # +# -4 1/16 0.0625 # +# -5 1/32 0.03125 # +# -6 1/64 0.015625 # +# -7 1/128 0.0078125 # +# -8 1/256 0.00390625 # +# -9 1/512 0.001953125 # +# -10 1/1024 0.0009765625 # +# -11 1/2048 0.00048828125 # +# -12 1/4096 0.000244140625 # +# -13 1/8192 0.0001220703125 # +# -14 1/16384 0.00006103515625 # +# -15 1/32768 0.000030517578125 # +# -16 1/65536 0.0000152587890625 # +#################################### diff --git a/phigrape.cpp b/phigrape.cpp index 6c1e805..f3d8d1e 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -63,7 +63,6 @@ struct Parameters { double binary_smbh_influence_radius_factor = 3.162277660168379497918067e+03; // R_INF int live_smbh_neighbor_number = 10; // TODO make sure it's smaller than N? or just warn if it's not bool binary_smbh_pn = true; // ADD_PN_BH - bool binary_smbh_spin = true; // ADD_SPIN_BH bool dt_min_warning = true; // DT_MIN_WARNING } parameters; @@ -659,7 +658,7 @@ void write_bh_data() { if (parameters.live_smbh_count == 2) { - out = fopen("bh.dat","a"); + out = fopen("bh.dat", "a"); for (int i=0; i < 2; i++) { // double (*a_pn)[3], (*adot_pn)[3], pot_bh, *a_bh, *adot_bh; @@ -759,7 +758,7 @@ void write_bh_data() fprintf(out,"\n"); fclose(out); } else if (parameters.live_smbh_count == 1) { - out = fopen("bh.dat","a"); + out = fopen("bh.dat", "a"); tmp_r = sqrt( SQR(x[0][0]) + SQR(x[0][1]) + SQR(x[0][2]) ); tmp_v = sqrt( SQR(v[0][0]) + SQR(v[0][1]) + SQR(v[0][2]) ); tmp_a = sqrt( SQR(a[0][0]) + SQR(a[0][1]) + SQR(a[0][2]) ); @@ -782,7 +781,7 @@ void write_bh_nb_data() int i_bh, nb = parameters.live_smbh_neighbor_number; double tmp, tmp_r, tmp_v; - out = fopen("bh_nb.dat", "a"); + out = fopen("bh_neighbors.dat", "a"); /* 1st BH */ @@ -1453,7 +1452,7 @@ void energy_contr() fflush(stdout); - out = fopen("contr.dat","a"); + out = fopen("contr.dat", "a"); fprintf(out,"%.8E \t %.8E %.8E %.8E \t % .8E % .8E % .8E % .8E % .8E \t % .8E % .8E \t % .8E % .8E % .8E \t %.8E %.8E %.8E \n", time_cur, timesteps, n_act_sum, g6_calls, E_pot, E_kin, E_pot_ext, @@ -1515,7 +1514,7 @@ int main(int argc, char *argv[]) t_end : end time of calculation dt_disk : interval of snapshot files output (0xxx.dat) dt_contr : interval for the energy control output (contr.dat) - dt_bh : interval for BH output (bh.dat & bh_nb.dat) + dt_bh : interval for BH output (bh.dat & bh_neighbors.dat) eta : parameter for timestep determination inp_data : name of the input file (data.inp) */ @@ -1618,11 +1617,11 @@ int main(int argc, char *argv[]) fflush(stdout); if ((diskstep == 0) && (time_cur == 0.0)) { - out = fopen("contr.dat","w"); + out = fopen("contr.dat", "w"); fclose(out); #ifdef TIMING - out = fopen("timing.dat","w"); + out = fopen("timing.dat", "w"); fclose(out); #endif @@ -1631,11 +1630,11 @@ int main(int argc, char *argv[]) fclose(out); } if ((parameters.live_smbh_neighbor_output) && (parameters.live_smbh_count > 0)) { - out = fopen("bh_nb.dat", "w"); + out = fopen("bh_neighbors.dat", "w"); fclose(out); } if (parameters.binary_smbh_influence_sphere_output) { - out = fopen("bbh.inf","w"); + out = fopen("bbh_inf.dat", "w"); fclose(out); } @@ -2440,7 +2439,7 @@ int main(int argc, char *argv[]) if (parameters.binary_smbh_influence_sphere_output) { if (myRank == rootRank) { - out = fopen("bbh.inf","a"); + out = fopen("bbh_inf.dat", "a"); m_bh1 = m_act[i_bh1]; m_bh2 = m_act[i_bh2]; @@ -2600,7 +2599,7 @@ int main(int argc, char *argv[]) /* possible OUT for timing !!! */ #ifdef TIMING - out = fopen("timing.dat","a"); + out = fopen("timing.dat", "a"); DT_TOT = DT_ACT_DEF1 + DT_ACT_DEF2 + DT_ACT_DEF3 + DT_ACT_PRED + DT_ACT_GRAV + DT_EXT_GRAV + DT_GMC_GRAV + From bb9a34376316cbc2f66f662253b74cf94176f3c3 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Mon, 16 Mar 2020 23:21:22 -0400 Subject: [PATCH 15/65] Improved parameter parsing from config file --- io.cpp | 97 ++++++++++++++++++++++++++++++++++++++++++++------- phigrape.conf | 3 +- phigrape.cpp | 31 ++++++++++------ phigrape.h | 21 +++++++++++ 4 files changed, 127 insertions(+), 25 deletions(-) create mode 100644 phigrape.h diff --git a/io.cpp b/io.cpp index b0a5641..29967ec 100644 --- a/io.cpp +++ b/io.cpp @@ -1,9 +1,12 @@ -#include +#include "phigrape.h" #include +#include +#include #include -#include #include +using Dictionary = std::unordered_map; + std::string strip(const std::string str) { std::string str_new = str; @@ -14,15 +17,11 @@ std::string strip(const std::string str) return str_new; } -int main() +Dictionary read_config_file(const std::string file_name) { std::unordered_map dictionary; - std::string file_name = "phigrape.conf"; std::ifstream file(file_name); - if (!file.good()) { - std::cout << "Not found!" << std::endl; - exit(1); - } + if (!file.good()) throw std::runtime_error("File not found."); std::string str; int line_number = 0; while (std::getline(file, str)) { @@ -32,19 +31,93 @@ int main() str = strip(str); if (str.size() == 0) continue; pos = str.find_first_of("="); - if (pos == std::string::npos) { - std::cerr << "Error: expected a key-value pair in line " << line_number << " of file " << file_name << std::endl; - exit(1); - } + if (pos == std::string::npos) throw std::runtime_error("Error: expected a key-value pair in line " + std::to_string(line_number) + " of file " + file_name); std::string key = strip(str.substr(0, pos)); pos = str.find_first_not_of(" \t", pos+1); std::string val = strip(str.substr(pos, str.size())); dictionary[key] = val; } + return dictionary; +} + +template T string_cast(const std::string str); + +template<> std::string string_cast(const std::string str) +{ + return str; +} + +template<> double string_cast(const std::string str) +{ + size_t idx; + auto value = std::stod(str, &idx); + if (idx == str.size()) return value; + else throw std::runtime_error("Cannot convert \"" + str + "\" into a double"); +} + +template<> int string_cast(const std::string str) +{ + size_t idx; + auto value = std::stoi(str, &idx); + if (idx == str.size()) return value; + else throw std::runtime_error("Cannot convert \"" + str + "\" into an int"); +} + +template<> bool string_cast(const std::string str) +{ + if ((str=="true") || (str=="True") || (str=="yes") || (str=="Yes") || (str=="1")) return true; + else if ((str=="false") || (str=="False") || (str=="no") || (str=="No") || (str=="0")) return false; + throw std::runtime_error("Cannot convert \"" + str + "\" into a bool"); +} + + +// For mandatory parameters +template +T get_parameter(Dictionary dictionary, std::string name) +{ + auto item = dictionary.find(name); + if (item==dictionary.end()) throw std::runtime_error("Mandatory parameter " + name + " must be defined"); + else return string_cast((*item).second); +} + +// For optional parameters +template +T get_parameter(Dictionary dictionary, std::string name, T default_value) +{ + auto item = dictionary.find(name); + if (item==dictionary.end()) return default_value; + else return string_cast((*item).second); +} + +int main() +{ + auto dictionary = read_config_file("phigrape.conf"); for (auto key_value : dictionary) { auto key = key_value.first; auto value = key_value.second; printf("dictionary[\"%s\"] = \"%s\"\n", key.c_str(), value.c_str()); } + + + Parameters parameters; + + // TODO check if dt_disk and dt_contr are powers of two + parameters.dt_bh = get_parameter(dictionary, "eps"); + parameters.t_end = get_parameter(dictionary, "t_end"); + parameters.dt_disk = get_parameter(dictionary, "dt_disk"); + parameters.dt_contr = get_parameter(dictionary, "dt_contr"); + parameters.dt_bh = get_parameter(dictionary, "dt_bh", parameters.dt_contr); + parameters.eta = get_parameter(dictionary, "eta"); + parameters.input_file_name = get_parameter(dictionary, "dt_bh", "data.con"); + parameters.dt_min_warning = get_parameter(dictionary, "dt_min_warning", false); + parameters.live_smbh_count = get_parameter(dictionary, "live_smbh_count", 0); + parameters.live_smbh_custom_eps = get_parameter(dictionary, "live_smbh_custom_eps", -1); + parameters.live_smbh_output = get_parameter(dictionary, "live_smbh_output", false); + parameters.live_smbh_neighbor_output = get_parameter(dictionary, "live_smbh_neighbor_output", false); + parameters.live_smbh_neighbor_number = get_parameter(dictionary, "live_smbh_neighbor_number", 10); + parameters.binary_smbh_pn = get_parameter(dictionary, "binary_smbh_pn", false); + parameters.binary_smbh_influence_sphere_output = get_parameter(dictionary, "binary_smbh_influence_sphere_output", false); + parameters.binary_smbh_influence_radius_factor = get_parameter(dictionary, "binary_smbh_influence_radius_factor", 10.); + } diff --git a/phigrape.conf b/phigrape.conf index 34ef7ce..dd01e95 100644 --- a/phigrape.conf +++ b/phigrape.conf @@ -2,7 +2,6 @@ # GENERAL PARAMETERS # ###################### - # Plummer softening parameter (can be even 0) eps = 1E-4 @@ -27,7 +26,7 @@ inp_data = data.con ##### NOT IMPLEMENTED ####################### output_format = HDF5 -dt_min_warning = true +dt_min_warning = false ############################################# ################################### diff --git a/phigrape.cpp b/phigrape.cpp index f3d8d1e..962d9b3 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -53,18 +53,27 @@ Coded by : Peter Berczik Version number : 19.04 Last redaction : 2019.04.16 12:55 *****************************************************************************/ +#include "phigrape.h" +Parameters parameters; -struct Parameters { - int live_smbh_count = 2; // ADD_BH1 or ADD_BH2 - double live_smbh_custom_eps = 0; // ADD_N_BH - bool live_smbh_output = true; // BH_OUT - bool live_smbh_neighbor_output = true; // BH_OUT_NB // NOTE needs `live_smbh_neighbor_number` - bool binary_smbh_influence_sphere_output = true; // BBH_INF // NOTE needs `binary_smbh_influence_radius_factor` - double binary_smbh_influence_radius_factor = 3.162277660168379497918067e+03; // R_INF - int live_smbh_neighbor_number = 10; // TODO make sure it's smaller than N? or just warn if it's not - bool binary_smbh_pn = true; // ADD_PN_BH - bool dt_min_warning = true; // DT_MIN_WARNING -} parameters; +// struct Parameters { +// double eps = 1E-4; +// double t_end = 1; +// double dt_disk = 0.125; +// double dt_contr = 0.125; +// double dt_bh = 0.125; +// double eta = 0.01; +// std::string input_file_name = "data.con"; +// bool dt_min_warning = true; // DT_MIN_WARNING +// int live_smbh_count = 2; // ADD_BH1 or ADD_BH2 +// double live_smbh_custom_eps = 0; // ADD_N_BH +// bool live_smbh_output = true; // BH_OUT +// bool live_smbh_neighbor_output = true; // BH_OUT_NB // NOTE needs `live_smbh_neighbor_number` +// int live_smbh_neighbor_number = 10; // TODO make sure it's smaller than N? or just warn if it's not +// bool binary_smbh_pn = true; // ADD_PN_BH +// bool binary_smbh_influence_sphere_output = true; // BBH_INF // NOTE needs `binary_smbh_influence_radius_factor` +// double binary_smbh_influence_radius_factor = 3.162277660168379497918067e+03; // R_INF +// } parameters; //#define NORM // Physical normalization diff --git a/phigrape.h b/phigrape.h new file mode 100644 index 0000000..2c68183 --- /dev/null +++ b/phigrape.h @@ -0,0 +1,21 @@ +#pragma once +#include + +struct Parameters { + double eps; + double t_end; + double dt_disk; + double dt_contr; + double dt_bh; + double eta; + std::string input_file_name; + bool dt_min_warning; + int live_smbh_count; + double live_smbh_custom_eps; + bool live_smbh_output; + bool live_smbh_neighbor_output; + int live_smbh_neighbor_number; + bool binary_smbh_pn; + bool binary_smbh_influence_sphere_output; + double binary_smbh_influence_radius_factor; +}; From 9296db060960cf6e6aa48a182efe492d9e409823 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Tue, 17 Mar 2020 12:24:53 -0400 Subject: [PATCH 16/65] Now config file handles most parameters (but not external potential) --- Makefile | 2 +- config.cpp | 126 +++++++++++++++++++++++++++++++++++++++++ phigrape.h => config.h | 14 ++++- io.cpp | 123 ---------------------------------------- phigrape.conf | 2 +- phigrape.cpp | 86 +++++++++++++++------------- 6 files changed, 188 insertions(+), 165 deletions(-) create mode 100644 config.cpp rename phigrape.h => config.h (51%) delete mode 100644 io.cpp diff --git a/Makefile b/Makefile index 1739015..e109393 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ MPICXX ?= mpic++ EXECUTABLE ?= phigrape default: - $(MPICXX) $(CPPFLAGS) $(CXXFLAGS) -DETICS_DTSCF=$(ETICS_DTSCF) $(INC) phigrape.cpp -o $(EXECUTABLE) $(LIB) + $(MPICXX) $(CPPFLAGS) $(CXXFLAGS) -DETICS_DTSCF=$(ETICS_DTSCF) $(INC) config.cpp phigrape.cpp -o $(EXECUTABLE) $(LIB) yebisu: CPPFLAGS := $(filter-out -DETICS, $(CPPFLAGS)) yebisu: default diff --git a/config.cpp b/config.cpp new file mode 100644 index 0000000..c4c229e --- /dev/null +++ b/config.cpp @@ -0,0 +1,126 @@ +#include "config.h" +#include +#include +#include + +using Dictionary = std::unordered_map; + +std::string Config::strip(const std::string str) +{ + std::string str_new = str; + auto pos = str_new.find_first_not_of(" \t"); + if (pos != std::string::npos) str_new = str_new.substr(pos, str_new.size()); + pos = str_new.find_last_not_of(" \t"); + if (pos != std::string::npos) str_new = str_new.substr(0, pos+1); + return str_new; +} + +Dictionary Config::read_config_file(const std::string file_name) +{ + std::unordered_map dictionary; + std::ifstream file(file_name); + if (!file.good()) throw std::runtime_error("File not found."); + std::string str; + int line_number = 0; + while (std::getline(file, str)) { + line_number++; + auto pos = str.find('#'); + if (pos != std::string::npos) str = str.substr(0, pos); + str = strip(str); + if (str.size() == 0) continue; + pos = str.find_first_of("="); + if (pos == std::string::npos) throw std::runtime_error("Error: expected a key-value pair in line " + std::to_string(line_number) + " of file " + file_name); + std::string key = strip(str.substr(0, pos)); + pos = str.find_first_not_of(" \t", pos+1); + std::string val = strip(str.substr(pos, str.size())); + dictionary[key] = val; + } + return dictionary; +} + +template<> std::string Config::string_cast(const std::string str) +{ + return str; +} + +template<> double Config::string_cast(const std::string str) +{ + size_t idx; + auto value = std::stod(str, &idx); + if (idx == str.size()) return value; + else throw std::runtime_error("Cannot convert \"" + str + "\" into a double"); +} + +template<> int Config::string_cast(const std::string str) +{ + size_t idx; + auto value = std::stoi(str, &idx); + if (idx == str.size()) return value; + else throw std::runtime_error("Cannot convert \"" + str + "\" into an int"); +} + +template<> bool Config::string_cast(const std::string str) +{ + if ((str=="true") || (str=="True") || (str=="yes") || (str=="Yes") || (str=="1")) return true; + else if ((str=="false") || (str=="False") || (str=="no") || (str=="No") || (str=="0")) return false; + throw std::runtime_error("Cannot convert \"" + str + "\" into a bool"); +} + + +// For mandatory parameters +template +T Config::get_parameter(Dictionary dictionary, std::string name) +{ + auto item = dictionary.find(name); + if (item==dictionary.end()) throw std::runtime_error("Mandatory parameter " + name + " must be defined"); + else return string_cast((*item).second); +} + +// For optional parameters +template +T Config::get_parameter(Dictionary dictionary, std::string name, T default_value) +{ + auto item = dictionary.find(name); + if (item==dictionary.end()) return default_value; + else return string_cast((*item).second); +} + +void Config::error_checking() +{ + if ((live_smbh_count < 0) || (live_smbh_count > 2)) + throw std::runtime_error("The number of live black holes (live_smbh_count) can be 0, 1, or 2"); + if (binary_smbh_pn && (live_smbh_count!=2)) + throw std::runtime_error("Post-Newtonian gravity (binary_smbh_pn=true) requires live_smbh_count=2"); + if (live_smbh_custom_eps == eps) live_smbh_custom_eps = -1; + if (live_smbh_output && (live_smbh_count == 0)) + throw std::runtime_error("Black hole output (live_smbh_output=true) requires at least one live black hole (live_smbh_count)"); + if (live_smbh_neighbor_output && (live_smbh_count == 0)) + throw std::runtime_error("Black hole neighbour output (live_smbh_neighbor_output=true) requires at least one live black hole (live_smbh_count)"); + if (binary_smbh_influence_sphere_output && (live_smbh_count != 2)) + throw std::runtime_error("Binary black hole influence sphere output (binary_smbh_influence_sphere_output=true) requires exactly two live black holes (live_smbh_count=2)"); +} + +Config::Config(std::string file_name) +{ + auto dictionary = read_config_file(file_name); + + // TODO check if dt_disk and dt_contr are powers of two + eps = get_parameter(dictionary, "eps"); + t_end = get_parameter(dictionary, "t_end"); + dt_disk = get_parameter(dictionary, "dt_disk"); + dt_contr = get_parameter(dictionary, "dt_contr"); + dt_bh = get_parameter(dictionary, "dt_bh", dt_contr); + eta = get_parameter(dictionary, "eta"); + input_file_name = get_parameter(dictionary, "input_file_name", "data.con"); + dt_min_warning = get_parameter(dictionary, "dt_min_warning", false); + live_smbh_count = get_parameter(dictionary, "live_smbh_count", 0); + live_smbh_custom_eps = get_parameter(dictionary, "live_smbh_custom_eps", -1); + live_smbh_output = get_parameter(dictionary, "live_smbh_output", false); + live_smbh_neighbor_output = get_parameter(dictionary, "live_smbh_neighbor_output", false); + live_smbh_neighbor_number = get_parameter(dictionary, "live_smbh_neighbor_number", 10); + binary_smbh_pn = get_parameter(dictionary, "binary_smbh_pn", false); + binary_smbh_influence_sphere_output = get_parameter(dictionary, "binary_smbh_influence_sphere_output", false); + binary_smbh_influence_radius_factor = get_parameter(dictionary, "binary_smbh_influence_radius_factor", 10.); + + error_checking(); +} diff --git a/phigrape.h b/config.h similarity index 51% rename from phigrape.h rename to config.h index 2c68183..5c06a7d 100644 --- a/phigrape.h +++ b/config.h @@ -1,7 +1,11 @@ #pragma once #include +#include + +class Config { +public: + Config(std::string file_name); -struct Parameters { double eps; double t_end; double dt_disk; @@ -18,4 +22,12 @@ struct Parameters { bool binary_smbh_pn; bool binary_smbh_influence_sphere_output; double binary_smbh_influence_radius_factor; +private: + using Dictionary = std::unordered_map; + Dictionary read_config_file(const std::string file_name); + std::string strip(const std::string str); + template T string_cast(const std::string str); + template T get_parameter(Dictionary dictionary, std::string name); + template T get_parameter(Dictionary dictionary, std::string name, T default_value); + void error_checking(); }; diff --git a/io.cpp b/io.cpp deleted file mode 100644 index 29967ec..0000000 --- a/io.cpp +++ /dev/null @@ -1,123 +0,0 @@ -#include "phigrape.h" -#include -#include -#include -#include -#include - -using Dictionary = std::unordered_map; - -std::string strip(const std::string str) -{ - std::string str_new = str; - auto pos = str_new.find_first_not_of(" \t"); - if (pos != std::string::npos) str_new = str_new.substr(pos, str_new.size()); - pos = str_new.find_last_not_of(" \t"); - if (pos != std::string::npos) str_new = str_new.substr(0, pos+1); - return str_new; -} - -Dictionary read_config_file(const std::string file_name) -{ - std::unordered_map dictionary; - std::ifstream file(file_name); - if (!file.good()) throw std::runtime_error("File not found."); - std::string str; - int line_number = 0; - while (std::getline(file, str)) { - line_number++; - auto pos = str.find('#'); - if (pos != std::string::npos) str = str.substr(0, pos); - str = strip(str); - if (str.size() == 0) continue; - pos = str.find_first_of("="); - if (pos == std::string::npos) throw std::runtime_error("Error: expected a key-value pair in line " + std::to_string(line_number) + " of file " + file_name); - std::string key = strip(str.substr(0, pos)); - pos = str.find_first_not_of(" \t", pos+1); - std::string val = strip(str.substr(pos, str.size())); - dictionary[key] = val; - } - return dictionary; -} - -template T string_cast(const std::string str); - -template<> std::string string_cast(const std::string str) -{ - return str; -} - -template<> double string_cast(const std::string str) -{ - size_t idx; - auto value = std::stod(str, &idx); - if (idx == str.size()) return value; - else throw std::runtime_error("Cannot convert \"" + str + "\" into a double"); -} - -template<> int string_cast(const std::string str) -{ - size_t idx; - auto value = std::stoi(str, &idx); - if (idx == str.size()) return value; - else throw std::runtime_error("Cannot convert \"" + str + "\" into an int"); -} - -template<> bool string_cast(const std::string str) -{ - if ((str=="true") || (str=="True") || (str=="yes") || (str=="Yes") || (str=="1")) return true; - else if ((str=="false") || (str=="False") || (str=="no") || (str=="No") || (str=="0")) return false; - throw std::runtime_error("Cannot convert \"" + str + "\" into a bool"); -} - - -// For mandatory parameters -template -T get_parameter(Dictionary dictionary, std::string name) -{ - auto item = dictionary.find(name); - if (item==dictionary.end()) throw std::runtime_error("Mandatory parameter " + name + " must be defined"); - else return string_cast((*item).second); -} - -// For optional parameters -template -T get_parameter(Dictionary dictionary, std::string name, T default_value) -{ - auto item = dictionary.find(name); - if (item==dictionary.end()) return default_value; - else return string_cast((*item).second); -} - -int main() -{ - auto dictionary = read_config_file("phigrape.conf"); - - for (auto key_value : dictionary) { - auto key = key_value.first; - auto value = key_value.second; - printf("dictionary[\"%s\"] = \"%s\"\n", key.c_str(), value.c_str()); - } - - - Parameters parameters; - - // TODO check if dt_disk and dt_contr are powers of two - parameters.dt_bh = get_parameter(dictionary, "eps"); - parameters.t_end = get_parameter(dictionary, "t_end"); - parameters.dt_disk = get_parameter(dictionary, "dt_disk"); - parameters.dt_contr = get_parameter(dictionary, "dt_contr"); - parameters.dt_bh = get_parameter(dictionary, "dt_bh", parameters.dt_contr); - parameters.eta = get_parameter(dictionary, "eta"); - parameters.input_file_name = get_parameter(dictionary, "dt_bh", "data.con"); - parameters.dt_min_warning = get_parameter(dictionary, "dt_min_warning", false); - parameters.live_smbh_count = get_parameter(dictionary, "live_smbh_count", 0); - parameters.live_smbh_custom_eps = get_parameter(dictionary, "live_smbh_custom_eps", -1); - parameters.live_smbh_output = get_parameter(dictionary, "live_smbh_output", false); - parameters.live_smbh_neighbor_output = get_parameter(dictionary, "live_smbh_neighbor_output", false); - parameters.live_smbh_neighbor_number = get_parameter(dictionary, "live_smbh_neighbor_number", 10); - parameters.binary_smbh_pn = get_parameter(dictionary, "binary_smbh_pn", false); - parameters.binary_smbh_influence_sphere_output = get_parameter(dictionary, "binary_smbh_influence_sphere_output", false); - parameters.binary_smbh_influence_radius_factor = get_parameter(dictionary, "binary_smbh_influence_radius_factor", 10.); - -} diff --git a/phigrape.conf b/phigrape.conf index dd01e95..732518f 100644 --- a/phigrape.conf +++ b/phigrape.conf @@ -6,7 +6,7 @@ eps = 1E-4 # End time of the calculation -t_end = 4.0 +t_end = 0.25 # Interval of snapshot files output (xxxxxx.dat) dt_disk = 1.0 diff --git a/phigrape.cpp b/phigrape.cpp index 962d9b3..b194e0b 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -53,8 +53,8 @@ Coded by : Peter Berczik Version number : 19.04 Last redaction : 2019.04.16 12:55 *****************************************************************************/ -#include "phigrape.h" -Parameters parameters; +#include "config.h" +Config *config; // struct Parameters { // double eps = 1E-4; @@ -665,7 +665,7 @@ fclose(out); void write_bh_data() { - if (parameters.live_smbh_count == 2) { + if (config->live_smbh_count == 2) { out = fopen("bh.dat", "a"); @@ -693,12 +693,12 @@ void write_bh_data() tmp_a = sqrt( SQR(a[i][0]) + SQR(a[i][1]) + SQR(a[i][2]) ); tmp_adot = sqrt( SQR(adot[i][0]) + SQR(adot[i][1]) + SQR(adot[i][2]) ); - if (parameters.live_smbh_custom_eps >= 0) { + if (config->live_smbh_custom_eps >= 0) { tmp_a_bh = sqrt( SQR(a_bh[0]) + SQR(a_bh[1]) + SQR(a_bh[2]) ); tmp_adot_bh = sqrt( SQR(adot_bh[0]) + SQR(adot_bh[1]) + SQR(adot_bh[2]) ); - if (parameters.binary_smbh_spin) { + if (config->binary_smbh_pn) { tmp_a_bh_pn0 = sqrt( SQR(a_pn[0][0]) + SQR(a_pn[0][1]) + SQR(a_pn[0][2]) ); tmp_a_bh_pn1 = sqrt( SQR(a_pn[1][0]) + SQR(a_pn[1][1]) + SQR(a_pn[1][2]) ); tmp_a_bh_pn2 = sqrt( SQR(a_pn[2][0]) + SQR(a_pn[2][1]) + SQR(a_pn[2][2]) ); @@ -766,7 +766,7 @@ void write_bh_data() } fprintf(out,"\n"); fclose(out); - } else if (parameters.live_smbh_count == 1) { + } else if (config->live_smbh_count == 1) { out = fopen("bh.dat", "a"); tmp_r = sqrt( SQR(x[0][0]) + SQR(x[0][1]) + SQR(x[0][2]) ); tmp_v = sqrt( SQR(v[0][0]) + SQR(v[0][1]) + SQR(v[0][2]) ); @@ -787,7 +787,7 @@ void write_bh_data() void write_bh_nb_data() { - int i_bh, nb = parameters.live_smbh_neighbor_number; + int i_bh, nb = config->live_smbh_neighbor_number; double tmp, tmp_r, tmp_v; out = fopen("bh_neighbors.dat", "a"); @@ -796,7 +796,7 @@ void write_bh_nb_data() i_bh = 0; - for (int i_bh=0; i_bh < parameters.live_smbh_count; i_bh++) { + for (int i_bh=0; i_bh < config->live_smbh_count; i_bh++) { for (i=0; ieps; + t_end = config->t_end; + dt_disk = config->dt_disk; + dt_contr = config->dt_contr; + dt_bh = config->dt_bh; + eta = config->eta; + strcpy(inp_fname, config->input_file_name.c_str()); + + if (config->binary_smbh_influence_sphere_output) for (i=0; i 0)) { + if (config->live_smbh_output && (config->live_smbh_count > 0)) { out = fopen("bh.dat", "w"); fclose(out); } - if ((parameters.live_smbh_neighbor_output) && (parameters.live_smbh_count > 0)) { + if ((config->live_smbh_neighbor_output) && (config->live_smbh_count > 0)) { out = fopen("bh_neighbors.dat", "w"); fclose(out); } - if (parameters.binary_smbh_influence_sphere_output) { + if (config->binary_smbh_influence_sphere_output) { out = fopen("bbh_inf.dat", "w"); fclose(out); } @@ -1872,11 +1880,11 @@ int main(int argc, char *argv[]) /* Wait to all processors to finish his works... */ MPI_Barrier(MPI_COMM_WORLD); - if (parameters.live_smbh_count == 2) { + if (config->live_smbh_count == 2) { i_bh1 = 0; i_bh2 = 1; - if (parameters.live_smbh_custom_eps >= 0) { + if (config->live_smbh_custom_eps >= 0) { m_bh1 = m[i_bh1]; m_bh2 = m[i_bh2]; @@ -1912,7 +1920,7 @@ int main(int argc, char *argv[]) tmp_i = calc_force_n_BH(m_bh1, x_bh1, v_bh1, m_bh2, x_bh2, v_bh2, - parameters.live_smbh_custom_eps, + config->live_smbh_custom_eps, &pot_bh1, a_bh1, adot_bh1, &pot_bh2, a_bh2, adot_bh2); @@ -1928,7 +1936,7 @@ int main(int argc, char *argv[]) } } - if (parameters.binary_smbh_pn) { + if (config->binary_smbh_pn) { // calculate and "plus" the new BH <-> BH : PN1, PN2, PN2.5, PN3, PN3.5 : acc, jerk @@ -2028,7 +2036,7 @@ int main(int argc, char *argv[]) dt[i] = dt_tmp; - if (parameters.dt_min_warning && (myRank == 0)) { + if (config->dt_min_warning && (myRank == 0)) { if (dt[i] == dt_min) { printf("!!! Warning0: dt = dt_min = %.6E \t ind = %07d \n", dt[i], ind[i]); fflush(stdout); @@ -2037,9 +2045,9 @@ int main(int argc, char *argv[]) } /* i */ - if (parameters.live_smbh_count > 0) { + if (config->live_smbh_count > 0) { double min_dt = *std::min_element(dt, dt+N); - for (int i=0; ilive_smbh_count; i++) dt[i] = min_dt; } /* Wait to all processors to finish his works... */ @@ -2067,10 +2075,10 @@ int main(int argc, char *argv[]) if (myRank == rootRank) { /* Write BH data... */ - if (parameters.live_smbh_output) write_bh_data(); + if (config->live_smbh_output) write_bh_data(); /* Write BH NB data... */ - if (parameters.live_smbh_neighbor_output) write_bh_nb_data(); + if (config->live_smbh_neighbor_output) write_bh_nb_data(); } /* if (myRank == rootRank) */ @@ -2207,7 +2215,7 @@ int main(int argc, char *argv[]) exit(1); } #else - if (parameters.live_smbh_count > 0) { + if (config->live_smbh_count > 0) { i_bh1 = 0; i_bh2 = 1; } @@ -2288,8 +2296,8 @@ int main(int argc, char *argv[]) DT_ACT_REDUCE += (CPU_tmp_user - CPU_tmp_user0); #endif - if (parameters.live_smbh_count == 2) { - if (parameters.live_smbh_custom_eps >= 0) { + if (config->live_smbh_count == 2) { + if (config->live_smbh_custom_eps >= 0) { m_bh1 = m_act[i_bh1]; m_bh2 = m_act[i_bh2]; @@ -2320,7 +2328,7 @@ int main(int argc, char *argv[]) tmp_i = calc_force_n_BH(m_bh1, x_bh1, v_bh1, m_bh2, x_bh2, v_bh2, - parameters.live_smbh_custom_eps, + config->live_smbh_custom_eps, &pot_bh1, a_bh1, adot_bh1, &pot_bh2, a_bh2, adot_bh2); @@ -2334,7 +2342,7 @@ int main(int argc, char *argv[]) adot_act_new[i_bh2] += adot_bh2; } - if (parameters.binary_smbh_pn) { + if (config->binary_smbh_pn) { // calculate and "plus" the new BH <-> BH : PN1, PN2, PN2.5, PN3, PN3.5 : acc, jerk dt_bh_tmp = dt[0]; @@ -2400,7 +2408,7 @@ int main(int argc, char *argv[]) a2dot1abs = a2dot1.norm(); a3dot1abs = a3.norm(); - if ((parameters.live_smbh_count > 0) && (ind_act[i] < parameters.live_smbh_count)) + if ((config->live_smbh_count > 0) && (ind_act[i] < config->live_smbh_count)) dt_new = sqrt(eta_bh*(a1abs*a2dot1abs+adot1abs*adot1abs)/(adot1abs*a3dot1abs+a2dot1abs*a2dot1abs)); else dt_new = sqrt(eta*(a1abs*a2dot1abs+adot1abs*adot1abs)/(adot1abs*a3dot1abs+a2dot1abs*a2dot1abs)); @@ -2428,7 +2436,7 @@ int main(int argc, char *argv[]) a_act[i] = a_act_new[i]; adot_act[i] = adot_act_new[i]; - if (parameters.dt_min_warning && (myRank == 0)) { + if (config->dt_min_warning && (myRank == 0)) { if (dt_act[i] == dt_min) { printf("!!! Warning1: dt_act = dt_min = %.6E \t ind_act = %07d \n", dt[i], ind_act[i]); fflush(stdout); @@ -2439,13 +2447,13 @@ int main(int argc, char *argv[]) /* define the min. dt over all the act. part. and set it also for the BH... */ - if (parameters.live_smbh_count > 0) { + if (config->live_smbh_count > 0) { double min_dt = *std::min_element(dt_act, dt_act+n_act); - if (parameters.live_smbh_count>=1) dt_act[i_bh1] = min_dt; - if (parameters.live_smbh_count==2) dt_act[i_bh2] = min_dt; + if (config->live_smbh_count>=1) dt_act[i_bh1] = min_dt; + if (config->live_smbh_count==2) dt_act[i_bh2] = min_dt; } - if (parameters.binary_smbh_influence_sphere_output) { + if (config->binary_smbh_influence_sphere_output) { if (myRank == rootRank) { out = fopen("bbh_inf.dat", "a"); @@ -2476,7 +2484,7 @@ int main(int argc, char *argv[]) iii = ind_act[i]; - if (tmp_r2 < SEMI_a2*SQR(parameters.binary_smbh_influence_radius_factor)) { + if (tmp_r2 < SEMI_a2*SQR(config->binary_smbh_influence_radius_factor)) { if (inf_event[iii] == 0) { @@ -2586,10 +2594,10 @@ int main(int argc, char *argv[]) if (time_cur >= t_bh) { if (myRank == rootRank) { /* Write BH data... */ - if (parameters.live_smbh_output) write_bh_data(); + if (config->live_smbh_output) write_bh_data(); /* Write BH NB data... */ - if (parameters.live_smbh_neighbor_output) write_bh_nb_data(); + if (config->live_smbh_neighbor_output) write_bh_nb_data(); } /* if (myRank == rootRank) */ From 22f983cf17964338f132659d3fbf6591dffad8fa Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Wed, 18 Mar 2020 11:55:24 -0400 Subject: [PATCH 17/65] Moved some variables from global to main and removed some unused variables --- .gitignore | 2 + phigrape.cpp | 265 ++++++++++++++++++++++++--------------------------- pn_bh_spin.c | 15 +-- 3 files changed, 130 insertions(+), 152 deletions(-) diff --git a/.gitignore b/.gitignore index 9f184f3..773bfd7 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ *.cfg *.inp *.mask +grapite-dev-exec-threshold +phigrape diff --git a/phigrape.cpp b/phigrape.cpp index b194e0b..b545836 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -306,39 +306,12 @@ double3 operator-(const double3& a, const double3& b) } -int name_proc, n_proc=1, myRank=0, rootRank=0, cur_rank, - i, j, k, ni, nj, diskstep=0, power, jjj, iii, - skip_con=0, tmp_i; - -double dt_disk, dt_contr, t_disk=0.0, t_contr=0.0, - dt_bh, t_bh=0.0, dt_bh_tmp, - t_end, time_cur, dt_min, dt_max, min_t, min_t_loc, dt_new, min_dt, - eta_s, eta, eta_bh, - E_pot, E_pot_ext, E_kin, E_tot, E_tot_0, DE_tot, - E_tot_corr, E_tot_corr_0, DE_tot_corr, - E_tot_corr_sd, E_tot_corr_sd_0, DE_tot_corr_sd, - E_corr = 0.0, E_sd = 0.0, t_diss_on = 0.125, - mcm, rcm_mod, vcm_mod, - rcm_sum=0.0, vcm_sum=0.0, - eps=0.0, eps2, - a2_mod, adot2_mod, - dt_tmp, dt2half, dt3over6, dt4over24, dt5over120, - dtinv, dt2inv, dt3inv, - a0mia1, ad04plad12, ad0plad1, - a1abs, adot1abs, a2dot1abs, a3dot1abs, - timesteps=0.0, n_act_sum=0.0, n_act_distr[N_MAX], g6_calls=0.0, g6_calls_sum=0.0, - tmp, tmp_r, tmp_v, tmp_rv, tmp_cpu, - tmp_pot, tmp_a, tmp_adot, - tmp_a_bh, tmp_adot_bh, - tmp_a_bh_pn0, tmp_a_bh_pn1, tmp_a_bh_pn2, tmp_a_bh_pn2_5, tmp_a_bh_pn3, tmp_a_bh_pn3_5, tmp_a_bh_spin, - tmp_adot_bh_pn0, tmp_adot_bh_pn1, tmp_adot_bh_pn2, tmp_adot_bh_pn2_5, tmp_adot_bh_pn3, tmp_adot_bh_pn3_5, tmp_adot_bh_spin; - double L[3]; // needed in pn_bh_spin.c // Needed for things related to BHs #include "debug.h" -int ind_sort[N_MAX]; -double var_sort[N_MAX]; +// int ind_sort[N_MAX]; +// double var_sort[N_MAX]; double3 xcm, vcm, mom, @@ -611,28 +584,24 @@ gettimeofday(&tv, NULL); } -void read_data() +void read_data(int *diskstep, int *N, double *time_cur, int ind[], double m[], double3 x[], double3 v[]) { -inp = fopen(inp_fname,"r"); -fscanf(inp,"%d \n", &diskstep); - -fscanf(inp,"%d \n", &N); - -fscanf(inp,"%lE \n", &time_cur); - -for (i=0; ilive_smbh_count == 2) { - out = fopen("bh.dat", "a"); + auto out = fopen("bh.dat", "a"); for (int i=0; i < 2; i++) { -// double (*a_pn)[3], (*adot_pn)[3], pot_bh, *a_bh, *adot_bh; double3 *a_pn, *adot_pn, a_bh, adot_bh; double pot_bh; if (i==0) { @@ -687,33 +655,33 @@ void write_bh_data() adot_bh = adot_bh2; } - tmp_r = sqrt( SQR(x[i][0]) + SQR(x[i][1]) + SQR(x[i][2]) ); - tmp_v = sqrt( SQR(v[i][0]) + SQR(v[i][1]) + SQR(v[i][2]) ); + double tmp_r = sqrt( SQR(x[i][0]) + SQR(x[i][1]) + SQR(x[i][2]) ); + double tmp_v = sqrt( SQR(v[i][0]) + SQR(v[i][1]) + SQR(v[i][2]) ); - tmp_a = sqrt( SQR(a[i][0]) + SQR(a[i][1]) + SQR(a[i][2]) ); - tmp_adot = sqrt( SQR(adot[i][0]) + SQR(adot[i][1]) + SQR(adot[i][2]) ); + double tmp_a = sqrt( SQR(a[i][0]) + SQR(a[i][1]) + SQR(a[i][2]) ); + double tmp_adot = sqrt( SQR(adot[i][0]) + SQR(adot[i][1]) + SQR(adot[i][2]) ); if (config->live_smbh_custom_eps >= 0) { - tmp_a_bh = sqrt( SQR(a_bh[0]) + SQR(a_bh[1]) + SQR(a_bh[2]) ); - tmp_adot_bh = sqrt( SQR(adot_bh[0]) + SQR(adot_bh[1]) + SQR(adot_bh[2]) ); + double tmp_a_bh = sqrt( SQR(a_bh[0]) + SQR(a_bh[1]) + SQR(a_bh[2]) ); + double tmp_adot_bh = sqrt( SQR(adot_bh[0]) + SQR(adot_bh[1]) + SQR(adot_bh[2]) ); if (config->binary_smbh_pn) { - tmp_a_bh_pn0 = sqrt( SQR(a_pn[0][0]) + SQR(a_pn[0][1]) + SQR(a_pn[0][2]) ); - tmp_a_bh_pn1 = sqrt( SQR(a_pn[1][0]) + SQR(a_pn[1][1]) + SQR(a_pn[1][2]) ); - tmp_a_bh_pn2 = sqrt( SQR(a_pn[2][0]) + SQR(a_pn[2][1]) + SQR(a_pn[2][2]) ); - tmp_a_bh_pn2_5 = sqrt( SQR(a_pn[3][0]) + SQR(a_pn[3][1]) + SQR(a_pn[3][2]) ); - tmp_a_bh_pn3 = sqrt( SQR(a_pn[4][0]) + SQR(a_pn[4][1]) + SQR(a_pn[4][2]) ); - tmp_a_bh_pn3_5 = sqrt( SQR(a_pn[5][0]) + SQR(a_pn[5][1]) + SQR(a_pn[5][2]) ); - tmp_a_bh_spin = sqrt( SQR(a_pn[6][0]) + SQR(a_pn[6][1]) + SQR(a_pn[6][2]) ); + double tmp_a_bh_pn0 = sqrt( SQR(a_pn[0][0]) + SQR(a_pn[0][1]) + SQR(a_pn[0][2]) ); + double tmp_a_bh_pn1 = sqrt( SQR(a_pn[1][0]) + SQR(a_pn[1][1]) + SQR(a_pn[1][2]) ); + double tmp_a_bh_pn2 = sqrt( SQR(a_pn[2][0]) + SQR(a_pn[2][1]) + SQR(a_pn[2][2]) ); + double tmp_a_bh_pn2_5 = sqrt( SQR(a_pn[3][0]) + SQR(a_pn[3][1]) + SQR(a_pn[3][2]) ); + double tmp_a_bh_pn3 = sqrt( SQR(a_pn[4][0]) + SQR(a_pn[4][1]) + SQR(a_pn[4][2]) ); + double tmp_a_bh_pn3_5 = sqrt( SQR(a_pn[5][0]) + SQR(a_pn[5][1]) + SQR(a_pn[5][2]) ); + double tmp_a_bh_spin = sqrt( SQR(a_pn[6][0]) + SQR(a_pn[6][1]) + SQR(a_pn[6][2]) ); - tmp_adot_bh_pn0 = sqrt( SQR(adot_pn[0][0]) + SQR(adot_pn[0][1]) + SQR(adot_pn[0][2]) ); - tmp_adot_bh_pn1 = sqrt( SQR(adot_pn[1][0]) + SQR(adot_pn[1][1]) + SQR(adot_pn[1][2]) ); - tmp_adot_bh_pn2 = sqrt( SQR(adot_pn[2][0]) + SQR(adot_pn[2][1]) + SQR(adot_pn[2][2]) ); - tmp_adot_bh_pn2_5 = sqrt( SQR(adot_pn[3][0]) + SQR(adot_pn[3][1]) + SQR(adot_pn[3][2]) ); - tmp_adot_bh_pn3 = sqrt( SQR(adot_pn[4][0]) + SQR(adot_pn[4][1]) + SQR(adot_pn[4][2]) ); - tmp_adot_bh_pn3_5 = sqrt( SQR(adot_pn[5][0]) + SQR(adot_pn[5][1]) + SQR(adot_pn[5][2]) ); - tmp_adot_bh_spin = sqrt( SQR(adot_pn[6][0]) + SQR(adot_pn[6][1]) + SQR(adot_pn[6][2]) ); + double tmp_adot_bh_pn0 = sqrt( SQR(adot_pn[0][0]) + SQR(adot_pn[0][1]) + SQR(adot_pn[0][2]) ); + double tmp_adot_bh_pn1 = sqrt( SQR(adot_pn[1][0]) + SQR(adot_pn[1][1]) + SQR(adot_pn[1][2]) ); + double tmp_adot_bh_pn2 = sqrt( SQR(adot_pn[2][0]) + SQR(adot_pn[2][1]) + SQR(adot_pn[2][2]) ); + double tmp_adot_bh_pn2_5 = sqrt( SQR(adot_pn[3][0]) + SQR(adot_pn[3][1]) + SQR(adot_pn[3][2]) ); + double tmp_adot_bh_pn3 = sqrt( SQR(adot_pn[4][0]) + SQR(adot_pn[4][1]) + SQR(adot_pn[4][2]) ); + double tmp_adot_bh_pn3_5 = sqrt( SQR(adot_pn[5][0]) + SQR(adot_pn[5][1]) + SQR(adot_pn[5][2]) ); + double tmp_adot_bh_spin = sqrt( SQR(adot_pn[6][0]) + SQR(adot_pn[6][1]) + SQR(adot_pn[6][2]) ); fprintf(out,"%.16E \t %.8E \t % .16E % .16E % .16E \t %.16E \t % .16E % .16E % .16E \t %.16E \t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t %.8E \t\t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t\t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \n", time_cur, m[i], @@ -768,10 +736,10 @@ void write_bh_data() fclose(out); } else if (config->live_smbh_count == 1) { out = fopen("bh.dat", "a"); - tmp_r = sqrt( SQR(x[0][0]) + SQR(x[0][1]) + SQR(x[0][2]) ); - tmp_v = sqrt( SQR(v[0][0]) + SQR(v[0][1]) + SQR(v[0][2]) ); - tmp_a = sqrt( SQR(a[0][0]) + SQR(a[0][1]) + SQR(a[0][2]) ); - tmp_adot = sqrt( SQR(adot[0][0]) + SQR(adot[0][1]) + SQR(adot[0][2]) ); + double tmp_r = sqrt( SQR(x[0][0]) + SQR(x[0][1]) + SQR(x[0][2]) ); + double tmp_v = sqrt( SQR(v[0][0]) + SQR(v[0][1]) + SQR(v[0][2]) ); + double tmp_a = sqrt( SQR(a[0][0]) + SQR(a[0][1]) + SQR(a[0][2]) ); + double tmp_adot = sqrt( SQR(adot[0][0]) + SQR(adot[0][1]) + SQR(adot[0][2]) ); fprintf(out,"%.16E \t %.8E \t % .16E % .16E % .16E \t %.16E \t % .16E % .16E % .16E \t %.16E \t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t %.8E \n", time_cur, m[0], x[0][0], x[0][1], x[0][2], tmp_r, @@ -785,19 +753,18 @@ void write_bh_data() } } -void write_bh_nb_data() +void write_bh_nb_data(double time_cur, double m[], double3 x[], double3 v[]) { - int i_bh, nb = config->live_smbh_neighbor_number; - double tmp, tmp_r, tmp_v; + int nb = config->live_smbh_neighbor_number; + int ind_sort[N_MAX]; + double var_sort[N_MAX]; out = fopen("bh_neighbors.dat", "a"); /* 1st BH */ - i_bh = 0; - for (int i_bh=0; i_bh < config->live_smbh_count; i_bh++) { - for (i=0; ilive_smbh_output) write_bh_data(); + if (config->live_smbh_output) write_bh_data(time_cur, m, x, v); /* Write BH NB data... */ - if (config->live_smbh_neighbor_output) write_bh_nb_data(); + if (config->live_smbh_neighbor_output) write_bh_nb_data(time_cur, m, x, v); } /* if (myRank == rootRank) */ @@ -2087,7 +2073,6 @@ int main(int argc, char *argv[]) if (myRank == rootRank) { get_CPU_time(&CPU_time_real0, &CPU_time_user0, &CPU_time_syst0); get_CPU_time(&CPU_time_real, &CPU_time_user, &CPU_time_syst); - tmp_cpu = CPU_time_real-CPU_time_real0; } /* if (myRank == rootRank) */ timesteps = 0.0; @@ -2275,7 +2260,7 @@ int main(int argc, char *argv[]) DT_ACT_PRED += (CPU_tmp_user - CPU_tmp_user0); #endif - calc_self_grav(min_t); + calc_self_grav(min_t, eps2, g6_calls); /* Reduce the "global" vectors from "local" on all the nodes */ @@ -2351,7 +2336,7 @@ int main(int argc, char *argv[]) m_bh2, x_bh2, v_bh2, s_bh2, C_NB, dt_bh_tmp, usedOrNot, (double(*)[3])a_pn1, (double(*)[3])adot_pn1, - (double(*)[3])a_pn2, (double(*)[3])adot_pn2); + (double(*)[3])a_pn2, (double(*)[3])adot_pn2, myRank, rootRank); a_act_new[i_bh1] += a_pn1[1] + a_pn1[2] + a_pn1[3] + a_pn1[4] + a_pn1[5] + a_pn1[6]; a_act_new[i_bh2] += a_pn2[1] + a_pn2[2] + a_pn2[3] + a_pn2[4] + a_pn2[5] + a_pn2[6]; @@ -2594,10 +2579,10 @@ int main(int argc, char *argv[]) if (time_cur >= t_bh) { if (myRank == rootRank) { /* Write BH data... */ - if (config->live_smbh_output) write_bh_data(); + if (config->live_smbh_output) write_bh_data(time_cur, m, x, v); /* Write BH NB data... */ - if (config->live_smbh_neighbor_output) write_bh_nb_data(); + if (config->live_smbh_neighbor_output) write_bh_nb_data(time_cur, m, x, v); } /* if (myRank == rootRank) */ @@ -2607,11 +2592,11 @@ int main(int argc, char *argv[]) if (time_cur >= t_contr) { if (myRank == rootRank) { - energy_contr(); + energy_contr(time_cur, timesteps, n_act_sum, g6_calls, rcm_sum, vcm_sum, E_tot_0, E_tot_corr_0, E_tot_corr_sd_0, skip_con); /* write cont data */ - write_cont_data(); + write_snap_data((char*)"data.con", diskstep, N, time_cur, ind, m, x, v); /* possible OUT for timing !!! */ @@ -2665,7 +2650,9 @@ int main(int argc, char *argv[]) if (time_cur >= t_disk) { if (myRank == rootRank) { diskstep++; - write_snap_data(); + char out_fname[256]; + sprintf(out_fname, "%06d.dat", diskstep); + write_snap_data(out_fname, diskstep, N, time_cur, ind, m, x, v); } /* if (myRank == rootRank) */ #ifdef ETICS_DUMP diff --git a/pn_bh_spin.c b/pn_bh_spin.c index 54822f3..c0e54da 100644 --- a/pn_bh_spin.c +++ b/pn_bh_spin.c @@ -10,7 +10,7 @@ int calc_force_pn_BH(double m1, double xx1[], double vv1[], double spin1[], double CCC_NB, double dt_bh, int usedOrNot[], double a_pn1[][3], double adot_pn1[][3], - double a_pn2[][3], double adot_pn2[][3]) + double a_pn2[][3], double adot_pn2[][3], int myRank, int rootRank) { /* @@ -52,7 +52,7 @@ double PI2 = 9.86960440108935; double c_1, c_2, c_4, c_5, c_6, c_7, RS_DIST; double M, eta, r, r2, r3, MOR; -double V1_V22,VWHOLE, RP, RPP, VA; +double V1_V22, RP, RPP, VA; double N[3], x[3], v[3], A[3]; double A1, B1, A2, B2, A2_5, B2_5, AK2, BK2, AK4, BK4, AK5, BK5; double A1D, A2D, A2_5D, B1D, B2D, B2_5D, ADK2, BDK2, ADK4, BDK4, ADK5, BDK5; @@ -72,7 +72,6 @@ double SS1aux[3],SS2aux[3],SU[3],SV[3],XAD[3],XSD[3]; double NDOTCS[3], NCSU[3], NDOTCSIG[3], NCSV[3], ACS[3], VCSU[3], ACSIG[3], VCSV[3], SNVDOT, SIGNVDOT, NSDOT, NSIGDOT, VSDOT, VSIGDOT, NXSDOT, NXADOT; double C1_5D[3],C2D[3], C2_5D[3]; -double ADK, BDK, AD[3], KSAK, KSBK; double nu, Spin1Abs2, Spin2Abs2, rS1, rS2, S1Dir[3], S2Dir[3], QM[3]; double Spin1Abs, Spin2Abs, QMAux2_1[3], QMAux2_2[3], QMAux1[3] , QMD[3], SPINPrev[3][2], SpinPrev2_1, SpinPrev2_2, SPSPP1, SPSPP2, Spin1AbsNew2, Spin2AbsNew2, Spin1AbsNew, Spin2AbsNew, S1DirNew[3], @@ -129,7 +128,6 @@ r3 = r2*r; MOR = M/r; V1_V22 = v[0]*v[0]+v[1]*v[1]+v[2]*v[2]; -VWHOLE = sqrt(V1_V22); RP = (x[0]*v[0]+x[1]*v[1]+x[2]*v[2])/r; @@ -667,15 +665,6 @@ if(usedOrNot[5] == 1) // PN3.5 ~1/c^7 } /* if(Van_Spin==1) */ - ADK = ADK2+ADK4+ADK5+ADK6+ADK7; - BDK = BDK2+BDK4+BDK5+BDK6+BDK7; - - KSAK = AK2+AK4+AK5+AK6+AK7; - KSBK = BK2+BK4+BK5+BK6+BK7; - - for(k=0;k<3;k++) AD[k] = -2.0*MOR*RP*(KSAK*N[k]+KSBK*v[k])/r2 + MOR*(ADK*N[k]+BDK*v[k])/r + MOR*(KSAK*(v[k]-N[k]*RP)/r+KSBK*AT[k])/r + C1_5D[k]/c_2 + C2D[k]/c_4 +C2_5D[k]/c_4 + QMD[k]/c_4; - - for(k=0;k<3;k++) // new values of the BH's spins, returned back to the main program... { spin1[k] = SPIN[k][0]; From c4830423a34bb107ee7813a82b5c32977c2b61b8 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Wed, 18 Mar 2020 22:50:00 -0400 Subject: [PATCH 18/65] Fixed the control output problem --- phigrape.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/phigrape.cpp b/phigrape.cpp index b545836..a82b749 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -1337,7 +1337,7 @@ DT_EXT_GRAV += (CPU_tmp_user - CPU_tmp_user0); #endif // EXTPOT } -void energy_contr(const double time_cur, const double timesteps, int n_act_sum, int g6_calls, double& rcm_sum, double& vcm_sum, double& E_tot_0, double& E_tot_corr_0, double& E_tot_corr_sd_0, int skip_con) // TODO how do we know N? +void energy_contr(const double time_cur, const double timesteps, const double n_act_sum, const double g6_calls, double& rcm_sum, double& vcm_sum, double& E_tot_0, double& E_tot_corr_0, double& E_tot_corr_sd_0, int &skip_con) // TODO how do we know N? { // TODO maybe use static variables here for the previous step energy? double E_pot = 0.0; @@ -1420,6 +1420,7 @@ void energy_contr(const double time_cur, const double timesteps, int n_act_sum, } double DE_tot = E_tot - E_tot_0; + /* This is the only output to screen */ printf("%.3E %.3E % .4E %.4E % .4E % .4E % .4E %.2E\n", time_cur, timesteps, E_pot, E_kin, E_pot_ext, E_tot, DE_tot, From 8f984b5158c6cfa77ce20c05be509fc65362ca34 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Wed, 18 Mar 2020 23:47:44 -0400 Subject: [PATCH 19/65] Moved more variables from global to main and removed some unused variables --- phigrape.cpp | 182 +++++++++++++++++++++++++-------------------------- 1 file changed, 90 insertions(+), 92 deletions(-) diff --git a/phigrape.cpp b/phigrape.cpp index a82b749..1b89885 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -314,46 +314,6 @@ double L[3]; // needed in pn_bh_spin.c // double var_sort[N_MAX]; -double3 xcm, vcm, mom, - xdc, vdc, - a2, a3, a2dot1; - -char processor_name[MPI_MAX_PROCESSOR_NAME], - inp_fname[30], - out_fname[30]; - -/* global variables */ - -int N, N_star, N_bh, - ind[N_MAX], name[N_MAX]; -double m[N_MAX], pot[N_MAX], t[N_MAX], dt[N_MAX]; -double3 x[N_MAX], v[N_MAX], a[N_MAX], adot[N_MAX]; - -/* local variables */ - -int n_loc, ind_loc[N_MAX_loc]; -double m_loc[N_MAX_loc], pot_loc[N_MAX_loc], t_loc[N_MAX_loc], dt_loc[N_MAX_loc]; -double3 x_loc[N_MAX_loc], v_loc[N_MAX_loc], - a_loc[N_MAX_loc], adot_loc[N_MAX_loc]; - -/* data for active particles */ - -int n_act, ind_act[N_MAX]; -double m_act[N_MAX], - pot_act[N_MAX], t_act[N_MAX], dt_act[N_MAX], - pot_act_new[N_MAX], - pot_act_tmp[N_MAX], - pot_act_tmp_loc[N_MAX]; - -double3 x_act[N_MAX], v_act[N_MAX], - a_act[N_MAX], adot_act[N_MAX], - x_act_new[N_MAX], v_act_new[N_MAX], - a_act_new[N_MAX], adot_act_new[N_MAX], - a_act_tmp[N_MAX], adot_act_tmp[N_MAX], - a_act_tmp_loc[N_MAX], adot_act_tmp_loc[N_MAX]; - -FILE *inp, *out; - double CPU_time_real0, CPU_time_user0, CPU_time_syst0; double CPU_time_real, CPU_time_user, CPU_time_syst; @@ -584,12 +544,11 @@ gettimeofday(&tv, NULL); } -void read_data(int *diskstep, int *N, double *time_cur, int ind[], double m[], double3 x[], double3 v[]) +void read_data(char inp_fname[], int *diskstep, int *N, double *time_cur, int ind[], double m[], double3 x[], double3 v[]) { auto inp = fopen(inp_fname, "r"); fscanf(inp, "%d \n", diskstep); fscanf(inp, "%d \n", N); - printf("zzzzzz reading *%s* %d\n", inp_fname, *N); fscanf(inp, "%lE \n", time_cur); for (int i=0; i<*N; i++) fscanf(inp,"%d %lE %lE %lE %lE %lE %lE %lE \n", &ind[i], &m[i], &x[i][0], &x[i][1], &x[i][2], &v[i][0], &v[i][1], &v[i][2]); fclose(inp); @@ -597,7 +556,7 @@ void read_data(int *diskstep, int *N, double *time_cur, int ind[], double m[], d void write_snap_data(char out_fname[], int diskstep, int N, double time_cur, int ind[], double m[], double3 x[], double3 v[]) { - out = fopen(out_fname, "w"); + auto out = fopen(out_fname, "w"); fprintf(out,"%06d \n", diskstep); fprintf(out,"%07d \n", N); fprintf(out,"%.10E \n", time_cur); @@ -611,28 +570,7 @@ void write_snap_data(char out_fname[], int diskstep, int N, double time_cur, int fclose(out); } -// // // // // // // // // // // void write_cont_data() // virtually identical to write_snap_data() -// // // // // // // // // // // { -// // // // // // // // // // // out = fopen("data.con","w"); -// // // // // // // // // // // fprintf(out,"%06d \n", diskstep); -// // // // // // // // // // // -// // // // // // // // // // // fprintf(out,"%07d \n", N); -// // // // // // // // // // // -// // // // // // // // // // // fprintf(out,"%.16E \n", time_cur); -// // // // // // // // // // // -// // // // // // // // // // // for (i=0; ilive_smbh_count == 2) { @@ -735,7 +673,7 @@ void write_bh_data(double time_cur, double m[], double3 x[], double3 v[]) fprintf(out,"\n"); fclose(out); } else if (config->live_smbh_count == 1) { - out = fopen("bh.dat", "a"); + auto out = fopen("bh.dat", "a"); double tmp_r = sqrt( SQR(x[0][0]) + SQR(x[0][1]) + SQR(x[0][2]) ); double tmp_v = sqrt( SQR(v[0][0]) + SQR(v[0][1]) + SQR(v[0][2]) ); double tmp_a = sqrt( SQR(a[0][0]) + SQR(a[0][1]) + SQR(a[0][2]) ); @@ -753,13 +691,13 @@ void write_bh_data(double time_cur, double m[], double3 x[], double3 v[]) } } -void write_bh_nb_data(double time_cur, double m[], double3 x[], double3 v[]) +void write_bh_nb_data(double time_cur, int N, double m[], double3 x[], double3 v[]) { int nb = config->live_smbh_neighbor_number; int ind_sort[N_MAX]; double var_sort[N_MAX]; - out = fopen("bh_neighbors.dat", "a"); + auto out = fopen("bh_neighbors.dat", "a"); /* 1st BH */ @@ -1039,7 +977,13 @@ for (i=0; ilive_smbh_output) write_bh_data(time_cur, m, x, v); + if (config->live_smbh_output) write_bh_data(time_cur, m, x, v, pot, a, adot, dt); /* Write BH NB data... */ - if (config->live_smbh_neighbor_output) write_bh_nb_data(time_cur, m, x, v); + if (config->live_smbh_neighbor_output) write_bh_nb_data(time_cur, N, m, x, v); } /* if (myRank == rootRank) */ @@ -2261,7 +2253,13 @@ double dt_disk, dt_contr, t_disk=0.0, t_contr=0.0, DT_ACT_PRED += (CPU_tmp_user - CPU_tmp_user0); #endif - calc_self_grav(min_t, eps2, g6_calls); + calc_self_grav(min_t, eps2, g6_calls, n_loc, + n_act, ind_act, + x_act_new, v_act_new, + pot_act_tmp, + a_act_tmp, + adot_act_tmp, + h2_i); /* Reduce the "global" vectors from "local" on all the nodes */ @@ -2580,10 +2578,10 @@ double dt_disk, dt_contr, t_disk=0.0, t_contr=0.0, if (time_cur >= t_bh) { if (myRank == rootRank) { /* Write BH data... */ - if (config->live_smbh_output) write_bh_data(time_cur, m, x, v); + if (config->live_smbh_output) write_bh_data(time_cur, m, x, v, pot, a, adot, dt); /* Write BH NB data... */ - if (config->live_smbh_neighbor_output) write_bh_nb_data(time_cur, m, x, v); + if (config->live_smbh_neighbor_output) write_bh_nb_data(time_cur, N, m, x, v); } /* if (myRank == rootRank) */ @@ -2593,7 +2591,7 @@ double dt_disk, dt_contr, t_disk=0.0, t_contr=0.0, if (time_cur >= t_contr) { if (myRank == rootRank) { - energy_contr(time_cur, timesteps, n_act_sum, g6_calls, rcm_sum, vcm_sum, E_tot_0, E_tot_corr_0, E_tot_corr_sd_0, skip_con); + energy_contr(time_cur, timesteps, n_act_sum, g6_calls, rcm_sum, vcm_sum, E_tot_0, E_tot_corr_0, E_tot_corr_sd_0, skip_con, N, m, x, v, pot); /* write cont data */ From 9b900eff6ed66c4e2642cac2e083672f21f4393b Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Sat, 21 Mar 2020 12:46:26 -0400 Subject: [PATCH 20/65] Prettied up the black hole output and removed some redundant variables --- phigrape.cpp | 276 +++++++++++++-------------------------------------- 1 file changed, 70 insertions(+), 206 deletions(-) diff --git a/phigrape.cpp b/phigrape.cpp index 1b89885..5f52247 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -56,49 +56,8 @@ Last redaction : 2019.04.16 12:55 #include "config.h" Config *config; -// struct Parameters { -// double eps = 1E-4; -// double t_end = 1; -// double dt_disk = 0.125; -// double dt_contr = 0.125; -// double dt_bh = 0.125; -// double eta = 0.01; -// std::string input_file_name = "data.con"; -// bool dt_min_warning = true; // DT_MIN_WARNING -// int live_smbh_count = 2; // ADD_BH1 or ADD_BH2 -// double live_smbh_custom_eps = 0; // ADD_N_BH -// bool live_smbh_output = true; // BH_OUT -// bool live_smbh_neighbor_output = true; // BH_OUT_NB // NOTE needs `live_smbh_neighbor_number` -// int live_smbh_neighbor_number = 10; // TODO make sure it's smaller than N? or just warn if it's not -// bool binary_smbh_pn = true; // ADD_PN_BH -// bool binary_smbh_influence_sphere_output = true; // BBH_INF // NOTE needs `binary_smbh_influence_radius_factor` -// double binary_smbh_influence_radius_factor = 3.162277660168379497918067e+03; // R_INF -// } parameters; - //#define NORM // Physical normalization -// // // //#define ADD_BH1 // add the Single BH - -// // // // #define ADD_BH2 // add the Binary BH's -// // // // #define ADD_N_BH // eps_BH = 0.0, but added only the Newtonian forces -// // // // #define ADD_PN_BH // extra - added also the Post-Newton forces -// // // // #define ADD_SPIN_BH // extra - added the SPIN for the BH's - DEFAULT !!! - -// // // // #define BH_OUT // extra output for BH's (live) -// // // // #define BH_OUT_NB // extra output for the BH's neighbours (live) - -// // // // #define BBH_INF // BBH influence sphere... -// // // // #define R_INF 3.162277660168379497918067e+03 // Factor for the influence sphere... if ( R < R_INF * DR_BBH ) -// // // // #define R_INF2 (R_INF*R_INF) - -// // // // #define DT_MIN_WARNING // dt < dt_min warning !!! - -//#define BH_OUT_NB_EXT // extra output for the BH's neighbours (external) - -//#define STARDESTR // disruption of stars by BH tidal forces - -//#define STARDESTR_EXT // disruption of stars by external BH tidal forces - //#define EXTPOT // external potential (BH? or galactic?) //#define EXTPOT_BH // BH - usually NB units @@ -107,21 +66,6 @@ Config *config; //#define EXTPOT_GAL_DEH // Dehnen Galactic - usually physical units //#define EXTPOT_GAL_LOG // Log Galactic - usually physical units -//#define EXTPOT_SC // SC extra POT for Bek test runs... -//#define DATAFILE eff0.05.tsf10.00.tab -//#define M_SC_DIM 100001 - -//#define CMCORR // CM correction in the zero step and in every dt_contr - -//#define LIMITS // for "0" mass particles !!! -//#define R_LIMITS 1.0E+03 // for "0" mass particles !!! - -//#define LIMITS_NEW // for "0" mass particles !!! - -//#define LIMITS_ALL_BEG // for ALL particles at the beginning... -//#define LIMITS_ALL // for ALL particles -//#define R_LIMITS_ALL 1.0E+03 // for ALL particles - #ifdef ETICS #include "grapite.h" // why do we need CEP as a compilaion flag... just have it always on when ETICS is on. IF there is no CEP, there should be a graceful skipping of those operations. @@ -592,85 +536,37 @@ void write_bh_data(double time_cur, double m[], double3 x[], double3 v[], double a_bh = a_bh2; adot_bh = adot_bh2; } - - double tmp_r = sqrt( SQR(x[i][0]) + SQR(x[i][1]) + SQR(x[i][2]) ); - double tmp_v = sqrt( SQR(v[i][0]) + SQR(v[i][1]) + SQR(v[i][2]) ); - - double tmp_a = sqrt( SQR(a[i][0]) + SQR(a[i][1]) + SQR(a[i][2]) ); - double tmp_adot = sqrt( SQR(adot[i][0]) + SQR(adot[i][1]) + SQR(adot[i][2]) ); - if (config->live_smbh_custom_eps >= 0) { - - double tmp_a_bh = sqrt( SQR(a_bh[0]) + SQR(a_bh[1]) + SQR(a_bh[2]) ); - double tmp_adot_bh = sqrt( SQR(adot_bh[0]) + SQR(adot_bh[1]) + SQR(adot_bh[2]) ); - + fprintf(out, "%.16E \t %.8E \t % .16E % .16E % .16E \t %.16E \t % .16E % .16E % .16E \t %.16E \t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t %.8E \t\t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E ", + time_cur, m[i], + x[i][0], x[i][1], x[i][2], x[i].norm(), + v[i][0], v[i][1], v[i][2], v[i].norm(), + pot[i], + a[i][0], a[i][1], a[i][2], a[i].norm(), + adot[i][0], adot[i][1], adot[i][2], adot[i].norm(), + dt[i], + pot_bh, + a_bh[0], a_bh[1], a_bh[2], a_bh.norm(), + adot_bh[0], adot_bh[1], adot_bh[2], adot_bh.norm()); if (config->binary_smbh_pn) { - double tmp_a_bh_pn0 = sqrt( SQR(a_pn[0][0]) + SQR(a_pn[0][1]) + SQR(a_pn[0][2]) ); - double tmp_a_bh_pn1 = sqrt( SQR(a_pn[1][0]) + SQR(a_pn[1][1]) + SQR(a_pn[1][2]) ); - double tmp_a_bh_pn2 = sqrt( SQR(a_pn[2][0]) + SQR(a_pn[2][1]) + SQR(a_pn[2][2]) ); - double tmp_a_bh_pn2_5 = sqrt( SQR(a_pn[3][0]) + SQR(a_pn[3][1]) + SQR(a_pn[3][2]) ); - double tmp_a_bh_pn3 = sqrt( SQR(a_pn[4][0]) + SQR(a_pn[4][1]) + SQR(a_pn[4][2]) ); - double tmp_a_bh_pn3_5 = sqrt( SQR(a_pn[5][0]) + SQR(a_pn[5][1]) + SQR(a_pn[5][2]) ); - double tmp_a_bh_spin = sqrt( SQR(a_pn[6][0]) + SQR(a_pn[6][1]) + SQR(a_pn[6][2]) ); - - double tmp_adot_bh_pn0 = sqrt( SQR(adot_pn[0][0]) + SQR(adot_pn[0][1]) + SQR(adot_pn[0][2]) ); - double tmp_adot_bh_pn1 = sqrt( SQR(adot_pn[1][0]) + SQR(adot_pn[1][1]) + SQR(adot_pn[1][2]) ); - double tmp_adot_bh_pn2 = sqrt( SQR(adot_pn[2][0]) + SQR(adot_pn[2][1]) + SQR(adot_pn[2][2]) ); - double tmp_adot_bh_pn2_5 = sqrt( SQR(adot_pn[3][0]) + SQR(adot_pn[3][1]) + SQR(adot_pn[3][2]) ); - double tmp_adot_bh_pn3 = sqrt( SQR(adot_pn[4][0]) + SQR(adot_pn[4][1]) + SQR(adot_pn[4][2]) ); - double tmp_adot_bh_pn3_5 = sqrt( SQR(adot_pn[5][0]) + SQR(adot_pn[5][1]) + SQR(adot_pn[5][2]) ); - double tmp_adot_bh_spin = sqrt( SQR(adot_pn[6][0]) + SQR(adot_pn[6][1]) + SQR(adot_pn[6][2]) ); - - fprintf(out,"%.16E \t %.8E \t % .16E % .16E % .16E \t %.16E \t % .16E % .16E % .16E \t %.16E \t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t %.8E \t\t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t\t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \n", - time_cur, m[i], - x[i][0], x[i][1], x[i][2], tmp_r, - v[i][0], v[i][1], v[i][2], tmp_v, - pot[i], - a[i][0], a[i][1], a[i][2], tmp_a, - adot[i][0], adot[i][1], adot[i][2], tmp_adot, - dt[i], - pot_bh, - a_bh[0], a_bh[1], a_bh[2], tmp_a_bh, - adot_bh[0], adot_bh[1], adot_bh[2], tmp_adot_bh, - a_pn[0][0], a_pn[0][1], a_pn[0][2], tmp_a_bh_pn0, - adot_pn[0][0], adot_pn[0][1], adot_pn[0][2], tmp_adot_bh_pn0, - a_pn[1][0], a_pn[1][1], a_pn[1][2], tmp_a_bh_pn1, - adot_pn[1][0], adot_pn[1][1], adot_pn[1][2], tmp_adot_bh_pn1, - a_pn[2][0], a_pn[2][1], a_pn[2][2], tmp_a_bh_pn2, - adot_pn[2][0], adot_pn[2][1], adot_pn[2][2], tmp_adot_bh_pn2, - a_pn[3][0], a_pn[3][1], a_pn[3][2], tmp_a_bh_pn2_5, - adot_pn[3][0], adot_pn[3][1], adot_pn[3][2], tmp_adot_bh_pn2_5, - a_pn[4][0], a_pn[4][1], a_pn[4][2], tmp_a_bh_pn3, - adot_pn[4][0], adot_pn[4][1], adot_pn[4][2], tmp_adot_bh_pn3, - a_pn[5][0], a_pn[5][1], a_pn[5][2], tmp_a_bh_pn3_5, - adot_pn[5][0], adot_pn[5][1], adot_pn[5][2], tmp_adot_bh_pn3_5, - a_pn[6][0], a_pn[6][1], a_pn[6][2], tmp_a_bh_spin, - adot_pn[6][0], adot_pn[6][1], adot_pn[6][2], tmp_adot_bh_spin); - } else { - fprintf(out,"%.16E \t %.8E \t % .16E % .16E % .16E \t %.16E \t % .16E % .16E % .16E \t %.16E \t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t %.8E \t\t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \n", - time_cur, m[i], - x[i][0], x[i][1], x[i][2], tmp_r, - v[i][0], v[i][1], v[i][2], tmp_v, - pot[i], - a[i][0], a[i][1], a[i][2], tmp_a, - adot[i][0], adot[i][1], adot[i][2], tmp_adot, - dt[i], - pot_bh, - a_bh[0], a_bh[1], a_bh[2], tmp_a_bh, - adot_bh[0], adot_bh[1], adot_bh[2], tmp_adot_bh); + fprintf(out, "\t"); + for (int pn_idx=0; pn_idx < 7; pn_idx++) { + fprintf(out, "\t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E ", a_pn[pn_idx][0], a_pn[pn_idx][1], a_pn[pn_idx][2], a_pn[pn_idx].norm(), adot_pn[pn_idx][0], adot_pn[pn_idx][1], adot_pn[pn_idx][2], adot_pn[pn_idx].norm()); + } } + fprintf(out, "\n"); } else { fprintf(out,"%.16E \t %.8E \t % .16E % .16E % .16E \t %.16E \t % .16E % .16E % .16E \t %.16E \t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t %.8E \n", time_cur, m[i], - x[i][0], x[i][1], x[i][2], tmp_r, - v[i][0], v[i][1], v[i][2], tmp_v, + x[i][0], x[i][1], x[i][2], x[i].norm(), + v[i][0], v[i][1], v[i][2], v[i].norm(), pot[i], - a[i][0], a[i][1], a[i][2], tmp_a, - adot[i][0], adot[i][1], adot[i][2], tmp_adot, + a[i][0], a[i][1], a[i][2], a[i].norm(), + adot[i][0], adot[i][1], adot[i][2], adot[i].norm(), dt[i]); } } - fprintf(out,"\n"); + fprintf(out, "\n"); fclose(out); } else if (config->live_smbh_count == 1) { auto out = fopen("bh.dat", "a"); @@ -991,11 +887,6 @@ void calc_self_grav(double t, double eps2, double &g6_calls, int n_loc, get_CPU_time(&CPU_tmp_real0, &CPU_tmp_user0, &CPU_tmp_syst0); #endif -// // // // // // // /* bad variables... */ -// // // // // // // double pot_act_tmp[N_MAX]; -// // // // // // // double3 a_act_tmp[N_MAX]; -// // // // // // // double3 adot_act_tmp[N_MAX]; - g6_set_ti(clusterid, t); int ni = n_act; // TODO why is this needed? @@ -1014,15 +905,6 @@ void calc_self_grav(double t, double eps2, double &g6_calls, int n_loc, g6_calls++; } /* i */ - /* Store the new value of the local partial force etc... */ - -// // // // // // // // for (int i=0; ieta; strcpy(inp_fname, config->input_file_name.c_str()); - if (config->binary_smbh_influence_sphere_output) for (i=0; ibinary_smbh_influence_sphere_output) for (int i=0; i BH _softened_ pot, acc & jerk @@ -1887,13 +1759,11 @@ double dt_disk, dt_contr, t_disk=0.0, t_contr=0.0, pot[i_bh1] -= pot_bh1; pot[i_bh2] -= pot_bh2; - for (k=0;k<3;k++) { - a[i_bh1][k] -= a_bh1[k]; - a[i_bh2][k] -= a_bh2[k]; + a[i_bh1] -= a_bh1; + a[i_bh2] -= a_bh2; - adot[i_bh1][k] -= adot_bh1[k]; - adot[i_bh2][k] -= adot_bh2[k]; - } + adot[i_bh1] -= adot_bh1; + adot[i_bh2] -= adot_bh2; // calculate and "plus" the new BH <-> BH _unsoftened_ pot, acc, jerk @@ -1906,13 +1776,11 @@ double dt_disk, dt_contr, t_disk=0.0, t_contr=0.0, pot[i_bh1] += pot_bh1; pot[i_bh2] += pot_bh2; - for (k=0;k<3;k++) { - a[i_bh1][k] += a_bh1[k]; - a[i_bh2][k] += a_bh2[k]; + a[i_bh1] += a_bh1; + a[i_bh2] += a_bh2; - adot[i_bh1][k] += adot_bh1[k]; - adot[i_bh2][k] += adot_bh2[k]; - } + adot[i_bh1] += adot_bh1; + adot[i_bh2] += adot_bh2; } if (config->binary_smbh_pn) { @@ -1927,13 +1795,11 @@ double dt_disk, dt_contr, t_disk=0.0, t_contr=0.0, (double(*)[3])a_pn1, (double(*)[3])adot_pn1, (double(*)[3])a_pn2, (double(*)[3])adot_pn2, myRank, rootRank); - for (k=0;k<3;k++) { - a[i_bh1][k] += a_pn1[1][k] + a_pn1[2][k] + a_pn1[3][k] + a_pn1[4][k] + a_pn1[5][k] + a_pn1[6][k]; - a[i_bh2][k] += a_pn2[1][k] + a_pn2[2][k] + a_pn2[3][k] + a_pn2[4][k] + a_pn2[5][k] + a_pn2[6][k]; + a[i_bh1] += a_pn1[1] + a_pn1[2] + a_pn1[3] + a_pn1[4] + a_pn1[5] + a_pn1[6]; + a[i_bh2] += a_pn2[1] + a_pn2[2] + a_pn2[3] + a_pn2[4] + a_pn2[5] + a_pn2[6]; - adot[i_bh1][k] += adot_pn1[1][k] + adot_pn1[2][k] + adot_pn1[3][k] + adot_pn1[4][k] + adot_pn1[5][k] + adot_pn1[6][k]; - adot[i_bh2][k] += adot_pn2[1][k] + adot_pn2[2][k] + adot_pn2[3][k] + adot_pn2[4][k] + adot_pn2[5][k] + adot_pn2[6][k]; - } + adot[i_bh1] += adot_pn1[1] + adot_pn1[2] + adot_pn1[3] + adot_pn1[4] + adot_pn1[5] + adot_pn1[6]; + adot[i_bh2] += adot_pn2[1] + adot_pn2[2] + adot_pn2[3] + adot_pn2[4] + adot_pn2[5] + adot_pn2[6]; if (myRank == rootRank) { if (tmp_i == 505) { @@ -1997,7 +1863,7 @@ double dt_disk, dt_contr, t_disk=0.0, t_contr=0.0, /* Define initial timestep for all particles on all nodes */ - for (i=0; ilive_smbh_count > 0) { @@ -2044,7 +1909,7 @@ double dt_disk, dt_contr, t_disk=0.0, t_contr=0.0, /* load the nj particles to the G6 */ - for (j=0; j Date: Sat, 21 Mar 2020 22:52:13 -0400 Subject: [PATCH 21/65] Added post-Newtonian parameters to the config file --- config.cpp | 28 +++++++++++++++++++++++++++- config.h | 35 +++++++++++++++++++---------------- phigrape.conf | 7 +++++++ phigrape.cpp | 10 +++++++--- 4 files changed, 60 insertions(+), 20 deletions(-) diff --git a/config.cpp b/config.cpp index c4c229e..fb121be 100644 --- a/config.cpp +++ b/config.cpp @@ -2,6 +2,7 @@ #include #include #include +#include using Dictionary = std::unordered_map; @@ -54,7 +55,7 @@ template<> double Config::string_cast(const std::string str) template<> int Config::string_cast(const std::string str) { size_t idx; - auto value = std::stoi(str, &idx); + auto value = std::stoi(str, &idx); // WARNING stoi can throw if (idx == str.size()) return value; else throw std::runtime_error("Cannot convert \"" + str + "\" into an int"); } @@ -66,6 +67,24 @@ template<> bool Config::string_cast(const std::string str) throw std::runtime_error("Cannot convert \"" + str + "\" into a bool"); } +#include +template<> std::vector Config::string_cast(const std::string str) +{ + auto error = std::runtime_error("Cannot convert \"" + str + "\" into an integer array"); + if (!( (str.front()=='{') && (str.back()=='}'))) throw error; + std::string new_str = strip(str.substr(1, str.length()-2)); + std::replace(new_str.begin(), new_str.end(), ',', ' '); + + std::vector result; + while (new_str.length() > 0) { + size_t idx; + auto value = std::stoi(new_str, &idx); + result.push_back(value); + new_str = new_str.substr(idx, new_str.length()-idx); + } + return result; +} + // For mandatory parameters template @@ -98,6 +117,11 @@ void Config::error_checking() throw std::runtime_error("Black hole neighbour output (live_smbh_neighbor_output=true) requires at least one live black hole (live_smbh_count)"); if (binary_smbh_influence_sphere_output && (live_smbh_count != 2)) throw std::runtime_error("Binary black hole influence sphere output (binary_smbh_influence_sphere_output=true) requires exactly two live black holes (live_smbh_count=2)"); + if (pn_usage.size() != 7) + throw std::runtime_error("PN usage array (pn_usage) must have exactly seven components"); + for (int i; i<7; i++) + if (!((pn_usage[i] == 0) || (pn_usage[i] == 1))) + throw std::runtime_error("PN usage array (pn_usage) must have ones and zeros only"); } Config::Config(std::string file_name) @@ -121,6 +145,8 @@ Config::Config(std::string file_name) binary_smbh_pn = get_parameter(dictionary, "binary_smbh_pn", false); binary_smbh_influence_sphere_output = get_parameter(dictionary, "binary_smbh_influence_sphere_output", false); binary_smbh_influence_radius_factor = get_parameter(dictionary, "binary_smbh_influence_radius_factor", 10.); + pn_usage = get_parameter>(dictionary, "pn_usage", std::vector({1,1,1,1,1,1,1})); + pn_c = get_parameter(dictionary, "pn_c", 500); error_checking(); } diff --git a/config.h b/config.h index 5c06a7d..6ce5d60 100644 --- a/config.h +++ b/config.h @@ -1,27 +1,30 @@ #pragma once #include #include +#include class Config { public: Config(std::string file_name); - double eps; - double t_end; - double dt_disk; - double dt_contr; - double dt_bh; - double eta; - std::string input_file_name; - bool dt_min_warning; - int live_smbh_count; - double live_smbh_custom_eps; - bool live_smbh_output; - bool live_smbh_neighbor_output; - int live_smbh_neighbor_number; - bool binary_smbh_pn; - bool binary_smbh_influence_sphere_output; - double binary_smbh_influence_radius_factor; + double eps; + double t_end; + double dt_disk; + double dt_contr; + double dt_bh; + double eta; + std::string input_file_name; + bool dt_min_warning; + int live_smbh_count; + double live_smbh_custom_eps; + bool live_smbh_output; + bool live_smbh_neighbor_output; + int live_smbh_neighbor_number; + bool binary_smbh_pn; + bool binary_smbh_influence_sphere_output; + double binary_smbh_influence_radius_factor; + std::vector pn_usage; + double pn_c; private: using Dictionary = std::unordered_map; Dictionary read_config_file(const std::string file_name); diff --git a/phigrape.conf b/phigrape.conf index 732518f..245a644 100644 --- a/phigrape.conf +++ b/phigrape.conf @@ -66,6 +66,13 @@ binary_smbh_influence_radius_factor = 3.162277660168379497918067e+03 # Add post Newtonian terms to SMBH-SMBH gravity. [default: false] binary_smbh_pn = true +# A mask array (zeros and ones) determining whether or not to use specific post-Newtonian terms. +# The elements represent {0, 1, 2, 2.5, 3, 3.5, spin} +pn_usage = {1, 1, 1, 1, 0, 0, 0} + +# The speed of light in N-body units [default: 500] +pn_c = 477.12 + #################################### # Negative powers of two # #################################### diff --git a/phigrape.cpp b/phigrape.cpp index 5f52247..dbf9514 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -400,9 +400,9 @@ return - 0 if everything OK // #ifdef ADD_PN_BH -double C_NB = 477.12; - -int usedOrNot[7] = {1, 1, 1, 1, 0, 0, 0}; +// double C_NB = 477.12; +// +// int usedOrNot[7] = {1, 1, 1, 1, 0, 0, 0}; // double a_pn1[7][3], adot_pn1[7][3], // a_pn2[7][3], adot_pn2[7][3]; @@ -1339,6 +1339,8 @@ int main(int argc, char *argv[]) FILE *out; + double C_NB; + int usedOrNot[7]; /* INIT the rand() !!! */ srand(19640916); /* it is just my birthday :-) */ @@ -1364,6 +1366,8 @@ int main(int argc, char *argv[]) /* read the input parameters to the rootRank */ config = new Config("phigrape.conf"); + C_NB = config->pn_c; + std::copy(config->pn_usage.begin(), config->pn_usage.end(), usedOrNot); if (myRank == rootRank) { From 562ea9618aef4218c79e57847eb3648597a3d084 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Tue, 24 Mar 2020 20:37:23 -0400 Subject: [PATCH 22/65] External potential (EXTPOT_GAL) cleaned up --- config.cpp | 28 ++- config.h | 11 ++ phigrape.conf | 144 ++++++++------ phigrape.cpp | 534 +++++++++++--------------------------------------- 4 files changed, 230 insertions(+), 487 deletions(-) diff --git a/config.cpp b/config.cpp index fb121be..aac05c2 100644 --- a/config.cpp +++ b/config.cpp @@ -110,6 +110,8 @@ void Config::error_checking() throw std::runtime_error("The number of live black holes (live_smbh_count) can be 0, 1, or 2"); if (binary_smbh_pn && (live_smbh_count!=2)) throw std::runtime_error("Post-Newtonian gravity (binary_smbh_pn=true) requires live_smbh_count=2"); + if (binary_smbh_pn && (pn_c <= 0)) + throw std::runtime_error("Post-Newtonian gravity (binary_smbh_pn=true) requires pn_c > 0"); if (live_smbh_custom_eps == eps) live_smbh_custom_eps = -1; if (live_smbh_output && (live_smbh_count == 0)) throw std::runtime_error("Black hole output (live_smbh_output=true) requires at least one live black hole (live_smbh_count)"); @@ -122,6 +124,14 @@ void Config::error_checking() for (int i; i<7; i++) if (!((pn_usage[i] == 0) || (pn_usage[i] == 1))) throw std::runtime_error("PN usage array (pn_usage) must have ones and zeros only"); + if (ext_units_physical && ((norm_mass == 0) || (norm_length == 0))) + throw std::runtime_error("Physical units for external gravity (ext_units_physical) requires ext_norm_mass and ext_norm_length to be positive numbers"); + if ((ext_m_bulge > 0) && (ext_b_bulge < 0)) + throw std::runtime_error("To use external bulge gravity, please specify positive ext_m_bulge and ext_b_bulge"); + if ((ext_m_halo_plummer > 0) && (ext_b_halo_plummer < 0)) + throw std::runtime_error("To use external Plummer halo gravity, please specify positive ext_m_halo_plummer and ext_b_halo_plummer"); + if ((ext_m_disk > 0) && ((ext_a_disk < 0) || (ext_b_disk < 0))) + throw std::runtime_error("To use external disk gravity, please specify positive ext_m_disk, ext_a_disk and ext_b_disk"); } Config::Config(std::string file_name) @@ -137,16 +147,30 @@ Config::Config(std::string file_name) eta = get_parameter(dictionary, "eta"); input_file_name = get_parameter(dictionary, "input_file_name", "data.con"); dt_min_warning = get_parameter(dictionary, "dt_min_warning", false); + live_smbh_count = get_parameter(dictionary, "live_smbh_count", 0); live_smbh_custom_eps = get_parameter(dictionary, "live_smbh_custom_eps", -1); live_smbh_output = get_parameter(dictionary, "live_smbh_output", false); live_smbh_neighbor_output = get_parameter(dictionary, "live_smbh_neighbor_output", false); live_smbh_neighbor_number = get_parameter(dictionary, "live_smbh_neighbor_number", 10); - binary_smbh_pn = get_parameter(dictionary, "binary_smbh_pn", false); + binary_smbh_influence_sphere_output = get_parameter(dictionary, "binary_smbh_influence_sphere_output", false); binary_smbh_influence_radius_factor = get_parameter(dictionary, "binary_smbh_influence_radius_factor", 10.); + + binary_smbh_pn = get_parameter(dictionary, "binary_smbh_pn", false); pn_usage = get_parameter>(dictionary, "pn_usage", std::vector({1,1,1,1,1,1,1})); - pn_c = get_parameter(dictionary, "pn_c", 500); + pn_c = get_parameter(dictionary, "pn_c", 0); + + ext_units_physical = get_parameter(dictionary, "ext_units_physical", false); + norm_mass = get_parameter(dictionary, "norm_mass", !ext_units_physical); + norm_length = get_parameter(dictionary, "norm_length", !ext_units_physical); + ext_m_bulge = get_parameter(dictionary, "ext_m_bulge", 0); + ext_b_bulge = get_parameter(dictionary, "ext_b_bulge", -1); + ext_m_disk = get_parameter(dictionary, "ext_m_disk", 0); + ext_a_disk = get_parameter(dictionary, "ext_a_disk", -1); + ext_b_disk = get_parameter(dictionary, "ext_b_disk", -1); + ext_m_halo_plummer = get_parameter(dictionary, "ext_m_halo_plummer", 0); + ext_b_halo_plummer = get_parameter(dictionary, "ext_b_halo_plummer", -1); error_checking(); } diff --git a/config.h b/config.h index 6ce5d60..f92d21b 100644 --- a/config.h +++ b/config.h @@ -25,6 +25,17 @@ public: double binary_smbh_influence_radius_factor; std::vector pn_usage; double pn_c; + bool ext_units_physical; + double norm_mass; + double norm_length; + double ext_m_bulge; + double ext_b_bulge; + double ext_m_disk; + double ext_a_disk; + double ext_b_disk; + double ext_m_halo_plummer; + double ext_b_halo_plummer; + private: using Dictionary = std::unordered_map; Dictionary read_config_file(const std::string file_name); diff --git a/phigrape.conf b/phigrape.conf index 245a644..337b154 100644 --- a/phigrape.conf +++ b/phigrape.conf @@ -29,67 +29,87 @@ output_format = HDF5 dt_min_warning = false ############################################# +#################### +# EXTERNAL GRAVITY # +#################### + +ext_units_physical = true +norm_mass = 1e5 +norm_length = 10 +# TODO add the option to normalize using other units + +# Notice that if physical units are used, the "a" and "b" parameters are in kiloparsec, not parsec! + +ext_m_bulge = 1e5 +ext_b_bulge = 20 +ext_m_disk = 1e6 +ext_a_disk = 80 +ext_b_disk = 70 +ext_m_halo_plummer = 1e6 +ext_b_halo_plummer = 200. + + +#################################### +## LIVE SUPERMASSIVE BLACK HOLE(S) # +#################################### +# +## There is special treatment for particles representing supermassive black holes (SMBHs): they are integrated at every time step, they can have custom softening in SMBH-SMBH interactions, and post Newtonian terms can be added to the gravity. +# +## The number of SMBH particles. Can be 0 (no SMBH), 1, or 2. [default: 0] +#live_smbh_count = 0 +# +## Custom softening length for SMBH-SMBH interactions (can also be zero). If non-negative, the custom softening is applied. [default: -1] +#live_smbh_custom_eps = 0 +# +## Output additional diagnostics about live SMBHs. [default: false] +##TODO# dt_bh +#live_smbh_output = true +# +## Output additional diagnostics about the SMBH's (or SMBHs') nearest neighbours (number could be set as shown below). [default: false] +#live_smbh_neighbor_output = true +# +## Number of nearest neighbours to the SMBH (or SMBHs) to include in output. [default: 10] +#live_smbh_neighbor_number = 10 +# ################################### -# LIVE SUPERMASSIVE BLACK HOLE(S) # +## BINARY SUPERMASSIVE BLACK HOLE # ################################### - -# There is special treatment for particles representing supermassive black holes (SMBHs): they are integrated at every time step, they can have custom softening in SMBH-SMBH interactions, and post Newtonian terms can be added to the gravity. - -# The number of SMBH particles. Can be 0 (no SMBH), 1, or 2. [default: 0] -live_smbh_count = 2 - -# Custom softening length for SMBH-SMBH interactions (can also be zero). If non-negative, the custom softening is applied. [default: -1] -live_smbh_custom_eps = 0 - -# Output additional diagnostics about live SMBHs. [default: false] -#TODO# dt_bh -live_smbh_output = true - -# Output additional diagnostics about the SMBH's (or SMBHs') nearest neighbours (number could be set as shown below). [default: false] -live_smbh_neighbor_output = true - -# Number of nearest neighbours to the SMBH (or SMBHs) to include in output. [default: 10] -live_smbh_neighbor_number = 10 - -################################## -# BINARY SUPERMASSIVE BLACK HOLE # -################################## - -# The following parameters can be set when `live_smbh_count` is 2. - -# Output additional diagnostics about the SMBH's sphere of influence (size could be set as shown below). [default: false] -binary_smbh_influence_sphere_output = true - -# The influence sphere is centred at the binary SMBH's centre of mass, and its radius is the semi-major axis of the binary times the factor below. [default: 10.0] -binary_smbh_influence_radius_factor = 3.162277660168379497918067e+03 - -# Add post Newtonian terms to SMBH-SMBH gravity. [default: false] -binary_smbh_pn = true - -# A mask array (zeros and ones) determining whether or not to use specific post-Newtonian terms. -# The elements represent {0, 1, 2, 2.5, 3, 3.5, spin} -pn_usage = {1, 1, 1, 1, 0, 0, 0} - -# The speed of light in N-body units [default: 500] -pn_c = 477.12 - -#################################### -# Negative powers of two # -#################################### -# -1 1/2 0.5 # -# -2 1/4 0.25 # -# -3 1/8 0.125 # -# -4 1/16 0.0625 # -# -5 1/32 0.03125 # -# -6 1/64 0.015625 # -# -7 1/128 0.0078125 # -# -8 1/256 0.00390625 # -# -9 1/512 0.001953125 # -# -10 1/1024 0.0009765625 # -# -11 1/2048 0.00048828125 # -# -12 1/4096 0.000244140625 # -# -13 1/8192 0.0001220703125 # -# -14 1/16384 0.00006103515625 # -# -15 1/32768 0.000030517578125 # -# -16 1/65536 0.0000152587890625 # -#################################### +# +## The following parameters can be set when `live_smbh_count` is 2. +# +## Output additional diagnostics about the SMBH's sphere of influence (size could be set as shown below). [default: false] +#binary_smbh_influence_sphere_output = true +# +## The influence sphere is centred at the binary SMBH's centre of mass, and its radius is the semi-major axis of the binary times the factor below. [default: 10.0] +#binary_smbh_influence_radius_factor = 3.162277660168379497918067e+03 +# +## Add post Newtonian terms to SMBH-SMBH gravity. [default: false] +#binary_smbh_pn = true +# +## A mask array (zeros and ones) determining whether or not to use specific post-Newtonian terms. +## The elements represent {0, 1, 2, 2.5, 3, 3.5, spin} +#pn_usage = {1, 1, 1, 1, 0, 0, 0} +# +## The speed of light in N-body units [default: 500] +#pn_c = 477.12 +# +##################################### +## Negative powers of two # +##################################### +## -1 1/2 0.5 # +## -2 1/4 0.25 # +## -3 1/8 0.125 # +## -4 1/16 0.0625 # +## -5 1/32 0.03125 # +## -6 1/64 0.015625 # +## -7 1/128 0.0078125 # +## -8 1/256 0.00390625 # +## -9 1/512 0.001953125 # +## -10 1/1024 0.0009765625 # +## -11 1/2048 0.00048828125 # +## -12 1/4096 0.000244140625 # +## -13 1/8192 0.0001220703125 # +## -14 1/16384 0.00006103515625 # +## -15 1/32768 0.000030517578125 # +## -16 1/65536 0.0000152587890625 # +##################################### diff --git a/phigrape.cpp b/phigrape.cpp index dbf9514..f46dc36 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -56,12 +56,11 @@ Last redaction : 2019.04.16 12:55 #include "config.h" Config *config; -//#define NORM // Physical normalization +#define NORM // Physical normalization -//#define EXTPOT // external potential (BH? or galactic?) +#define EXTPOT // external potential (BH? or galactic?) //#define EXTPOT_BH // BH - usually NB units -//#define EXTPOT_GAL // Galactic B+D+H PK - usually physical units //#define EXTPOT_GAL_DEH // Dehnen Galactic - usually physical units //#define EXTPOT_GAL_LOG // Log Galactic - usually physical units @@ -112,6 +111,7 @@ Config *config; #include #include +#include #define G6_NPIPE 2048 #include "grape6.h" @@ -217,7 +217,11 @@ struct double3 { data[2] /= c; return *this; } - double norm() + double norm2() const + { + return data[0]*data[0]+data[1]*data[1]+data[2]*data[2]; + } + double norm() const { return sqrt(data[0]*data[0]+data[1]*data[1]+data[2]*data[2]); } @@ -234,6 +238,11 @@ double3 operator*(const double3& a, const double& c) return double3(a.data[0]*c, a.data[1]*c, a.data[2]*c); } +double operator*(const double3& a, const double3& b) +{ + return a.data[0]*b.data[0]+a.data[1]*b.data[1]+a.data[2]*b.data[2]; +} + double3 operator/(const double3& a, const double& c) { return double3(a.data[0]/c, a.data[1]/c, a.data[2]/c); @@ -292,9 +301,7 @@ double3 a2by18, a1by6, aby2; /* normalization... */ -#ifdef NORM double m_norm, r_norm, v_norm, t_norm; -#endif double eps_BH=0.0; @@ -302,14 +309,6 @@ double eps_BH=0.0; #ifdef EXTPOT -#ifdef EXTPOT_GAL -double m_bulge, a_bulge, b_bulge, - m_disk, a_disk, b_disk, - m_halo, a_halo, b_halo, // NOTE there are other "halo" variables in EXTPOT_GAL_LOG - x2_ij, y2_ij, z2_ij, // NOTE this variable exist also in EXTPOT_GAL_LOG - r_tmp, r2_tmp, z_tmp, z2_tmp; -#endif - #ifdef EXTPOT_GAL_DEH double m_ext, r_ext, g_ext, tmp_r2, tmp_r3, dum, dum2, dum3, dum_g, tmp_g; @@ -624,254 +623,72 @@ void write_bh_nb_data(double time_cur, int N, double m[], double3 x[], double3 v fclose(out); } -void calc_ext_grav_zero() -{ - -#ifdef EXTPOT - -/* Define the external potential for all particles on all nodes */ - -ni = n_act; - -for (i=0; i 0) + external_gravity.calc_plummer(ni, x_act_new,v_act_new, pot_act_ext, a_act_new, adot_act_new, 1); // Bulge + if (external_gravity.m_disk > 0) + external_gravity.calc_disk(ni, x_act_new,v_act_new, pot_act_ext, a_act_new, adot_act_new); // Disk + if (external_gravity.m_halo > 0) + external_gravity.calc_plummer(ni, x_act_new,v_act_new, pot_act_ext, a_act_new, adot_act_new, 2); // Halo + + + +for (int i=0; iext_m_bulge/config->norm_mass; + external_gravity.b_bulge = config->ext_b_bulge/config->norm_length*1000; + external_gravity.m_disk = config->ext_m_disk/config->norm_mass; + external_gravity.a_disk = config->ext_a_disk/config->norm_length*1000; + external_gravity.b_disk = config->ext_b_disk/config->norm_length*1000; + external_gravity.m_halo = config->ext_m_halo_plummer/config->norm_mass; + external_gravity.b_halo = config->ext_b_halo_plummer/config->norm_length*1000; + + if (external_gravity.m_bulge > 0) + printf("m_bulge = %.4E b_bulge = %.4E\n", external_gravity.m_bulge, external_gravity.b_bulge); + if (external_gravity.m_disk > 0) + printf("m_disk = %.4E a_disk = %.4E b_disk = %.4E\n", external_gravity.m_disk, external_gravity.a_disk, external_gravity.b_disk); + if (external_gravity.m_halo > 0) + printf("m_halo = %.4E b_halo = %.4E\n", external_gravity.m_halo, external_gravity.b_halo); + + eta_s = eta/ETA_S_CORR; eta_bh = eta/ETA_BH_CORR; @@ -1636,7 +1323,7 @@ int main(int argc, char *argv[]) /* init the local GRAPE's */ #ifdef MPI_OVERRIDE - numGPU = 1; + numGPU = 1; // TODO get this from config file clusterid = myRank % numGPU; #else MPI_Comm shmcomm; @@ -1816,7 +1503,8 @@ int main(int argc, char *argv[]) } #ifdef EXTPOT - calc_ext_grav_zero(); +// /*/*/*/*/*/*calc_ext_grav_zero();*/*/*/*/*/*/ + calc_ext_grav(n_act, x_act, v_act, a, adot); #endif /* Wait to all processors to finish his works... */ @@ -2223,7 +1911,7 @@ int main(int argc, char *argv[]) } #ifdef EXTPOT - calc_ext_grav(); + calc_ext_grav(n_act, x_act_new, v_act_new, a_act_new, adot_act_new); #endif /* correct the active particles positions etc... on all the nodes */ From 23d32c6dcf84a5c733cea05ab1b5599da6c54ed5 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Wed, 25 Mar 2020 16:37:55 -0400 Subject: [PATCH 23/65] New approach to external potential --- phigrape.conf | 14 ++-- phigrape.cpp | 214 +++++++++++++++++++++++--------------------------- 2 files changed, 105 insertions(+), 123 deletions(-) diff --git a/phigrape.conf b/phigrape.conf index 337b154..2414d1e 100644 --- a/phigrape.conf +++ b/phigrape.conf @@ -40,13 +40,13 @@ norm_length = 10 # Notice that if physical units are used, the "a" and "b" parameters are in kiloparsec, not parsec! -ext_m_bulge = 1e5 -ext_b_bulge = 20 -ext_m_disk = 1e6 -ext_a_disk = 80 -ext_b_disk = 70 -ext_m_halo_plummer = 1e6 -ext_b_halo_plummer = 200. +ext_m_bulge = 0 +ext_b_bulge = 0 +ext_m_disk = 1e9 +ext_a_disk = 0.8 +ext_b_disk = 0.2 +ext_m_halo_plummer = 0 +ext_b_halo_plummer = 0 #################################### diff --git a/phigrape.cpp b/phigrape.cpp index f46dc36..e4153a1 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -58,7 +58,6 @@ Config *config; #define NORM // Physical normalization -#define EXTPOT // external potential (BH? or galactic?) //#define EXTPOT_BH // BH - usually NB units @@ -307,7 +306,6 @@ double eps_BH=0.0; /* external potential... */ -#ifdef EXTPOT #ifdef EXTPOT_GAL_DEH double m_ext, r_ext, g_ext, @@ -329,7 +327,6 @@ double r2, rv_ij, double pot_ext[N_MAX], pot_act_ext[N_MAX]; // for all EXTPOT -#endif int i_bh, i_bh1, i_bh2, num_bh = 0, num_bh1 = 0, num_bh2 = 0; @@ -625,70 +622,85 @@ void write_bh_nb_data(double time_cur, int N, double m[], double3 x[], double3 v class External_gravity { public: - External_gravity() {} - void calc_plummer(const int n_act, const double3 x[], const double3 v[], double pot[], double3 a[], double3 adot[], int mode) + void apply(const int n_act, const double3 x[], const double3 v[], double pot[], double3 a[], double3 adot[]) { - /* This funcion calculates gravity due to a smeared point source using Plummer softening. The `mode` parameter determines whether we use the BH, bulge, or halo. */ // TODO change mode to class enum? - - double m, b; - switch (mode) { - case 0: m=m_bh; b=b_bh; break; - case 1: m=m_bulge; b=b_bulge; break; - case 2: m=m_halo; b=b_halo; break; - default: - throw std::runtime_error("Unknown mode in external_gravity.calc_plummer"); - } for (int i=0; iset_coordinates(x[i], v[i]); + this->calc_gravity(); + pot[i] += potential; + a[i] += acceleration; + adot[i] += jerk; } } - void calc_disk(const int n_act, double3 x[], double3 v[], double pot[], double3 a[], double3 adot[]) //TODO change x and v to const + virtual void calc_gravity() = 0; + bool is_active; +protected: + double potential; + double3 acceleration, jerk; + double3 x, v; + void set_coordinates(double3 x, double3 v) { - int i = 0; - double z2_tmp = x[i][2]*x[i][2] + b_disk*b_disk; - double z_tmp = sqrt(z2_tmp); - double r2_tmp = x[i][0]*x[i][0] + x[i][1]*x[i][1] + SQR(z_tmp + a_disk); - double r_tmp = sqrt(r2_tmp); - pot[i] -= m_disk / r_tmp; - double tmp = m_disk / (r2_tmp*r_tmp); - a[i][0] -= tmp * x_ij; - a[i][1] -= tmp * y_ij; - a[i][2] -= tmp * z_ij * (z_tmp + a_disk)/z_tmp; - tmp = m_disk / (z_tmp*r2_tmp*r2_tmp*r_tmp); - adot[i][0] += tmp * (- v[i][0]*z_tmp*r2_tmp - + 3*x[i][0]*v[i][0]*x[i][0]*z_tmp - + 3*x[i][0]*v[i][1]*x[i][1]*z_tmp - + 3*x[i][0]*v[i][2]*x[i][2]*SQR(z_tmp + a_disk)); - adot[i][1] += tmp * (- v[i][1]*z_tmp*r2_tmp - + 3*x[i][1]*v[i][0]*x[i][0]*z_tmp - + 3*x[i][1]*v[i][1]*x[i][1]*z_tmp - + 3*x[i][1]*v[i][2]*x[i][2]*SQR(z_tmp + a_disk)); - adot[i][2] += tmp * (- v[i][2]*(z_tmp + a_disk)*(x[i][0]*(z2_tmp*z_tmp + a_disk*SQR(b_disk)) + - x[i][1]*(z2_tmp*z_tmp + a_disk*SQR(b_disk)) - - (2*a_disk*(SQR(x[i][2]) - SQR(b_disk))*z_tmp + - 2*SQR(x[i][2]*x[i][2]) + - SQR(b_disk)*SQR(x[i][2]) - - SQR(b_disk)*( SQR(a_disk) + SQR(b_disk)))) - + 3*v[i][0]*x[i][0]*x[i][2]*z2_tmp*(z_tmp + a_disk) - + 3*v[i][1]*x[i][1]*x[i][2]*z2_tmp*(z_tmp + a_disk)) / z2_tmp; - + this->x = x; + this->v = v; } -//private: //TODO make private - double m_bh, b_bh, - m_bulge, b_bulge, - m_disk, a_disk, b_disk, - m_halo, b_halo; }; -External_gravity external_gravity; +class Plummer : public External_gravity { +public: + Plummer(double m, double b) : m(m), b(b) {is_active=(m>0);} +private: + void calc_gravity() + { + double r2 = SQR(b); + r2 += x.norm2(); + double r = sqrt(r2); + double rv_ij = v*x; + double tmp = m / r; + potential = -tmp; + tmp /= r2; + acceleration = - tmp * x; + jerk = - tmp * (v - 3*rv_ij * x/r2); + } + double m, b; +}; + +class Miyamoto_Nagai : public External_gravity { +public: + Miyamoto_Nagai(double m, double a, double b) : m(m), a(a), b(b) {is_active=(m>0);} +private: + void calc_gravity() + { + double x_ij=x[0], y_ij=x[1], z_ij=x[2]; + double vx_ij=v[0], vy_ij=v[1], vz_ij=v[2]; + auto z2_tmp = z_ij*z_ij + SQR(b); + auto z_tmp = sqrt(z2_tmp); + auto r2_tmp = x_ij*x_ij + y_ij*y_ij + SQR(z_tmp + a); + auto r_tmp = sqrt(r2_tmp); + potential = - m / r_tmp; + auto tmp = m / (r2_tmp*r_tmp); + acceleration[0] = - tmp * x_ij; + acceleration[1] = - tmp * y_ij; + acceleration[2] = - tmp * z_ij * (z_tmp + a)/z_tmp; + tmp = m / (z_tmp*r2_tmp*r2_tmp*r_tmp); + jerk[0] = tmp * (- vx_ij*z_tmp*r2_tmp + + 3.0*x_ij*vx_ij*x_ij*z_tmp + + 3.0*x_ij*vy_ij*y_ij*z_tmp + + 3.0*x_ij*vz_ij*z_ij*SQR(z_tmp + a)); + jerk[1] = tmp * (- vy_ij*z_tmp*r2_tmp + + 3.0*y_ij*vx_ij*x_ij*z_tmp + + 3.0*y_ij*vy_ij*y_ij*z_tmp + + 3.0*y_ij*vz_ij*z_ij*SQR(z_tmp + a)); + jerk[2] = tmp * (- vz_ij*(z_tmp + a)*(x_ij*x_ij*(z2_tmp*z_tmp + a*SQR(b)) + + y_ij*y_ij*(z2_tmp*z_tmp + a*SQR(b)) - + (2.0*a*(SQR(z_ij) - SQR(b))*z_tmp + + 2.0*SQR(z_ij*z_ij) + + SQR(b)*SQR(z_ij) - + SQR(b)*(SQR(a) + SQR(b)))) + + 3.0*vx_ij*x_ij*z_ij*z2_tmp*(z_tmp + a) + + 3.0*vy_ij*y_ij*z_ij*z2_tmp*(z_tmp + a)) / z2_tmp; + } + double m, a, b; +}; void calc_self_grav(double t, double eps2, double &g6_calls, int n_loc, int n_act, int ind_act[], @@ -728,27 +740,18 @@ void calc_self_grav(double t, double eps2, double &g6_calls, int n_loc, #endif } -void calc_ext_grav(int n_act, double3 *x_act_new, double3 *v_act_new, double3 *a_act_new, double3* adot_act_new) +void calc_ext_grav(std::vector &external_gravity_components, int n_act, double3 *x_act_new, double3 *v_act_new, double *pot_act_ext, double3 *a_act_new, double3* adot_act_new) { -#ifdef EXTPOT - /* Define the external potential for all active particles on all nodes */ -int ni = n_act; +int ni = n_act; // TODO redundant? - if (external_gravity.m_bulge > 0) - external_gravity.calc_plummer(ni, x_act_new,v_act_new, pot_act_ext, a_act_new, adot_act_new, 1); // Bulge - if (external_gravity.m_disk > 0) - external_gravity.calc_disk(ni, x_act_new,v_act_new, pot_act_ext, a_act_new, adot_act_new); // Disk - if (external_gravity.m_halo > 0) - external_gravity.calc_plummer(ni, x_act_new,v_act_new, pot_act_ext, a_act_new, adot_act_new, 2); // Halo + std::fill(pot_act_ext, pot_act_ext+n_act, 0.); - - -for (int i=0; iis_active) + component->apply(n_act, x_act_new, v_act_new, pot_act_ext, a_act_new, adot_act_new); } #ifdef TIMING @@ -880,7 +883,6 @@ get_CPU_time(&CPU_tmp_real, &CPU_tmp_user, &CPU_tmp_syst); DT_EXT_GRAV += (CPU_tmp_user - CPU_tmp_user0); #endif -#endif // EXTPOT } void energy_contr(const double time_cur, const double timesteps, const double n_act_sum, const double g6_calls, double& rcm_sum, double& vcm_sum, double& E_tot_0, double& E_tot_corr_0, double& E_tot_corr_sd_0, int &skip_con, int N, double m[], double3 x[], double3 v[], double pot[]) @@ -895,9 +897,8 @@ void energy_contr(const double time_cur, const double timesteps, const double n_ E_kin *= 0.5; double E_pot_ext = 0.0; -#ifdef EXTPOT + for (int i=0; iext_m_bulge/config->norm_mass; - external_gravity.b_bulge = config->ext_b_bulge/config->norm_length*1000; - external_gravity.m_disk = config->ext_m_disk/config->norm_mass; - external_gravity.a_disk = config->ext_a_disk/config->norm_length*1000; - external_gravity.b_disk = config->ext_b_disk/config->norm_length*1000; - external_gravity.m_halo = config->ext_m_halo_plummer/config->norm_mass; - external_gravity.b_halo = config->ext_b_halo_plummer/config->norm_length*1000; + double normalization_mass=1, normalization_length=1; + if (config->ext_units_physical) { + normalization_mass = 1/config->norm_mass; + normalization_length = 1000/config->norm_length; + } + Plummer ext_bulge(config->ext_m_bulge*normalization_mass, config->ext_b_bulge*normalization_length); + Miyamoto_Nagai ext_disk(config->ext_m_disk*normalization_mass, config->ext_a_disk*normalization_length, config->ext_b_disk*normalization_length); + Plummer ext_halo_plummer(config->ext_m_halo_plummer*normalization_mass, config->ext_b_halo_plummer*normalization_length); - if (external_gravity.m_bulge > 0) - printf("m_bulge = %.4E b_bulge = %.4E\n", external_gravity.m_bulge, external_gravity.b_bulge); - if (external_gravity.m_disk > 0) - printf("m_disk = %.4E a_disk = %.4E b_disk = %.4E\n", external_gravity.m_disk, external_gravity.a_disk, external_gravity.b_disk); - if (external_gravity.m_halo > 0) - printf("m_halo = %.4E b_halo = %.4E\n", external_gravity.m_halo, external_gravity.b_halo); - + std::vector external_gravity_components; + external_gravity_components.push_back(&ext_bulge); + external_gravity_components.push_back(&ext_disk); + external_gravity_components.push_back(&ext_halo_plummer); + + if (config->ext_m_bulge > 0) printf("m_bulge = %.4E b_bulge = %.4E\n", config->ext_m_bulge*normalization_mass, config->ext_b_bulge*normalization_length); + if (config->ext_m_disk > 0) printf("m_disk = %.4E a_disk = %.4E b_disk = %.4E\n", config->ext_m_disk*normalization_mass, config->ext_a_disk*normalization_length, config->ext_b_disk*normalization_length); + if (config->ext_m_halo_plummer > 0) printf("m_halo = %.4E b_halo = %.4E\n", config->ext_m_halo_plummer*normalization_mass, config->ext_b_halo_plummer*normalization_length); + printf("\n"); + fflush(stdout); eta_s = eta/ETA_S_CORR; eta_bh = eta/ETA_BH_CORR; @@ -1502,10 +1493,7 @@ int main(int argc, char *argv[]) } } -#ifdef EXTPOT -// /*/*/*/*/*/*calc_ext_grav_zero();*/*/*/*/*/*/ - calc_ext_grav(n_act, x_act, v_act, a, adot); -#endif + calc_ext_grav(external_gravity_components, n_act, x_act, v_act, pot_ext, a, adot); /* Wait to all processors to finish his works... */ MPI_Barrier(MPI_COMM_WORLD); @@ -1777,9 +1765,7 @@ int main(int argc, char *argv[]) pot_act[i] = pot[iii]; -#ifdef EXTPOT pot_act_ext[i] = pot_ext[iii]; -#endif a_act[i] = a[iii]; adot_act[i] = adot[iii]; @@ -1910,9 +1896,7 @@ int main(int argc, char *argv[]) } } -#ifdef EXTPOT - calc_ext_grav(n_act, x_act_new, v_act_new, a_act_new, adot_act_new); -#endif + calc_ext_grav(external_gravity_components, n_act, x_act_new, v_act_new, pot_act_ext, a_act_new, adot_act_new); /* correct the active particles positions etc... on all the nodes */ @@ -2080,9 +2064,7 @@ int main(int argc, char *argv[]) pot[iii] = pot_act[i]; -#ifdef EXTPOT pot_ext[iii] = pot_act_ext[i]; -#endif a[iii] = a_act[i]; adot[iii] = adot_act[i]; From 8cba5b5e1d24f8c2eac7589630fb6919d145400d Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Wed, 25 Mar 2020 16:58:46 -0400 Subject: [PATCH 24/65] Got rid of more global variables --- config.cpp | 2 +- phigrape.cpp | 158 ++++++++++----------------------------------------- 2 files changed, 32 insertions(+), 128 deletions(-) diff --git a/config.cpp b/config.cpp index aac05c2..301e259 100644 --- a/config.cpp +++ b/config.cpp @@ -121,7 +121,7 @@ void Config::error_checking() throw std::runtime_error("Binary black hole influence sphere output (binary_smbh_influence_sphere_output=true) requires exactly two live black holes (live_smbh_count=2)"); if (pn_usage.size() != 7) throw std::runtime_error("PN usage array (pn_usage) must have exactly seven components"); - for (int i; i<7; i++) + for (int i=0; i<7; i++) if (!((pn_usage[i] == 0) || (pn_usage[i] == 1))) throw std::runtime_error("PN usage array (pn_usage) must have ones and zeros only"); if (ext_units_physical && ((norm_mass == 0) || (norm_length == 0))) diff --git a/phigrape.cpp b/phigrape.cpp index e4153a1..99d88e7 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -325,26 +325,6 @@ double r2, rv_ij, // NOTE this is a mess. Looks like eps_bh is never used, and the m_bh from outside the block is never used. #endif -double pot_ext[N_MAX], pot_act_ext[N_MAX]; // for all EXTPOT - - -int i_bh, i_bh1, i_bh2, - num_bh = 0, num_bh1 = 0, num_bh2 = 0; - -double m_bh, m_bh1, m_bh2, b_bh, - r, r2, - x_ij, y_ij, z_ij, - vx_ij, vy_ij, vz_ij, rv_ij; - -// #ifdef BBH_INF -int inf_event[N_MAX]; -double DR2, tmp_r2; -double3 x_bbhc, v_bbhc; -double DV2, EB, SEMI_a, SEMI_a2; -// #endif // BBH_INF - -// #ifdef ADD_N_BH - // double x_bh1[3], x_bh2[3], v_bh1[3], v_bh2[3]; double3 x_bh1, x_bh2, v_bh1, v_bh2; @@ -358,99 +338,11 @@ double3 a_bh1, adot_bh1, a_bh2, adot_bh2; #include "n_bh.c" -/* -int calc_force_n_BH(double m1, double xx1[], double vv1[], - double m2, double xx2[], double vv2[], - double eps_BH, - double pot_n1, double a_n1[], double adot_n1[], - double pot_n2, double a_n2[], double adot_n2[]) -*/ - -/* - INPUT - -m1 - mass of the 1 BH -xx1[0,1,2] - coordinate of the 1 BH -vv1[0,1,2] - velocity of the 1 BH - -m2 - mass of the 2 BH -xx2[0,1,2] - coordinate of the 2 BH -vv2[0,1,2] - velocity of the 2 BH - -eps_BH - force softening, can be even exactly 0.0 ! - - OUTPUT - -pot_n1 for the 1 BH -a_n1 [0,1,2] for the 1 BH -adot_n1 [0,1,2] for the 1 BH - -pot_n2 for the 2 BH -a_n2 [0,1,2] for the 2 BH -adot_n2 [0,1,2] for the 2 BH - -return - 0 if everything OK -*/ - -// #endif // ADD_N_BH - -// #ifdef ADD_PN_BH - -// double C_NB = 477.12; -// -// int usedOrNot[7] = {1, 1, 1, 1, 0, 0, 0}; - -// double a_pn1[7][3], adot_pn1[7][3], -// a_pn2[7][3], adot_pn2[7][3]; double3 a_pn1[7], adot_pn1[7], a_pn2[7], adot_pn2[7]; -double s_bh1[3] = {0.0, 0.0, 1.0}; -double s_bh2[3] = {0.0, 0.0, 1.0}; #include "pn_bh_spin.c" -/* -int calc_force_pn_BH(double m1, double xx1[], double vv1[], double ss1[], - double m2, double xx2[], double vv2[], double ss2[], - double CCC_NB, double dt_bh, - int usedOrNot[], - double a_pn1[][3], double adot_pn1[][3], - double a_pn2[][3], double adot_pn2[][3]) -*/ - -/* - INPUT - -m1 - mass of the 1 BH -xx1[0,1,2] - coordinate of the 1 BH -vv1[0,1,2] - velocity of the 1 BH -spin1[0,1,2] - normalized spin of the 1 BH - -m2 - mass of the 2 BH -xx2[0,1,2] - coordinate of the 2 BH -vv2[0,1,2] - velocity of the 2 BH -spin2[0,1,2] - normalized spin of the 2 BH - -CCC_NB - Speed of light "c" in internal units -dt_BH - timestep of the BH's, needed for the SPIN integration - -usedOrNot[PN0, PN1, PN2, PN2.5, PN3, PN3.5, SPIN] - different PN term usage: PN1, PN2, PN2.5, PN3, PN3.5, SPIN - 0 1 2 3 4 5 6 - - OUTPUT - -a_pn1 [0 - PN0; 1 - PN1; 2 - PN2; 3 - PN2.5, 4 - PN3, 5 - PN3.5, 6 - SPIN] [3] for the 1 BH -adot_pn1[0 - PN0; 1 - PN1; 2 - PN2; 3 - PN2.5, 4 - PN3, 5 - PN3.5, 6 - SPIN] [3] for the 1 BH - -a_pn2 [0 - PN0; 1 - PN1; 2 - PN2; 3 - PN2.5, 4 - PN3, 5 - PN3.5, 6 - SPIN] [3] for the 2 BH -adot_pn2[0 - PN0; 1 - PN1; 2 - PN2; 3 - PN2.5, 4 - PN3, 5 - PN3.5, 6 - SPIN] [3] for the 2 BH - -return - 0 if everything OK - - 505 if BH's separation < 4 x (RSwarch1 + RSwarch2) -*/ - -// #endif // ADD_N_BH - #ifdef ETICS double t_exp, dt_exp=ETICS_DTSCF; // t_exp is just the initial value #ifdef ETICS_CEP @@ -460,28 +352,25 @@ int grapite_cep_index; void get_CPU_time(double *time_real, double *time_user, double *time_syst) { -struct rusage xxx; -double sec_u, microsec_u, sec_s, microsec_s; -struct timeval tv; + struct rusage xxx; + double sec_u, microsec_u, sec_s, microsec_s; + struct timeval tv; -getrusage(RUSAGE_SELF,&xxx); + getrusage(RUSAGE_SELF,&xxx); -sec_u = xxx.ru_utime.tv_sec; -sec_s = xxx.ru_stime.tv_sec; + sec_u = xxx.ru_utime.tv_sec; + sec_s = xxx.ru_stime.tv_sec; -microsec_u = xxx.ru_utime.tv_usec; -microsec_s = xxx.ru_stime.tv_usec; + microsec_u = xxx.ru_utime.tv_usec; + microsec_s = xxx.ru_stime.tv_usec; -*time_user = sec_u + microsec_u * 1.0E-06; -*time_syst = sec_s + microsec_s * 1.0E-06; + *time_user = sec_u + microsec_u * 1.0E-06; + *time_syst = sec_s + microsec_s * 1.0E-06; -// *time_real = time(NULL); - -gettimeofday(&tv, NULL); -*time_real = tv.tv_sec + 1.0E-06 * tv.tv_usec; - -*time_user = *time_real; + gettimeofday(&tv, NULL); + *time_real = tv.tv_sec + 1.0E-06 * tv.tv_usec; + *time_user = *time_real; } void read_data(char inp_fname[], int *diskstep, int *N, double *time_cur, int ind[], double m[], double3 x[], double3 v[]) @@ -885,7 +774,7 @@ DT_EXT_GRAV += (CPU_tmp_user - CPU_tmp_user0); } -void energy_contr(const double time_cur, const double timesteps, const double n_act_sum, const double g6_calls, double& rcm_sum, double& vcm_sum, double& E_tot_0, double& E_tot_corr_0, double& E_tot_corr_sd_0, int &skip_con, int N, double m[], double3 x[], double3 v[], double pot[]) +void energy_contr(const double time_cur, const double timesteps, const double n_act_sum, const double g6_calls, double& rcm_sum, double& vcm_sum, double& E_tot_0, double& E_tot_corr_0, double& E_tot_corr_sd_0, int &skip_con, int N, double m[], double3 x[], double3 v[], double pot[], double pot_ext[]) { // TODO maybe use static variables here for the previous step energy? double E_pot = 0.0; @@ -1058,6 +947,21 @@ int main(int argc, char *argv[]) double C_NB; int usedOrNot[7]; + double pot_ext[N_MAX], pot_act_ext[N_MAX]; // for all EXTPOT + + int i_bh1, i_bh2; + + double m_bh1, m_bh2; + + int inf_event[N_MAX]; + double DR2, tmp_r2; + double3 x_bbhc, v_bbhc; + double DV2, EB, SEMI_a, SEMI_a2; + + double s_bh1[3] = {0.0, 0.0, 1.0}; + double s_bh2[3] = {0.0, 0.0, 1.0}; + + /* INIT the rand() !!! */ srand(19640916); /* it is just my birthday :-) */ @@ -1503,7 +1407,7 @@ int main(int argc, char *argv[]) /* Energy control... */ if (myRank == rootRank) { - energy_contr(time_cur, timesteps, n_act_sum, g6_calls, rcm_sum, vcm_sum, E_tot_0, E_tot_corr_0, E_tot_corr_sd_0, skip_con, N, m, x, v, pot); + energy_contr(time_cur, timesteps, n_act_sum, g6_calls, rcm_sum, vcm_sum, E_tot_0, E_tot_corr_0, E_tot_corr_sd_0, skip_con, N, m, x, v, pot, pot_ext); } /* if (myRank == rootRank) */ #ifdef ETICS_DUMP @@ -2130,7 +2034,7 @@ int main(int argc, char *argv[]) if (time_cur >= t_contr) { if (myRank == rootRank) { - energy_contr(time_cur, timesteps, n_act_sum, g6_calls, rcm_sum, vcm_sum, E_tot_0, E_tot_corr_0, E_tot_corr_sd_0, skip_con, N, m, x, v, pot); + energy_contr(time_cur, timesteps, n_act_sum, g6_calls, rcm_sum, vcm_sum, E_tot_0, E_tot_corr_0, E_tot_corr_sd_0, skip_con, N, m, x, v, pot, pot_ext); /* write cont data */ From 131642aa715a3a72c4f367489a699d97968dfe20 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Wed, 25 Mar 2020 21:42:29 -0400 Subject: [PATCH 25/65] Added logarithmic external potential --- Makefile | 2 +- config.cpp | 13 +++++-- config.h | 6 ++- phigrape.conf | 14 ++++--- phigrape.cpp | 100 ++++++++++++++------------------------------------ 5 files changed, 51 insertions(+), 84 deletions(-) diff --git a/Makefile b/Makefile index e109393..933616e 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CUDAHOME ?= /usr/local/cuda -CPPFLAGS += -DYEBISU -DETICS +CPPFLAGS += -DETICS OPTIMIZATION ?= 3 ETICS_DTSCF ?= 0.015625 diff --git a/config.cpp b/config.cpp index 301e259..25f79cb 100644 --- a/config.cpp +++ b/config.cpp @@ -124,14 +124,16 @@ void Config::error_checking() for (int i=0; i<7; i++) if (!((pn_usage[i] == 0) || (pn_usage[i] == 1))) throw std::runtime_error("PN usage array (pn_usage) must have ones and zeros only"); - if (ext_units_physical && ((norm_mass == 0) || (norm_length == 0))) - throw std::runtime_error("Physical units for external gravity (ext_units_physical) requires ext_norm_mass and ext_norm_length to be positive numbers"); + if (ext_units_physical && ((unit_mass == 0) || (unit_length == 0))) + throw std::runtime_error("Physical units for external gravity (ext_units_physical) requires ext_unit_mass and ext_unit_length to be positive numbers"); if ((ext_m_bulge > 0) && (ext_b_bulge < 0)) throw std::runtime_error("To use external bulge gravity, please specify positive ext_m_bulge and ext_b_bulge"); if ((ext_m_halo_plummer > 0) && (ext_b_halo_plummer < 0)) throw std::runtime_error("To use external Plummer halo gravity, please specify positive ext_m_halo_plummer and ext_b_halo_plummer"); if ((ext_m_disk > 0) && ((ext_a_disk < 0) || (ext_b_disk < 0))) throw std::runtime_error("To use external disk gravity, please specify positive ext_m_disk, ext_a_disk and ext_b_disk"); + if (((ext_log_halo_r > 0) && (ext_log_halo_v <= 0)) || ((ext_log_halo_r <= 0) && (ext_log_halo_v > 0))) + throw std::runtime_error("To use external logarithmic halo gravity, please specify positive ext_log_halo_r and ext_log_halo_v"); } Config::Config(std::string file_name) @@ -162,8 +164,8 @@ Config::Config(std::string file_name) pn_c = get_parameter(dictionary, "pn_c", 0); ext_units_physical = get_parameter(dictionary, "ext_units_physical", false); - norm_mass = get_parameter(dictionary, "norm_mass", !ext_units_physical); - norm_length = get_parameter(dictionary, "norm_length", !ext_units_physical); + unit_mass = get_parameter(dictionary, "unit_mass", !ext_units_physical); + unit_length = get_parameter(dictionary, "unit_length", !ext_units_physical); ext_m_bulge = get_parameter(dictionary, "ext_m_bulge", 0); ext_b_bulge = get_parameter(dictionary, "ext_b_bulge", -1); ext_m_disk = get_parameter(dictionary, "ext_m_disk", 0); @@ -171,6 +173,9 @@ Config::Config(std::string file_name) ext_b_disk = get_parameter(dictionary, "ext_b_disk", -1); ext_m_halo_plummer = get_parameter(dictionary, "ext_m_halo_plummer", 0); ext_b_halo_plummer = get_parameter(dictionary, "ext_b_halo_plummer", -1); + ext_log_halo_v = get_parameter(dictionary, "ext_log_halo_v", 0); + ext_log_halo_r = get_parameter(dictionary, "ext_log_halo_r", 0); + error_checking(); } diff --git a/config.h b/config.h index f92d21b..5275bf7 100644 --- a/config.h +++ b/config.h @@ -26,8 +26,8 @@ public: std::vector pn_usage; double pn_c; bool ext_units_physical; - double norm_mass; - double norm_length; + double unit_mass; + double unit_length; double ext_m_bulge; double ext_b_bulge; double ext_m_disk; @@ -35,6 +35,8 @@ public: double ext_b_disk; double ext_m_halo_plummer; double ext_b_halo_plummer; + double ext_log_halo_r; + double ext_log_halo_v; private: using Dictionary = std::unordered_map; diff --git a/phigrape.conf b/phigrape.conf index 2414d1e..c9394b4 100644 --- a/phigrape.conf +++ b/phigrape.conf @@ -34,19 +34,23 @@ dt_min_warning = false #################### ext_units_physical = true -norm_mass = 1e5 -norm_length = 10 +unit_mass = 1e5 +unit_length = 10 # TODO add the option to normalize using other units # Notice that if physical units are used, the "a" and "b" parameters are in kiloparsec, not parsec! ext_m_bulge = 0 ext_b_bulge = 0 -ext_m_disk = 1e9 -ext_a_disk = 0.8 -ext_b_disk = 0.2 +ext_m_disk = 0 +ext_a_disk = 0 +ext_b_disk = 0 ext_m_halo_plummer = 0 ext_b_halo_plummer = 0 +ext_log_halo_v = 30 +# here the length scale for the logarithmic halo is in kpc, not pc like in the old phigrape. +ext_log_halo_r = 0.04 + #################################### diff --git a/phigrape.cpp b/phigrape.cpp index 99d88e7..04059b8 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -62,7 +62,6 @@ Config *config; //#define EXTPOT_GAL_DEH // Dehnen Galactic - usually physical units -//#define EXTPOT_GAL_LOG // Log Galactic - usually physical units #ifdef ETICS #include "grapite.h" @@ -312,12 +311,6 @@ double m_ext, r_ext, g_ext, tmp_r2, tmp_r3, dum, dum2, dum3, dum_g, tmp_g; #endif -#ifdef EXTPOT_GAL_LOG -double v_halo, r_halo, - v2_halo, r2_halo, r2_r2_halo, - x2_ij, y2_ij, z2_ij; -#endif - #ifdef EXTPOT_BH double r2, rv_ij, m_bh, b_bh, eps_bh; // NOTE different from eps_BH @@ -591,6 +584,24 @@ private: double m, a, b; }; +class Logarithmic_halo : public External_gravity { +public: + Logarithmic_halo(double v_halo, double r_halo) : v2_halo(v_halo*v_halo), r2_halo(r_halo*r_halo) {is_active=(r_halo>0);} +private: + void calc_gravity() + { + auto r2 = x.norm2(); + auto rv_ij = 2.0*(v*x); + auto r2_r2_halo = (r2 + r2_halo); + potential = - 0.5*v2_halo * log(1.0 + r2/r2_halo); + auto tmp = v2_halo/r2_r2_halo; + acceleration = - tmp * x; + tmp /= (r2 + r2_halo); + jerk = tmp * (rv_ij * x - r2_r2_halo * v); + } + double v2_halo, r2_halo; +}; + void calc_self_grav(double t, double eps2, double &g6_calls, int n_loc, int n_act, int ind_act[], double3 x_act_new[], double3 v_act_new[], @@ -688,44 +699,6 @@ for (i=0; iext_units_physical) { - normalization_mass = 1/config->norm_mass; - normalization_length = 1000/config->norm_length; + normalization_mass = 1/config->unit_mass; + normalization_length = 1000/config->unit_length; + normalization_velocity = 1.52484071426404437233e+01*sqrt(config->unit_length/config->unit_mass); } Plummer ext_bulge(config->ext_m_bulge*normalization_mass, config->ext_b_bulge*normalization_length); Miyamoto_Nagai ext_disk(config->ext_m_disk*normalization_mass, config->ext_a_disk*normalization_length, config->ext_b_disk*normalization_length); Plummer ext_halo_plummer(config->ext_m_halo_plummer*normalization_mass, config->ext_b_halo_plummer*normalization_length); + Logarithmic_halo ext_log_halo(config->ext_log_halo_v*normalization_velocity, config->ext_log_halo_r*normalization_length); std::vector external_gravity_components; external_gravity_components.push_back(&ext_bulge); external_gravity_components.push_back(&ext_disk); external_gravity_components.push_back(&ext_halo_plummer); + external_gravity_components.push_back(&ext_log_halo); - if (config->ext_m_bulge > 0) printf("m_bulge = %.4E b_bulge = %.4E\n", config->ext_m_bulge*normalization_mass, config->ext_b_bulge*normalization_length); - if (config->ext_m_disk > 0) printf("m_disk = %.4E a_disk = %.4E b_disk = %.4E\n", config->ext_m_disk*normalization_mass, config->ext_a_disk*normalization_length, config->ext_b_disk*normalization_length); - if (config->ext_m_halo_plummer > 0) printf("m_halo = %.4E b_halo = %.4E\n", config->ext_m_halo_plummer*normalization_mass, config->ext_b_halo_plummer*normalization_length); + if (ext_bulge.is_active) printf("m_bulge = %.4E b_bulge = %.4E\n", config->ext_m_bulge*normalization_mass, config->ext_b_bulge*normalization_length); + if (ext_disk.is_active) printf("m_disk = %.4E a_disk = %.4E b_disk = %.4E\n", config->ext_m_disk*normalization_mass, config->ext_a_disk*normalization_length, config->ext_b_disk*normalization_length); + if (ext_halo_plummer.is_active) printf("m_halo = %.4E b_halo = %.4E\n", config->ext_m_halo_plummer*normalization_mass, config->ext_b_halo_plummer*normalization_length); + if (ext_log_halo.is_active) printf("v_halo = %.6E r_halo = %.6E \n", config->ext_log_halo_v*normalization_velocity, config->ext_log_halo_r*normalization_length); printf("\n"); fflush(stdout); From f065566c6bdf85dd5134cd641552f9f7bd793399 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Thu, 26 Mar 2020 15:09:15 -0400 Subject: [PATCH 26/65] Added an HDF5 writer --- io.cpp | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 io.cpp diff --git a/io.cpp b/io.cpp new file mode 100644 index 0000000..6cacd25 --- /dev/null +++ b/io.cpp @@ -0,0 +1,81 @@ +#include "hdf5.h" +#include +struct double3 {double x,y,z;}; + +void h5_write(const std::string file_name, const int step_num, const double t, const int N, const double *m, const double3 *x, const double3 *v, const double *pot, const double3 *acc, const double3 *jrk, const int write_mode=0, const bool use_double_precision=true) +{ + char group_name[32], dataset_path[32]; + bool write_pot = (write_mode )%2; + bool write_acc = (write_mode>>1)%2; + bool write_jrk = (write_mode>>2)%2; + + hid_t file_id, group_id, attribute_id, dataset_id, dataspace_id; /* identifiers */ + hsize_t dims[2] = {(hsize_t)N, 3}; + herr_t status; + + hid_t h5_float_type; + if (use_double_precision) h5_float_type = H5T_IEEE_F64LE; + else h5_float_type = H5T_IEEE_F32LE; + + file_id = H5Fcreate(file_name.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + sprintf(group_name, "/Step#%d", step_num); + group_id = H5Gcreate2(file_id, group_name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + dataspace_id = H5Screate(H5S_SCALAR); + attribute_id = H5Acreate2 (group_id, "Time", H5T_IEEE_F64LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT); + H5Awrite(attribute_id, H5T_NATIVE_DOUBLE, &t); + + dataspace_id = H5Screate_simple(1, dims, NULL); + sprintf(dataset_path, "%s/MASS", group_name); + dataset_id = H5Dcreate2(file_id, dataset_path, h5_float_type, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, m); + + dataspace_id = H5Screate_simple(2, dims, NULL); + sprintf(dataset_path, "%s/X", group_name); + dataset_id = H5Dcreate2(file_id, dataset_path, h5_float_type, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, x); + + dataspace_id = H5Screate_simple(2, dims, NULL); + sprintf(dataset_path, "%s/V", group_name); + dataset_id = H5Dcreate2(file_id, dataset_path, h5_float_type, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, v); + + if (write_pot) { + dataspace_id = H5Screate_simple(1, dims, NULL); + sprintf(dataset_path, "%s/POT", group_name); + dataset_id = H5Dcreate2(file_id, dataset_path, h5_float_type, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, pot); + } + + if (write_acc) { + dataspace_id = H5Screate_simple(2, dims, NULL); + sprintf(dataset_path, "%s/ACC", group_name); + dataset_id = H5Dcreate2(file_id, dataset_path, h5_float_type, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, acc); + } + + if (write_jrk) { + dataspace_id = H5Screate_simple(2, dims, NULL); + sprintf(dataset_path, "%s/JRK", group_name); + dataset_id = H5Dcreate2(file_id, dataset_path, h5_float_type, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, jrk); + } + + H5Dclose(dataset_id); + H5Gclose(group_id); + H5Sclose(dataspace_id); + H5Fclose(file_id); +} + +int main() +{ + double3 aaa; + double pot; + int N = 25; + double3 x[N]; + for (int i=0; i Date: Thu, 26 Mar 2020 19:56:12 -0400 Subject: [PATCH 27/65] Working on HDF5 reader --- io.cpp | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 82 insertions(+), 9 deletions(-) diff --git a/io.cpp b/io.cpp index 6cacd25..40f009c 100644 --- a/io.cpp +++ b/io.cpp @@ -1,5 +1,7 @@ #include "hdf5.h" #include +#include +#include struct double3 {double x,y,z;}; void h5_write(const std::string file_name, const int step_num, const double t, const int N, const double *m, const double3 *x, const double3 *v, const double *pot, const double3 *acc, const double3 *jrk, const int write_mode=0, const bool use_double_precision=true) @@ -9,9 +11,8 @@ void h5_write(const std::string file_name, const int step_num, const double t, c bool write_acc = (write_mode>>1)%2; bool write_jrk = (write_mode>>2)%2; - hid_t file_id, group_id, attribute_id, dataset_id, dataspace_id; /* identifiers */ + hid_t file_id, group_id, attribute_id, dataset_id, dataspace_id; hsize_t dims[2] = {(hsize_t)N, 3}; - herr_t status; hid_t h5_float_type; if (use_double_precision) h5_float_type = H5T_IEEE_F64LE; @@ -23,53 +24,99 @@ void h5_write(const std::string file_name, const int step_num, const double t, c dataspace_id = H5Screate(H5S_SCALAR); attribute_id = H5Acreate2 (group_id, "Time", H5T_IEEE_F64LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT); H5Awrite(attribute_id, H5T_NATIVE_DOUBLE, &t); + H5Sclose(dataspace_id); dataspace_id = H5Screate_simple(1, dims, NULL); sprintf(dataset_path, "%s/MASS", group_name); dataset_id = H5Dcreate2(file_id, dataset_path, h5_float_type, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, m); + H5Dclose(dataset_id); + H5Sclose(dataspace_id); dataspace_id = H5Screate_simple(2, dims, NULL); sprintf(dataset_path, "%s/X", group_name); dataset_id = H5Dcreate2(file_id, dataset_path, h5_float_type, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, x); + H5Dclose(dataset_id); + H5Sclose(dataspace_id); dataspace_id = H5Screate_simple(2, dims, NULL); sprintf(dataset_path, "%s/V", group_name); dataset_id = H5Dcreate2(file_id, dataset_path, h5_float_type, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, v); + H5Dclose(dataset_id); + H5Sclose(dataspace_id); if (write_pot) { dataspace_id = H5Screate_simple(1, dims, NULL); sprintf(dataset_path, "%s/POT", group_name); dataset_id = H5Dcreate2(file_id, dataset_path, h5_float_type, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, pot); + H5Dclose(dataset_id); + H5Sclose(dataspace_id); } - if (write_acc) { dataspace_id = H5Screate_simple(2, dims, NULL); sprintf(dataset_path, "%s/ACC", group_name); dataset_id = H5Dcreate2(file_id, dataset_path, h5_float_type, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, acc); + H5Dclose(dataset_id); + H5Sclose(dataspace_id); } - if (write_jrk) { dataspace_id = H5Screate_simple(2, dims, NULL); sprintf(dataset_path, "%s/JRK", group_name); dataset_id = H5Dcreate2(file_id, dataset_path, h5_float_type, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, jrk); + H5Dclose(dataset_id); + H5Sclose(dataspace_id); } - - H5Dclose(dataset_id); H5Gclose(group_id); - H5Sclose(dataspace_id); + + + group_id = H5Gcreate2(file_id, "/Step#22", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + H5Gclose(group_id); + + H5Fclose(file_id); } + + + +herr_t file_info(hid_t loc_id, const char *name, void *opdata) +{ + H5G_stat_t statbuf; + + /* + * Get type of the object and display its name and type. + * The name of the object is passed to this function by + * the Library. Some magic :-) + */ + H5Gget_objinfo(loc_id, name, 0, &statbuf); + switch (statbuf.type) { + case H5G_GROUP: + printf(" Object with name %s is a group \n", name); + break; + case H5G_DATASET: + printf(" Object with name %s is a dataset \n", name); + break; + case H5G_TYPE: + printf(" Object with name %s is a named datatype \n", name); + break; + default: + printf(" Unable to identify an object "); + } + return 0; + } + + + + int main() { - double3 aaa; - double pot; +// double3 aaa; +// double pot; int N = 25; double3 x[N]; for (int i=0; i step_num; + for (int i=0; i Date: Fri, 27 Mar 2020 16:53:01 -0400 Subject: [PATCH 28/65] Continued working on HDF5 plugin --- io.cpp | 186 ++++++++++++++++++++++++++------------------------------- 1 file changed, 84 insertions(+), 102 deletions(-) diff --git a/io.cpp b/io.cpp index 40f009c..b1286af 100644 --- a/io.cpp +++ b/io.cpp @@ -2,11 +2,13 @@ #include #include #include -struct double3 {double x,y,z;}; +#include +struct double3 {double x,y,z; +}; -void h5_write(const std::string file_name, const int step_num, const double t, const int N, const double *m, const double3 *x, const double3 *v, const double *pot, const double3 *acc, const double3 *jrk, const int write_mode=0, const bool use_double_precision=true) + +void h5_write(const std::string file_name, const int step_num, const int N, const double t, const double *m, const double3 *x, const double3 *v, const double *pot, const double3 *acc, const double3 *jrk, const int write_mode=0, const bool use_double_precision=true) { - char group_name[32], dataset_path[32]; bool write_pot = (write_mode )%2; bool write_acc = (write_mode>>1)%2; bool write_jrk = (write_mode>>2)%2; @@ -19,6 +21,7 @@ void h5_write(const std::string file_name, const int step_num, const double t, c else h5_float_type = H5T_IEEE_F32LE; file_id = H5Fcreate(file_name.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + char group_name[32]; sprintf(group_name, "/Step#%d", step_num); group_id = H5Gcreate2(file_id, group_name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); dataspace_id = H5Screate(H5S_SCALAR); @@ -26,97 +29,89 @@ void h5_write(const std::string file_name, const int step_num, const double t, c H5Awrite(attribute_id, H5T_NATIVE_DOUBLE, &t); H5Sclose(dataspace_id); - dataspace_id = H5Screate_simple(1, dims, NULL); - sprintf(dataset_path, "%s/MASS", group_name); - dataset_id = H5Dcreate2(file_id, dataset_path, h5_float_type, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); - H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, m); - H5Dclose(dataset_id); - H5Sclose(dataspace_id); - - dataspace_id = H5Screate_simple(2, dims, NULL); - sprintf(dataset_path, "%s/X", group_name); - dataset_id = H5Dcreate2(file_id, dataset_path, h5_float_type, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); - H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, x); - H5Dclose(dataset_id); - H5Sclose(dataspace_id); - - dataspace_id = H5Screate_simple(2, dims, NULL); - sprintf(dataset_path, "%s/V", group_name); - dataset_id = H5Dcreate2(file_id, dataset_path, h5_float_type, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); - H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, v); - H5Dclose(dataset_id); - H5Sclose(dataspace_id); - - if (write_pot) { - dataspace_id = H5Screate_simple(1, dims, NULL); - sprintf(dataset_path, "%s/POT", group_name); - dataset_id = H5Dcreate2(file_id, dataset_path, h5_float_type, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); - H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, pot); + auto write_dataset = [&](const char dataset_name[], int ndims, double *data) { + hid_t dataspace_id = H5Screate_simple(ndims, dims, NULL); + char dataset_path[32]; + sprintf(dataset_path, "%s/%s", group_name, dataset_name); + hid_t dataset_id = H5Dcreate2(file_id, dataset_path, h5_float_type, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, data); H5Dclose(dataset_id); H5Sclose(dataspace_id); - } - if (write_acc) { - dataspace_id = H5Screate_simple(2, dims, NULL); - sprintf(dataset_path, "%s/ACC", group_name); - dataset_id = H5Dcreate2(file_id, dataset_path, h5_float_type, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); - H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, acc); - H5Dclose(dataset_id); - H5Sclose(dataspace_id); - } - if (write_jrk) { - dataspace_id = H5Screate_simple(2, dims, NULL); - sprintf(dataset_path, "%s/JRK", group_name); - dataset_id = H5Dcreate2(file_id, dataset_path, h5_float_type, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); - H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, jrk); - H5Dclose(dataset_id); - H5Sclose(dataspace_id); - } + }; + + write_dataset("MASS", 1, (double*)m); + write_dataset("X", 2, (double*)x); + write_dataset("V", 2, (double*)v); + if (write_pot) write_dataset("POT", 1, (double*)pot); + if (write_acc) write_dataset("ACC", 2, (double*)acc); + if (write_jrk) write_dataset("JRK", 2, (double*)jrk); + H5Gclose(group_id); - - - group_id = H5Gcreate2(file_id, "/Step#22", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); - H5Gclose(group_id); - - H5Fclose(file_id); } - - -herr_t file_info(hid_t loc_id, const char *name, void *opdata) +void h5_read(const std::string file_name, int *step_num, int *N, double *t, double m[], double3 x[], double3 v[]) { - H5G_stat_t statbuf; - - /* - * Get type of the object and display its name and type. - * The name of the object is passed to this function by - * the Library. Some magic :-) - */ - H5Gget_objinfo(loc_id, name, 0, &statbuf); - switch (statbuf.type) { - case H5G_GROUP: - printf(" Object with name %s is a group \n", name); - break; - case H5G_DATASET: - printf(" Object with name %s is a dataset \n", name); - break; - case H5G_TYPE: - printf(" Object with name %s is a named datatype \n", name); - break; - default: - printf(" Unable to identify an object "); + // Open file and root group; count number of top level objects + hid_t file_id = H5Fopen(file_name.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT); + hid_t group_id = H5Gopen2(file_id, "/", H5P_DEFAULT); + H5G_info_t object_info; + H5Gget_info(group_id, &object_info); + // Iterate over objects and add the number of each "step" group into a vector + std::vector step_num_arr; + for (int i=0; i step_num; - for (int i=0; i Date: Sat, 28 Mar 2020 01:34:37 -0400 Subject: [PATCH 29/65] Improved HDF5 reader and added ASCII writer with custom precision --- io.cpp | 48 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/io.cpp b/io.cpp index b1286af..dce1d55 100644 --- a/io.cpp +++ b/io.cpp @@ -1,4 +1,5 @@ #include "hdf5.h" +#include #include #include #include @@ -6,6 +7,18 @@ struct double3 {double x,y,z; }; +void ascii_write(const std::string file_name, const int step_num, const int N, const double t, const double *m, const double3 *x, const double3 *v, int precision=10) +{ + int id_width = (int)log10(N-1) + 1; + char string_template[256]; + sprintf(string_template, "%%0%dd%%%d.%dE%%%d.%dE%%%d.%dE%%%d.%dE%%%d.%dE%%%d.%dE%%%d.%dE\n", id_width, precision+7, precision, precision+8, precision, precision+8, precision, precision+8, precision, precision+8, precision, precision+8, precision, precision+8, precision); + printf("%d\n", step_num); + printf("%d\n", N); + printf("%.16E\n", t); + for (int i=0; i Date: Tue, 31 Mar 2020 19:04:18 -0400 Subject: [PATCH 30/65] Completed HDF5 support --- Makefile | 6 +- config.cpp | 5 ++ config.h | 1 + double3.h | 82 ++++++++++++++++++++ io.cpp | 202 ++++++++++++++++++++++++++++++-------------------- io.h | 16 ++++ phigrape.conf | 14 ++-- phigrape.cpp | 117 +++++------------------------ 8 files changed, 258 insertions(+), 185 deletions(-) create mode 100644 double3.h create mode 100644 io.h diff --git a/Makefile b/Makefile index 933616e..792b77e 100644 --- a/Makefile +++ b/Makefile @@ -20,8 +20,12 @@ LIB = $(GRAPELIB) $(CUDALIB) -lm MPICXX ?= mpic++ EXECUTABLE ?= phigrape +# HDF5 +CPPFLAGS += -DHAS_HDF5 +LIB += -lhdf5 -lz -ldl + default: - $(MPICXX) $(CPPFLAGS) $(CXXFLAGS) -DETICS_DTSCF=$(ETICS_DTSCF) $(INC) config.cpp phigrape.cpp -o $(EXECUTABLE) $(LIB) + $(MPICXX) $(CPPFLAGS) $(CXXFLAGS) -DETICS_DTSCF=$(ETICS_DTSCF) $(INC) io.cpp config.cpp phigrape.cpp -o $(EXECUTABLE) $(LIB) yebisu: CPPFLAGS := $(filter-out -DETICS, $(CPPFLAGS)) yebisu: default diff --git a/config.cpp b/config.cpp index 25f79cb..f66a014 100644 --- a/config.cpp +++ b/config.cpp @@ -106,6 +106,10 @@ T Config::get_parameter(Dictionary dictionary, std::string name, T default_value void Config::error_checking() { +#ifndef HAS_HDF5 + if (output_hdf5) + throw std::runtime_error("HDF5 output format (output_hdf5=true) requires the code to be compiled with HAS_HDF5"); +#endif if ((live_smbh_count < 0) || (live_smbh_count > 2)) throw std::runtime_error("The number of live black holes (live_smbh_count) can be 0, 1, or 2"); if (binary_smbh_pn && (live_smbh_count!=2)) @@ -148,6 +152,7 @@ Config::Config(std::string file_name) dt_bh = get_parameter(dictionary, "dt_bh", dt_contr); eta = get_parameter(dictionary, "eta"); input_file_name = get_parameter(dictionary, "input_file_name", "data.con"); + output_hdf5 = get_parameter(dictionary, "output_hdf5", false); dt_min_warning = get_parameter(dictionary, "dt_min_warning", false); live_smbh_count = get_parameter(dictionary, "live_smbh_count", 0); diff --git a/config.h b/config.h index 5275bf7..d4b68b6 100644 --- a/config.h +++ b/config.h @@ -14,6 +14,7 @@ public: double dt_bh; double eta; std::string input_file_name; + bool output_hdf5; bool dt_min_warning; int live_smbh_count; double live_smbh_custom_eps; diff --git a/double3.h b/double3.h new file mode 100644 index 0000000..ce0f3ef --- /dev/null +++ b/double3.h @@ -0,0 +1,82 @@ +#pragma once +#include + +struct double3 { + double data[3]; + double3() {} + double3(const double x, const double y, const double z) + { + data[0] = x; + data[1] = y; + data[2] = z; + } + double& operator[](int i) {return data[i];} + const double operator[](int i) const {return data[i];} + double3& operator=(const double3& a) + { + data[0] = a.data[0]; + data[1] = a.data[1]; + data[2] = a.data[2]; + return *this; + } + double3& operator+=(const double3& a) + { + data[0] += a.data[0]; + data[1] += a.data[1]; + data[2] += a.data[2]; + return *this; + } + double3& operator-=(const double3& a) + { + data[0] -= a.data[0]; + data[1] -= a.data[1]; + data[2] -= a.data[2]; + return *this; + } + double3& operator/=(const double& c) + { + data[0] /= c; + data[1] /= c; + data[2] /= c; + return *this; + } + double norm2() const + { + return data[0]*data[0]+data[1]*data[1]+data[2]*data[2]; + } + double norm() const + { + return sqrt(data[0]*data[0]+data[1]*data[1]+data[2]*data[2]); + } + operator double*() {return data;} +}; + +inline double3 operator*(const double& c, const double3& a) +{ + return double3(a.data[0]*c, a.data[1]*c, a.data[2]*c); +} + +inline double3 operator*(const double3& a, const double& c) +{ + return double3(a.data[0]*c, a.data[1]*c, a.data[2]*c); +} + +inline double operator*(const double3& a, const double3& b) +{ + return a.data[0]*b.data[0]+a.data[1]*b.data[1]+a.data[2]*b.data[2]; +} + +inline double3 operator/(const double3& a, const double& c) +{ + return double3(a.data[0]/c, a.data[1]/c, a.data[2]/c); +} + +inline double3 operator+(const double3& a, const double3& b) +{ + return double3(a.data[0]+b.data[0], a.data[1]+b.data[1], a.data[2]+b.data[2]); +} + +inline double3 operator-(const double3& a, const double3& b) +{ + return double3(a.data[0]-b.data[0], a.data[1]-b.data[1], a.data[2]-b.data[2]); +} diff --git a/io.cpp b/io.cpp index dce1d55..122415e 100644 --- a/io.cpp +++ b/io.cpp @@ -1,71 +1,79 @@ +#ifdef HAS_HDF5 #include "hdf5.h" +#endif + +#include "double3.h" +#include +#include #include -#include #include #include +#include #include -struct double3 {double x,y,z; -}; + + +bool is_hdf5(std::string file_name) +{ + std::ifstream file(file_name, std::ifstream::binary); + const char hdf5_magic[] = "\x89HDF\x0d\x0a\x1a\x0a"; + char buffer[8]; + file.read(buffer, 8); + if (!file) throw std::runtime_error("Unable to read file " + file_name); + bool result = (memcmp(buffer, hdf5_magic, 8)==0); + file.close(); + return result; +} + +void ascii_read(const std::string file_name, int *step_num, int *N, double *t, double *m, double3 *x, double3 *v) +{ + char rest[512]; + int result; + + std::ifstream file(file_name); + if (!file.good()) throw std::runtime_error("File " + file_name + " not found."); + std::string str; + + std::getline(file, str); + result = sscanf(str.c_str(), "%d%s", step_num, rest); + if (result!=1) throw std::runtime_error("Error parsing line 1: expected one integer"); + + std::getline(file, str); + result = sscanf(str.c_str(), "%d%s", N, rest); + if (result!=1) throw std::runtime_error("Error parsing line 2: expected one integer"); + + std::getline(file, str); + result = sscanf(str.c_str(), "%lf%s", t, rest); + if (result!=1) throw std::runtime_error("Error parsing line 3: expected one real number"); + + int i = -1; + while (std::getline(file, str)) { + if (++i > *N) throw std::runtime_error("Error parsing line " + std::to_string(i+4) + ": particle out of range"); + result = sscanf(str.c_str(), "%*s %lf %lf %lf %lf %lf %lf %lf%s", &m[i], &x[i][0], &x[i][1], &x[i][2], &v[i][0], &v[i][1], &v[i][2], rest); + } + file.close(); +} void ascii_write(const std::string file_name, const int step_num, const int N, const double t, const double *m, const double3 *x, const double3 *v, int precision=10) { + auto file = std::ofstream(file_name); + if (!file.is_open()) throw std::runtime_error("Cannot open file for output"); int id_width = (int)log10(N-1) + 1; - char string_template[256]; + char string_template[256], output_string[256]; + file << step_num << '\n'; + file << N << '\n'; + file.precision(16); + file << std::scientific << t << '\n'; sprintf(string_template, "%%0%dd%%%d.%dE%%%d.%dE%%%d.%dE%%%d.%dE%%%d.%dE%%%d.%dE%%%d.%dE\n", id_width, precision+7, precision, precision+8, precision, precision+8, precision, precision+8, precision, precision+8, precision, precision+8, precision, precision+8, precision); - printf("%d\n", step_num); - printf("%d\n", N); - printf("%.16E\n", t); for (int i=0; i>1)%2; - bool write_jrk = (write_mode>>2)%2; - - hid_t file_id, group_id, attribute_id, dataset_id, dataspace_id; - hsize_t dims[2] = {(hsize_t)N, 3}; - - hid_t h5_float_type; - if (use_double_precision) h5_float_type = H5T_IEEE_F64LE; - else h5_float_type = H5T_IEEE_F32LE; - - file_id = H5Fcreate(file_name.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); - char group_name[32]; - sprintf(group_name, "/Step#%d", step_num); - group_id = H5Gcreate2(file_id, group_name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); - dataspace_id = H5Screate(H5S_SCALAR); - attribute_id = H5Acreate2 (group_id, "Time", H5T_IEEE_F64LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT); - H5Awrite(attribute_id, H5T_NATIVE_DOUBLE, &t); - H5Sclose(dataspace_id); - - auto write_dataset = [&](const char dataset_name[], int ndims, double *data) { - hid_t dataspace_id = H5Screate_simple(ndims, dims, NULL); - char dataset_path[32]; - sprintf(dataset_path, "%s/%s", group_name, dataset_name); - hid_t dataset_id = H5Dcreate2(file_id, dataset_path, h5_float_type, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); - H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, data); - H5Dclose(dataset_id); - H5Sclose(dataspace_id); - }; - - write_dataset("MASS", 1, (double*)m); - write_dataset("X", 2, (double*)x); - write_dataset("V", 2, (double*)v); - if (write_pot) write_dataset("POT", 1, (double*)pot); - if (write_acc) write_dataset("ACC", 2, (double*)acc); - if (write_jrk) write_dataset("JRK", 2, (double*)jrk); - - H5Gclose(group_id); - H5Fclose(file_id); -} - - void h5_read(const std::string file_name, int *step_num, int *N, double *t, double m[], double3 x[], double3 v[]) { +#ifdef HAS_HDF5 // Open file and root group; count number of top level objects hid_t file_id = H5Fopen(file_name.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT); hid_t group_id = H5Gopen2(file_id, "/", H5P_DEFAULT); @@ -91,6 +99,7 @@ void h5_read(const std::string file_name, int *step_num, int *N, double *t, doub sprintf(path, "/Step#%d", *step_num); attr_id = H5Aopen_by_name(file_id, path, "Time", H5P_DEFAULT, H5P_DEFAULT); H5Aread(attr_id, H5T_NATIVE_DOUBLE, t); + H5Aclose(attr_id); sprintf(path, "/Step#%d/MASS", *step_num); dataset_id = H5Dopen2(file_id, path, H5P_DEFAULT); @@ -100,6 +109,8 @@ void h5_read(const std::string file_name, int *step_num, int *N, double *t, doub throw std::runtime_error("Dataset MASS in Step#" + std::to_string(*step_num) + " of file " + file_name + " is " + std::to_string(ndims) + "-dimensional (expected 1-dimensional)"); H5Sget_simple_extent_dims(dataspace_id, dims, NULL); H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, m); + H5Sclose(dataspace_id); + H5Dclose(dataset_id); *N = dims[0]; sprintf(path, "/Step#%d/X", *step_num); @@ -110,6 +121,8 @@ void h5_read(const std::string file_name, int *step_num, int *N, double *t, doub H5Sget_simple_extent_dims(dataspace_id, dims, NULL); if ((dims[0] != *N) || (dims[1] != 3)) throw std::runtime_error("Bad dimensionality"); H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, (double*)x); + H5Sclose(dataspace_id); + H5Dclose(dataset_id); sprintf(path, "/Step#%d/V", *step_num); dataset_id = H5Dopen2(file_id, path, H5P_DEFAULT); @@ -119,36 +132,65 @@ void h5_read(const std::string file_name, int *step_num, int *N, double *t, doub H5Sget_simple_extent_dims(dataspace_id, dims, NULL); if ((dims[0] != *N) || (dims[1] != 3)) throw std::runtime_error("Bad dimensionality"); H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, (double*)v); + H5Sclose(dataspace_id); + H5Dclose(dataset_id); + + H5Gclose(group_id); + H5Fclose(file_id); +#else + throw std::runtime_error("h5_read was called but compiled without HDF5 support"); +#endif } - -int main() +void h5_write(const std::string file_name, const int step_num, const int N, const double t, const double *m, const double3 *x, const double3 *v, const double *pot, const double3 *acc, const double3 *jrk, const int write_mode=0, const bool use_double_precision=true) { -// double3 aaa; -// double pot; - std::string file_name = "new_file.h5"; - int N = 25; - double3 x[N]; - for (int i=0; i> 1) % 2; + bool write_jrk = (write_mode >> 2) % 2; + if (write_pot) write_dataset("POT", 1, (double*)pot); + if (write_acc) write_dataset("ACC", 2, (double*)acc); + if (write_jrk) write_dataset("JRK", 2, (double*)jrk); + + H5Gclose(group_id); + H5Fclose(file_id); + H5close(); // If we don't do that (HDF5 1.10.5) then the file isn't really closed... +#else + throw std::runtime_error("h5_write was called but compiled without HDF5 support"); +#endif } diff --git a/io.h b/io.h new file mode 100644 index 0000000..1baa152 --- /dev/null +++ b/io.h @@ -0,0 +1,16 @@ +#pragma once +#include +#include "double3.h" + +bool is_hdf5(std::string file_name); +// This function is implemented independently of the HDF5 library + +void ascii_read(const std::string file_name, int *step_num, int *N, double *t, double *m, double3 *x, double3 *v); + +void ascii_write(const std::string file_name, const int step_num, const int N, const double t, const double *m, const double3 *x, const double3 *v, int precision=10); + +void h5_read(const std::string file_name, int *step_num, int *N, double *t, double m[], double3 x[], double3 v[]); +// In case the code is compiled without HDF5 support, the implementation of this function just throws an error + +void h5_write(const std::string file_name, const int step_num, const int N, const double t, const double *m, const double3 *x, const double3 *v, const double *pot, const double3 *acc, const double3 *jrk, const int write_mode=0, const bool use_double_precision=true); +// In case the code is compiled without HDF5 support, the implementation of this function just throws an error diff --git a/phigrape.conf b/phigrape.conf index c9394b4..0ceaa73 100644 --- a/phigrape.conf +++ b/phigrape.conf @@ -21,11 +21,11 @@ dt_bh = 0.125 eta = 0.01 # Name of the input file; use "data.con" in most cases -inp_data = data.con +input_file_name = data.con +output_hdf5 = true ##### NOT IMPLEMENTED ####################### -output_format = HDF5 dt_min_warning = false ############################################# @@ -33,9 +33,9 @@ dt_min_warning = false # EXTERNAL GRAVITY # #################### -ext_units_physical = true -unit_mass = 1e5 -unit_length = 10 +ext_units_physical = false +#unit_mass = 1e5 +#unit_length = 10 # TODO add the option to normalize using other units # Notice that if physical units are used, the "a" and "b" parameters are in kiloparsec, not parsec! @@ -47,9 +47,9 @@ ext_a_disk = 0 ext_b_disk = 0 ext_m_halo_plummer = 0 ext_b_halo_plummer = 0 -ext_log_halo_v = 30 +ext_log_halo_v = 0 # here the length scale for the logarithmic halo is in kpc, not pc like in the old phigrape. -ext_log_halo_r = 0.04 +ext_log_halo_r = 0 diff --git a/phigrape.cpp b/phigrape.cpp index 04059b8..81eda25 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -53,7 +53,10 @@ Coded by : Peter Berczik Version number : 19.04 Last redaction : 2019.04.16 12:55 *****************************************************************************/ +#include "double3.h" #include "config.h" +#include "io.h" + Config *config; #define NORM // Physical normalization @@ -177,84 +180,6 @@ Config *config; #define N_MAX (6*MB) #define N_MAX_loc (2*MB) -struct double3 { - double data[3]; - double3() {} - double3(const double x, const double y, const double z) - { - data[0] = x; - data[1] = y; - data[2] = z; - } - double& operator[](int i) {return data[i];} - double3& operator=(const double3& a) - { - data[0] = a.data[0]; - data[1] = a.data[1]; - data[2] = a.data[2]; - return *this; - } - double3& operator+=(const double3& a) - { - data[0] += a.data[0]; - data[1] += a.data[1]; - data[2] += a.data[2]; - return *this; - } - double3& operator-=(const double3& a) - { - data[0] -= a.data[0]; - data[1] -= a.data[1]; - data[2] -= a.data[2]; - return *this; - } - double3& operator/=(const double& c) - { - data[0] /= c; - data[1] /= c; - data[2] /= c; - return *this; - } - double norm2() const - { - return data[0]*data[0]+data[1]*data[1]+data[2]*data[2]; - } - double norm() const - { - return sqrt(data[0]*data[0]+data[1]*data[1]+data[2]*data[2]); - } - operator double*() {return data;} -}; - -double3 operator*(const double& c, const double3& a) -{ - return double3(a.data[0]*c, a.data[1]*c, a.data[2]*c); -} - -double3 operator*(const double3& a, const double& c) -{ - return double3(a.data[0]*c, a.data[1]*c, a.data[2]*c); -} - -double operator*(const double3& a, const double3& b) -{ - return a.data[0]*b.data[0]+a.data[1]*b.data[1]+a.data[2]*b.data[2]; -} - -double3 operator/(const double3& a, const double& c) -{ - return double3(a.data[0]/c, a.data[1]/c, a.data[2]/c); -} - -double3 operator+(const double3& a, const double3& b) -{ - return double3(a.data[0]+b.data[0], a.data[1]+b.data[1], a.data[2]+b.data[2]); -} - -double3 operator-(const double3& a, const double3& b) -{ - return double3(a.data[0]-b.data[0], a.data[1]-b.data[1], a.data[2]-b.data[2]); -} @@ -366,16 +291,6 @@ void get_CPU_time(double *time_real, double *time_user, double *time_syst) *time_user = *time_real; } -void read_data(char inp_fname[], int *diskstep, int *N, double *time_cur, int ind[], double m[], double3 x[], double3 v[]) -{ - auto inp = fopen(inp_fname, "r"); - fscanf(inp, "%d \n", diskstep); - fscanf(inp, "%d \n", N); - fscanf(inp, "%lE \n", time_cur); - for (int i=0; i<*N; i++) fscanf(inp,"%d %lE %lE %lE %lE %lE %lE %lE \n", &ind[i], &m[i], &x[i][0], &x[i][1], &x[i][2], &v[i][0], &v[i][1], &v[i][2]); - fclose(inp); -} - void write_snap_data(char out_fname[], int diskstep, int N, double time_cur, int ind[], double m[], double3 x[], double3 v[]) { auto out = fopen(out_fname, "w"); @@ -962,6 +877,17 @@ int main(int argc, char *argv[]) C_NB = config->pn_c; std::copy(config->pn_usage.begin(), config->pn_usage.end(), usedOrNot); + if (is_hdf5(config->input_file_name)) { +#ifndef HAS_HDF5 + fprintf(stderr, "ERROR: input file is in HDF5 format, but the code was compiled without HDF5 support\n") + return -1; +#endif + h5_read(config->input_file_name, &diskstep, &N, &time_cur, m, x, v); + } + else + ascii_read(config->input_file_name, &diskstep, &N, &time_cur, m, x, v); + std::iota(ind, ind+N, 0); + if (myRank == rootRank) { //TODO move it out of (myRank == rootRank) so you don't need to communicate them. @@ -995,12 +921,6 @@ int main(int argc, char *argv[]) fscanf(inp,"%lE %lE %lE", &m_ext, &r_ext, &g_ext); #endif - /* read the global data for particles to the rootRank */ - - read_data(inp_fname, &diskstep, &N, &time_cur, ind, m, x, v); - - /* possible coordinate & velocity limits for ALL particles !!! */ - printf("\n"); printf("Begin the calculation of phi-GRAPE program on %03d processors\n", n_proc); printf("\n"); @@ -1994,7 +1914,8 @@ int main(int argc, char *argv[]) /* write cont data */ - write_snap_data((char*)"data.con", diskstep, N, time_cur, ind, m, x, v); + if (config->output_hdf5) h5_write("data.con", diskstep, N, time_cur, m, x, v, pot, a, adot, 0, true); + else ascii_write("data.con", diskstep, N, time_cur, m, x, v, 16); /* possible OUT for timing !!! */ @@ -2049,8 +1970,10 @@ int main(int argc, char *argv[]) if (myRank == rootRank) { diskstep++; char out_fname[256]; - sprintf(out_fname, "%06d.dat", diskstep); - write_snap_data(out_fname, diskstep, N, time_cur, ind, m, x, v); + sprintf(out_fname, "%06d", diskstep); + if (config->output_hdf5) h5_write(std::string(out_fname) + ".h5", diskstep, N, time_cur, m, x, v, pot, a, adot, 0, true); + else ascii_write(std::string(out_fname) + ".dat", diskstep, N, time_cur, m, x, v, 10); + // TODO custom precision } /* if (myRank == rootRank) */ #ifdef ETICS_DUMP From 62b0d7e491deeeeabd4e2c25644db2d2a863f924 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Tue, 31 Mar 2020 22:06:04 -0400 Subject: [PATCH 31/65] Improved output and config --- .gitignore | 1 + config.cpp | 6 ++ config.h | 3 + io.cpp | 14 ++-- phigrape.conf | 188 +++++++++++++++++++++++++++++--------------------- phigrape.cpp | 21 +----- 6 files changed, 126 insertions(+), 107 deletions(-) diff --git a/.gitignore b/.gitignore index 773bfd7..9a8c7cc 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ *.mask grapite-dev-exec-threshold phigrape +*.h5 diff --git a/config.cpp b/config.cpp index f66a014..ce229d9 100644 --- a/config.cpp +++ b/config.cpp @@ -151,8 +151,14 @@ Config::Config(std::string file_name) dt_contr = get_parameter(dictionary, "dt_contr"); dt_bh = get_parameter(dictionary, "dt_bh", dt_contr); eta = get_parameter(dictionary, "eta"); + input_file_name = get_parameter(dictionary, "input_file_name", "data.con"); + output_hdf5 = get_parameter(dictionary, "output_hdf5", false); + output_hdf5_double_precision = get_parameter(dictionary, "output_hdf5_double_precision", true); + output_ascii_precision = get_parameter(dictionary, "output_ascii_precision", 10); + output_extra_mode = get_parameter(dictionary, "output_extra_mode", 10); + dt_min_warning = get_parameter(dictionary, "dt_min_warning", false); live_smbh_count = get_parameter(dictionary, "live_smbh_count", 0); diff --git a/config.h b/config.h index d4b68b6..832d517 100644 --- a/config.h +++ b/config.h @@ -15,6 +15,9 @@ public: double eta; std::string input_file_name; bool output_hdf5; + bool output_hdf5_double_precision; + int output_ascii_precision; + int output_extra_mode; bool dt_min_warning; int live_smbh_count; double live_smbh_custom_eps; diff --git a/io.cpp b/io.cpp index 122415e..a2c0d3d 100644 --- a/io.cpp +++ b/io.cpp @@ -142,7 +142,7 @@ void h5_read(const std::string file_name, int *step_num, int *N, double *t, doub #endif } -void h5_write(const std::string file_name, const int step_num, const int N, const double t, const double *m, const double3 *x, const double3 *v, const double *pot, const double3 *acc, const double3 *jrk, const int write_mode=0, const bool use_double_precision=true) +void h5_write(const std::string file_name, const int step_num, const int N, const double t, const double *m, const double3 *x, const double3 *v, const double *pot, const double3 *acc, const double3 *jrk, const int extra_mode=0, const bool use_double_precision=true) { #ifdef HAS_HDF5 hid_t file_id, group_id, attribute_id, dataset_id, dataspace_id; @@ -151,13 +151,7 @@ void h5_write(const std::string file_name, const int step_num, const int N, cons hid_t h5_float_type; if (use_double_precision) h5_float_type = H5T_IEEE_F64LE; else h5_float_type = H5T_IEEE_F32LE; - -// static int zzz = 5; file_id = H5Fcreate(file_name.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); - -// file_id = H5Fcreate(std::to_string(zzz).c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); - -// zzz++; char group_name[32]; sprintf(group_name, "/Step#%d", step_num); group_id = H5Gcreate2(file_id, group_name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); @@ -180,9 +174,9 @@ void h5_write(const std::string file_name, const int step_num, const int N, cons write_dataset("X", 2, (double*)x); write_dataset("V", 2, (double*)v); - bool write_pot = (write_mode ) % 2; - bool write_acc = (write_mode >> 1) % 2; - bool write_jrk = (write_mode >> 2) % 2; + bool write_pot = (extra_mode ) % 2; + bool write_acc = (extra_mode >> 1) % 2; + bool write_jrk = (extra_mode >> 2) % 2; if (write_pot) write_dataset("POT", 1, (double*)pot); if (write_acc) write_dataset("ACC", 2, (double*)acc); if (write_jrk) write_dataset("JRK", 2, (double*)jrk); diff --git a/phigrape.conf b/phigrape.conf index 0ceaa73..acb3a82 100644 --- a/phigrape.conf +++ b/phigrape.conf @@ -8,8 +8,8 @@ eps = 1E-4 # End time of the calculation t_end = 0.25 -# Interval of snapshot files output (xxxxxx.dat) -dt_disk = 1.0 +# Interval of snapshot files output +dt_disk = 0.125 # Interval for the energy control output (contr.dat) dt_contr = 0.125 @@ -20,100 +20,132 @@ dt_bh = 0.125 # Parameter for timestep determination eta = 0.01 -# Name of the input file; use "data.con" in most cases +# Name of the input file; use "data.con" in most cases [default: data.con] input_file_name = data.con -output_hdf5 = true -##### NOT IMPLEMENTED ####################### -dt_min_warning = false -############################################# +########## +# OUTPUT # +########## + +# Whether to use HDF5 format for snapshot and restart; regular ASCII snapshorts are saved if false [default: false] +#output_hdf5 = true + +# If using HDF5 output, use double precision or not [default: true] +# Consider setting to false to save disk space. Restart file is always saved in double precision. +#output_hdf5_double_precision = true + +# If using ASCII output, the number of digits after the decimal point [default: 10] +# Restart file is saved with 16 digits after the decimal point. +#output_ascii_precision = 6 + +# Extra output: optionally save potential, acceleration and jerk in snapshot files [default: 0] +# This is a number between 0 and 7 that encodes the output options in the following way: +# [value] = [save jerk]*4 + [save acceleration]*2 + [save potential] +# Example: choose 5 if it is needed to save the jerk and the potential, but not the acceleration for some reason. +# Currently implemented in HDF5 output only. +#output_extra_mode = 7 + +# Whether to output a warning on the screen when the minimum time step is encountered. [default: false] +#dt_min_warning = false #################### # EXTERNAL GRAVITY # #################### -ext_units_physical = false -#unit_mass = 1e5 -#unit_length = 10 -# TODO add the option to normalize using other units +# Remember that external gravity models are applied at the same coordinate system as the particles. If the idea is to simulate a globular cluster orbiting in an external field, be sure to set the initial conditions appropriately (applying a shift to the coordinates and velocities). -# Notice that if physical units are used, the "a" and "b" parameters are in kiloparsec, not parsec! +# Whether the parameters for the external gravitational field given below are in physical units or Hénon units. If true, the system used is {kiloparsec, solar mass, kilometre per second} [default: false] +#ext_units_physical = true -ext_m_bulge = 0 -ext_b_bulge = 0 -ext_m_disk = 0 -ext_a_disk = 0 -ext_b_disk = 0 -ext_m_halo_plummer = 0 -ext_b_halo_plummer = 0 -ext_log_halo_v = 0 -# here the length scale for the logarithmic halo is in kpc, not pc like in the old phigrape. -ext_log_halo_r = 0 +# If Physical units were selected, specify the simulation's unit mass (is solar masses) and unit lenght (in parsec; not kiloparsec) +# TODO: add the option to normalize using other units. +#unit_mass = 4E5 # MSun +#unit_length = 15 # pc + + +# The bulge is a Plummer potential with the following total mass and radius. +#ext_m_bulge = 5E9 # MSun +#ext_b_bulge = 1.9 # kpc + + +# The disk is a Miyamoto-Nagai potential with the following total mass, scale length, and scale height +#ext_m_disk = 6.8E10 # MSun +#ext_a_disk = 3.00 # kpc +#ext_b_disk = 0.28 # kpc + + +# This halo option is yet another Plummer potential with the following total mass and radius. +#ext_m_halo_plummer = 8E11 # MSun +#ext_b_halo_plummer = 245 # kpc + + +# This halo option is a logarithmic potential with the following velocity and radius parameters. +#ext_log_halo_v = 240 # km/s +#ext_log_halo_r = 1 # kpc -#################################### -## LIVE SUPERMASSIVE BLACK HOLE(S) # -#################################### -# -## There is special treatment for particles representing supermassive black holes (SMBHs): they are integrated at every time step, they can have custom softening in SMBH-SMBH interactions, and post Newtonian terms can be added to the gravity. -# -## The number of SMBH particles. Can be 0 (no SMBH), 1, or 2. [default: 0] -#live_smbh_count = 0 -# -## Custom softening length for SMBH-SMBH interactions (can also be zero). If non-negative, the custom softening is applied. [default: -1] +################################### +# LIVE SUPERMASSIVE BLACK HOLE(S) # +################################### + +# There is special treatment for particles representing supermassive black holes (SMBHs): they are integrated at every time step, they can have custom softening in SMBH-SMBH interactions, and post Newtonian terms can be added to the gravity. + +# The number of SMBH particles. Can be 0 (no SMBH), 1, or 2. [default: 0] +#live_smbh_count = 2 + +# Custom softening length for SMBH-SMBH interactions (can also be zero). If non-negative, the custom softening is applied. [default: -1] #live_smbh_custom_eps = 0 -# -## Output additional diagnostics about live SMBHs. [default: false] -##TODO# dt_bh + +# Output additional diagnostics about live SMBHs. [default: false] #live_smbh_output = true -# -## Output additional diagnostics about the SMBH's (or SMBHs') nearest neighbours (number could be set as shown below). [default: false] + +# Output additional diagnostics about the SMBH's (or SMBHs') nearest neighbours (number could be set as shown below). [default: false] #live_smbh_neighbor_output = true -# -## Number of nearest neighbours to the SMBH (or SMBHs) to include in output. [default: 10] + +# Number of nearest neighbours to the SMBH (or SMBHs) to include in output. [default: 10] #live_smbh_neighbor_number = 10 -# -################################### -## BINARY SUPERMASSIVE BLACK HOLE # -################################### -# -## The following parameters can be set when `live_smbh_count` is 2. -# -## Output additional diagnostics about the SMBH's sphere of influence (size could be set as shown below). [default: false] + +################################## +# BINARY SUPERMASSIVE BLACK HOLE # +################################## + +# The following parameters can be set when live_smbh_count is 2. + +# Output additional diagnostics about the sphere of influence (size could be set as shown below). [default: false] #binary_smbh_influence_sphere_output = true -# -## The influence sphere is centred at the binary SMBH's centre of mass, and its radius is the semi-major axis of the binary times the factor below. [default: 10.0] -#binary_smbh_influence_radius_factor = 3.162277660168379497918067e+03 -# -## Add post Newtonian terms to SMBH-SMBH gravity. [default: false] + +# The influence sphere is centred at the binary SMBH's centre of mass, and its radius is the semi-major axis of the binary times the factor below. [default: 10] +#binary_smbh_influence_radius_factor = 10 + +# Add post Newtonian terms to SMBH-SMBH gravity. [default: false] #binary_smbh_pn = true -# -## A mask array (zeros and ones) determining whether or not to use specific post-Newtonian terms. -## The elements represent {0, 1, 2, 2.5, 3, 3.5, spin} + +# A mask array (zeros and ones) determining whether or not to use specific post-Newtonian terms. +# The elements represent {0, 1, 2, 2.5, 3, 3.5, spin} [default: {1,1,1,1,1,1,1}] #pn_usage = {1, 1, 1, 1, 0, 0, 0} -# -## The speed of light in N-body units [default: 500] + +# The speed of light in N-body units [default: 500] #pn_c = 477.12 -# -##################################### -## Negative powers of two # -##################################### -## -1 1/2 0.5 # -## -2 1/4 0.25 # -## -3 1/8 0.125 # -## -4 1/16 0.0625 # -## -5 1/32 0.03125 # -## -6 1/64 0.015625 # -## -7 1/128 0.0078125 # -## -8 1/256 0.00390625 # -## -9 1/512 0.001953125 # -## -10 1/1024 0.0009765625 # -## -11 1/2048 0.00048828125 # -## -12 1/4096 0.000244140625 # -## -13 1/8192 0.0001220703125 # -## -14 1/16384 0.00006103515625 # -## -15 1/32768 0.000030517578125 # -## -16 1/65536 0.0000152587890625 # -##################################### + +#################################### +# Negative powers of two # +#################################### +# -1 1/2 0.5 # +# -2 1/4 0.25 # +# -3 1/8 0.125 # +# -4 1/16 0.0625 # +# -5 1/32 0.03125 # +# -6 1/64 0.015625 # +# -7 1/128 0.0078125 # +# -8 1/256 0.00390625 # +# -9 1/512 0.001953125 # +# -10 1/1024 0.0009765625 # +# -11 1/2048 0.00048828125 # +# -12 1/4096 0.000244140625 # +# -13 1/8192 0.0001220703125 # +# -14 1/16384 0.00006103515625 # +# -15 1/32768 0.000030517578125 # +# -16 1/65536 0.0000152587890625 # +#################################### diff --git a/phigrape.cpp b/phigrape.cpp index 81eda25..91143f9 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -291,22 +291,6 @@ void get_CPU_time(double *time_real, double *time_user, double *time_syst) *time_user = *time_real; } -void write_snap_data(char out_fname[], int diskstep, int N, double time_cur, int ind[], double m[], double3 x[], double3 v[]) -{ - auto out = fopen(out_fname, "w"); - fprintf(out,"%06d \n", diskstep); - fprintf(out,"%07d \n", N); - fprintf(out,"%.10E \n", time_cur); - for (int i=0; ilive_smbh_count == 2) { @@ -1971,9 +1955,8 @@ int main(int argc, char *argv[]) diskstep++; char out_fname[256]; sprintf(out_fname, "%06d", diskstep); - if (config->output_hdf5) h5_write(std::string(out_fname) + ".h5", diskstep, N, time_cur, m, x, v, pot, a, adot, 0, true); - else ascii_write(std::string(out_fname) + ".dat", diskstep, N, time_cur, m, x, v, 10); - // TODO custom precision + if (config->output_hdf5) h5_write(std::string(out_fname) + ".h5", diskstep, N, time_cur, m, x, v, pot, a, adot, config->output_extra_mode, config->output_hdf5_double_precision); + else ascii_write(std::string(out_fname) + ".dat", diskstep, N, time_cur, m, x, v, config->output_ascii_precision); } /* if (myRank == rootRank) */ #ifdef ETICS_DUMP From c79cef895acbd6c03a9f6f21d79096d1eb0031ea Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Wed, 1 Apr 2020 15:18:25 -0400 Subject: [PATCH 32/65] Added Dehnen potential and moved external potentials to a new compilation unit --- Makefile | 2 +- config.cpp | 9 +- config.h | 3 + external.cpp | 86 ++++++++++++++++ external.h | 59 +++++++++++ phigrape.conf | 7 ++ phigrape.cpp | 280 +------------------------------------------------- 7 files changed, 168 insertions(+), 278 deletions(-) create mode 100644 external.cpp create mode 100644 external.h diff --git a/Makefile b/Makefile index 792b77e..319f579 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,7 @@ CPPFLAGS += -DHAS_HDF5 LIB += -lhdf5 -lz -ldl default: - $(MPICXX) $(CPPFLAGS) $(CXXFLAGS) -DETICS_DTSCF=$(ETICS_DTSCF) $(INC) io.cpp config.cpp phigrape.cpp -o $(EXECUTABLE) $(LIB) + $(MPICXX) $(CPPFLAGS) $(CXXFLAGS) -DETICS_DTSCF=$(ETICS_DTSCF) $(INC) external.cpp io.cpp config.cpp phigrape.cpp -o $(EXECUTABLE) $(LIB) yebisu: CPPFLAGS := $(filter-out -DETICS, $(CPPFLAGS)) yebisu: default diff --git a/config.cpp b/config.cpp index ce229d9..28ac76f 100644 --- a/config.cpp +++ b/config.cpp @@ -3,9 +3,12 @@ #include #include #include +#include using Dictionary = std::unordered_map; +static constexpr double nix = -std::numeric_limits::max(); // avoid nans + std::string Config::strip(const std::string str) { std::string str_new = str; @@ -138,6 +141,8 @@ void Config::error_checking() throw std::runtime_error("To use external disk gravity, please specify positive ext_m_disk, ext_a_disk and ext_b_disk"); if (((ext_log_halo_r > 0) && (ext_log_halo_v <= 0)) || ((ext_log_halo_r <= 0) && (ext_log_halo_v > 0))) throw std::runtime_error("To use external logarithmic halo gravity, please specify positive ext_log_halo_r and ext_log_halo_v"); + if ((ext_dehnen_m > 0) && ((ext_dehnen_r <= 0) || (ext_dehnen_gamma <= 0))) + throw std::runtime_error("To use external Dehnen model, please specify positive ext_dehnen_r and ext_dehnen_gamma"); } Config::Config(std::string file_name) @@ -186,7 +191,9 @@ Config::Config(std::string file_name) ext_b_halo_plummer = get_parameter(dictionary, "ext_b_halo_plummer", -1); ext_log_halo_v = get_parameter(dictionary, "ext_log_halo_v", 0); ext_log_halo_r = get_parameter(dictionary, "ext_log_halo_r", 0); - + ext_dehnen_m = get_parameter(dictionary, "ext_dehnen_m", 0); + ext_dehnen_r = get_parameter(dictionary, "ext_dehnen_r", -1); + ext_dehnen_gamma = get_parameter(dictionary, "ext_dehnen_gamma", -1); error_checking(); } diff --git a/config.h b/config.h index 832d517..e9d537a 100644 --- a/config.h +++ b/config.h @@ -41,6 +41,9 @@ public: double ext_b_halo_plummer; double ext_log_halo_r; double ext_log_halo_v; + double ext_dehnen_m; + double ext_dehnen_r; + double ext_dehnen_gamma; private: using Dictionary = std::unordered_map; diff --git a/external.cpp b/external.cpp new file mode 100644 index 0000000..27c5f71 --- /dev/null +++ b/external.cpp @@ -0,0 +1,86 @@ +#include "external.h" + +inline double square(double x) {return x*x;} + +void Plummer::calc_gravity() +{ + double r2 = square(b); + r2 += x.norm2(); + double r = sqrt(r2); + double rv_ij = v*x; + double tmp = m / r; + potential = -tmp; + tmp /= r2; + acceleration = - tmp * x; + jerk = - tmp * (v - 3*rv_ij * x/r2); +} + +void Miyamoto_Nagai::calc_gravity() +{ + double x_ij=x[0], y_ij=x[1], z_ij=x[2]; + double vx_ij=v[0], vy_ij=v[1], vz_ij=v[2]; + auto z2_tmp = z_ij*z_ij + square(b); + auto z_tmp = sqrt(z2_tmp); + auto r2_tmp = x_ij*x_ij + y_ij*y_ij + square(z_tmp + a); + auto r_tmp = sqrt(r2_tmp); + potential = - m / r_tmp; + auto tmp = m / (r2_tmp*r_tmp); + acceleration[0] = - tmp * x_ij; + acceleration[1] = - tmp * y_ij; + acceleration[2] = - tmp * z_ij * (z_tmp + a)/z_tmp; + tmp = m / (z_tmp*r2_tmp*r2_tmp*r_tmp); + jerk[0] = tmp * (- vx_ij*z_tmp*r2_tmp + + 3.0*x_ij*vx_ij*x_ij*z_tmp + + 3.0*x_ij*vy_ij*y_ij*z_tmp + + 3.0*x_ij*vz_ij*z_ij*square(z_tmp + a)); + jerk[1] = tmp * (- vy_ij*z_tmp*r2_tmp + + 3.0*y_ij*vx_ij*x_ij*z_tmp + + 3.0*y_ij*vy_ij*y_ij*z_tmp + + 3.0*y_ij*vz_ij*z_ij*square(z_tmp + a)); + jerk[2] = tmp * (- vz_ij*(z_tmp + a)*(x_ij*x_ij*(z2_tmp*z_tmp + a*square(b)) + + y_ij*y_ij*(z2_tmp*z_tmp + a*square(b)) - + (2.0*a*(square(z_ij) - square(b))*z_tmp + + 2.0*square(z_ij*z_ij) + + square(b)*square(z_ij) - + square(b)*(square(a) + square(b)))) + + 3.0*vx_ij*x_ij*z_ij*z2_tmp*(z_tmp + a) + + 3.0*vy_ij*y_ij*z_ij*z2_tmp*(z_tmp + a)) / z2_tmp; +} + +void Logarithmic_halo::calc_gravity() +{ + auto r2 = x.norm2(); + auto rv_ij = 2.0*(v*x); + auto r2_r2_halo = (r2 + r2_halo); + potential = - 0.5*v2_halo * log(1.0 + r2/r2_halo); + auto tmp = v2_halo/r2_r2_halo; + acceleration = - tmp * x; + tmp /= (r2 + r2_halo); + jerk = tmp * (rv_ij * x - r2_r2_halo * v); +} + + +void Dehnen::calc_gravity() +{ + + auto tmp_r = x.norm(); + auto tmp_r2 = tmp_r*tmp_r; + auto tmp_r3 = tmp_r2*tmp_r; + + auto dum = tmp_r/(tmp_r + r); + auto dum2 = dum*dum; + auto dum3 = dum2*dum; + auto dum_g = pow(dum, -gamma); + + potential = - ( (m/r) / (2.0-gamma) ) * ( 1.0 - dum2 * dum_g ); + + auto tmp = (m/tmp_r3) * dum3 * dum_g; + + acceleration = - tmp * x; + + auto rv_ij = v*x; + tmp = ( m/((tmp_r+r)*(tmp_r+r)*(tmp_r+r)) ) * dum_g; + auto tmp_g = ( (r*gamma + 3.0*tmp_r)/(tmp_r2*(tmp_r+r)) ) * rv_ij; + + jerk = tmp * (tmp_g * x - v); +} diff --git a/external.h b/external.h new file mode 100644 index 0000000..aedcab5 --- /dev/null +++ b/external.h @@ -0,0 +1,59 @@ +#pragma once +#include "double3.h" + +class External_gravity { +public: + void apply(const int n_act, const double3 x[], const double3 v[], double pot[], double3 a[], double3 adot[]) + { + for (int i=0; iset_coordinates(x[i], v[i]); + this->calc_gravity(); + pot[i] += potential; + a[i] += acceleration; + adot[i] += jerk; + } + } + virtual void calc_gravity() = 0; + bool is_active; +protected: + double potential; + double3 acceleration, jerk; + double3 x, v; + void set_coordinates(double3 x, double3 v) + { + this->x = x; + this->v = v; + } +}; + +class Plummer : public External_gravity { +public: + Plummer(double m, double b) : m(m), b(b) {is_active=(m>0);} + void calc_gravity(); +private: + double m, b; +}; + +class Miyamoto_Nagai : public External_gravity { +public: + Miyamoto_Nagai(double m, double a, double b) : m(m), a(a), b(b) {is_active=(m>0);} + void calc_gravity(); +private: + double m, a, b; +}; + +class Logarithmic_halo : public External_gravity { +public: + Logarithmic_halo(double v_halo, double r_halo) : v2_halo(v_halo*v_halo), r2_halo(r_halo*r_halo) {is_active=(r_halo>0);} + void calc_gravity(); +private: + double v2_halo, r2_halo; +}; + +class Dehnen : public External_gravity { +public: + Dehnen(double m, double r, double gamma) : m(m), r(r), gamma(gamma) {is_active=(m>0);} + void calc_gravity(); +private: + double m, r, gamma; +}; diff --git a/phigrape.conf b/phigrape.conf index acb3a82..419971f 100644 --- a/phigrape.conf +++ b/phigrape.conf @@ -49,6 +49,7 @@ input_file_name = data.con # Whether to output a warning on the screen when the minimum time step is encountered. [default: false] #dt_min_warning = false + #################### # EXTERNAL GRAVITY # #################### @@ -84,6 +85,10 @@ input_file_name = data.con #ext_log_halo_v = 240 # km/s #ext_log_halo_r = 1 # kpc +# This is a spherical Dehnen model. +#ext_dehnen_m = 1E11 # MSun +#ext_dehnen_r = 2 # kpc +#ext_dehnen_gamma = 0.5 ################################### @@ -107,6 +112,7 @@ input_file_name = data.con # Number of nearest neighbours to the SMBH (or SMBHs) to include in output. [default: 10] #live_smbh_neighbor_number = 10 + ################################## # BINARY SUPERMASSIVE BLACK HOLE # ################################## @@ -129,6 +135,7 @@ input_file_name = data.con # The speed of light in N-body units [default: 500] #pn_c = 477.12 + #################################### # Negative powers of two # #################################### diff --git a/phigrape.cpp b/phigrape.cpp index 91143f9..4ffe33f 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -56,16 +56,10 @@ Last redaction : 2019.04.16 12:55 #include "double3.h" #include "config.h" #include "io.h" +#include "external.h" Config *config; -#define NORM // Physical normalization - -//#define EXTPOT_BH // BH - usually NB units - - -//#define EXTPOT_GAL_DEH // Dehnen Galactic - usually physical units - #ifdef ETICS #include "grapite.h" // why do we need CEP as a compilaion flag... just have it always on when ETICS is on. IF there is no CEP, there should be a graceful skipping of those operations. @@ -131,35 +125,6 @@ Config *config; #define TWOPi 6.283185307179 #define sqrt_TWOPi 2.506628274631 -#ifdef NORM -//http://pdg.lbl.gov/2015/reviews/rpp2015-rev-astrophysical-constants.pdf - -#define G 6.67388E-11 // (m/s^2) * (m^2/kg) -#define Msol 1.988489E+30 // kg -#define Rsol 6.957E+08 // m -#define AU 149597870700.0 // m -#define pc 3.08567758149E+16 // m -#define Year 31556925.2 // s -#define c_feny 299792458.0 // m/s - -#define kpc (1.0E+03*pc) // m -#define km 1.0E+03 // km -> m -#define cm3 1.0E-06 // cm^3 -> m^3 -#define Myr (1.0E+06*Year) // s -#define Gyr (1.0E+09*Year) // s -#define R_gas 8.31447215 // J/(K*mol) -#define k_gas 1.380650424E-23 // J/K -#define N_A 6.022141510E+23 // 1/mol -#define mu 1.6605388628E-27 // kg -#define mp 1.67262163783E-27 // kg -#define me 9.1093821545E-31 // kg - -#define pc2 (pc*pc) -#define pc3 (pc*pc*pc) -#define kpc2 (kpc*kpc) -#define kpc3 (kpc*kpc*kpc) -#endif - /* 1KB = 1024 2KB = 2048 @@ -230,24 +195,8 @@ double eps_BH=0.0; /* external potential... */ - -#ifdef EXTPOT_GAL_DEH -double m_ext, r_ext, g_ext, - tmp_r2, tmp_r3, dum, dum2, dum3, dum_g, tmp_g; -#endif - -#ifdef EXTPOT_BH -double r2, rv_ij, - m_bh, b_bh, eps_bh; // NOTE different from eps_BH - // NOTE there are other m_bh and b_bh defined outside this ifdef block - // NOTE this is a mess. Looks like eps_bh is never used, and the m_bh from outside the block is never used. -#endif - -// double x_bh1[3], x_bh2[3], v_bh1[3], v_bh2[3]; double3 x_bh1, x_bh2, v_bh1, v_bh2; -// double pot_bh1, a_bh1[3], adot_bh1[3], -// pot_bh2, a_bh2[3], adot_bh2[3]; double pot_bh1, pot_bh2; double3 a_bh1, adot_bh1, a_bh2, adot_bh2; @@ -401,106 +350,6 @@ void write_bh_nb_data(double time_cur, int N, double m[], double3 x[], double3 v fclose(out); } -class External_gravity { -public: - void apply(const int n_act, const double3 x[], const double3 v[], double pot[], double3 a[], double3 adot[]) - { - for (int i=0; iset_coordinates(x[i], v[i]); - this->calc_gravity(); - pot[i] += potential; - a[i] += acceleration; - adot[i] += jerk; - } - } - virtual void calc_gravity() = 0; - bool is_active; -protected: - double potential; - double3 acceleration, jerk; - double3 x, v; - void set_coordinates(double3 x, double3 v) - { - this->x = x; - this->v = v; - } -}; - -class Plummer : public External_gravity { -public: - Plummer(double m, double b) : m(m), b(b) {is_active=(m>0);} -private: - void calc_gravity() - { - double r2 = SQR(b); - r2 += x.norm2(); - double r = sqrt(r2); - double rv_ij = v*x; - double tmp = m / r; - potential = -tmp; - tmp /= r2; - acceleration = - tmp * x; - jerk = - tmp * (v - 3*rv_ij * x/r2); - } - double m, b; -}; - -class Miyamoto_Nagai : public External_gravity { -public: - Miyamoto_Nagai(double m, double a, double b) : m(m), a(a), b(b) {is_active=(m>0);} -private: - void calc_gravity() - { - double x_ij=x[0], y_ij=x[1], z_ij=x[2]; - double vx_ij=v[0], vy_ij=v[1], vz_ij=v[2]; - auto z2_tmp = z_ij*z_ij + SQR(b); - auto z_tmp = sqrt(z2_tmp); - auto r2_tmp = x_ij*x_ij + y_ij*y_ij + SQR(z_tmp + a); - auto r_tmp = sqrt(r2_tmp); - potential = - m / r_tmp; - auto tmp = m / (r2_tmp*r_tmp); - acceleration[0] = - tmp * x_ij; - acceleration[1] = - tmp * y_ij; - acceleration[2] = - tmp * z_ij * (z_tmp + a)/z_tmp; - tmp = m / (z_tmp*r2_tmp*r2_tmp*r_tmp); - jerk[0] = tmp * (- vx_ij*z_tmp*r2_tmp - + 3.0*x_ij*vx_ij*x_ij*z_tmp - + 3.0*x_ij*vy_ij*y_ij*z_tmp - + 3.0*x_ij*vz_ij*z_ij*SQR(z_tmp + a)); - jerk[1] = tmp * (- vy_ij*z_tmp*r2_tmp - + 3.0*y_ij*vx_ij*x_ij*z_tmp - + 3.0*y_ij*vy_ij*y_ij*z_tmp - + 3.0*y_ij*vz_ij*z_ij*SQR(z_tmp + a)); - jerk[2] = tmp * (- vz_ij*(z_tmp + a)*(x_ij*x_ij*(z2_tmp*z_tmp + a*SQR(b)) + - y_ij*y_ij*(z2_tmp*z_tmp + a*SQR(b)) - - (2.0*a*(SQR(z_ij) - SQR(b))*z_tmp + - 2.0*SQR(z_ij*z_ij) + - SQR(b)*SQR(z_ij) - - SQR(b)*(SQR(a) + SQR(b)))) - + 3.0*vx_ij*x_ij*z_ij*z2_tmp*(z_tmp + a) - + 3.0*vy_ij*y_ij*z_ij*z2_tmp*(z_tmp + a)) / z2_tmp; - } - double m, a, b; -}; - -class Logarithmic_halo : public External_gravity { -public: - Logarithmic_halo(double v_halo, double r_halo) : v2_halo(v_halo*v_halo), r2_halo(r_halo*r_halo) {is_active=(r_halo>0);} -private: - void calc_gravity() - { - auto r2 = x.norm2(); - auto rv_ij = 2.0*(v*x); - auto r2_r2_halo = (r2 + r2_halo); - potential = - 0.5*v2_halo * log(1.0 + r2/r2_halo); - auto tmp = v2_halo/r2_r2_halo; - acceleration = - tmp * x; - tmp /= (r2 + r2_halo); - jerk = tmp * (rv_ij * x - r2_r2_halo * v); - } - double v2_halo, r2_halo; -}; - void calc_self_grav(double t, double eps2, double &g6_calls, int n_loc, int n_act, int ind_act[], double3 x_act_new[], double3 v_act_new[], @@ -555,90 +404,10 @@ int ni = n_act; // TODO redundant? #ifdef TIMING get_CPU_time(&CPU_tmp_real0, &CPU_tmp_user0, &CPU_tmp_syst0); -#endif - -#ifdef EXTPOT_GAL_DEH - -for (i=0; iext_m_disk*normalization_mass, config->ext_a_disk*normalization_length, config->ext_b_disk*normalization_length); Plummer ext_halo_plummer(config->ext_m_halo_plummer*normalization_mass, config->ext_b_halo_plummer*normalization_length); Logarithmic_halo ext_log_halo(config->ext_log_halo_v*normalization_velocity, config->ext_log_halo_r*normalization_length); + Dehnen ext_dehnen(config->ext_dehnen_m*normalization_mass, config->ext_dehnen_r*normalization_length, config->ext_dehnen_gamma); std::vector external_gravity_components; external_gravity_components.push_back(&ext_bulge); external_gravity_components.push_back(&ext_disk); external_gravity_components.push_back(&ext_halo_plummer); external_gravity_components.push_back(&ext_log_halo); + external_gravity_components.push_back(&ext_dehnen); if (ext_bulge.is_active) printf("m_bulge = %.4E b_bulge = %.4E\n", config->ext_m_bulge*normalization_mass, config->ext_b_bulge*normalization_length); if (ext_disk.is_active) printf("m_disk = %.4E a_disk = %.4E b_disk = %.4E\n", config->ext_m_disk*normalization_mass, config->ext_a_disk*normalization_length, config->ext_b_disk*normalization_length); if (ext_halo_plummer.is_active) printf("m_halo = %.4E b_halo = %.4E\n", config->ext_m_halo_plummer*normalization_mass, config->ext_b_halo_plummer*normalization_length); if (ext_log_halo.is_active) printf("v_halo = %.6E r_halo = %.6E \n", config->ext_log_halo_v*normalization_velocity, config->ext_log_halo_r*normalization_length); + if (ext_dehnen.is_active) printf("m_ext = %.6E r_ext = %.6E \t g_ext = %.3E \n", config->ext_dehnen_m*normalization_mass, config->ext_dehnen_r*normalization_length, config->ext_dehnen_gamma); printf("\n"); fflush(stdout); From ea94dbb62678ee94cf85a9a3dfe2310e695528b2 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Thu, 2 Apr 2020 21:49:52 -0400 Subject: [PATCH 33/65] Moved the active search outside of the main loop --- phigrape.cpp | 153 +++++++++++++++++++++++++++------------------------ 1 file changed, 81 insertions(+), 72 deletions(-) diff --git a/phigrape.cpp b/phigrape.cpp index 4ffe33f..0e61467 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -529,6 +529,60 @@ void energy_contr(const double time_cur, const double timesteps, const double n_ E_tot_corr_sd_0 = 0; } +class Active_search { + // TODO you can add pointers to t and dt at the constructor, no point giving them at get_minimum_time but without the size. +public: + Active_search(const int myRank, const int n_proc, const int n_loc, const int N) + : myRank(myRank), n_proc(n_proc), n_loc(n_loc), N(N) + { + ind_act_loc = new int[n_loc]; + } + ~Active_search() { delete[] ind_act_loc; }; + double get_minimum_time(const double t[], const double dt[]) + { + double min_t_loc, min_t; +#ifdef ACT_DEF_GRAPITE + min_t_loc = grapite_get_minimum_time(); +#else + min_t_loc = t[myRank*n_loc]+dt[myRank*n_loc]; + for (int j=myRank*n_loc+1; j<(myRank+1)*n_loc; j++) { + double tmp = t[j] + dt[j]; + if (tmp < min_t_loc) min_t_loc = tmp; + } +#endif + /* Reduce the "global" min_t from min_t_loc "local" on all processors) */ + MPI_Allreduce(&min_t_loc, &min_t, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD); + return min_t; + } + void get_active_indices(const double min_t, const double t[], const double dt[], int ind_act[], int *n_act) + { +#ifdef ACT_DEF_GRAPITE + int n_act_loc; + grapite_active_search(min_t, ind_act_loc, &n_act_loc); + if (myRank > 0) + for (int i=0; i 0) - for (int i=0; i Date: Fri, 3 Apr 2020 21:40:11 -0400 Subject: [PATCH 34/65] Started moving toward dynamical allocation; removed the _loc variables which were only used in the zeroth step and were pretty unnecessary anyway --- config.cpp | 2 + phigrape.cpp | 175 +++++++++++++++++---------------------------------- 2 files changed, 59 insertions(+), 118 deletions(-) diff --git a/config.cpp b/config.cpp index 28ac76f..e9b001d 100644 --- a/config.cpp +++ b/config.cpp @@ -5,6 +5,8 @@ #include #include +// Would be a bit more elegant to do the whole thing with std::variant. + using Dictionary = std::unordered_map; static constexpr double nix = -std::numeric_limits::max(); // avoid nans diff --git a/phigrape.cpp b/phigrape.cpp index 0e61467..681089e 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -77,25 +77,6 @@ Config *config; #define DTMAXPOWER -3.0 #define DTMINPOWER -36.0 -/* --3.0 0.125 --4.0 0.0625 --5.0 0.03125 --7.0 ~1e-2 --10.0 ~1e-3 -............. --20.0 ~1e-6 --23.0 ~1e-7 --26.0 ~1e-8 --30.0 ~1e-9 -*/ - -//#define ACT_DEF_LL - -#if defined(ACT_DEF_LL) && defined(ACT_DEF_GRAPITE) -#error "Contradicting preprocessor flags!" -#endif - #include #include #include @@ -114,46 +95,19 @@ Config *config; #include /* Some "good" functions and constants... */ -#define SIG(x) (((x)<0) ? (-1):(1) ) -#define ABS(x) (((x)<0) ? (-x):(x) ) -#define MAX(a,b) (((a)>(b)) ? (a):(b) ) +// TODO replace with inline functions #define MIN(a,b) (((a)<(b)) ? (a):(b) ) #define SQR(x) ((x)*(x) ) -#define POW3(x) ((x)*SQR(x) ) -#define Pi 3.14159265358979323846 -#define TWOPi 6.283185307179 -#define sqrt_TWOPi 2.506628274631 - -/* - 1KB = 1024 - 2KB = 2048 - 4KB = 4096 - 8KB = 8192 -16KB = 16384 -32KB = 32768 -64KB = 65536 -128KB = 131072 -256KB = 262144 -512KB = 524288 -1024KB = 1048576 -> 1MB -*/ #define KB 1024 #define MB (KB*KB) #define N_MAX (6*MB) -#define N_MAX_loc (2*MB) - - - double L[3]; // needed in pn_bh_spin.c // Needed for things related to BHs #include "debug.h" -// int ind_sort[N_MAX]; -// double var_sort[N_MAX]; - double CPU_time_real0, CPU_time_user0, CPU_time_syst0; double CPU_time_real, CPU_time_user, CPU_time_syst; @@ -185,11 +139,6 @@ double3 x_i[G6_NPIPE], v_i[G6_NPIPE], int new_tunit=51, new_xunit=51; double ti=0.0; -double3 a2by18, a1by6, aby2; - -/* normalization... */ - -double m_norm, r_norm, v_norm, t_norm; double eps_BH=0.0; @@ -200,14 +149,10 @@ double3 x_bh1, x_bh2, v_bh1, v_bh2; double pot_bh1, pot_bh2; double3 a_bh1, adot_bh1, a_bh2, adot_bh2; - -//double eps_BH = 0.0; - #include "n_bh.c" double3 a_pn1[7], adot_pn1[7], a_pn2[7], adot_pn2[7]; - #include "pn_bh_spin.c" #ifdef ETICS @@ -318,6 +263,7 @@ void write_bh_nb_data(double time_cur, int N, double m[], double3 x[], double3 v int nb = config->live_smbh_neighbor_number; int ind_sort[N_MAX]; double var_sort[N_MAX]; + //TODO you don't want and probably don't need to allocate these here. Maybe just need size nb, or maybe use as private variables. auto out = fopen("bh_neighbors.dat", "a"); @@ -583,6 +529,39 @@ private: int *ind_act_loc; }; +class Source_particle_list { +public: + Source_particle_list(int N) + : N(N) + { + ind = new int[N]; + m = new double[N]; + x = new double3[N]; + v = new double3[N]; + pot = new double[N]; + a = new double3[N]; + adot = new double3[N]; + t = new double[N]; + dt = new double[N]; + } + ~Source_particle_list() + { + delete[] ind; + delete[] m; + delete[] x; + delete[] v; + delete[] pot; + delete[] a; + delete[] adot; + delete[] t; + delete[] dt; + } + int N; + int *ind; + double3 *x, *v, *a, *adot; + double *m, *t, *dt, *pot; +}; + int main(int argc, char *argv[]) { int name_proc, n_proc=1, myRank=0, rootRank=0, cur_rank, @@ -612,16 +591,21 @@ int main(int argc, char *argv[]) /* global variables */ - int N, ind[N_MAX]; - double m[N_MAX], pot[N_MAX], t[N_MAX], dt[N_MAX]; - double3 x[N_MAX], v[N_MAX], a[N_MAX], adot[N_MAX]; + Source_particle_list source_particle_list(N_MAX); + + int N; + int *ind = source_particle_list.ind; + double *m = source_particle_list.m; + double3 *x = source_particle_list.x; + double3 *v = source_particle_list.v; + double *pot = source_particle_list.pot; + double3 *a = source_particle_list.a; + double3 *adot = source_particle_list.adot; + double *t = source_particle_list.t; + double *dt = source_particle_list.dt; /* local variables */ - - int n_loc, ind_loc[N_MAX_loc]; - double m_loc[N_MAX_loc], pot_loc[N_MAX_loc], t_loc[N_MAX_loc], dt_loc[N_MAX_loc]; - double3 x_loc[N_MAX_loc], v_loc[N_MAX_loc], - a_loc[N_MAX_loc], adot_loc[N_MAX_loc]; + int n_loc; /* data for active particles */ @@ -655,7 +639,8 @@ int main(int argc, char *argv[]) double s_bh1[3] = {0.0, 0.0, 1.0}; double s_bh2[3] = {0.0, 0.0, 1.0}; - + + double3 zeros = {0, 0, 0}; // Dummy; can't really be const because of the GRAPE interface. /* INIT the rand() !!! */ srand(19640916); /* it is just my birthday :-) */ @@ -848,14 +833,6 @@ int main(int argc, char *argv[]) /* Wait to all processors to finish his works... */ MPI_Barrier(MPI_COMM_WORLD); - /* Scatter the "local" vectors from "global" */ - MPI_Scatter(ind, n_loc, MPI_INT, ind_loc, n_loc, MPI_INT, rootRank, MPI_COMM_WORLD); - MPI_Scatter(m, n_loc, MPI_DOUBLE, m_loc, n_loc, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Scatter(t, n_loc, MPI_DOUBLE, t_loc, n_loc, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Scatter(dt, n_loc, MPI_DOUBLE, dt_loc, n_loc, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Scatter(x, 3*n_loc, MPI_DOUBLE, x_loc, 3*n_loc, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Scatter(v, 3*n_loc, MPI_DOUBLE, v_loc, 3*n_loc, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - /* Wait to all processors to finish his works... */ MPI_Barrier(MPI_COMM_WORLD); @@ -885,17 +862,11 @@ int main(int argc, char *argv[]) grapite_set_t_exp(t_exp); #endif - /* initial load the particles to the local GRAPE's */ - - nj=n_loc; - /* load the nj particles to the G6 */ - for (int j=0; j Date: Sat, 4 Apr 2020 23:03:06 -0400 Subject: [PATCH 35/65] Moved some tasks from the correction+timestep adjustment loop outside --- phigrape.cpp | 240 ++++++++++++++++++++++++++++----------------------- 1 file changed, 133 insertions(+), 107 deletions(-) diff --git a/phigrape.cpp b/phigrape.cpp index 681089e..23e7bf4 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -562,6 +562,110 @@ public: double *m, *t, *dt, *pot; }; +inline void calc_high_derivatives(const double dt_tmp, const double3 a_act, const double3 a_act_new, const double3 adot_act, const double3 adot_act_new, double3 *a2, double3 *a3) +{ + double dtinv = 1.0/dt_tmp; + double dt2inv = dtinv*dtinv; + double dt3inv = dt2inv*dtinv; + + double3 a0mia1 = a_act-a_act_new; + double3 ad04plad12 = 4.0*adot_act + 2.0*adot_act_new; + double3 ad0plad1 = adot_act + adot_act_new; + + *a2 = -6.0*a0mia1*dt2inv - ad04plad12*dtinv; + *a3 = 12.0*a0mia1*dt3inv + 6.0*ad0plad1*dt2inv; +} + +inline void corrector(const double dt_tmp, const double3 a2, const double3 a3, double3* x_act_new, double3* v_act_new) +{ + double dt3over6 = dt_tmp*dt_tmp*dt_tmp/6.0; + double dt4over24 = dt3over6*dt_tmp/4.0; + double dt5over120 = dt4over24*dt_tmp/5.0; + + *x_act_new += dt4over24*a2 + dt5over120*a3; + *v_act_new += dt3over6*a2 + dt4over24*a3; +} + +inline double aarseth_step(const double eta, const double dt_tmp, const double3 a_act_new, const double3 adot_act_new, const double3 a2, const double3 a3) +{ + double a1abs = a_act_new.norm(); + double adot1abs = adot_act_new.norm(); + double3 a2dot1 = a2 + dt_tmp*a3; + double a2dot1abs = a2dot1.norm(); + double a3dot1abs = a3.norm(); + + return sqrt(eta*(a1abs*a2dot1abs+adot1abs*adot1abs)/(adot1abs*a3dot1abs+a2dot1abs*a2dot1abs)); +} + +void binary_smbh_influence_sphere_output(int i_bh1, int i_bh2, int ind_act[], double m_act[], double3 x_act[], double3 v_act[], double pot_act[], double dt_act[], int n_act, double timesteps, double time_cur, double factor, int inf_event[]) +{ + //TODO !!IMPORTANT!! only open the file IF THERE IS ANYTHING TO WRITE!!! + //TODO inf_event to be static or something? + auto out = fopen("bbh_inf.dat", "a"); + + double m_bh1 = m_act[i_bh1]; + double m_bh2 = m_act[i_bh2]; + + double3 x_bh1 = x_act[i_bh1]; + double3 x_bh2 = x_act[i_bh2]; + + double3 v_bh1 = v_act[i_bh1]; + double3 v_bh2 = v_act[i_bh2]; + + double3 x_bbhc = (m_bh1*x_bh1 + m_bh2*x_bh2)/(m_bh1 + m_bh2); + double3 v_bbhc = (m_bh1*v_bh1 + m_bh2*v_bh2)/(m_bh1 + m_bh2); + + double DR2 = SQR(x_bh1[0] - x_bh2[0]) + SQR(x_bh1[1] - x_bh2[1]) + SQR(x_bh1[2] - x_bh2[2]); + double DV2 = SQR(v_bh1[0] - v_bh2[0]) + SQR(v_bh1[1] - v_bh2[1]) + SQR(v_bh1[2] - v_bh2[2]); + + double EB = -(m_bh1 + m_bh2) / sqrt(DR2) + 0.5 * DV2; + + double SEMI_a = -0.5 * (m_bh1 + m_bh2)/EB; + double SEMI_a2 = SQR(SEMI_a); + + for (int i=2; ilive_smbh_count > 0) && (ind_act[i] < config->live_smbh_count)) eta_curr = eta_bh; + else eta_curr = eta; - x_act_new[i] += dt4over24*a2 + dt5over120*a3; - v_act_new[i] += dt3over6*a2 + dt4over24*a3; - - a1abs = sqrt(a_act_new[i][0]*a_act_new[i][0]+a_act_new[i][1]*a_act_new[i][1]+a_act_new[i][2]*a_act_new[i][2]); - adot1abs = sqrt(adot_act_new[i][0]*adot_act_new[i][0]+adot_act_new[i][1]*adot_act_new[i][1]+adot_act_new[i][2]*adot_act_new[i][2]); - - a2dot1 = a2 + dt_tmp*a3; - - a2dot1abs = a2dot1.norm(); - a3dot1abs = a3.norm(); - - if ((config->live_smbh_count > 0) && (ind_act[i] < config->live_smbh_count)) - dt_new = sqrt(eta_bh*(a1abs*a2dot1abs+adot1abs*adot1abs)/(adot1abs*a3dot1abs+a2dot1abs*a2dot1abs)); - else - dt_new = sqrt(eta*(a1abs*a2dot1abs+adot1abs*adot1abs)/(adot1abs*a3dot1abs+a2dot1abs*a2dot1abs)); + double dt_new = aarseth_step(eta_curr, dt_tmp, a_act_new[i], adot_act_new[i], a2, a3); + //TODO the below should be moved to a function if (dt_new < dt_min) dt_tmp = dt_min; if ((dt_new < dt_tmp) && (dt_new > dt_min)) { power = log(dt_new)/log(2.0) - 1; - - dt_tmp = pow(2.0, (double)power); + dt_tmp = pow(2.0, (double)power); // TODO why is this casting needed here? } - if ((dt_new > 2.0*dt_tmp) && (fmod(min_t, 2.0*dt_tmp) == 0.0) && (2.0*dt_tmp <= dt_max)) { - dt_tmp *= 2.0; + if ((dt_new > 2*dt_tmp) && (fmod(min_t, 2*dt_tmp) == 0) && (2*dt_tmp <= dt_max)) { + dt_tmp *= 2; } + if (config->dt_min_warning && (myRank == 0)) { + if (dt_act[i] == dt_min) { + printf("!!! Warning1: dt_act = dt_min = %.6E \t ind_act = %07d \n", dt[i], ind_act[i]); + fflush(stdout); + } + } + + /* BEGIN copy of everything */ + dt_act[i] = dt_tmp; - t_act[i] = min_t; pot_act[i] = pot_act_new[i]; @@ -1404,13 +1498,10 @@ int main(int argc, char *argv[]) v_act[i] = v_act_new[i]; a_act[i] = a_act_new[i]; adot_act[i] = adot_act_new[i]; + + /* END copy of everything */ + - if (config->dt_min_warning && (myRank == 0)) { - if (dt_act[i] == dt_min) { - printf("!!! Warning1: dt_act = dt_min = %.6E \t ind_act = %07d \n", dt[i], ind_act[i]); - fflush(stdout); - } - } } /* i */ @@ -1422,74 +1513,9 @@ int main(int argc, char *argv[]) if (config->live_smbh_count==2) dt_act[i_bh2] = min_dt; } - if (config->binary_smbh_influence_sphere_output) { - if (myRank == rootRank) { - - out = fopen("bbh_inf.dat", "a"); - - m_bh1 = m_act[i_bh1]; - m_bh2 = m_act[i_bh2]; - - x_bh1 = x_act[i_bh1]; - x_bh2 = x_act[i_bh2]; - - v_bh1 = v_act[i_bh1]; - v_bh2 = v_act[i_bh2]; - - x_bbhc = (m_bh1*x_bh1 + m_bh2*x_bh2)/(m_bh1 + m_bh2); - v_bbhc = (m_bh1*v_bh1 + m_bh2*v_bh2)/(m_bh1 + m_bh2); - - DR2 = SQR(x_bh1[0] - x_bh2[0]) + SQR(x_bh1[1] - x_bh2[1]) + SQR(x_bh1[2] - x_bh2[2]); - DV2 = SQR(v_bh1[0] - v_bh2[0]) + SQR(v_bh1[1] - v_bh2[1]) + SQR(v_bh1[2] - v_bh2[2]); - - EB = -(m_bh1 + m_bh2) / sqrt(DR2) + 0.5 * DV2; - - SEMI_a = -0.5 * (m_bh1 + m_bh2)/EB; - SEMI_a2 = SQR(SEMI_a); - - for (int i=2; ibinary_smbh_influence_radius_factor)) { - - if (inf_event[iii] == 0) { - - fprintf(out,"INF1 %.6E %.16E %07d %07d %.6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E \n", - timesteps, time_cur, i, ind_act[i], - sqrt(DR2), x_bbhc[0], x_bbhc[1], x_bbhc[2], v_bbhc[0], v_bbhc[1], v_bbhc[2], - m_bh1, x_bh1[0], x_bh1[1], x_bh1[2], v_bh1[0], v_bh1[1], v_bh1[2], pot_act[0], - m_bh2, x_bh2[0], x_bh2[1], x_bh2[2], v_bh2[0], v_bh2[1], v_bh2[2], pot_act[1], - sqrt(tmp_r2), - m_act[i], x_act[i][0], x_act[i][1], x_act[i][2], v_act[i][0], v_act[i][1], v_act[i][2], pot_act[i], - dt_act[i]); - - inf_event[iii] = 1; - } - - } else { - if (inf_event[iii] == 1) { - fprintf(out,"INF2 %.6E %.16E %07d %07d %.6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E \n", - timesteps, time_cur, i, ind_act[i], - sqrt(DR2), x_bbhc[0], x_bbhc[1], x_bbhc[2], v_bbhc[0], v_bbhc[1], v_bbhc[2], - m_bh1, x_bh1[0], x_bh1[1], x_bh1[2], v_bh1[0], v_bh1[1], v_bh1[2], pot_act[0], - m_bh2, x_bh2[0], x_bh2[1], x_bh2[2], v_bh2[0], v_bh2[1], v_bh2[2], pot_act[1], - sqrt(tmp_r2), - m_act[i], x_act[i][0], x_act[i][1], x_act[i][2], v_act[i][0], v_act[i][1], v_act[i][2], pot_act[i], - dt_act[i]); - } - - inf_event[iii] = 0; - - } /* if (tmp_r2 < DR2*R_INF2) */ - - } /* i */ - - fclose(out); - - } /* if (myRank == rootRank) */ + if (config->binary_smbh_influence_sphere_output && (myRank == rootRank)) { + //TODO clean up this mass. We don't want to have all these _act arrays; they are only needed for this lame function. + binary_smbh_influence_sphere_output(i_bh1, i_bh2, ind_act, m_act, x_act, v_act, pot_act, dt_act, n_act, timesteps, time_cur, config->binary_smbh_influence_radius_factor, inf_event); } /* Return back the new coordinates + etc... of active part. to the global data... */ From 56abe820c37b67ee5aa6c7fc9268a1f17aff9905 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Sun, 5 Apr 2020 11:17:21 -0400 Subject: [PATCH 36/65] Number of devices can be overriden in config file --- config.cpp | 5 ++--- config.h | 7 ++++++- phigrape.conf | 9 +++++++-- phigrape.cpp | 18 +++++++++--------- 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/config.cpp b/config.cpp index e9b001d..cce97cd 100644 --- a/config.cpp +++ b/config.cpp @@ -158,16 +158,15 @@ Config::Config(std::string file_name) dt_contr = get_parameter(dictionary, "dt_contr"); dt_bh = get_parameter(dictionary, "dt_bh", dt_contr); eta = get_parameter(dictionary, "eta"); - input_file_name = get_parameter(dictionary, "input_file_name", "data.con"); + devices_per_node = get_parameter(dictionary, "devices_per_node", 0); + dt_min_warning = get_parameter(dictionary, "dt_min_warning", false); output_hdf5 = get_parameter(dictionary, "output_hdf5", false); output_hdf5_double_precision = get_parameter(dictionary, "output_hdf5_double_precision", true); output_ascii_precision = get_parameter(dictionary, "output_ascii_precision", 10); output_extra_mode = get_parameter(dictionary, "output_extra_mode", 10); - dt_min_warning = get_parameter(dictionary, "dt_min_warning", false); - live_smbh_count = get_parameter(dictionary, "live_smbh_count", 0); live_smbh_custom_eps = get_parameter(dictionary, "live_smbh_custom_eps", -1); live_smbh_output = get_parameter(dictionary, "live_smbh_output", false); diff --git a/config.h b/config.h index e9d537a..f331315 100644 --- a/config.h +++ b/config.h @@ -14,21 +14,26 @@ public: double dt_bh; double eta; std::string input_file_name; + int devices_per_node; + bool dt_min_warning; + bool output_hdf5; bool output_hdf5_double_precision; int output_ascii_precision; int output_extra_mode; - bool dt_min_warning; + int live_smbh_count; double live_smbh_custom_eps; bool live_smbh_output; bool live_smbh_neighbor_output; int live_smbh_neighbor_number; + bool binary_smbh_pn; bool binary_smbh_influence_sphere_output; double binary_smbh_influence_radius_factor; std::vector pn_usage; double pn_c; + bool ext_units_physical; double unit_mass; double unit_length; diff --git a/phigrape.conf b/phigrape.conf index 419971f..707b597 100644 --- a/phigrape.conf +++ b/phigrape.conf @@ -21,7 +21,12 @@ dt_bh = 0.125 eta = 0.01 # Name of the input file; use "data.con" in most cases [default: data.con] -input_file_name = data.con +#input_file_name = data.con + + +# Number of devices (GRAPEs or GPUs per node) [default: 0] +# By default, each MPI process will attempt to bind to one device. To change this behaviour, set the value to the number of available devices in the system. For example, if from some reason you want to run multiple MPI processes on a machine with a single device, set the value to 1 and use the mpirun utility (or whatever is used in your job scheduler) to launch as many processes as you like. +#devices_per_node = 1 ########## @@ -123,7 +128,7 @@ input_file_name = data.con #binary_smbh_influence_sphere_output = true # The influence sphere is centred at the binary SMBH's centre of mass, and its radius is the semi-major axis of the binary times the factor below. [default: 10] -#binary_smbh_influence_radius_factor = 10 +#binary_smbh_influence_radius_factor = 20 # Add post Newtonian terms to SMBH-SMBH gravity. [default: false] #binary_smbh_pn = true diff --git a/phigrape.cpp b/phigrape.cpp index 23e7bf4..090bcfa 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -942,15 +942,15 @@ int main(int argc, char *argv[]) /* init the local GRAPE's */ -#ifdef MPI_OVERRIDE - numGPU = 1; // TODO get this from config file - clusterid = myRank % numGPU; -#else - MPI_Comm shmcomm; - MPI_Comm_split_type(MPI_COMM_WORLD, MPI_COMM_TYPE_SHARED, 0, MPI_INFO_NULL, &shmcomm); - MPI_Comm_size(shmcomm, &numGPU); - MPI_Comm_rank(shmcomm, &clusterid); -#endif + if (config->devices_per_node==0) { + MPI_Comm shmcomm; + MPI_Comm_split_type(MPI_COMM_WORLD, MPI_COMM_TYPE_SHARED, 0, MPI_INFO_NULL, &shmcomm); + MPI_Comm_size(shmcomm, &numGPU); + MPI_Comm_rank(shmcomm, &clusterid); + } else { + numGPU = config->devices_per_node; + clusterid = myRank % numGPU; + } printf("Rank of the processor %03d : Number of GPUs %01d : Cluster ID %01d \n", myRank, numGPU, clusterid); fflush(stdout); From d9e3aea24397b827f53878a381eaa94184ab0fb4 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Sun, 5 Apr 2020 19:54:10 -0400 Subject: [PATCH 37/65] Moved SMBH de-softening to a function (still not pretty) and improved init script --- init.py | 49 +++++++++++++++++++++++++- phigrape.cpp | 98 ++++++++++++++++++++++++++++------------------------ 2 files changed, 100 insertions(+), 47 deletions(-) diff --git a/init.py b/init.py index e5aa76c..a12d55c 100644 --- a/init.py +++ b/init.py @@ -33,6 +33,38 @@ def gen_plum(N, seed=None, RMAX=10): i += 1 return particle_list +def kepler_to_cartesian(a, e, i, Omega, w, nu, G=1.0, M=1.0): + def to_arrays(*args): + result = [] + for arg in args: result.append(np.atleast_1d(arg)) + return result + a, e, i, Omega, w, nu = to_arrays(a, e, i, Omega, w, nu) + P = [np.cos(w)*np.cos(Omega) - np.sin(w)*np.cos(i)*np.sin(Omega), + np.cos(w)*np.sin(Omega) + np.sin(w)*np.cos(i)*np.cos(Omega), + np.sin(w)*np.sin(i)] + Q = [-np.sin(w)*np.cos(Omega) - np.cos(w)*np.cos(i)*np.sin(Omega), + -np.sin(w)*np.sin(Omega) + np.cos(w)*np.cos(i)*np.cos(Omega), + np.sin(i)*np.cos(w)] + cosnu = np.cos(nu) + cosE = (e+cosnu)/(1+e*cosnu) + E = np.arccos(cosE) + E[nu > np.pi] = 2*np.pi - E[nu > np.pi] + X = a*((np.cos(E)-e)*P + np.sqrt(1-e**2)*np.sin(E)*Q) + V = (np.sqrt(G*M/a)/(1-e*np.cos(E)))*(-np.sin(E)*P + np.sqrt(1-e**2)*np.cos(E)*Q) + if X.shape[1]==1: + X=X[:,0] + V=V[:,0] + return X.T, V.T + +def generate_binary(a, e, i, Omega, w, nu, m1, m2): + X, V = kepler_to_cartesian(a, e, i, Omega, w, nu, M=m1+m2) + q = np.double(m2)/np.double(m1) + X1 = -q/(q+1)*X + V1 = -q/(q+1)*V + X2 = 1/(q+1)*X + V2 = 1/(q+1)*V + return X1, V1, X2, V2 + def write_phi_grape_config(**kargs): if 'file_name' in kargs: file_name = kargs['file_name'] else: file_name = 'phi-GRAPE.cfg' @@ -86,6 +118,7 @@ if __name__=='__main__': parser.add_argument('--dt_bh', type=np.double, default=.125, help='interval for BH output (bh.dat & bh_nb.dat)') parser.add_argument('--eta', type=np.double, default=.01, help='parameter for timestep determination (0.02 or 0.01)') parser.add_argument('--frac', type=np.double, default=0, help='fraction of collisional particles (by angular momentum)') + parser.add_argument('--bsmbh', type=bool, default=0, help='generate a binary supermassive black hole (parameters hardcoded in the script)') args = parser.parse_args() try: @@ -97,9 +130,23 @@ if __name__=='__main__': write_phi_grape_config(**vars(args)) particle_list = gen_plum(N, seed=args.seed) + m = np.ones(N)/N - write_particles(particle_list) + if args.bsmbh: + m1, m2 = 0.075, 0.025 + a, e, i, Omega, w, nu = 0.001, 0.5, 0, 0, 0, 0 + X1, V1, X2, V2 = generate_binary(a, e, i, Omega, w, nu, m1, m2) + m[:2] = m1, m2 + m[2:] = 1/(N-2) + particle_list[0,:3] = X1 + particle_list[0,3:] = V1 + particle_list[1,:3] = X2 + particle_list[1,3:] = V2 + + write_particles(particle_list, m=m) mask = gen_mask(particle_list, args.frac) + if args.bsmbh: + mask[:2] = 3 write_mask(mask) diff --git a/phigrape.cpp b/phigrape.cpp index 090bcfa..dfe3e13 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -666,6 +666,54 @@ void binary_smbh_influence_sphere_output(int i_bh1, int i_bh2, int ind_act[], do } +void adjust_bsmbh_softening(const double eps, const double eps_bh, const int i_bh1, const int i_bh2, const double m_act[], const double3 x_act_new[], const double3 v_act_new[], double pot_act_new[], double3 a_act_new[], double3 adot_act_new[]) +{ + double m_bh1 = m_act[i_bh1]; + double m_bh2 = m_act[i_bh2]; + + double3 x_bh1 = x_act_new[i_bh1]; + double3 v_bh1 = v_act_new[i_bh1]; + + double3 x_bh2 = x_act_new[i_bh2]; + double3 v_bh2 = v_act_new[i_bh2]; + + // calculate and "minus" the BH <-> BH softened pot, acc & jerk + + double tmp_i; + tmp_i = calc_force_n_BH(m_bh1, x_bh1, v_bh1, + m_bh2, x_bh2, v_bh2, + eps, + &pot_bh1, a_bh1, adot_bh1, + &pot_bh2, a_bh2, adot_bh2); + + pot_act_new[i_bh1] -= pot_bh1; + pot_act_new[i_bh2] -= pot_bh2; + + a_act_new[i_bh1] -= a_bh1; + a_act_new[i_bh2] -= a_bh2; + + adot_act_new[i_bh1] -= adot_bh1; + adot_act_new[i_bh2] -= adot_bh2; + + // calculate and "plus" the new BH <-> BH unsoftened pot, acc, jerk + + tmp_i = calc_force_n_BH(m_bh1, x_bh1, v_bh1, + m_bh2, x_bh2, v_bh2, + eps_bh, + &pot_bh1, a_bh1, adot_bh1, + &pot_bh2, a_bh2, adot_bh2); + + pot_act_new[i_bh1] += pot_bh1; + pot_act_new[i_bh2] += pot_bh2; + + a_act_new[i_bh1] += a_bh1; + a_act_new[i_bh2] += a_bh2; + + adot_act_new[i_bh1] += adot_bh1; + adot_act_new[i_bh2] += adot_bh2; + +} + int main(int argc, char *argv[]) { int name_proc, n_proc=1, myRank=0, rootRank=0, cur_rank, @@ -1306,6 +1354,7 @@ int main(int argc, char *argv[]) #endif for (int i=0; ilive_smbh_count == 2) { if (config->live_smbh_custom_eps >= 0) { - m_bh1 = m_act[i_bh1]; - m_bh2 = m_act[i_bh2]; - - x_bh1 = x_act_new[i_bh1]; - v_bh1 = v_act_new[i_bh1]; - - x_bh2 = x_act_new[i_bh2]; - v_bh2 = v_act_new[i_bh2]; - - // calculate and "minus" the BH <-> BH softened pot, acc & jerk - - tmp_i = calc_force_n_BH(m_bh1, x_bh1, v_bh1, - m_bh2, x_bh2, v_bh2, - eps, - &pot_bh1, a_bh1, adot_bh1, - &pot_bh2, a_bh2, adot_bh2); - - pot_act_new[i_bh1] -= pot_bh1; - pot_act_new[i_bh2] -= pot_bh2; - - a_act_new[i_bh1] -= a_bh1; - a_act_new[i_bh2] -= a_bh2; - - adot_act_new[i_bh1] -= adot_bh1; - adot_act_new[i_bh2] -= adot_bh2; - - // calculate and "plus" the new BH <-> BH unsoftened pot, acc, jerk - - tmp_i = calc_force_n_BH(m_bh1, x_bh1, v_bh1, - m_bh2, x_bh2, v_bh2, - config->live_smbh_custom_eps, - &pot_bh1, a_bh1, adot_bh1, - &pot_bh2, a_bh2, adot_bh2); - - pot_act_new[i_bh1] += pot_bh1; - pot_act_new[i_bh2] += pot_bh2; - - a_act_new[i_bh1] += a_bh1; - a_act_new[i_bh2] += a_bh2; - - adot_act_new[i_bh1] += adot_bh1; - adot_act_new[i_bh2] += adot_bh2; + adjust_bsmbh_softening(eps, config->live_smbh_custom_eps, i_bh1, i_bh2, m_act, x_act_new, v_act_new, pot_act_new, a_act_new, adot_act_new); } if (config->binary_smbh_pn) { @@ -1498,11 +1506,9 @@ int main(int argc, char *argv[]) v_act[i] = v_act_new[i]; a_act[i] = a_act_new[i]; adot_act[i] = adot_act_new[i]; - + /* END copy of everything */ - - } /* i */ /* define the min. dt over all the act. part. and set it also for the BH... */ @@ -1515,7 +1521,7 @@ int main(int argc, char *argv[]) if (config->binary_smbh_influence_sphere_output && (myRank == rootRank)) { //TODO clean up this mass. We don't want to have all these _act arrays; they are only needed for this lame function. - binary_smbh_influence_sphere_output(i_bh1, i_bh2, ind_act, m_act, x_act, v_act, pot_act, dt_act, n_act, timesteps, time_cur, config->binary_smbh_influence_radius_factor, inf_event); + binary_smbh_influence_sphere_output(i_bh1, i_bh2, ind_act, m_act, x_act_new, v_act_new, pot_act_new, dt_act, n_act, timesteps, time_cur, config->binary_smbh_influence_radius_factor, inf_event); } /* Return back the new coordinates + etc... of active part. to the global data... */ From ebec3280f8e9f60407a8792fe8b9112073c3f80b Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Tue, 7 Apr 2020 22:40:54 -0400 Subject: [PATCH 38/65] Cleaned unused variables and fixed a bug with PN (also tested PN against old version) --- .gitignore | 2 ++ io.cpp | 2 +- n_bh.c | 4 +-- phigrape.cpp | 84 +++++++++++++++++++++++----------------------------- 4 files changed, 41 insertions(+), 51 deletions(-) diff --git a/.gitignore b/.gitignore index 9a8c7cc..737bf91 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,5 @@ grapite-dev-exec-threshold phigrape *.h5 +.* +.gitignore diff --git a/io.cpp b/io.cpp index a2c0d3d..e739e30 100644 --- a/io.cpp +++ b/io.cpp @@ -81,7 +81,7 @@ void h5_read(const std::string file_name, int *step_num, int *N, double *t, doub H5Gget_info(group_id, &object_info); // Iterate over objects and add the number of each "step" group into a vector std::vector step_num_arr; - for (int i=0; i &external_gravity_components, int n_act, double3 *x_act_new, double3 *v_act_new, double *pot_act_ext, double3 *a_act_new, double3* adot_act_new) { +#ifdef TIMING + get_CPU_time(&CPU_tmp_real0, &CPU_tmp_user0, &CPU_tmp_syst0); +#endif -/* Define the external potential for all active particles on all nodes */ - -int ni = n_act; // TODO redundant? + /* Define the external potential for all active particles on all nodes */ std::fill(pot_act_ext, pot_act_ext+n_act, 0.); @@ -348,15 +349,11 @@ int ni = n_act; // TODO redundant? component->apply(n_act, x_act_new, v_act_new, pot_act_ext, a_act_new, adot_act_new); } -#ifdef TIMING -get_CPU_time(&CPU_tmp_real0, &CPU_tmp_user0, &CPU_tmp_syst0); -#endif - /* For simple Plummer potential... */ #ifdef TIMING -get_CPU_time(&CPU_tmp_real, &CPU_tmp_user, &CPU_tmp_syst); -DT_EXT_GRAV += (CPU_tmp_user - CPU_tmp_user0); + get_CPU_time(&CPU_tmp_real, &CPU_tmp_user, &CPU_tmp_syst); + DT_EXT_GRAV += (CPU_tmp_user - CPU_tmp_user0); #endif } @@ -679,12 +676,11 @@ void adjust_bsmbh_softening(const double eps, const double eps_bh, const int i_b // calculate and "minus" the BH <-> BH softened pot, acc & jerk - double tmp_i; - tmp_i = calc_force_n_BH(m_bh1, x_bh1, v_bh1, - m_bh2, x_bh2, v_bh2, - eps, - &pot_bh1, a_bh1, adot_bh1, - &pot_bh2, a_bh2, adot_bh2); + calc_force_n_BH(m_bh1, x_bh1, v_bh1, + m_bh2, x_bh2, v_bh2, + eps, + &pot_bh1, a_bh1, adot_bh1, + &pot_bh2, a_bh2, adot_bh2); pot_act_new[i_bh1] -= pot_bh1; pot_act_new[i_bh2] -= pot_bh2; @@ -697,11 +693,11 @@ void adjust_bsmbh_softening(const double eps, const double eps_bh, const int i_b // calculate and "plus" the new BH <-> BH unsoftened pot, acc, jerk - tmp_i = calc_force_n_BH(m_bh1, x_bh1, v_bh1, - m_bh2, x_bh2, v_bh2, - eps_bh, - &pot_bh1, a_bh1, adot_bh1, - &pot_bh2, a_bh2, adot_bh2); + calc_force_n_BH(m_bh1, x_bh1, v_bh1, + m_bh2, x_bh2, v_bh2, + eps_bh, + &pot_bh1, a_bh1, adot_bh1, + &pot_bh2, a_bh2, adot_bh2); pot_act_new[i_bh1] += pot_bh1; pot_act_new[i_bh2] += pot_bh2; @@ -711,28 +707,24 @@ void adjust_bsmbh_softening(const double eps, const double eps_bh, const int i_b adot_act_new[i_bh1] += adot_bh1; adot_act_new[i_bh2] += adot_bh2; - } int main(int argc, char *argv[]) { int name_proc, n_proc=1, myRank=0, rootRank=0, cur_rank, - nj, diskstep=0, power, jjj, iii, + diskstep=0, power, jjj, iii, skip_con=0, tmp_i; double dt_disk, dt_contr, t_disk=0.0, t_contr=0.0, dt_bh, t_bh=0.0, dt_bh_tmp, - t_end, time_cur, dt_min, dt_max, min_t, min_t_loc, dt_new, + t_end, time_cur, dt_min, dt_max, min_t, min_t_loc, eta_s, eta, eta_bh, E_tot_0, E_tot_corr_0, E_tot_corr_sd_0, rcm_sum=0.0, vcm_sum=0.0, eps=0.0, eps2, a2_mod, adot2_mod, - dt_tmp, dt2half, dt3over6, dt4over24, dt5over120, - dtinv, dt2inv, dt3inv, - a1abs, adot1abs, a2dot1abs, a3dot1abs, - timesteps=0.0, n_act_sum=0.0, n_act_distr[N_MAX], g6_calls=0.0, g6_calls_sum=0.0, - tmp; + dt_tmp, dt2half, dt3over6, + timesteps=0.0, n_act_sum=0.0, n_act_distr[N_MAX], g6_calls=0.0, g6_calls_sum=0.0; double3 xcm, vcm, mom, xdc, vdc, @@ -785,9 +777,7 @@ int main(int argc, char *argv[]) double m_bh1, m_bh2; int inf_event[N_MAX]; - double DR2, tmp_r2; double3 x_bbhc, v_bbhc; - double DV2, EB, SEMI_a, SEMI_a2; double s_bh1[3] = {0.0, 0.0, 1.0}; double s_bh2[3] = {0.0, 0.0, 1.0}; @@ -823,7 +813,7 @@ int main(int argc, char *argv[]) if (is_hdf5(config->input_file_name)) { #ifndef HAS_HDF5 - fprintf(stderr, "ERROR: input file is in HDF5 format, but the code was compiled without HDF5 support\n") + fprintf(stderr, "ERROR: input file is in HDF5 format, but the code was compiled without HDF5 support\n"); return -1; #endif h5_read(config->input_file_name, &diskstep, &N, &time_cur, m, x, v); @@ -1097,11 +1087,11 @@ int main(int argc, char *argv[]) // calculate and "minus" the BH <-> BH _softened_ pot, acc & jerk - tmp_i = calc_force_n_BH(m_bh1, x_bh1, v_bh1, - m_bh2, x_bh2, v_bh2, - eps, - &pot_bh1, a_bh1, adot_bh1, - &pot_bh2, a_bh2, adot_bh2); + calc_force_n_BH(m_bh1, x_bh1, v_bh1, + m_bh2, x_bh2, v_bh2, + eps, + &pot_bh1, a_bh1, adot_bh1, + &pot_bh2, a_bh2, adot_bh2); pot[i_bh1] -= pot_bh1; pot[i_bh2] -= pot_bh2; @@ -1114,11 +1104,11 @@ int main(int argc, char *argv[]) // calculate and "plus" the new BH <-> BH _unsoftened_ pot, acc, jerk - tmp_i = calc_force_n_BH(m_bh1, x_bh1, v_bh1, - m_bh2, x_bh2, v_bh2, - config->live_smbh_custom_eps, - &pot_bh1, a_bh1, adot_bh1, - &pot_bh2, a_bh2, adot_bh2); + calc_force_n_BH(m_bh1, x_bh1, v_bh1, + m_bh2, x_bh2, v_bh2, + config->live_smbh_custom_eps, + &pot_bh1, a_bh1, adot_bh1, + &pot_bh2, a_bh2, adot_bh2); pot[i_bh1] += pot_bh1; pot[i_bh2] += pot_bh2; @@ -1427,11 +1417,11 @@ int main(int argc, char *argv[]) dt_bh_tmp = dt[0]; - tmp_i = calc_force_pn_BH(m_bh1, x_bh1, v_bh1, s_bh1, - m_bh2, x_bh2, v_bh2, s_bh2, - C_NB, dt_bh_tmp, usedOrNot, - (double(*)[3])a_pn1, (double(*)[3])adot_pn1, - (double(*)[3])a_pn2, (double(*)[3])adot_pn2, myRank, rootRank); + tmp_i = calc_force_pn_BH(m_bh1, x_act_new[i_bh1], v_act_new[i_bh1], s_bh1, + m_bh2, x_act_new[i_bh2], v_act_new[i_bh2], s_bh2, + C_NB, dt_bh_tmp, usedOrNot, + (double(*)[3])a_pn1, (double(*)[3])adot_pn1, + (double(*)[3])a_pn2, (double(*)[3])adot_pn2, myRank, rootRank); a_act_new[i_bh1] += a_pn1[1] + a_pn1[2] + a_pn1[3] + a_pn1[4] + a_pn1[5] + a_pn1[6]; a_act_new[i_bh2] += a_pn2[1] + a_pn2[2] + a_pn2[3] + a_pn2[4] + a_pn2[5] + a_pn2[6]; From 75ad0f0e89c4a12427b2dd8c28e28064909c1e34 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Wed, 8 Apr 2020 20:38:36 -0400 Subject: [PATCH 39/65] Added spins to config file and got rid of more _act arrays --- config.cpp | 42 ++++++++-- config.h | 84 +++++++++---------- init.py | 10 +-- phigrape.cpp | 227 +++++++++++++++++++++------------------------------ 4 files changed, 178 insertions(+), 185 deletions(-) diff --git a/config.cpp b/config.cpp index cce97cd..36d2b16 100644 --- a/config.cpp +++ b/config.cpp @@ -72,7 +72,6 @@ template<> bool Config::string_cast(const std::string str) throw std::runtime_error("Cannot convert \"" + str + "\" into a bool"); } -#include template<> std::vector Config::string_cast(const std::string str) { auto error = std::runtime_error("Cannot convert \"" + str + "\" into an integer array"); @@ -90,6 +89,23 @@ template<> std::vector Config::string_cast(const std::string str) return result; } +template<> std::vector Config::string_cast(const std::string str) +{ + auto error = std::runtime_error("Cannot convert \"" + str + "\" into an integer array"); + if (!( (str.front()=='{') && (str.back()=='}'))) throw error; + std::string new_str = strip(str.substr(1, str.length()-2)); + std::replace(new_str.begin(), new_str.end(), ',', ' '); + + std::vector result; + while (new_str.length() > 0) { + size_t idx; + auto value = std::stod(new_str, &idx); + result.push_back(value); + new_str = new_str.substr(idx, new_str.length()-idx); + } + return result; +} + // For mandatory parameters template @@ -109,6 +125,8 @@ T Config::get_parameter(Dictionary dictionary, std::string name, T default_value else return string_cast((*item).second); } +#include + void Config::error_checking() { #ifndef HAS_HDF5 @@ -130,9 +148,21 @@ void Config::error_checking() throw std::runtime_error("Binary black hole influence sphere output (binary_smbh_influence_sphere_output=true) requires exactly two live black holes (live_smbh_count=2)"); if (pn_usage.size() != 7) throw std::runtime_error("PN usage array (pn_usage) must have exactly seven components"); - for (int i=0; i<7; i++) - if (!((pn_usage[i] == 0) || (pn_usage[i] == 1))) - throw std::runtime_error("PN usage array (pn_usage) must have ones and zeros only"); + if (binary_smbh_pn) + for (int i=0; i<7; i++) + if (!((pn_usage[i] == 0) || (pn_usage[i] == 1))) + throw std::runtime_error("PN usage array (pn_usage) must be a 7-component vector filled with ones and zeros only"); + if ((smbh1_spin.size()!=3) || (smbh2_spin.size()!=3)) + throw std::runtime_error("Spins must be three-component vectors"); + if ((pn_usage[6]==1) && ((smbh1_spin[0]==nix) || (smbh2_spin[0]==nix))) + throw std::runtime_error("Please define smbh1_spin and smbh2_spin or disable the spin by setting the last component of pn_usage to zero"); + std::cout << smbh1_spin[0] << std::endl; + std::cout << smbh1_spin[1] << std::endl; + std::cout << smbh1_spin[2] << std::endl; + if ((pn_usage[6]==0) && ((smbh1_spin[0]!=nix) || (smbh2_spin[0]!=nix))) + throw std::runtime_error("Spins (smbh1_spin and smbh2_spin) may not be defined if the last element of pn_usage is set to zero"); + + if (ext_units_physical && ((unit_mass == 0) || (unit_length == 0))) throw std::runtime_error("Physical units for external gravity (ext_units_physical) requires ext_unit_mass and ext_unit_length to be positive numbers"); if ((ext_m_bulge > 0) && (ext_b_bulge < 0)) @@ -177,8 +207,10 @@ Config::Config(std::string file_name) binary_smbh_influence_radius_factor = get_parameter(dictionary, "binary_smbh_influence_radius_factor", 10.); binary_smbh_pn = get_parameter(dictionary, "binary_smbh_pn", false); - pn_usage = get_parameter>(dictionary, "pn_usage", std::vector({1,1,1,1,1,1,1})); + pn_usage = get_parameter>(dictionary, "pn_usage", std::vector({-1,-1,-1,-1,-1,-1,-1})); pn_c = get_parameter(dictionary, "pn_c", 0); + smbh1_spin = get_parameter>(dictionary, "smbh1_spin", std::vector({nix,nix,nix})); + smbh2_spin = get_parameter>(dictionary, "smbh2_spin", std::vector({nix,nix,nix})); ext_units_physical = get_parameter(dictionary, "ext_units_physical", false); unit_mass = get_parameter(dictionary, "unit_mass", !ext_units_physical); diff --git a/config.h b/config.h index f331315..6805646 100644 --- a/config.h +++ b/config.h @@ -7,48 +7,50 @@ class Config { public: Config(std::string file_name); - double eps; - double t_end; - double dt_disk; - double dt_contr; - double dt_bh; - double eta; - std::string input_file_name; - int devices_per_node; - bool dt_min_warning; + double eps; + double t_end; + double dt_disk; + double dt_contr; + double dt_bh; + double eta; + std::string input_file_name; + int devices_per_node; + bool dt_min_warning; + + bool output_hdf5; + bool output_hdf5_double_precision; + int output_ascii_precision; + int output_extra_mode; + + int live_smbh_count; + double live_smbh_custom_eps; + bool live_smbh_output; + bool live_smbh_neighbor_output; + int live_smbh_neighbor_number; + + bool binary_smbh_pn; + bool binary_smbh_influence_sphere_output; + double binary_smbh_influence_radius_factor; + std::vector pn_usage; + double pn_c; + std::vector smbh1_spin; + std::vector smbh2_spin; - bool output_hdf5; - bool output_hdf5_double_precision; - int output_ascii_precision; - int output_extra_mode; - - int live_smbh_count; - double live_smbh_custom_eps; - bool live_smbh_output; - bool live_smbh_neighbor_output; - int live_smbh_neighbor_number; - - bool binary_smbh_pn; - bool binary_smbh_influence_sphere_output; - double binary_smbh_influence_radius_factor; - std::vector pn_usage; - double pn_c; - - bool ext_units_physical; - double unit_mass; - double unit_length; - double ext_m_bulge; - double ext_b_bulge; - double ext_m_disk; - double ext_a_disk; - double ext_b_disk; - double ext_m_halo_plummer; - double ext_b_halo_plummer; - double ext_log_halo_r; - double ext_log_halo_v; - double ext_dehnen_m; - double ext_dehnen_r; - double ext_dehnen_gamma; + bool ext_units_physical; + double unit_mass; + double unit_length; + double ext_m_bulge; + double ext_b_bulge; + double ext_m_disk; + double ext_a_disk; + double ext_b_disk; + double ext_m_halo_plummer; + double ext_b_halo_plummer; + double ext_log_halo_r; + double ext_log_halo_v; + double ext_dehnen_m; + double ext_dehnen_r; + double ext_dehnen_gamma; private: using Dictionary = std::unordered_map; diff --git a/init.py b/init.py index a12d55c..649f75f 100644 --- a/init.py +++ b/init.py @@ -13,7 +13,7 @@ def gen_plum(N, seed=None, RMAX=10): X = np.sqrt(R**2 - Z**2) * np.cos(2*np.pi*X3) Y = np.sqrt(R**2 - Z**2) * np.sin(2*np.pi*X3) - Ve = np.sqrt(2)*(1.0 + R**2)**(-0.25); + Ve = np.sqrt(2)*(1.0 + R**2)**(-0.25) X4, X5 = 0, 0 while 0.1*X5 >= X4**2*(1-X4**2)**3.5: @@ -22,9 +22,9 @@ def gen_plum(N, seed=None, RMAX=10): V = Ve*X4 X6, X7 = np.random.random(2) - Vz = (1 - 2*X6)*V; - Vx = np.sqrt(V**2 - Vz**2) * np.cos(2*np.pi*X7); - Vy = np.sqrt(V**2 - Vz**2) * np.sin(2*np.pi*X7); + Vz = (1 - 2*X6)*V + Vx = np.sqrt(V**2 - Vz**2) * np.cos(2*np.pi*X7) + Vy = np.sqrt(V**2 - Vz**2) * np.sin(2*np.pi*X7) X, Y, Z = np.array([X, Y, Z])*3*np.pi/16 Vx, Vy, Vz = np.array([Vx, Vy, Vz])/np.sqrt(3*np.pi/16) @@ -38,7 +38,7 @@ def kepler_to_cartesian(a, e, i, Omega, w, nu, G=1.0, M=1.0): result = [] for arg in args: result.append(np.atleast_1d(arg)) return result - a, e, i, Omega, w, nu = to_arrays(a, e, i, Omega, w, nu) + a, e, i, Omega, w, nu = to_arrays(a, e, i, Omega, w, nu) # pylint: disable=unbalanced-tuple-unpacking P = [np.cos(w)*np.cos(Omega) - np.sin(w)*np.cos(i)*np.sin(Omega), np.cos(w)*np.sin(Omega) + np.sin(w)*np.cos(i)*np.cos(Omega), np.sin(w)*np.sin(i)] diff --git a/phigrape.cpp b/phigrape.cpp index f4b5267..eae49f2 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -594,80 +594,79 @@ inline double aarseth_step(const double eta, const double dt_tmp, const double3 return sqrt(eta*(a1abs*a2dot1abs+adot1abs*adot1abs)/(adot1abs*a3dot1abs+a2dot1abs*a2dot1abs)); } -void binary_smbh_influence_sphere_output(int i_bh1, int i_bh2, int ind_act[], double m_act[], double3 x_act[], double3 v_act[], double pot_act[], double dt_act[], int n_act, double timesteps, double time_cur, double factor, int inf_event[]) +void binary_smbh_influence_sphere_output(int i_bh1, int i_bh2, int ind_act[], int n_act, double timesteps, double time_cur, double factor, int inf_event[], Source_particle_list *source_particle_list) { //TODO !!IMPORTANT!! only open the file IF THERE IS ANYTHING TO WRITE!!! //TODO inf_event to be static or something? auto out = fopen("bbh_inf.dat", "a"); - double m_bh1 = m_act[i_bh1]; - double m_bh2 = m_act[i_bh2]; - - double3 x_bh1 = x_act[i_bh1]; - double3 x_bh2 = x_act[i_bh2]; - - double3 v_bh1 = v_act[i_bh1]; - double3 v_bh2 = v_act[i_bh2]; + double m_bh1 = source_particle_list->m[0]; + double m_bh2 = source_particle_list->m[1]; + double3 x_bh1 = source_particle_list->x[0]; + double3 x_bh2 = source_particle_list->x[1]; + double3 v_bh1 = source_particle_list->v[0]; + double3 v_bh2 = source_particle_list->v[1]; double3 x_bbhc = (m_bh1*x_bh1 + m_bh2*x_bh2)/(m_bh1 + m_bh2); double3 v_bbhc = (m_bh1*v_bh1 + m_bh2*v_bh2)/(m_bh1 + m_bh2); - double DR2 = SQR(x_bh1[0] - x_bh2[0]) + SQR(x_bh1[1] - x_bh2[1]) + SQR(x_bh1[2] - x_bh2[2]); - double DV2 = SQR(v_bh1[0] - v_bh2[0]) + SQR(v_bh1[1] - v_bh2[1]) + SQR(v_bh1[2] - v_bh2[2]); - + double DR2 = (x_bh1 - x_bh2).norm2(); + double DV2 = (v_bh1 - v_bh2).norm2(); double EB = -(m_bh1 + m_bh2) / sqrt(DR2) + 0.5 * DV2; - double SEMI_a = -0.5 * (m_bh1 + m_bh2)/EB; double SEMI_a2 = SQR(SEMI_a); - for (int i=2; ipot[0]; + double& pot_bh2 = source_particle_list->pot[1]; + double& m_act = source_particle_list->m[j_act]; + double3& x_act = source_particle_list->x[j_act]; + double3& v_act = source_particle_list->v[j_act]; + double& dt_act = source_particle_list->dt[j_act]; + double& pot_act = source_particle_list->pot[j_act]; + double tmp_r2 = (x_act - x_bbhc).norm2(); if (tmp_r2 < SEMI_a2*SQR(factor)) { - if (inf_event[iii] == 0) { + if (inf_event[j_act] == 0) { fprintf(out,"INF1 %.6E %.16E %07d %07d %.6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E \n", - timesteps, time_cur, i, ind_act[i], + timesteps, time_cur, i, j_act, sqrt(DR2), x_bbhc[0], x_bbhc[1], x_bbhc[2], v_bbhc[0], v_bbhc[1], v_bbhc[2], - m_bh1, x_bh1[0], x_bh1[1], x_bh1[2], v_bh1[0], v_bh1[1], v_bh1[2], pot_act[0], - m_bh2, x_bh2[0], x_bh2[1], x_bh2[2], v_bh2[0], v_bh2[1], v_bh2[2], pot_act[1], + m_bh1, x_bh1[0], x_bh1[1], x_bh1[2], v_bh1[0], v_bh1[1], v_bh1[2], pot_bh1, + m_bh2, x_bh2[0], x_bh2[1], x_bh2[2], v_bh2[0], v_bh2[1], v_bh2[2], pot_bh2, sqrt(tmp_r2), - m_act[i], x_act[i][0], x_act[i][1], x_act[i][2], v_act[i][0], v_act[i][1], v_act[i][2], pot_act[i], - dt_act[i]); + m_act, x_act[0], x_act[1], x_act[2], v_act[0], v_act[1], v_act[2], pot_act, + dt_act); - inf_event[iii] = 1; + inf_event[j_act] = 1; } } else { - if (inf_event[iii] == 1) { + if (inf_event[j_act] == 1) { fprintf(out,"INF2 %.6E %.16E %07d %07d %.6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E \n", timesteps, time_cur, i, ind_act[i], sqrt(DR2), x_bbhc[0], x_bbhc[1], x_bbhc[2], v_bbhc[0], v_bbhc[1], v_bbhc[2], - m_bh1, x_bh1[0], x_bh1[1], x_bh1[2], v_bh1[0], v_bh1[1], v_bh1[2], pot_act[0], - m_bh2, x_bh2[0], x_bh2[1], x_bh2[2], v_bh2[0], v_bh2[1], v_bh2[2], pot_act[1], + m_bh1, x_bh1[0], x_bh1[1], x_bh1[2], v_bh1[0], v_bh1[1], v_bh1[2], pot_bh1, + m_bh2, x_bh2[0], x_bh2[1], x_bh2[2], v_bh2[0], v_bh2[1], v_bh2[2], pot_bh2, sqrt(tmp_r2), - m_act[i], x_act[i][0], x_act[i][1], x_act[i][2], v_act[i][0], v_act[i][1], v_act[i][2], pot_act[i], - dt_act[i]); + m_act, x_act[0], x_act[1], x_act[2], v_act[0], v_act[1], v_act[2], pot_act, + dt_act); } - inf_event[iii] = 0; + inf_event[j_act] = 0; } /* if (tmp_r2 < DR2*R_INF2) */ } /* i */ fclose(out); - } -void adjust_bsmbh_softening(const double eps, const double eps_bh, const int i_bh1, const int i_bh2, const double m_act[], const double3 x_act_new[], const double3 v_act_new[], double pot_act_new[], double3 a_act_new[], double3 adot_act_new[]) +inline void adjust_bsmbh_softening(const double eps, const double eps_bh, const int i_bh1, const int i_bh2, const double m_bh1, const double m_bh2, const double3 x_act_new[], const double3 v_act_new[], double pot_act_new[], double3 a_act_new[], double3 adot_act_new[]) { - double m_bh1 = m_act[i_bh1]; - double m_bh2 = m_act[i_bh2]; - double3 x_bh1 = x_act_new[i_bh1]; double3 v_bh1 = v_act_new[i_bh1]; @@ -767,9 +766,6 @@ int main(int argc, char *argv[]) FILE *out; - double C_NB; - int usedOrNot[7]; - double pot_ext[N_MAX], pot_act_ext[N_MAX]; // for all EXTPOT int i_bh1, i_bh2; @@ -779,9 +775,6 @@ int main(int argc, char *argv[]) int inf_event[N_MAX]; double3 x_bbhc, v_bbhc; - double s_bh1[3] = {0.0, 0.0, 1.0}; - double s_bh2[3] = {0.0, 0.0, 1.0}; - double3 zeros = {0, 0, 0}; // Dummy; can't really be const because of the GRAPE interface. /* INIT the rand() !!! */ @@ -808,8 +801,6 @@ int main(int argc, char *argv[]) /* read the input parameters to the rootRank */ config = new Config("phigrape.conf"); - C_NB = config->pn_c; - std::copy(config->pn_usage.begin(), config->pn_usage.end(), usedOrNot); if (is_hdf5(config->input_file_name)) { #ifndef HAS_HDF5 @@ -1006,10 +997,10 @@ int main(int argc, char *argv[]) /* load the nj particles to the G6 */ - for (int j=0; j BH : PN1, PN2, PN2.5, PN3, PN3.5 : acc, jerk - dt_bh_tmp = dt[0]; - - tmp_i = calc_force_pn_BH(m_bh1, x_bh1, v_bh1, s_bh1, - m_bh2, x_bh2, v_bh2, s_bh2, - C_NB, dt_bh_tmp, usedOrNot, - (double(*)[3])a_pn1, (double(*)[3])adot_pn1, - (double(*)[3])a_pn2, (double(*)[3])adot_pn2, myRank, rootRank); + tmp_i = calc_force_pn_BH(m[i_bh1], x[i_bh1], v[i_bh1], config->smbh1_spin.data(), + m[i_bh2], x[i_bh2], v[i_bh2], config->smbh2_spin.data(), + config->pn_c, dt[i_bh1], config->pn_usage.data(), + (double(*)[3])a_pn1, (double(*)[3])adot_pn1, + (double(*)[3])a_pn2, (double(*)[3])adot_pn2, myRank, rootRank); a[i_bh1] += a_pn1[1] + a_pn1[2] + a_pn1[3] + a_pn1[4] + a_pn1[5] + a_pn1[6]; a[i_bh2] += a_pn2[1] + a_pn2[2] + a_pn2[3] + a_pn2[4] + a_pn2[5] + a_pn2[6]; @@ -1187,14 +1176,12 @@ int main(int argc, char *argv[]) /* Define initial timestep for all particles on all nodes */ - for (int i=0; i dt_max) dt_tmp = dt_max; - dt[i] = dt_tmp; + dt[j] = dt_tmp; if (config->dt_min_warning && (myRank == 0)) { - if (dt[i] == dt_min) { - printf("!!! Warning0: dt = dt_min = %.6E \t ind = %07d \n", dt[i], ind[i]); + if (dt[j] == dt_min) { + printf("!!! Warning0: dt = dt_min = %.6E \t ind = %07d \n", dt[j], ind[j]); fflush(stdout); } } - } /* i */ + } /* j */ if (config->live_smbh_count > 0) { double min_dt = *std::min_element(dt, dt+N); @@ -1224,10 +1211,10 @@ int main(int argc, char *argv[]) /* load the new values for particles to the local GRAPE's */ /* load the nj particles to the G6 */ - for (int j=0; jlive_smbh_count == 2) { if (config->live_smbh_custom_eps >= 0) { - adjust_bsmbh_softening(eps, config->live_smbh_custom_eps, i_bh1, i_bh2, m_act, x_act_new, v_act_new, pot_act_new, a_act_new, adot_act_new); + adjust_bsmbh_softening(eps, config->live_smbh_custom_eps, i_bh1, i_bh2, m[0], m[1], x_act_new, v_act_new, pot_act_new, a_act_new, adot_act_new); } if (config->binary_smbh_pn) { // calculate and "plus" the new BH <-> BH : PN1, PN2, PN2.5, PN3, PN3.5 : acc, jerk - dt_bh_tmp = dt[0]; - - tmp_i = calc_force_pn_BH(m_bh1, x_act_new[i_bh1], v_act_new[i_bh1], s_bh1, - m_bh2, x_act_new[i_bh2], v_act_new[i_bh2], s_bh2, - C_NB, dt_bh_tmp, usedOrNot, + tmp_i = calc_force_pn_BH(m[0], x_act_new[i_bh1], v_act_new[i_bh1], config->smbh1_spin.data(), + m[1], x_act_new[i_bh2], v_act_new[i_bh2], config->smbh2_spin.data(), + config->pn_c, dt[i_bh1], config->pn_usage.data(), (double(*)[3])a_pn1, (double(*)[3])adot_pn1, (double(*)[3])a_pn2, (double(*)[3])adot_pn2, myRank, rootRank); @@ -1447,6 +1433,7 @@ int main(int argc, char *argv[]) get_CPU_time(&CPU_tmp_real0, &CPU_tmp_user0, &CPU_tmp_syst0); #endif + double min_dt = dt_max; for (int i=0; ilive_smbh_count > 0) && (ind_act[i] < config->live_smbh_count)) eta_curr = eta_bh; @@ -1468,7 +1454,6 @@ int main(int argc, char *argv[]) //TODO the below should be moved to a function if (dt_new < dt_min) dt_tmp = dt_min; - if ((dt_new < dt_tmp) && (dt_new > dt_min)) { power = log(dt_new)/log(2.0) - 1; dt_tmp = pow(2.0, (double)power); // TODO why is this casting needed here? @@ -1479,63 +1464,37 @@ int main(int argc, char *argv[]) } if (config->dt_min_warning && (myRank == 0)) { - if (dt_act[i] == dt_min) { - printf("!!! Warning1: dt_act = dt_min = %.6E \t ind_act = %07d \n", dt[i], ind_act[i]); + if (dt_tmp == dt_min) { + printf("!!! Warning1: dt_act = dt_min = %.6E \t ind_act = %07d \n", dt_tmp, ind_act[i]); fflush(stdout); } } + if (dt_tmp < min_dt) min_dt = dt_tmp; - /* BEGIN copy of everything */ - - dt_act[i] = dt_tmp; - t_act[i] = min_t; - - pot_act[i] = pot_act_new[i]; - - x_act[i] = x_act_new[i]; - v_act[i] = v_act_new[i]; - a_act[i] = a_act_new[i]; - adot_act[i] = adot_act_new[i]; - - /* END copy of everything */ - + int j_act = ind_act[i]; + x[j_act] = x_act_new[i]; + v[j_act] = v_act_new[i]; + t[j_act] = min_t; + dt[j_act] = dt_tmp; + pot[j_act] = pot_act_new[i]; + pot_ext[j_act] = pot_act_ext[i]; // ??? + a[j_act] = a_act_new[i]; + adot[j_act] = adot_act_new[i]; } /* i */ /* define the min. dt over all the act. part. and set it also for the BH... */ if (config->live_smbh_count > 0) { - double min_dt = *std::min_element(dt_act, dt_act+n_act); - if (config->live_smbh_count>=1) dt_act[i_bh1] = min_dt; - if (config->live_smbh_count==2) dt_act[i_bh2] = min_dt; + if (config->live_smbh_count>=1) dt[0] = min_dt; + if (config->live_smbh_count==2) dt[1] = min_dt; + } if (config->binary_smbh_influence_sphere_output && (myRank == rootRank)) { //TODO clean up this mass. We don't want to have all these _act arrays; they are only needed for this lame function. - binary_smbh_influence_sphere_output(i_bh1, i_bh2, ind_act, m_act, x_act_new, v_act_new, pot_act_new, dt_act, n_act, timesteps, time_cur, config->binary_smbh_influence_radius_factor, inf_event); + binary_smbh_influence_sphere_output(i_bh1, i_bh2, ind_act, n_act, timesteps, time_cur, config->binary_smbh_influence_radius_factor, inf_event, &source_particle_list); } - /* Return back the new coordinates + etc... of active part. to the global data... */ - - for (int i=0; i Date: Mon, 13 Apr 2020 23:08:42 -0400 Subject: [PATCH 40/65] Now working as the hybrid code Removed the need for the annoying ETICS_CEP flag; now dt_scf is read from the config file. --- Makefile | 4 +- config.cpp | 7 ++++ config.h | 7 ++++ phigrape.conf | 114 +++++++++++++++++++++++++++++++++++++++----------- phigrape.cpp | 103 ++++++++++++++++----------------------------- 5 files changed, 140 insertions(+), 95 deletions(-) diff --git a/Makefile b/Makefile index 319f579..6e4538f 100644 --- a/Makefile +++ b/Makefile @@ -2,8 +2,6 @@ CUDAHOME ?= /usr/local/cuda CPPFLAGS += -DETICS OPTIMIZATION ?= 3 -ETICS_DTSCF ?= 0.015625 - CUDAINC = -I$(CUDAHOME)/include -I$(CUDAHOME)/samples/common/inc/ CUDALIB = -L$(CUDAHOME)/lib64 -lcudart -lcudadevrt @@ -25,7 +23,7 @@ CPPFLAGS += -DHAS_HDF5 LIB += -lhdf5 -lz -ldl default: - $(MPICXX) $(CPPFLAGS) $(CXXFLAGS) -DETICS_DTSCF=$(ETICS_DTSCF) $(INC) external.cpp io.cpp config.cpp phigrape.cpp -o $(EXECUTABLE) $(LIB) + $(MPICXX) $(CPPFLAGS) $(CXXFLAGS) $(INC) external.cpp io.cpp config.cpp phigrape.cpp -o $(EXECUTABLE) $(LIB) yebisu: CPPFLAGS := $(filter-out -DETICS, $(CPPFLAGS)) yebisu: default diff --git a/config.cpp b/config.cpp index 36d2b16..6223df7 100644 --- a/config.cpp +++ b/config.cpp @@ -228,5 +228,12 @@ Config::Config(std::string file_name) ext_dehnen_r = get_parameter(dictionary, "ext_dehnen_r", -1); ext_dehnen_gamma = get_parameter(dictionary, "ext_dehnen_gamma", -1); +#ifdef ETICS + dt_scf = get_parameter(dictionary, "dt_scf"); + grapite_mask_file_name = get_parameter(dictionary, "grapite_mask_file_name", "grapite.mask"); + etics_dump_coeffs = get_parameter(dictionary, "etics_dump_coeffs", false); + grapite_active_search = get_parameter(dictionary, "grapite_active_search", false); +#endif + error_checking(); } diff --git a/config.h b/config.h index 6805646..875d626 100644 --- a/config.h +++ b/config.h @@ -52,6 +52,13 @@ public: double ext_dehnen_r; double ext_dehnen_gamma; +#ifdef ETICS + double dt_scf; + std::string grapite_mask_file_name; + bool etics_dump_coeffs; + bool grapite_active_search; +#endif + private: using Dictionary = std::unordered_map; Dictionary read_config_file(const std::string file_name); diff --git a/phigrape.conf b/phigrape.conf index 707b597..3c7411b 100644 --- a/phigrape.conf +++ b/phigrape.conf @@ -6,7 +6,7 @@ eps = 1E-4 # End time of the calculation -t_end = 0.25 +t_end = 1 # Interval of snapshot files output dt_disk = 0.125 @@ -25,33 +25,44 @@ eta = 0.01 # Number of devices (GRAPEs or GPUs per node) [default: 0] -# By default, each MPI process will attempt to bind to one device. To change this behaviour, set the value to the number of available devices in the system. For example, if from some reason you want to run multiple MPI processes on a machine with a single device, set the value to 1 and use the mpirun utility (or whatever is used in your job scheduler) to launch as many processes as you like. -#devices_per_node = 1 +# By default, each MPI process will attempt to bind to one device. To change +# this behaviour, set the value to the number of available devices in the +# system. For example, if from some reason you want to run multiple MPI +# processes on a machine with a single device, set the value to 1 and use the +# mpirun utility (or whatever is used in your job scheduler) to launch as many +# processes as you like. +devices_per_node = 1 ########## # OUTPUT # ########## -# Whether to use HDF5 format for snapshot and restart; regular ASCII snapshorts are saved if false [default: false] +# Whether to use HDF5 format for snapshot and restart; regular ASCII snapshorts +# are saved if false [default: false] #output_hdf5 = true -# If using HDF5 output, use double precision or not [default: true] -# Consider setting to false to save disk space. Restart file is always saved in double precision. +# If using HDF5 output, use double precision or not [default: true] Consider +# setting to false to save disk space. Restart file is always saved in double +# precision. #output_hdf5_double_precision = true # If using ASCII output, the number of digits after the decimal point [default: 10] # Restart file is saved with 16 digits after the decimal point. #output_ascii_precision = 6 -# Extra output: optionally save potential, acceleration and jerk in snapshot files [default: 0] -# This is a number between 0 and 7 that encodes the output options in the following way: +# Extra output: optionally save potential, acceleration and jerk in snapshot +# files [default: 0] +# This is a number between 0 and 7 that encodes the output options in the +# following way: # [value] = [save jerk]*4 + [save acceleration]*2 + [save potential] -# Example: choose 5 if it is needed to save the jerk and the potential, but not the acceleration for some reason. +# Example: choose 5 if it is needed to save the jerk and the potential, but not +# the acceleration for some reason. # Currently implemented in HDF5 output only. #output_extra_mode = 7 -# Whether to output a warning on the screen when the minimum time step is encountered. [default: false] +# Whether to output a warning on the screen when the minimum time step is +# encountered. [default: false] #dt_min_warning = false @@ -59,12 +70,18 @@ eta = 0.01 # EXTERNAL GRAVITY # #################### -# Remember that external gravity models are applied at the same coordinate system as the particles. If the idea is to simulate a globular cluster orbiting in an external field, be sure to set the initial conditions appropriately (applying a shift to the coordinates and velocities). +# Remember that external gravity models are applied at the same coordinate +# system as the particles. If the idea is to simulate a globular cluster +# orbiting in an external field, be sure to set the initial conditions +# appropriately (applying a shift to the coordinates and velocities). -# Whether the parameters for the external gravitational field given below are in physical units or Hénon units. If true, the system used is {kiloparsec, solar mass, kilometre per second} [default: false] +# Whether the parameters for the external gravitational field given below are in +# physical units or Hénon units. If true, the system used is {kiloparsec, solar +# mass, kilometre per second} [default: false] #ext_units_physical = true -# If Physical units were selected, specify the simulation's unit mass (is solar masses) and unit lenght (in parsec; not kiloparsec) +# If Physical units were selected, specify the simulation's unit mass (is solar +# masses) and unit lenght (in parsec; not kiloparsec) # TODO: add the option to normalize using other units. #unit_mass = 4E5 # MSun #unit_length = 15 # pc @@ -75,18 +92,21 @@ eta = 0.01 #ext_b_bulge = 1.9 # kpc -# The disk is a Miyamoto-Nagai potential with the following total mass, scale length, and scale height +# The disk is a Miyamoto-Nagai potential with the following total mass, scale +# length, and scale height #ext_m_disk = 6.8E10 # MSun #ext_a_disk = 3.00 # kpc #ext_b_disk = 0.28 # kpc -# This halo option is yet another Plummer potential with the following total mass and radius. +# This halo option is yet another Plummer potential with the following total +# mass and radius. #ext_m_halo_plummer = 8E11 # MSun #ext_b_halo_plummer = 245 # kpc -# This halo option is a logarithmic potential with the following velocity and radius parameters. +# This halo option is a logarithmic potential with the following velocity and +# radius parameters. #ext_log_halo_v = 240 # km/s #ext_log_halo_r = 1 # kpc @@ -100,18 +120,24 @@ eta = 0.01 # LIVE SUPERMASSIVE BLACK HOLE(S) # ################################### -# There is special treatment for particles representing supermassive black holes (SMBHs): they are integrated at every time step, they can have custom softening in SMBH-SMBH interactions, and post Newtonian terms can be added to the gravity. +# There is special treatment for particles representing supermassive black holes +# (SMBHs): they are integrated at every time step, they can have custom +# softening in SMBH-SMBH interactions, and post Newtonian terms can be added to +# the gravity. # The number of SMBH particles. Can be 0 (no SMBH), 1, or 2. [default: 0] #live_smbh_count = 2 -# Custom softening length for SMBH-SMBH interactions (can also be zero). If non-negative, the custom softening is applied. [default: -1] +# Custom softening length for SMBH-SMBH interactions (can also be zero). If +# non-negative, the custom softening is applied. [default: -1] #live_smbh_custom_eps = 0 +#TODO this is actually related only to BINARY smbh! # Output additional diagnostics about live SMBHs. [default: false] #live_smbh_output = true -# Output additional diagnostics about the SMBH's (or SMBHs') nearest neighbours (number could be set as shown below). [default: false] +# Output additional diagnostics about the SMBH's (or SMBHs') nearest neighbours +# (number could be set as shown below). [default: false] #live_smbh_neighbor_output = true # Number of nearest neighbours to the SMBH (or SMBHs) to include in output. [default: 10] @@ -124,22 +150,62 @@ eta = 0.01 # The following parameters can be set when live_smbh_count is 2. -# Output additional diagnostics about the sphere of influence (size could be set as shown below). [default: false] +# Output additional diagnostics about the sphere of influence (size could be set +# as shown below). [default: false] #binary_smbh_influence_sphere_output = true -# The influence sphere is centred at the binary SMBH's centre of mass, and its radius is the semi-major axis of the binary times the factor below. [default: 10] -#binary_smbh_influence_radius_factor = 20 +# The influence sphere is centred at the binary SMBH's centre of mass, and its +# radius is the semi-major axis of the binary times the factor below. [default: 10] +#binary_smbh_influence_radius_factor = 3.162277660168379497918067e+03 # Add post Newtonian terms to SMBH-SMBH gravity. [default: false] #binary_smbh_pn = true -# A mask array (zeros and ones) determining whether or not to use specific post-Newtonian terms. -# The elements represent {0, 1, 2, 2.5, 3, 3.5, spin} [default: {1,1,1,1,1,1,1}] +# A mask array (zeros and ones) determining whether or not to use specific +# post-Newtonian terms. +# The elements represent {Newtonian, 1, 2, 2.5, 3, 3.5, spin} +# Note: the first element in the array has no effect, the Newtonian force is +# always included. #pn_usage = {1, 1, 1, 1, 0, 0, 0} # The speed of light in N-body units [default: 500] #pn_c = 477.12 +# The spin vectors of the two SMBHs. Only define these if the last component of +# pn_usage is set to one. +#smbh1_spin = {0, 0, 1} +#smbh2_spin = {0, 0, 1} + + +############### +# HYBRID CODE # +############### + +# The hybridization with the SCF code is enabled if the ETICS preprocessor flag +# is defined in the when compiling. + +# Time intervals to calculate the SCF series expansion. +dt_scf = 0.015625 + +# Name of the mask file for GRAPite [default: grapite.mask] +grapite_mask_file_name = grapite.mask + +# Whether to write to disk a list of SCF coefficients at every dt_disk. [default: false] +etics_dump_coeffs = true + +# Whether to use an alternative procedure for active particle search that is +# available in the GRAPite library. This requires the number of particles in +# each MPI process to be exactly divisible by 32. This can substantially +# accelerate the calculation in some circumstances [default: false] +grapite_active_search = true + + +# TODO +######## +# etics dump mode +# threshold for execution on device for grapite +# scaling parameter override + #################################### # Negative powers of two # diff --git a/phigrape.cpp b/phigrape.cpp index eae49f2..d8bbd04 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -62,11 +62,6 @@ Config *config; #ifdef ETICS #include "grapite.h" -// why do we need CEP as a compilaion flag... just have it always on when ETICS is on. IF there is no CEP, there should be a graceful skipping of those operations. -//#define ETICS_CEP -#ifndef ETICS_DTSCF -#error "ETICS_DTSCF must be defined" -#endif #endif #define TIMING @@ -140,8 +135,6 @@ int new_tunit=51, new_xunit=51; double ti=0.0; -double eps_BH=0.0; - /* external potential... */ double3 x_bh1, x_bh2, v_bh1, v_bh2; @@ -156,11 +149,8 @@ double3 a_pn1[7], adot_pn1[7], a_pn2[7], adot_pn2[7]; #include "pn_bh_spin.c" #ifdef ETICS -double t_exp, dt_exp=ETICS_DTSCF; // t_exp is just the initial value -#ifdef ETICS_CEP int grapite_cep_index; #endif -#endif void get_CPU_time(double *time_real, double *time_user, double *time_syst) { @@ -989,10 +979,9 @@ int main(int argc, char *argv[]) g6_set_xunit(new_xunit); #ifdef ETICS - grapite_read_particle_tags(N, "grapite.mask", myRank, n_loc); - grapite_set_dt_exp(dt_exp); - dt_exp = time_cur; // if we don't have a binary restart then we don't remember the coefficients, and we need to calculate them now. - grapite_set_t_exp(t_exp); + grapite_read_particle_tags(N, config->grapite_mask_file_name.c_str(), myRank, n_loc); + grapite_set_dt_exp(config->dt_scf); + grapite_set_t_exp(time_cur); #endif /* load the nj particles to the G6 */ @@ -1004,24 +993,17 @@ int main(int argc, char *argv[]) #ifdef ETICS double etics_length_scale; - if (myRank == rootRank) etics_length_scale = grapite_get_length_scale(N, m, x, v); // We don't want all ranks to do it, because they need to write a file and might confuse each other + if (myRank == rootRank) etics_length_scale = grapite_get_length_scale(N, m, (double(*)[3])x, (double(*)[3])v); // We don't want all ranks to do it, because they need to write a file and might confuse each other MPI_Bcast(&etics_length_scale, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); grapite_set_length_scale(etics_length_scale); -#endif -#ifdef ETICS_CEP - // First time only: get the CEP index grapite_cep_index = grapite_get_cep_index(); - - // First calculate the DC - grapite_calc_center(N, m, x, v, xcm, vcm, xdc, vdc); - - // Now copy it to the global particle list - memcpy(x[grapite_cep_index], xdc, 3*sizeof(double)); - memcpy(v[grapite_cep_index], vdc, 3*sizeof(double)); - - double zeros[3] = {0., 0., 0.}; // We haven't calculated the force yet! - grapite_update_cep(time_cur, xdc, vdc, zeros, zeros); + if (grapite_cep_index >= 0) { + grapite_calc_center(N, m, (double(*)[3])x, (double(*)[3])v, xcm, vcm, xdc, vdc); + memcpy(x[grapite_cep_index], xdc, 3*sizeof(double)); + memcpy(v[grapite_cep_index], vdc, 3*sizeof(double)); + grapite_update_cep(time_cur, xdc, vdc, zeros, zeros); + } #endif /* define the all particles as a active on all the processors for the first time grav calc. */ @@ -1150,25 +1132,19 @@ int main(int argc, char *argv[]) energy_contr(time_cur, timesteps, n_act_sum, g6_calls, rcm_sum, vcm_sum, E_tot_0, E_tot_corr_0, E_tot_corr_sd_0, skip_con, N, m, x, v, pot, pot_ext); } /* if (myRank == rootRank) */ -#ifdef ETICS_DUMP - if (diskstep==0) { +#ifdef ETICS + if (config->etics_dump_coeffs && (diskstep==0)) { + char out_fname[256]; sprintf(out_fname, "coeffs.%06d.%02d.dat", 0, myRank); grapite_dump(out_fname, 2); } -#endif - /* Wait to all processors to finish his works... */ - MPI_Barrier(MPI_COMM_WORLD); - -#ifdef ETICS_CEP - // First calculate the DC - grapite_calc_center(N, m, x, v, xcm, vcm, xdc, vdc); - - // Now copy it to the global particle list - memcpy(x[grapite_cep_index], xdc, 3*sizeof(double)); - memcpy(v[grapite_cep_index], vdc, 3*sizeof(double)); - - grapite_update_cep(time_cur, xdc, vdc, a[grapite_cep_index], adot[grapite_cep_index]); + if (grapite_cep_index >= 0) { + grapite_calc_center(N, m, (double(*)[3])x, (double(*)[3])v, xcm, vcm, xdc, vdc); + memcpy(x[grapite_cep_index], xdc, 3*sizeof(double)); + memcpy(v[grapite_cep_index], vdc, 3*sizeof(double)); + grapite_update_cep(time_cur, xdc, vdc, a[grapite_cep_index], adot[grapite_cep_index]); + } #endif /* Wait to all processors to finish his works... */ @@ -1506,9 +1482,9 @@ int main(int argc, char *argv[]) get_CPU_time(&CPU_tmp_real0, &CPU_tmp_user0, &CPU_tmp_syst0); #endif - for (int i=0; i= 0) { + grapite_calc_center(N, m, (double(*)[3])x, (double(*)[3])v, xcm, vcm, xdc, vdc); + memcpy(x[grapite_cep_index], xdc, 3*sizeof(double)); + memcpy(v[grapite_cep_index], vdc, 3*sizeof(double)); + grapite_update_cep(time_cur, xdc, vdc, a[grapite_cep_index], adot[grapite_cep_index]); } - grapite_update_cep(time_cur, xdc, vdc, a[grapite_cep_index], adot[grapite_cep_index]); #endif t_contr += dt_contr; } /* if (time_cur >= t_contr) */ if (time_cur >= t_disk) { + char out_fname[256]; + diskstep++; if (myRank == rootRank) { - diskstep++; - char out_fname[256]; sprintf(out_fname, "%06d", diskstep); if (config->output_hdf5) h5_write(std::string(out_fname) + ".h5", diskstep, N, time_cur, m, x, v, pot, a, adot, config->output_extra_mode, config->output_hdf5_double_precision); else ascii_write(std::string(out_fname) + ".dat", diskstep, N, time_cur, m, x, v, config->output_ascii_precision); } /* if (myRank == rootRank) */ -#ifdef ETICS_DUMP - sprintf(out_fname, "coeffs.%06d.%02d.dat", diskstep, myRank); - grapite_dump(out_fname, 2); +#ifdef ETICS + if (config->etics_dump_coeffs) { + sprintf(out_fname, "coeffs.%06d.%02d.dat", diskstep, myRank); + grapite_dump(out_fname, 2); + } #endif - t_disk += dt_disk; } /* if (time_cur >= t_disk) */ - } /* while (time_cur < t_end) */ /* close the local GRAPEs */ - g6_close(clusterid); /* Wait to all processors to finish his works... */ From 30ae8631a95f6b6244a43e527d4cb7476adda0ca Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Tue, 14 Apr 2020 20:20:39 -0400 Subject: [PATCH 41/65] Moved calc_self_grav to a class and cleaned up a little --- phigrape.cpp | 199 +++++++++++++++++---------------------------------- 1 file changed, 67 insertions(+), 132 deletions(-) diff --git a/phigrape.cpp b/phigrape.cpp index d8bbd04..8e43da3 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -123,17 +123,7 @@ double DT_ACT_REDUCE; #endif -/* some local settings for G6a board's */ -int clusterid, ii, nn, numGPU; - -int npipe=G6_NPIPE, index_i[G6_NPIPE]; -double h2_i[G6_NPIPE], p_i[G6_NPIPE]; -double3 x_i[G6_NPIPE], v_i[G6_NPIPE], - a_i[G6_NPIPE], jerk_i[G6_NPIPE]; -int new_tunit=51, new_xunit=51; - -double ti=0.0; /* external potential... */ @@ -286,43 +276,32 @@ void write_bh_nb_data(double time_cur, int N, double m[], double3 x[], double3 v fclose(out); } -void calc_self_grav(double t, double eps2, double &g6_calls, int n_loc, - int n_act, int ind_act[], - double3 x_act_new[], double3 v_act_new[], - double pot_act_tmp[], - double3 a_act_tmp[], - double3 adot_act_tmp[], - double h2_i[]) -{ - /* calc the new grav for the active particles */ - -#ifdef TIMING - get_CPU_time(&CPU_tmp_real0, &CPU_tmp_user0, &CPU_tmp_syst0); -#endif - - g6_set_ti(clusterid, t); - - int ni = n_act; // TODO why is this needed? - - /* define the local phi, a, adot for these active particles */ - - for (int i=0; i h2; +}; void calc_ext_grav(std::vector &external_gravity_components, int n_act, double3 *x_act_new, double3 *v_act_new, double *pot_act_ext, double3 *a_act_new, double3* adot_act_new) { @@ -705,15 +684,15 @@ int main(int argc, char *argv[]) skip_con=0, tmp_i; double dt_disk, dt_contr, t_disk=0.0, t_contr=0.0, - dt_bh, t_bh=0.0, dt_bh_tmp, + dt_bh, t_bh=0.0, t_end, time_cur, dt_min, dt_max, min_t, min_t_loc, eta_s, eta, eta_bh, E_tot_0, E_tot_corr_0, E_tot_corr_sd_0, rcm_sum=0.0, vcm_sum=0.0, - eps=0.0, eps2, + eps, a2_mod, adot2_mod, dt_tmp, dt2half, dt3over6, - timesteps=0.0, n_act_sum=0.0, n_act_distr[N_MAX], g6_calls=0.0, g6_calls_sum=0.0; + timesteps=0.0, n_act_sum=0.0, n_act_distr[N_MAX]; double3 xcm, vcm, mom, xdc, vdc, @@ -743,13 +722,11 @@ int main(int argc, char *argv[]) /* data for active particles */ int n_act, ind_act[N_MAX]; - double m_act[N_MAX], - pot_act[N_MAX], t_act[N_MAX], dt_act[N_MAX], + double t_act[N_MAX], pot_act_new[N_MAX], pot_act_tmp[N_MAX]; - double3 x_act[N_MAX], v_act[N_MAX], - a_act[N_MAX], adot_act[N_MAX], + double3 a_act[N_MAX], adot_act[N_MAX], x_act_new[N_MAX], v_act_new[N_MAX], a_act_new[N_MAX], adot_act_new[N_MAX], a_act_tmp[N_MAX], adot_act_tmp[N_MAX];; @@ -765,6 +742,12 @@ int main(int argc, char *argv[]) int inf_event[N_MAX]; double3 x_bbhc, v_bbhc; + /* some local settings for G6a board's */ + + int clusterid, numGPU, npipe=G6_NPIPE; + + int new_tunit=51, new_xunit=51; + double3 zeros = {0, 0, 0}; // Dummy; can't really be const because of the GRAPE interface. /* INIT the rand() !!! */ @@ -801,31 +784,19 @@ int main(int argc, char *argv[]) } else ascii_read(config->input_file_name, &diskstep, &N, &time_cur, m, x, v); + std::iota(ind, ind+N, 0); + eps = config->eps; + eta = config->eta; + t_end = config->t_end; + dt_disk = config->dt_disk; + dt_contr = config->dt_contr; + dt_bh = config->dt_bh; + if (myRank == rootRank) { - - //TODO move it out of (myRank == rootRank) so you don't need to communicate them. - eps = config->eps; - t_end = config->t_end; - dt_disk = config->dt_disk; - dt_contr = config->dt_contr; - dt_bh = config->dt_bh; - eta = config->eta; - strcpy(inp_fname, config->input_file_name.c_str()); - if (config->binary_smbh_influence_sphere_output) for (int i=0; iext_units_physical) { normalization_mass = 1/config->unit_mass; @@ -915,8 +873,6 @@ int main(int argc, char *argv[]) eta_s = eta/ETA_S_CORR; eta_bh = eta/ETA_BH_CORR; - eps2 = SQR(eps); - dt_min = 1.0*pow(2.0, DTMINPOWER); dt_max = 1.0*pow(2.0, DTMAXPOWER); @@ -942,25 +898,13 @@ int main(int argc, char *argv[]) n_loc = N/n_proc; + Calc_self_grav calc_self_grav(N, n_loc, clusterid, npipe, eps); + Active_search active_search(myRank, n_proc, n_loc, N); /* Wait to all processors to finish his works... */ MPI_Barrier(MPI_COMM_WORLD); - /* Broadcast the values of all particles to all processors... */ - MPI_Bcast(ind, N, MPI_INT, rootRank, MPI_COMM_WORLD); - MPI_Bcast(m, N, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Bcast(x, 3*N, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - MPI_Bcast(v, 3*N, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); - - /* Wait to all processors to finish his works... */ - MPI_Barrier(MPI_COMM_WORLD); - - /* Wait to all processors to finish his works... */ - MPI_Barrier(MPI_COMM_WORLD); - - /* init the local GRAPE's */ - if (config->devices_per_node==0) { MPI_Comm shmcomm; MPI_Comm_split_type(MPI_COMM_WORLD, MPI_COMM_TYPE_SHARED, 0, MPI_INFO_NULL, &shmcomm); @@ -973,6 +917,7 @@ int main(int argc, char *argv[]) printf("Rank of the processor %03d : Number of GPUs %01d : Cluster ID %01d \n", myRank, numGPU, clusterid); fflush(stdout); + /* init the local GRAPEs */ g6_open(clusterid); npipe = g6_npipes(); g6_set_tunit(new_tunit); @@ -1011,26 +956,14 @@ int main(int argc, char *argv[]) n_act = N; for (int i=0; i= t_contr) { if (myRank == rootRank) { - energy_contr(time_cur, timesteps, n_act_sum, g6_calls, rcm_sum, vcm_sum, E_tot_0, E_tot_corr_0, E_tot_corr_sd_0, skip_con, N, m, x, v, pot, pot_ext); + energy_contr(time_cur, timesteps, n_act_sum, calc_self_grav.g6_calls, rcm_sum, vcm_sum, E_tot_0, E_tot_corr_0, E_tot_corr_sd_0, skip_con, N, m, x, v, pot, pot_ext); /* write cont data */ @@ -1600,7 +1534,8 @@ int main(int argc, char *argv[]) /* Wait to all processors to finish his works... */ MPI_Barrier(MPI_COMM_WORLD); - MPI_Reduce(&g6_calls, &g6_calls_sum, 1, MPI_DOUBLE, MPI_SUM, rootRank, MPI_COMM_WORLD); + double g6_calls_sum; + MPI_Reduce(&calc_self_grav.g6_calls, &g6_calls_sum, 1, MPI_DOUBLE, MPI_SUM, rootRank, MPI_COMM_WORLD); /* Wait to all processors to finish his works... */ MPI_Barrier(MPI_COMM_WORLD); @@ -1610,7 +1545,7 @@ int main(int argc, char *argv[]) /* Write some output for the timestep annalize... */ printf("\n"); - printf("timesteps = %.0f Total sum of integrated part. = %.0f g6_calls on all nodes = %.0f \n", timesteps, n_act_sum, g6_calls); + printf("timesteps = %.0f Total sum of integrated part. = %.0f g6_calls on all nodes = %.0f \n", timesteps, n_act_sum, g6_calls_sum); printf("\n"); printf("Real Speed = %.3f GFlops \n", 57.0*N*n_act_sum/(CPU_time_user-CPU_time_user0)/1.0E+09); fflush(stdout); From 2a50f0fc9ae6fb51a80d209cf44993f366602062 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Sat, 18 Apr 2020 21:48:46 -0400 Subject: [PATCH 42/65] Lots of cleanup and started moving the PN out of the main --- double3.h | 51 +++--- io.cpp | 6 +- phigrape.cpp | 440 +++++++++++++++++++++++++++++---------------------- 3 files changed, 278 insertions(+), 219 deletions(-) diff --git a/double3.h b/double3.h index ce0f3ef..1010a2d 100644 --- a/double3.h +++ b/double3.h @@ -2,81 +2,80 @@ #include struct double3 { - double data[3]; + union { + struct {double x, y, z;}; + double data[3]; // For legacy access + }; double3() {} double3(const double x, const double y, const double z) - { - data[0] = x; - data[1] = y; - data[2] = z; - } + : x(x), y(y), z(z) {} double& operator[](int i) {return data[i];} const double operator[](int i) const {return data[i];} double3& operator=(const double3& a) { - data[0] = a.data[0]; - data[1] = a.data[1]; - data[2] = a.data[2]; + x = a.x; + y = a.y; + z = a.z; return *this; } double3& operator+=(const double3& a) { - data[0] += a.data[0]; - data[1] += a.data[1]; - data[2] += a.data[2]; + x += a.x; + y += a.y; + z += a.z; return *this; } double3& operator-=(const double3& a) { - data[0] -= a.data[0]; - data[1] -= a.data[1]; - data[2] -= a.data[2]; + x -= a.x; + y -= a.y; + z -= a.z; return *this; } double3& operator/=(const double& c) { - data[0] /= c; - data[1] /= c; - data[2] /= c; + x /= c; + y /= c; + z /= c; return *this; } double norm2() const { - return data[0]*data[0]+data[1]*data[1]+data[2]*data[2]; + return x*x + y*y + z*z; } double norm() const { - return sqrt(data[0]*data[0]+data[1]*data[1]+data[2]*data[2]); + return sqrt(x*x + y*y + z*z); } operator double*() {return data;} }; inline double3 operator*(const double& c, const double3& a) { - return double3(a.data[0]*c, a.data[1]*c, a.data[2]*c); + return double3(a.x*c, a.y*c, a.z*c); } inline double3 operator*(const double3& a, const double& c) { - return double3(a.data[0]*c, a.data[1]*c, a.data[2]*c); + return double3(a.x*c, a.y*c, a.z*c); } inline double operator*(const double3& a, const double3& b) { - return a.data[0]*b.data[0]+a.data[1]*b.data[1]+a.data[2]*b.data[2]; + return a.x*b.x+a.y*b.y+a.z*b.z; } inline double3 operator/(const double3& a, const double& c) { - return double3(a.data[0]/c, a.data[1]/c, a.data[2]/c); + return double3(a.x/c, a.y/c, a.z/c); } inline double3 operator+(const double3& a, const double3& b) { - return double3(a.data[0]+b.data[0], a.data[1]+b.data[1], a.data[2]+b.data[2]); + return double3(a.x+b.x, a.y+b.y, a.z+b.z); } inline double3 operator-(const double3& a, const double3& b) { - return double3(a.data[0]-b.data[0], a.data[1]-b.data[1], a.data[2]-b.data[2]); + return double3(a.x-b.x, a.y-b.y, a.z-b.z); } diff --git a/io.cpp b/io.cpp index e739e30..ea496c4 100644 --- a/io.cpp +++ b/io.cpp @@ -174,9 +174,9 @@ void h5_write(const std::string file_name, const int step_num, const int N, cons write_dataset("X", 2, (double*)x); write_dataset("V", 2, (double*)v); - bool write_pot = (extra_mode ) % 2; - bool write_acc = (extra_mode >> 1) % 2; - bool write_jrk = (extra_mode >> 2) % 2; + bool write_pot = (extra_mode ) & 1; + bool write_acc = (extra_mode >> 1) & 1; + bool write_jrk = (extra_mode >> 2) & 1; if (write_pot) write_dataset("POT", 1, (double*)pot); if (write_acc) write_dataset("ACC", 2, (double*)acc); if (write_jrk) write_dataset("JRK", 2, (double*)jrk); diff --git a/phigrape.cpp b/phigrape.cpp index 8e43da3..20bc500 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -84,7 +84,6 @@ Config *config; #include #include -#define G6_NPIPE 2048 #include "grape6.h" #include @@ -165,6 +164,137 @@ void get_CPU_time(double *time_real, double *time_user, double *time_syst) *time_user = *time_real; } + + +void two_body_gravity( + const double m1, const double3 x1, const double3 v1, + const double m2, const double3 x2, const double3 v2, + const double eps, + double& pot1, double3& acc1, double3& jrk1, + double& pot2, double3& acc2, double3& jrk2) +{ + double3 dx = x1 - x2; + double3 dv = v1 - v2; + double r2 = dx.norm2() + eps*eps; + double r = sqrt(r2); + double r3 = r2*r; + double r4 = r2*r2; + double RP = 3*(dx*dv)/r; + + pot1 = -m2/r; + pot2 = -m1/r; + acc1 = -m2*dx/r3; + acc2 = m1*dx/r3; + jrk1 = -m2*(dv/r3 - RP*dx/r4); + jrk2 = m1*(dv/r3 - RP*dx/r4); +} + + + +class Black_hole_physics { +public: + Black_hole_physics() + : count(0) {} + Black_hole_physics(const double m1, const double m2, const int myRank, const int rootRank) + : m1(m1), m2(m2), count(2), myRank(myRank), rootRank(rootRank) {} + void set_post_newtonian(const double c, const int pn_usage[7]) + { + this->c = c; + std::copy(pn_usage, pn_usage+7, this->pn_usage); + } + void set_spins(const double spin1[3], const double spin2[3]) + { + std::copy(spin1, spin1+3, this->spin1); + std::copy(spin2, spin2+3, this->spin2); + } + void adjust_softening( + const double eps_old, const double eps_new, + const double3& x1, const double3& x2, + const double3& v1, const double3& v2, + double& pot1, double& pot2, + double3& acc1, double3& acc2, + double3& jrk1, double3& jrk2); + + void adjust_post_newtonian( + const double dt_bh, // pn_usage should be const + double3& x1, double3& x2, + double3& v1, double3& v2, + double& pot1, double& pot2, + double3& acc1, double3& acc2, + double3& jrk1, double3& jrk2); +public: //TODO make private + double m1, m2; + int count; + int myRank, rootRank; + double c; + int pn_usage[7]; + double3 a_pn1[7], a_pn2[7], adot_pn1[7], adot_pn2[7]; + double spin1[3], spin2[3]; +}; + +void Black_hole_physics::adjust_softening( + const double eps_old, const double eps_new, + const double3& x1, const double3& x2, + const double3& v1, const double3& v2, + double& pot1, double& pot2, + double3& acc1, double3& acc2, + double3& jrk1, double3& jrk2) +{ + double pot_bh1, pot_bh2; + double3 a_bh1, a_bh2, adot_bh1, adot_bh2; + // calculate and "minus" the BH <-> BH softened pot, acc & jerk + two_body_gravity( + m1, x1, v1, + m2, x2, v2, + eps_old, + pot_bh1, a_bh1, adot_bh1, + pot_bh2, a_bh2, adot_bh2); + pot1 -= pot_bh1; + pot2 -= pot_bh2; + acc1 -= a_bh1; + acc2 -= a_bh2; + jrk1 -= adot_bh1; + jrk2 -= adot_bh2; + + // calculate and "plus" the new BH <-> BH unsoftened pot, acc, jerk + two_body_gravity( + m1, x1, v1, + m2, x2, v2, + eps_new, + pot_bh1, a_bh1, adot_bh1, + pot_bh2, a_bh2, adot_bh2); + pot1 += pot_bh1; + pot2 += pot_bh2; + acc1 += a_bh1; + acc2 += a_bh2; + jrk1 += adot_bh1; + jrk2 += adot_bh2; +} + +void Black_hole_physics::adjust_post_newtonian( + const double dt_bh, // pn_usage should be const + double3& x1, double3& x2, + double3& v1, double3& v2, + double& pot1, double& pot2, + double3& acc1, double3& acc2, + double3& jrk1, double3& jrk2) +{ + // calculate and "plus" the new BH <-> BH : PN1, PN2, PN2.5, PN3, PN3.5 : acc, jerk + int tmp; + tmp = calc_force_pn_BH(m1, x1, v1, spin1, + m2, x2, v2, spin2, + c, dt_bh, pn_usage, + (double(*)[3])a_pn1, (double(*)[3])adot_pn1, + (double(*)[3])a_pn2, (double(*)[3])adot_pn2, myRank, rootRank); + if (tmp == 505) { + exit(-1); // Very ugly way to terminate + } + acc1 += a_pn1[1] + a_pn1[2] + a_pn1[3] + a_pn1[4] + a_pn1[5] + a_pn1[6]; + acc2 += a_pn2[1] + a_pn2[2] + a_pn2[3] + a_pn2[4] + a_pn2[5] + a_pn2[6]; + jrk1 += adot_pn1[1] + adot_pn1[2] + adot_pn1[3] + adot_pn1[4] + adot_pn1[5] + adot_pn1[6]; + jrk2 += adot_pn2[1] + adot_pn2[2] + adot_pn2[3] + adot_pn2[4] + adot_pn2[5] + adot_pn2[6]; +} + void write_bh_data(double time_cur, double m[], double3 x[], double3 v[], double pot[], double3 a[], double3 adot[], double dt[]) { if (config->live_smbh_count == 2) { @@ -679,59 +809,25 @@ inline void adjust_bsmbh_softening(const double eps, const double eps_bh, const int main(int argc, char *argv[]) { - int name_proc, n_proc=1, myRank=0, rootRank=0, cur_rank, - diskstep=0, power, jjj, iii, - skip_con=0, tmp_i; + int skip_con=0; // skip_con should just be a static in the energy control function - double dt_disk, dt_contr, t_disk=0.0, t_contr=0.0, - dt_bh, t_bh=0.0, - t_end, time_cur, dt_min, dt_max, min_t, min_t_loc, - eta_s, eta, eta_bh, - E_tot_0, E_tot_corr_0, E_tot_corr_sd_0, + double E_tot_0, E_tot_corr_0, E_tot_corr_sd_0, rcm_sum=0.0, vcm_sum=0.0, - eps, - a2_mod, adot2_mod, - dt_tmp, dt2half, dt3over6, timesteps=0.0, n_act_sum=0.0, n_act_distr[N_MAX]; - double3 xcm, vcm, mom, - xdc, vdc, - a2, a3, a2dot1; - - char processor_name[MPI_MAX_PROCESSOR_NAME], - inp_fname[30]; - - /* global variables */ - - Source_particle_list source_particle_list(N_MAX); - - int N; - int *ind = source_particle_list.ind; - double *m = source_particle_list.m; - double3 *x = source_particle_list.x; - double3 *v = source_particle_list.v; - double *pot = source_particle_list.pot; - double3 *a = source_particle_list.a; - double3 *adot = source_particle_list.adot; - double *t = source_particle_list.t; - double *dt = source_particle_list.dt; - - /* local variables */ - int n_loc; + double3 xcm, vcm, xdc, vdc; // these should go away /* data for active particles */ - int n_act, ind_act[N_MAX]; double t_act[N_MAX], pot_act_new[N_MAX], pot_act_tmp[N_MAX]; - double3 a_act[N_MAX], adot_act[N_MAX], - x_act_new[N_MAX], v_act_new[N_MAX], - a_act_new[N_MAX], adot_act_new[N_MAX], - a_act_tmp[N_MAX], adot_act_tmp[N_MAX];; - - FILE *out; + // x_act_new and v_act_new arrays hold the predicted position and velocity of i-particles, which is later corrected before moving into the j-particle memory. The _old arrays hold the previous values which are needed to calculate the high derivatives. The _old arrays hold the previous values which are needed to calculate the high derivatives. The [a,adot]_act_tmp arrays hold the calculation results from each node. The [a,adot]_act_new arrays hold the reduced calculation results from all nodes. + double3 x_act_new[N_MAX], v_act_new[N_MAX], + a_act_old[N_MAX], adot_act_old[N_MAX], + a_act_tmp[N_MAX], adot_act_tmp[N_MAX], + a_act_new[N_MAX], adot_act_new[N_MAX]; double pot_ext[N_MAX], pot_act_ext[N_MAX]; // for all EXTPOT @@ -742,10 +838,6 @@ int main(int argc, char *argv[]) int inf_event[N_MAX]; double3 x_bbhc, v_bbhc; - /* some local settings for G6a board's */ - - int clusterid, numGPU, npipe=G6_NPIPE; - int new_tunit=51, new_xunit=51; double3 zeros = {0, 0, 0}; // Dummy; can't really be const because of the GRAPE interface. @@ -756,13 +848,15 @@ int main(int argc, char *argv[]) /* Init MPI */ MPI_Init(&argc, &argv); - /* Define the total number of processors */ + /* Define the total number of processors and the Rank of each processors */ + int n_proc, myRank; + const int rootRank = 0; MPI_Comm_size(MPI_COMM_WORLD, &n_proc); - - /* Define of the Rank of each processors */ MPI_Comm_rank(MPI_COMM_WORLD, &myRank); /* Define the processors names */ + int name_proc; + char processor_name[MPI_MAX_PROCESSOR_NAME]; MPI_Get_processor_name(processor_name, &name_proc); /* Print the Rank and the names of processors */ @@ -771,10 +865,23 @@ int main(int argc, char *argv[]) /* Wait to all processors to finish his works... */ MPI_Barrier(MPI_COMM_WORLD); - /* read the input parameters to the rootRank */ - + /* read the input parameters */ config = new Config("phigrape.conf"); + Source_particle_list source_particle_list(N_MAX); + + int *ind = source_particle_list.ind; + double *m = source_particle_list.m; + double3 *x = source_particle_list.x; + double3 *v = source_particle_list.v; + double *pot = source_particle_list.pot; + double3 *a = source_particle_list.a; + double3 *adot = source_particle_list.adot; + double *t = source_particle_list.t; + double *dt = source_particle_list.dt; + + int diskstep, N; + double time_cur; if (is_hdf5(config->input_file_name)) { #ifndef HAS_HDF5 fprintf(stderr, "ERROR: input file is in HDF5 format, but the code was compiled without HDF5 support\n"); @@ -784,15 +891,14 @@ int main(int argc, char *argv[]) } else ascii_read(config->input_file_name, &diskstep, &N, &time_cur, m, x, v); - std::iota(ind, ind+N, 0); - eps = config->eps; - eta = config->eta; - t_end = config->t_end; - dt_disk = config->dt_disk; - dt_contr = config->dt_contr; - dt_bh = config->dt_bh; + double eps = config->eps; + double eta = config->eta; + double t_end = config->t_end; + double dt_disk = config->dt_disk; + double dt_contr = config->dt_contr; + double dt_bh = config->dt_bh; if (myRank == rootRank) { if (config->binary_smbh_influence_sphere_output) for (int i=0; ilive_smbh_output && (config->live_smbh_count > 0)) { out = fopen("bh.dat", "w"); fclose(out); @@ -831,10 +932,7 @@ int main(int argc, char *argv[]) out = fopen("bbh_inf.dat", "w"); fclose(out); } - - } else { // if (diskstep == 0) - - } // if (diskstep == 0) + } get_CPU_time(&CPU_time_real0, &CPU_time_user0, &CPU_time_syst0); @@ -861,7 +959,15 @@ int main(int argc, char *argv[]) external_gravity_components.push_back(&ext_halo_plummer); external_gravity_components.push_back(&ext_log_halo); external_gravity_components.push_back(&ext_dehnen); + bool has_external_gravity = false; + for (auto component : external_gravity_components) { + if (component->is_active) { + has_external_gravity = true; + break; + } + } + if (has_external_gravity) printf("External Potential: \n\n"); if (ext_bulge.is_active) printf("m_bulge = %.4E b_bulge = %.4E\n", config->ext_m_bulge*normalization_mass, config->ext_b_bulge*normalization_length); if (ext_disk.is_active) printf("m_disk = %.4E a_disk = %.4E b_disk = %.4E\n", config->ext_m_disk*normalization_mass, config->ext_a_disk*normalization_length, config->ext_b_disk*normalization_length); if (ext_halo_plummer.is_active) printf("m_halo = %.4E b_halo = %.4E\n", config->ext_m_halo_plummer*normalization_mass, config->ext_b_halo_plummer*normalization_length); @@ -870,22 +976,14 @@ int main(int argc, char *argv[]) printf("\n"); fflush(stdout); - eta_s = eta/ETA_S_CORR; - eta_bh = eta/ETA_BH_CORR; + double eta_bh = eta/ETA_BH_CORR; - dt_min = 1.0*pow(2.0, DTMINPOWER); - dt_max = 1.0*pow(2.0, DTMAXPOWER); + const double dt_min = pow(2, DTMINPOWER); + const double dt_max = std::min({dt_disk, dt_contr, pow(2, DTMAXPOWER)}); - if (dt_disk == dt_contr) - dt_max = dt_contr; - else - dt_max = MIN(dt_disk, dt_contr); - - if (dt_max > 1.0) dt_max = 1.0; - - t_disk = dt_disk*(1.0+floor(time_cur/dt_disk)); - t_contr = dt_contr*(1.0+floor(time_cur/dt_contr)); - t_bh = dt_bh*(1.0+floor(time_cur/dt_bh)); + double t_disk = dt_disk*(1+floor(time_cur/dt_disk)); + double t_contr = dt_contr*(1+floor(time_cur/dt_contr)); + double t_bh = dt_bh*(1+floor(time_cur/dt_bh)); if (myRank == rootRank) { printf("t_disk = %.6E t_contr = %.6E t_bh = %.6E \n", t_disk, t_contr, t_bh); @@ -896,15 +994,12 @@ int main(int argc, char *argv[]) std::fill(t, t+N, time_cur); std::fill(dt, dt+N, dt_min); - n_loc = N/n_proc; - - Calc_self_grav calc_self_grav(N, n_loc, clusterid, npipe, eps); - - Active_search active_search(myRank, n_proc, n_loc, N); - /* Wait to all processors to finish his works... */ MPI_Barrier(MPI_COMM_WORLD); + + /* some local settings for G6a boards */ + int clusterid, numGPU; if (config->devices_per_node==0) { MPI_Comm shmcomm; MPI_Comm_split_type(MPI_COMM_WORLD, MPI_COMM_TYPE_SHARED, 0, MPI_INFO_NULL, &shmcomm); @@ -919,10 +1014,23 @@ int main(int argc, char *argv[]) /* init the local GRAPEs */ g6_open(clusterid); - npipe = g6_npipes(); + int npipe = g6_npipes(); g6_set_tunit(new_tunit); g6_set_xunit(new_xunit); + int n_loc = N/n_proc; + Calc_self_grav calc_self_grav(N, n_loc, clusterid, npipe, eps); + Active_search active_search(myRank, n_proc, n_loc, N); + Black_hole_physics black_hole_physics; + if (config->live_smbh_count == 1) + black_hole_physics = Black_hole_physics(m[0], 0, myRank, rootRank); + else if (config->live_smbh_count == 2) + black_hole_physics = Black_hole_physics(m[0], m[1], myRank, rootRank); + if (config->binary_smbh_pn) { + black_hole_physics.set_post_newtonian(config->pn_c, config->pn_usage.data()); + if (config->pn_usage[6]) black_hole_physics.set_spins(config->smbh1_spin.data(), config->smbh2_spin.data()); + } + #ifdef ETICS grapite_read_particle_tags(N, config->grapite_mask_file_name.c_str(), myRank, n_loc); grapite_set_dt_exp(config->dt_scf); @@ -945,33 +1053,23 @@ int main(int argc, char *argv[]) grapite_cep_index = grapite_get_cep_index(); if (grapite_cep_index >= 0) { grapite_calc_center(N, m, (double(*)[3])x, (double(*)[3])v, xcm, vcm, xdc, vdc); - memcpy(x[grapite_cep_index], xdc, 3*sizeof(double)); - memcpy(v[grapite_cep_index], vdc, 3*sizeof(double)); + x[grapite_cep_index] = xdc; + v[grapite_cep_index] = vdc; grapite_update_cep(time_cur, xdc, vdc, zeros, zeros); } #endif /* define the all particles as a active on all the processors for the first time grav calc. */ - n_act = N; - - for (int i=0; ilive_smbh_custom_eps >= 0) { - - m_bh1 = m[i_bh1]; - m_bh2 = m[i_bh2]; - - x_bh1 = x[i_bh1]; - v_bh1 = v[i_bh1]; - - x_bh2 = x[i_bh2]; - v_bh2 = v[i_bh2]; - - // calculate and "minus" the BH <-> BH _softened_ pot, acc & jerk - - calc_force_n_BH(m_bh1, x_bh1, v_bh1, - m_bh2, x_bh2, v_bh2, - eps, - &pot_bh1, a_bh1, adot_bh1, - &pot_bh2, a_bh2, adot_bh2); - - pot[i_bh1] -= pot_bh1; - pot[i_bh2] -= pot_bh2; - - a[i_bh1] -= a_bh1; - a[i_bh2] -= a_bh2; - - adot[i_bh1] -= adot_bh1; - adot[i_bh2] -= adot_bh2; - - // calculate and "plus" the new BH <-> BH _unsoftened_ pot, acc, jerk - - calc_force_n_BH(m_bh1, x_bh1, v_bh1, - m_bh2, x_bh2, v_bh2, - config->live_smbh_custom_eps, - &pot_bh1, a_bh1, adot_bh1, - &pot_bh2, a_bh2, adot_bh2); - - pot[i_bh1] += pot_bh1; - pot[i_bh2] += pot_bh2; - - a[i_bh1] += a_bh1; - a[i_bh2] += a_bh2; - - adot[i_bh1] += adot_bh1; - adot[i_bh2] += adot_bh2; - } + if (config->live_smbh_custom_eps >= 0) black_hole_physics.adjust_softening(eps, config->live_smbh_custom_eps, x[0], x[1], v[0], v[1], pot[0], pot[1], a[0], a[1], adot[0], adot[1]); if (config->binary_smbh_pn) { // calculate and "plus" the new BH <-> BH : PN1, PN2, PN2.5, PN3, PN3.5 : acc, jerk - - tmp_i = calc_force_pn_BH(m[i_bh1], x[i_bh1], v[i_bh1], config->smbh1_spin.data(), - m[i_bh2], x[i_bh2], v[i_bh2], config->smbh2_spin.data(), - config->pn_c, dt[i_bh1], config->pn_usage.data(), - (double(*)[3])a_pn1, (double(*)[3])adot_pn1, - (double(*)[3])a_pn2, (double(*)[3])adot_pn2, myRank, rootRank); + int tmp; + tmp = calc_force_pn_BH(m[i_bh1], x[i_bh1], v[i_bh1], config->smbh1_spin.data(), + m[i_bh2], x[i_bh2], v[i_bh2], config->smbh2_spin.data(), + config->pn_c, dt[i_bh1], config->pn_usage.data(), + (double(*)[3])a_pn1, (double(*)[3])adot_pn1, + (double(*)[3])a_pn2, (double(*)[3])adot_pn2, myRank, rootRank); a[i_bh1] += a_pn1[1] + a_pn1[2] + a_pn1[3] + a_pn1[4] + a_pn1[5] + a_pn1[6]; a[i_bh2] += a_pn2[1] + a_pn2[2] + a_pn2[3] + a_pn2[4] + a_pn2[5] + a_pn2[6]; @@ -1043,7 +1097,7 @@ int main(int argc, char *argv[]) adot[i_bh2] += adot_pn2[1] + adot_pn2[2] + adot_pn2[3] + adot_pn2[4] + adot_pn2[5] + adot_pn2[6]; if (myRank == rootRank) { - if (tmp_i == 505) { + if (tmp == 505) { printf("PN RSDIST: %.8E \t %.8E \n", timesteps, time_cur); fflush(stdout); exit(-1); @@ -1052,7 +1106,7 @@ int main(int argc, char *argv[]) } } - calc_ext_grav(external_gravity_components, n_act, x, v, pot_ext, a, adot); + calc_ext_grav(external_gravity_components, N, x, v, pot_ext, a, adot); /* Wait to all processors to finish his works... */ MPI_Barrier(MPI_COMM_WORLD); @@ -1074,8 +1128,8 @@ int main(int argc, char *argv[]) if (grapite_cep_index >= 0) { grapite_calc_center(N, m, (double(*)[3])x, (double(*)[3])v, xcm, vcm, xdc, vdc); - memcpy(x[grapite_cep_index], xdc, 3*sizeof(double)); - memcpy(v[grapite_cep_index], vdc, 3*sizeof(double)); + x[grapite_cep_index] = xdc; + v[grapite_cep_index] = vdc; grapite_update_cep(time_cur, xdc, vdc, a[grapite_cep_index], adot[grapite_cep_index]); } #endif @@ -1086,13 +1140,14 @@ int main(int argc, char *argv[]) /* Define initial timestep for all particles on all nodes */ for (int j=0; jlive_smbh_count == 2) { - if (config->live_smbh_custom_eps >= 0) { - adjust_bsmbh_softening(eps, config->live_smbh_custom_eps, i_bh1, i_bh2, m[0], m[1], x_act_new, v_act_new, pot_act_new, a_act_new, adot_act_new); - } + //if (config->live_smbh_custom_eps >= 0) adjust_bsmbh_softening(eps, config->live_smbh_custom_eps, i_bh1, i_bh2, m[0], m[1], x_act_new, v_act_new, pot_act_new, a_act_new, adot_act_new); + if (config->live_smbh_custom_eps >= 0) black_hole_physics.adjust_softening(eps, config->live_smbh_custom_eps, x_act_new[i_bh1], x_act_new[i_bh2], v_act_new[i_bh1], v_act_new[i_bh2], pot_act_new[i_bh1], pot_act_new[i_bh2], a_act_new[i_bh1], a_act_new[i_bh2], adot_act_new[i_bh1], adot_act_new[i_bh2]); + + //TODO the below works but it interferes with the printing + /* if (config->binary_smbh_pn) black_hole_physics.adjust_post_newtonian( + dt[i_bh1], + x_act_new[i_bh1], x_act_new[i_bh2], + v_act_new[i_bh1], v_act_new[i_bh2], +pot_act_new[i_bh1], pot_act_new[i_bh2], a_act_new[i_bh1], a_act_new[i_bh2], adot_act_new[i_bh1], adot_act_new[i_bh2]); */ if (config->binary_smbh_pn) { // calculate and "plus" the new BH <-> BH : PN1, PN2, PN2.5, PN3, PN3.5 : acc, jerk - - tmp_i = calc_force_pn_BH(m[0], x_act_new[i_bh1], v_act_new[i_bh1], config->smbh1_spin.data(), - m[1], x_act_new[i_bh2], v_act_new[i_bh2], config->smbh2_spin.data(), - config->pn_c, dt[i_bh1], config->pn_usage.data(), - (double(*)[3])a_pn1, (double(*)[3])adot_pn1, - (double(*)[3])a_pn2, (double(*)[3])adot_pn2, myRank, rootRank); + int tmp; + tmp = calc_force_pn_BH(m[0], x_act_new[i_bh1], v_act_new[i_bh1], config->smbh1_spin.data(), + m[1], x_act_new[i_bh2], v_act_new[i_bh2], config->smbh2_spin.data(), + config->pn_c, dt[i_bh1], config->pn_usage.data(), + (double(*)[3])a_pn1, (double(*)[3])adot_pn1, + (double(*)[3])a_pn2, (double(*)[3])adot_pn2, myRank, rootRank); a_act_new[i_bh1] += a_pn1[1] + a_pn1[2] + a_pn1[3] + a_pn1[4] + a_pn1[5] + a_pn1[6]; a_act_new[i_bh2] += a_pn2[1] + a_pn2[2] + a_pn2[3] + a_pn2[4] + a_pn2[5] + a_pn2[6]; @@ -1326,7 +1387,7 @@ int main(int argc, char *argv[]) adot_act_new[i_bh2] += adot_pn2[1] + adot_pn2[2] + adot_pn2[3] + adot_pn2[4] + adot_pn2[5] + adot_pn2[6]; if (myRank == rootRank) { - if (tmp_i == 505) { + if (tmp == 505) { printf("PN RSDIST: TS = %.8E \t t = %.8E \n", timesteps, time_cur); fflush(stdout); exit(-1); @@ -1348,10 +1409,10 @@ int main(int argc, char *argv[]) // NOTICE looks like we're doing three unrelated things in this loop: (1) correcting positions and velocities (2) calculating new steps, and (3) putting the corrected values from the _act_new back in the _act arrays. // After going back to the _act arrays they don't do much before they go back to the main arrays, so this copy seems redundant (the SMBH influence sphere printout needs these values but it should be a function anyway). // TODO split this loop into the three tasks it is doing, and remove the redundancy. - dt_tmp = min_t - t_act[i]; + double dt_tmp = min_t - t_act[i]; double3 a2, a3; - calc_high_derivatives(dt_tmp, a_act[i], a_act_new[i], adot_act[i], adot_act_new[i], &a2, &a3); + calc_high_derivatives(dt_tmp, a_act_old[i], a_act_new[i], adot_act_old[i], adot_act_new[i], &a2, &a3); corrector(dt_tmp, a2, a3, &x_act_new[i], &v_act_new[i]); @@ -1365,7 +1426,7 @@ int main(int argc, char *argv[]) //TODO the below should be moved to a function if (dt_new < dt_min) dt_tmp = dt_min; if ((dt_new < dt_tmp) && (dt_new > dt_min)) { - power = log(dt_new)/log(2.0) - 1; + int power = log(dt_new)/log(2.0) - 1; dt_tmp = pow(2.0, (double)power); // TODO why is this casting needed here? } @@ -1420,13 +1481,12 @@ int main(int argc, char *argv[]) #ifdef ETICS if (ind_act[i] == grapite_cep_index) grapite_update_cep(t[grapite_cep_index], x[grapite_cep_index], v[grapite_cep_index], a[grapite_cep_index], adot[grapite_cep_index]); // All ranks should do it. #endif - cur_rank = ind_act[i]/n_loc; + int cur_rank = ind_act[i]/n_loc; if (myRank == cur_rank) { int j_act = ind_act[i]; - jjj = ind_act[i] - myRank*n_loc; - - g6_set_j_particle(clusterid, jjj, ind_act[i], t[j_act], dt[j_act], m[j_act], zeros, adot[j_act]*(1./6.), a[j_act]*0.5, v[j_act], x[j_act]); + int address = ind_act[i] - myRank*n_loc; + g6_set_j_particle(clusterid, address, ind_act[i], t[j_act], dt[j_act], m[j_act], zeros, adot[j_act]*(1./6.), a[j_act]*0.5, v[j_act], x[j_act]); } /* if (myRank == cur_rank) */ @@ -1471,7 +1531,7 @@ int main(int argc, char *argv[]) /* possible OUT for timing !!! */ #ifdef TIMING - out = fopen("timing.dat", "a"); + FILE *out = fopen("timing.dat", "a"); DT_TOT = DT_ACT_DEF1 + DT_ACT_DEF2 + DT_ACT_DEF3 + DT_ACT_PRED + DT_ACT_GRAV + DT_EXT_GRAV + DT_GMC_GRAV + @@ -1500,8 +1560,8 @@ int main(int argc, char *argv[]) // We are /inside/ a control step, so all particles must be synchronized; we can safely calculate their density centre. The acceleration and jerk currently in the memory are for the predicted position of the CEP, by calling grapite_calc_center we "correct" the position and velocity, but not the gravity at that point. if (grapite_cep_index >= 0) { grapite_calc_center(N, m, (double(*)[3])x, (double(*)[3])v, xcm, vcm, xdc, vdc); - memcpy(x[grapite_cep_index], xdc, 3*sizeof(double)); - memcpy(v[grapite_cep_index], vdc, 3*sizeof(double)); + x[grapite_cep_index] = xdc; + v[grapite_cep_index] = vdc; grapite_update_cep(time_cur, xdc, vdc, a[grapite_cep_index], adot[grapite_cep_index]); } #endif From 19ce85da885be5b102fc2f4faca6cd1608c4fee2 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Sun, 19 Apr 2020 14:16:03 -0400 Subject: [PATCH 43/65] Moved out almost all BH-related stuff to a different compilation unit --- Makefile | 2 +- black_holes.cpp | 255 +++++++++++++++++++++++++++++++++ black_holes.h | 59 ++++++++ phigrape.cpp | 373 +++--------------------------------------------- 4 files changed, 331 insertions(+), 358 deletions(-) create mode 100644 black_holes.cpp create mode 100644 black_holes.h diff --git a/Makefile b/Makefile index 6e4538f..06637d0 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,7 @@ CPPFLAGS += -DHAS_HDF5 LIB += -lhdf5 -lz -ldl default: - $(MPICXX) $(CPPFLAGS) $(CXXFLAGS) $(INC) external.cpp io.cpp config.cpp phigrape.cpp -o $(EXECUTABLE) $(LIB) + $(MPICXX) $(CPPFLAGS) $(CXXFLAGS) $(INC) black_holes.cpp external.cpp io.cpp config.cpp phigrape.cpp -o $(EXECUTABLE) $(LIB) yebisu: CPPFLAGS := $(filter-out -DETICS, $(CPPFLAGS)) yebisu: default diff --git a/black_holes.cpp b/black_holes.cpp new file mode 100644 index 0000000..48685a6 --- /dev/null +++ b/black_holes.cpp @@ -0,0 +1,255 @@ +#include +#include +#include "black_holes.h" + + +// TODO do not include c files! +#define SQR(x) ((x)*(x)) +double L[3]; // needed in pn_bh_spin.c +#include "n_bh.c" +#include "pn_bh_spin.c" + +void two_body_gravity( + const double m1, const double3 x1, const double3 v1, + const double m2, const double3 x2, const double3 v2, + const double eps, + double& pot1, double3& acc1, double3& jrk1, + double& pot2, double3& acc2, double3& jrk2) +{ + double3 dx = x1 - x2; + double3 dv = v1 - v2; + double r2 = dx.norm2() + eps*eps; + double r = sqrt(r2); + double r3 = r2*r; + double r4 = r2*r2; + double RP = 3*(dx*dv)/r; + + pot1 = -m2/r; + pot2 = -m1/r; + acc1 = -m2*dx/r3; + acc2 = m1*dx/r3; + jrk1 = -m2*(dv/r3 - RP*dx/r4); + jrk2 = m1*(dv/r3 - RP*dx/r4); +} + +// class Black_hole_physics { +// public: +// Black_hole_physics() +// : count(0), c(0) {} +// Black_hole_physics(const double m1, const double m2, const int myRank, const int rootRank) +// : m1(m1), m2(m2), count(2), c(0), myRank(myRank), rootRank(rootRank) {} +// void set_post_newtonian(const double c, const int pn_usage[7]) +// { +// this->c = c; +// std::copy(pn_usage, pn_usage+7, this->pn_usage); +// } +// void set_spins(const double spin1[3], const double spin2[3]) +// { +// std::copy(spin1, spin1+3, this->bbh_grav.spin1); +// std::copy(spin2, spin2+3, this->bbh_grav.spin2); +// } +// void set_xv(const double3& x1, const double3& x2, const double3& v1, const double3& v2) +// { +// this->x1 = x1; +// this->x2 = x2; +// this->v1 = v1; +// this->v2 = v2; +// } +// void set_softening(const double eps_old, const double eps_new) +// { +// this->eps_old = eps_old; +// this->eps_new = eps_new; +// } +// void adjust_softening( +// double& pot1, double& pot2, +// double3& acc1, double3& acc2, +// double3& jrk1, double3& jrk2); + +// void adjust_post_newtonian( +// const double dt_bh, // pn_usage should be const +// double3& acc1, double3& acc2, +// double3& jrk1, double3& jrk2); +// void write_bh_data(double time_cur, double m[], double3 x[], double3 v[], double pot[], double3 a[], double3 adot[], double dt[]); +// public: //TODO make private +// double m1, m2; +// int count; +// int myRank, rootRank; +// double eps_old, eps_new; +// double3 x1, v1, x2, v2; +// double c; +// int pn_usage[7]; +// Bbh_gravity bbh_grav; +// }; + +void Black_hole_physics::adjust_softening( + double& pot1, double& pot2, + double3& acc1, double3& acc2, + double3& jrk1, double3& jrk2) +{ + if (eps_new < 0) return; + // calculate and "minus" the BH <-> BH softened pot, acc & jerk + two_body_gravity( + m1, x1, v1, + m2, x2, v2, + eps_old, + bbh_grav.pot1, bbh_grav.a1, bbh_grav.adot1, + bbh_grav.pot2, bbh_grav.a2, bbh_grav.adot2); + pot1 -= bbh_grav.pot1; + pot2 -= bbh_grav.pot2; + acc1 -= bbh_grav.a1; + acc2 -= bbh_grav.a2; + jrk1 -= bbh_grav.adot1; + jrk2 -= bbh_grav.adot2; + + // calculate and "plus" the new BH <-> BH unsoftened pot, acc, jerk + two_body_gravity( + m1, x1, v1, + m2, x2, v2, + eps_new, + bbh_grav.pot1, bbh_grav.a1, bbh_grav.adot1, + bbh_grav.pot2, bbh_grav.a2, bbh_grav.adot2); + pot1 += bbh_grav.pot1; + pot2 += bbh_grav.pot2; + acc1 += bbh_grav.a1; + acc2 += bbh_grav.a2; + jrk1 += bbh_grav.adot1; + jrk2 += bbh_grav.adot2; +} + +void Black_hole_physics::adjust_post_newtonian( + const double dt_bh, // pn_usage should be const + double3& acc1, double3& acc2, + double3& jrk1, double3& jrk2) +{ + // calculate and "plus" the new BH <-> BH : PN1, PN2, PN2.5, PN3, PN3.5 : acc, jerk + // TODO maybe have the PN terms as local variables here? + int tmp; + tmp = calc_force_pn_BH(m1, x1, v1, bbh_grav.spin1, + m2, x2, v2, bbh_grav.spin2, + c, dt_bh, pn_usage, + (double(*)[3])bbh_grav.a_pn1, (double(*)[3])bbh_grav.adot_pn1, + (double(*)[3])bbh_grav.a_pn2, (double(*)[3])bbh_grav.adot_pn2, myRank, rootRank); + if (tmp == 505) exit(-1); // Very ugly way to terminate + + // NOTE we have these _corr variables accumulating the corrections before + // applying it. It's almost the same but different from applying each + // correction term in a loop. + double3 acc1_corr(0,0,0), acc2_corr(0,0,0), jrk1_corr(0,0,0), jrk2_corr(0,0,0); + for (int i=1; i<7; i++) { + acc1_corr += bbh_grav.a_pn1[i]; + acc2_corr += bbh_grav.a_pn2[i]; + jrk1_corr += bbh_grav.adot_pn1[i]; + jrk2_corr += bbh_grav.adot_pn2[i]; + } + acc1 += acc1_corr; + acc2 += acc2_corr; + jrk1 += jrk1_corr; + jrk2 += jrk2_corr; +} + +void Black_hole_physics::write_bh_data(double time_cur, double m[], double3 x[], double3 v[], double pot[], double3 a[], double3 adot[], double dt[]) +{ + // This function logs data on the black hole(s). It uses both external data + // (the arguments to this function) and optionall internal data to this + // object (the most recently calculated force and post-Newtonian terms). + auto out = fopen("bh.dat", "a"); + if (count == 2) { + for (int i=0; i < 2; i++) { + double3 *a_pn, *adot_pn, a_bh, adot_bh; + double pot_bh; + if (i==0) { + a_pn = bbh_grav.a_pn1; + adot_pn = bbh_grav.adot_pn1; + pot_bh = bbh_grav.pot1; + a_bh = bbh_grav.a1; + adot_bh = bbh_grav.adot1; + } else { + a_pn = bbh_grav.a_pn2; + adot_pn = bbh_grav.adot_pn2; + pot_bh = bbh_grav.pot2; + a_bh = bbh_grav.a2; + adot_bh = bbh_grav.adot2; + } + if (eps_new >= 0) { + fprintf(out, "%.16E \t %.8E \t % .16E % .16E % .16E \t %.16E \t % .16E % .16E % .16E \t %.16E \t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t %.8E \t\t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E ", + time_cur, m[i], + x[i][0], x[i][1], x[i][2], x[i].norm(), + v[i][0], v[i][1], v[i][2], v[i].norm(), + pot[i], + a[i][0], a[i][1], a[i][2], a[i].norm(), + adot[i][0], adot[i][1], adot[i][2], adot[i].norm(), + dt[i], + pot_bh, + a_bh[0], a_bh[1], a_bh[2], a_bh.norm(), + adot_bh[0], adot_bh[1], adot_bh[2], adot_bh.norm()); + if (c > 0) { + fprintf(out, "\t"); + for (int pn_idx=0; pn_idx < 7; pn_idx++) { + fprintf(out, "\t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E ", a_pn[pn_idx][0], a_pn[pn_idx][1], a_pn[pn_idx][2], a_pn[pn_idx].norm(), adot_pn[pn_idx][0], adot_pn[pn_idx][1], adot_pn[pn_idx][2], adot_pn[pn_idx].norm()); + } + } + fprintf(out, "\n"); + } else { + fprintf(out,"%.16E \t %.8E \t % .16E % .16E % .16E \t %.16E \t % .16E % .16E % .16E \t %.16E \t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t %.8E \n", + time_cur, m[i], + x[i][0], x[i][1], x[i][2], x[i].norm(), + v[i][0], v[i][1], v[i][2], v[i].norm(), + pot[i], + a[i][0], a[i][1], a[i][2], a[i].norm(), + adot[i][0], adot[i][1], adot[i][2], adot[i].norm(), + dt[i]); + } + } + fprintf(out, "\n"); + } else if (count == 1) { + fprintf(out,"%.16E \t %.8E \t % .16E % .16E % .16E \t %.16E \t % .16E % .16E % .16E \t %.16E \t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t %.8E \n", + time_cur, m[0], + x[0][0], x[0][1], x[0][2], x[0].norm(), + v[0][0], v[0][1], v[0][2], v[0].norm(), + pot[0], + a[0][0], a[0][1], a[0][2], a[0].norm(), + adot[0][0], adot[0][1], adot[0][2], adot[0].norm(), + dt[0]); + fprintf(out,"\n"); + } + fclose(out); +} + +void write_bh_nb_data(int nb, int smbh_count, double time_cur, int N, double m[], double3 x[], double3 v[]) +{ + //int nb = config->live_smbh_neighbor_number; + // TODO fix below!!! Should be class members. + int ind_sort[30000]; + double var_sort[30000]; + //TODO you don't want and probably don't need to allocate these here. Maybe just need size nb, or maybe use as private variables. + + auto out = fopen("bh_neighbors.dat", "a"); + + /* 1st BH */ + + for (int i_bh=0; i_bh < smbh_count; i_bh++) { + for (int i=0; i +#include "double3.h" + +struct Bbh_gravity { + double pot1, pot2; + double3 a1, a2, adot1, adot2, a_pn1[7], a_pn2[7], adot_pn1[7], adot_pn2[7]; + double spin1[3], spin2[3]; +}; + +class Black_hole_physics { +public: + Black_hole_physics() + : count(0), c(0) {} + Black_hole_physics(const double m1, const double m2, const int myRank, const int rootRank) + : m1(m1), m2(m2), count(2), c(0), myRank(myRank), rootRank(rootRank) {} + void set_post_newtonian(const double c, const int pn_usage[7]) + { + this->c = c; + std::copy(pn_usage, pn_usage+7, this->pn_usage); + } + void set_spins(const double spin1[3], const double spin2[3]) + { + std::copy(spin1, spin1+3, this->bbh_grav.spin1); + std::copy(spin2, spin2+3, this->bbh_grav.spin2); + } + void set_xv(const double3& x1, const double3& x2, const double3& v1, const double3& v2) + { + this->x1 = x1; + this->x2 = x2; + this->v1 = v1; + this->v2 = v2; + } + void set_softening(const double eps_old, const double eps_new) + { + this->eps_old = eps_old; + this->eps_new = eps_new; + } + void adjust_softening( + double& pot1, double& pot2, + double3& acc1, double3& acc2, + double3& jrk1, double3& jrk2); + + void adjust_post_newtonian( + const double dt_bh, // pn_usage should be const + double3& acc1, double3& acc2, + double3& jrk1, double3& jrk2); + void write_bh_data(double time_cur, double m[], double3 x[], double3 v[], double pot[], double3 a[], double3 adot[], double dt[]); +public: //TODO make private + double m1, m2; + int count; + int myRank, rootRank; + double eps_old, eps_new; + double3 x1, v1, x2, v2; + double c; + int pn_usage[7]; + Bbh_gravity bbh_grav; +}; + +void write_bh_nb_data(int nb, int smbh_count, double time_cur, int N, double m[], double3 x[], double3 v[]); diff --git a/phigrape.cpp b/phigrape.cpp index 20bc500..86d8121 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -54,6 +54,7 @@ Version number : 19.04 Last redaction : 2019.04.16 12:55 *****************************************************************************/ #include "double3.h" +#include "black_holes.h" #include "config.h" #include "io.h" #include "external.h" @@ -99,7 +100,7 @@ Config *config; #define N_MAX (32*KB) -double L[3]; // needed in pn_bh_spin.c +// double L[3]; // needed in pn_bh_spin.c // Needed for things related to BHs #include "debug.h" @@ -131,11 +132,11 @@ double3 x_bh1, x_bh2, v_bh1, v_bh2; double pot_bh1, pot_bh2; double3 a_bh1, adot_bh1, a_bh2, adot_bh2; -#include "n_bh.c" +//#include "n_bh.c" -double3 a_pn1[7], adot_pn1[7], a_pn2[7], adot_pn2[7]; +//double3 a_pn1[7], adot_pn1[7], a_pn2[7], adot_pn2[7]; -#include "pn_bh_spin.c" +//#include "pn_bh_spin.c" #ifdef ETICS int grapite_cep_index; @@ -164,248 +165,6 @@ void get_CPU_time(double *time_real, double *time_user, double *time_syst) *time_user = *time_real; } - - -void two_body_gravity( - const double m1, const double3 x1, const double3 v1, - const double m2, const double3 x2, const double3 v2, - const double eps, - double& pot1, double3& acc1, double3& jrk1, - double& pot2, double3& acc2, double3& jrk2) -{ - double3 dx = x1 - x2; - double3 dv = v1 - v2; - double r2 = dx.norm2() + eps*eps; - double r = sqrt(r2); - double r3 = r2*r; - double r4 = r2*r2; - double RP = 3*(dx*dv)/r; - - pot1 = -m2/r; - pot2 = -m1/r; - acc1 = -m2*dx/r3; - acc2 = m1*dx/r3; - jrk1 = -m2*(dv/r3 - RP*dx/r4); - jrk2 = m1*(dv/r3 - RP*dx/r4); -} - - - -class Black_hole_physics { -public: - Black_hole_physics() - : count(0) {} - Black_hole_physics(const double m1, const double m2, const int myRank, const int rootRank) - : m1(m1), m2(m2), count(2), myRank(myRank), rootRank(rootRank) {} - void set_post_newtonian(const double c, const int pn_usage[7]) - { - this->c = c; - std::copy(pn_usage, pn_usage+7, this->pn_usage); - } - void set_spins(const double spin1[3], const double spin2[3]) - { - std::copy(spin1, spin1+3, this->spin1); - std::copy(spin2, spin2+3, this->spin2); - } - void adjust_softening( - const double eps_old, const double eps_new, - const double3& x1, const double3& x2, - const double3& v1, const double3& v2, - double& pot1, double& pot2, - double3& acc1, double3& acc2, - double3& jrk1, double3& jrk2); - - void adjust_post_newtonian( - const double dt_bh, // pn_usage should be const - double3& x1, double3& x2, - double3& v1, double3& v2, - double& pot1, double& pot2, - double3& acc1, double3& acc2, - double3& jrk1, double3& jrk2); -public: //TODO make private - double m1, m2; - int count; - int myRank, rootRank; - double c; - int pn_usage[7]; - double3 a_pn1[7], a_pn2[7], adot_pn1[7], adot_pn2[7]; - double spin1[3], spin2[3]; -}; - -void Black_hole_physics::adjust_softening( - const double eps_old, const double eps_new, - const double3& x1, const double3& x2, - const double3& v1, const double3& v2, - double& pot1, double& pot2, - double3& acc1, double3& acc2, - double3& jrk1, double3& jrk2) -{ - double pot_bh1, pot_bh2; - double3 a_bh1, a_bh2, adot_bh1, adot_bh2; - // calculate and "minus" the BH <-> BH softened pot, acc & jerk - two_body_gravity( - m1, x1, v1, - m2, x2, v2, - eps_old, - pot_bh1, a_bh1, adot_bh1, - pot_bh2, a_bh2, adot_bh2); - pot1 -= pot_bh1; - pot2 -= pot_bh2; - acc1 -= a_bh1; - acc2 -= a_bh2; - jrk1 -= adot_bh1; - jrk2 -= adot_bh2; - - // calculate and "plus" the new BH <-> BH unsoftened pot, acc, jerk - two_body_gravity( - m1, x1, v1, - m2, x2, v2, - eps_new, - pot_bh1, a_bh1, adot_bh1, - pot_bh2, a_bh2, adot_bh2); - pot1 += pot_bh1; - pot2 += pot_bh2; - acc1 += a_bh1; - acc2 += a_bh2; - jrk1 += adot_bh1; - jrk2 += adot_bh2; -} - -void Black_hole_physics::adjust_post_newtonian( - const double dt_bh, // pn_usage should be const - double3& x1, double3& x2, - double3& v1, double3& v2, - double& pot1, double& pot2, - double3& acc1, double3& acc2, - double3& jrk1, double3& jrk2) -{ - // calculate and "plus" the new BH <-> BH : PN1, PN2, PN2.5, PN3, PN3.5 : acc, jerk - int tmp; - tmp = calc_force_pn_BH(m1, x1, v1, spin1, - m2, x2, v2, spin2, - c, dt_bh, pn_usage, - (double(*)[3])a_pn1, (double(*)[3])adot_pn1, - (double(*)[3])a_pn2, (double(*)[3])adot_pn2, myRank, rootRank); - if (tmp == 505) { - exit(-1); // Very ugly way to terminate - } - acc1 += a_pn1[1] + a_pn1[2] + a_pn1[3] + a_pn1[4] + a_pn1[5] + a_pn1[6]; - acc2 += a_pn2[1] + a_pn2[2] + a_pn2[3] + a_pn2[4] + a_pn2[5] + a_pn2[6]; - jrk1 += adot_pn1[1] + adot_pn1[2] + adot_pn1[3] + adot_pn1[4] + adot_pn1[5] + adot_pn1[6]; - jrk2 += adot_pn2[1] + adot_pn2[2] + adot_pn2[3] + adot_pn2[4] + adot_pn2[5] + adot_pn2[6]; -} - -void write_bh_data(double time_cur, double m[], double3 x[], double3 v[], double pot[], double3 a[], double3 adot[], double dt[]) -{ - if (config->live_smbh_count == 2) { - - auto out = fopen("bh.dat", "a"); - - for (int i=0; i < 2; i++) { - double3 *a_pn, *adot_pn, a_bh, adot_bh; - double pot_bh; - if (i==0) { - a_pn = a_pn1; - adot_pn = adot_pn1; - pot_bh = pot_bh1; - a_bh = a_bh1; - adot_bh = adot_bh1; - } else { - a_pn = a_pn2; - adot_pn = adot_pn2; - pot_bh = pot_bh2; - a_bh = a_bh2; - adot_bh = adot_bh2; - } - if (config->live_smbh_custom_eps >= 0) { - fprintf(out, "%.16E \t %.8E \t % .16E % .16E % .16E \t %.16E \t % .16E % .16E % .16E \t %.16E \t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t %.8E \t\t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E ", - time_cur, m[i], - x[i][0], x[i][1], x[i][2], x[i].norm(), - v[i][0], v[i][1], v[i][2], v[i].norm(), - pot[i], - a[i][0], a[i][1], a[i][2], a[i].norm(), - adot[i][0], adot[i][1], adot[i][2], adot[i].norm(), - dt[i], - pot_bh, - a_bh[0], a_bh[1], a_bh[2], a_bh.norm(), - adot_bh[0], adot_bh[1], adot_bh[2], adot_bh.norm()); - if (config->binary_smbh_pn) { - fprintf(out, "\t"); - for (int pn_idx=0; pn_idx < 7; pn_idx++) { - fprintf(out, "\t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E ", a_pn[pn_idx][0], a_pn[pn_idx][1], a_pn[pn_idx][2], a_pn[pn_idx].norm(), adot_pn[pn_idx][0], adot_pn[pn_idx][1], adot_pn[pn_idx][2], adot_pn[pn_idx].norm()); - } - } - fprintf(out, "\n"); - } else { - fprintf(out,"%.16E \t %.8E \t % .16E % .16E % .16E \t %.16E \t % .16E % .16E % .16E \t %.16E \t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t %.8E \n", - time_cur, m[i], - x[i][0], x[i][1], x[i][2], x[i].norm(), - v[i][0], v[i][1], v[i][2], v[i].norm(), - pot[i], - a[i][0], a[i][1], a[i][2], a[i].norm(), - adot[i][0], adot[i][1], adot[i][2], adot[i].norm(), - dt[i]); - } - } - fprintf(out, "\n"); - fclose(out); - } else if (config->live_smbh_count == 1) { - auto out = fopen("bh.dat", "a"); - double tmp_r = sqrt( SQR(x[0][0]) + SQR(x[0][1]) + SQR(x[0][2]) ); - double tmp_v = sqrt( SQR(v[0][0]) + SQR(v[0][1]) + SQR(v[0][2]) ); - double tmp_a = sqrt( SQR(a[0][0]) + SQR(a[0][1]) + SQR(a[0][2]) ); - double tmp_adot = sqrt( SQR(adot[0][0]) + SQR(adot[0][1]) + SQR(adot[0][2]) ); - fprintf(out,"%.16E \t %.8E \t % .16E % .16E % .16E \t %.16E \t % .16E % .16E % .16E \t %.16E \t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t %.8E \n", - time_cur, m[0], - x[0][0], x[0][1], x[0][2], tmp_r, - v[0][0], v[0][1], v[0][2], tmp_v, - pot[0], - a[0][0], a[0][1], a[0][2], tmp_a, - adot[0][0], adot[0][1], adot[0][2], tmp_adot, - dt[0]); - fprintf(out,"\n"); - fclose(out); - } -} - -void write_bh_nb_data(double time_cur, int N, double m[], double3 x[], double3 v[]) -{ - int nb = config->live_smbh_neighbor_number; - int ind_sort[N_MAX]; - double var_sort[N_MAX]; - //TODO you don't want and probably don't need to allocate these here. Maybe just need size nb, or maybe use as private variables. - - auto out = fopen("bh_neighbors.dat", "a"); - - /* 1st BH */ - - for (int i_bh=0; i_bh < config->live_smbh_count; i_bh++) { - for (int i=0; i BH softened pot, acc & jerk - - calc_force_n_BH(m_bh1, x_bh1, v_bh1, - m_bh2, x_bh2, v_bh2, - eps, - &pot_bh1, a_bh1, adot_bh1, - &pot_bh2, a_bh2, adot_bh2); - - pot_act_new[i_bh1] -= pot_bh1; - pot_act_new[i_bh2] -= pot_bh2; - - a_act_new[i_bh1] -= a_bh1; - a_act_new[i_bh2] -= a_bh2; - - adot_act_new[i_bh1] -= adot_bh1; - adot_act_new[i_bh2] -= adot_bh2; - - // calculate and "plus" the new BH <-> BH unsoftened pot, acc, jerk - - calc_force_n_BH(m_bh1, x_bh1, v_bh1, - m_bh2, x_bh2, v_bh2, - eps_bh, - &pot_bh1, a_bh1, adot_bh1, - &pot_bh2, a_bh2, adot_bh2); - - pot_act_new[i_bh1] += pot_bh1; - pot_act_new[i_bh2] += pot_bh2; - - a_act_new[i_bh1] += a_bh1; - a_act_new[i_bh2] += a_bh2; - - adot_act_new[i_bh1] += adot_bh1; - adot_act_new[i_bh2] += adot_bh2; -} - int main(int argc, char *argv[]) { int skip_con=0; // skip_con should just be a static in the energy control function @@ -1030,6 +746,7 @@ int main(int argc, char *argv[]) black_hole_physics.set_post_newtonian(config->pn_c, config->pn_usage.data()); if (config->pn_usage[6]) black_hole_physics.set_spins(config->smbh1_spin.data(), config->smbh2_spin.data()); } + black_hole_physics.set_softening(eps, config->live_smbh_custom_eps); #ifdef ETICS grapite_read_particle_tags(N, config->grapite_mask_file_name.c_str(), myRank, n_loc); @@ -1075,35 +792,9 @@ int main(int argc, char *argv[]) MPI_Barrier(MPI_COMM_WORLD); if (config->live_smbh_count == 2) { - i_bh1 = 0; - i_bh2 = 1; - - if (config->live_smbh_custom_eps >= 0) black_hole_physics.adjust_softening(eps, config->live_smbh_custom_eps, x[0], x[1], v[0], v[1], pot[0], pot[1], a[0], a[1], adot[0], adot[1]); - - if (config->binary_smbh_pn) { - - // calculate and "plus" the new BH <-> BH : PN1, PN2, PN2.5, PN3, PN3.5 : acc, jerk - int tmp; - tmp = calc_force_pn_BH(m[i_bh1], x[i_bh1], v[i_bh1], config->smbh1_spin.data(), - m[i_bh2], x[i_bh2], v[i_bh2], config->smbh2_spin.data(), - config->pn_c, dt[i_bh1], config->pn_usage.data(), - (double(*)[3])a_pn1, (double(*)[3])adot_pn1, - (double(*)[3])a_pn2, (double(*)[3])adot_pn2, myRank, rootRank); - - a[i_bh1] += a_pn1[1] + a_pn1[2] + a_pn1[3] + a_pn1[4] + a_pn1[5] + a_pn1[6]; - a[i_bh2] += a_pn2[1] + a_pn2[2] + a_pn2[3] + a_pn2[4] + a_pn2[5] + a_pn2[6]; - - adot[i_bh1] += adot_pn1[1] + adot_pn1[2] + adot_pn1[3] + adot_pn1[4] + adot_pn1[5] + adot_pn1[6]; - adot[i_bh2] += adot_pn2[1] + adot_pn2[2] + adot_pn2[3] + adot_pn2[4] + adot_pn2[5] + adot_pn2[6]; - - if (myRank == rootRank) { - if (tmp == 505) { - printf("PN RSDIST: %.8E \t %.8E \n", timesteps, time_cur); - fflush(stdout); - exit(-1); - } - } - } + black_hole_physics.set_xv(x[0], x[1], v[0], v[1]); + if (config->live_smbh_custom_eps >= 0) black_hole_physics.adjust_softening(pot[0], pot[1], a[0], a[1], adot[0], adot[1]); + if (config->binary_smbh_pn) black_hole_physics.adjust_post_newtonian(dt[0], a[0], a[1], adot[0], adot[1]); } calc_ext_grav(external_gravity_components, N, x, v, pot_ext, a, adot); @@ -1111,8 +802,6 @@ int main(int argc, char *argv[]) /* Wait to all processors to finish his works... */ MPI_Barrier(MPI_COMM_WORLD); - /* Wait to all processors to finish his works... */ - MPI_Barrier(MPI_COMM_WORLD); /* Energy control... */ if (myRank == rootRank) { @@ -1183,10 +872,10 @@ int main(int argc, char *argv[]) if (myRank == rootRank) { /* Write BH data... */ - if (config->live_smbh_output) write_bh_data(time_cur, m, x, v, pot, a, adot, dt); + if (config->live_smbh_output) black_hole_physics.write_bh_data(time_cur, m, x, v, pot, a, adot, dt); /* Write BH NB data... */ - if (config->live_smbh_neighbor_output) write_bh_nb_data(time_cur, N, m, x, v); + if (config->live_smbh_neighbor_output) write_bh_nb_data(config->live_smbh_neighbor_number, config->live_smbh_count, time_cur, N, m, x, v); } /* if (myRank == rootRank) */ @@ -1361,39 +1050,9 @@ int main(int argc, char *argv[]) #endif if (config->live_smbh_count == 2) { - //if (config->live_smbh_custom_eps >= 0) adjust_bsmbh_softening(eps, config->live_smbh_custom_eps, i_bh1, i_bh2, m[0], m[1], x_act_new, v_act_new, pot_act_new, a_act_new, adot_act_new); - if (config->live_smbh_custom_eps >= 0) black_hole_physics.adjust_softening(eps, config->live_smbh_custom_eps, x_act_new[i_bh1], x_act_new[i_bh2], v_act_new[i_bh1], v_act_new[i_bh2], pot_act_new[i_bh1], pot_act_new[i_bh2], a_act_new[i_bh1], a_act_new[i_bh2], adot_act_new[i_bh1], adot_act_new[i_bh2]); - - //TODO the below works but it interferes with the printing - /* if (config->binary_smbh_pn) black_hole_physics.adjust_post_newtonian( - dt[i_bh1], - x_act_new[i_bh1], x_act_new[i_bh2], - v_act_new[i_bh1], v_act_new[i_bh2], -pot_act_new[i_bh1], pot_act_new[i_bh2], a_act_new[i_bh1], a_act_new[i_bh2], adot_act_new[i_bh1], adot_act_new[i_bh2]); */ - - if (config->binary_smbh_pn) { - // calculate and "plus" the new BH <-> BH : PN1, PN2, PN2.5, PN3, PN3.5 : acc, jerk - int tmp; - tmp = calc_force_pn_BH(m[0], x_act_new[i_bh1], v_act_new[i_bh1], config->smbh1_spin.data(), - m[1], x_act_new[i_bh2], v_act_new[i_bh2], config->smbh2_spin.data(), - config->pn_c, dt[i_bh1], config->pn_usage.data(), - (double(*)[3])a_pn1, (double(*)[3])adot_pn1, - (double(*)[3])a_pn2, (double(*)[3])adot_pn2, myRank, rootRank); - - a_act_new[i_bh1] += a_pn1[1] + a_pn1[2] + a_pn1[3] + a_pn1[4] + a_pn1[5] + a_pn1[6]; - a_act_new[i_bh2] += a_pn2[1] + a_pn2[2] + a_pn2[3] + a_pn2[4] + a_pn2[5] + a_pn2[6]; - - adot_act_new[i_bh1] += adot_pn1[1] + adot_pn1[2] + adot_pn1[3] + adot_pn1[4] + adot_pn1[5] + adot_pn1[6]; - adot_act_new[i_bh2] += adot_pn2[1] + adot_pn2[2] + adot_pn2[3] + adot_pn2[4] + adot_pn2[5] + adot_pn2[6]; - - if (myRank == rootRank) { - if (tmp == 505) { - printf("PN RSDIST: TS = %.8E \t t = %.8E \n", timesteps, time_cur); - fflush(stdout); - exit(-1); - } - } - } + black_hole_physics.set_xv(x_act_new[i_bh1], x_act_new[i_bh2], v_act_new[i_bh1], v_act_new[i_bh2]); + if (config->live_smbh_custom_eps >= 0) black_hole_physics.adjust_softening(pot_act_new[i_bh1], pot_act_new[i_bh2], a_act_new[i_bh1], a_act_new[i_bh2], adot_act_new[i_bh1], adot_act_new[i_bh2]); + if (config->binary_smbh_pn) black_hole_physics.adjust_post_newtonian(dt[i_bh1], a_act_new[i_bh1], a_act_new[i_bh2], adot_act_new[i_bh1], adot_act_new[i_bh2]); } calc_ext_grav(external_gravity_components, n_act, x_act_new, v_act_new, pot_act_ext, a_act_new, adot_act_new); @@ -1508,10 +1167,10 @@ pot_act_new[i_bh1], pot_act_new[i_bh2], a_act_new[i_bh1], a_act_new[i_bh2], adot if (time_cur >= t_bh) { if (myRank == rootRank) { /* Write BH data... */ - if (config->live_smbh_output) write_bh_data(time_cur, m, x, v, pot, a, adot, dt); + if (config->live_smbh_output) black_hole_physics.write_bh_data(time_cur, m, x, v, pot, a, adot, dt); /* Write BH NB data... */ - if (config->live_smbh_neighbor_output) write_bh_nb_data(time_cur, N, m, x, v); + if (config->live_smbh_neighbor_output) write_bh_nb_data(config->live_smbh_neighbor_number, config->live_smbh_count, time_cur, N, m, x, v); } /* if (myRank == rootRank) */ From df5d89a0c8ca564050a7ac5160758c41358b52ee Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Sun, 19 Apr 2020 22:10:19 -0400 Subject: [PATCH 44/65] Finished moving the BH stuff into their compilation unit --- black_holes.cpp | 136 ++++++++++++++++++++++++------------------------ black_holes.h | 49 ++++++++++++++++- n_bh.c | 74 -------------------------- phigrape.cpp | 104 ++++-------------------------------- 4 files changed, 127 insertions(+), 236 deletions(-) delete mode 100644 n_bh.c diff --git a/black_holes.cpp b/black_holes.cpp index 48685a6..0db9a13 100644 --- a/black_holes.cpp +++ b/black_holes.cpp @@ -2,12 +2,13 @@ #include #include "black_holes.h" - -// TODO do not include c files! -#define SQR(x) ((x)*(x)) +/* BEGIN legacy inclusion */ +// I'm not going to touch this C file +#define SQR(x) ((x)*(x)) double L[3]; // needed in pn_bh_spin.c -#include "n_bh.c" #include "pn_bh_spin.c" +#undef SQR +/* END legacy inclusion */ void two_body_gravity( const double m1, const double3 x1, const double3 v1, @@ -32,55 +33,6 @@ void two_body_gravity( jrk2 = m1*(dv/r3 - RP*dx/r4); } -// class Black_hole_physics { -// public: -// Black_hole_physics() -// : count(0), c(0) {} -// Black_hole_physics(const double m1, const double m2, const int myRank, const int rootRank) -// : m1(m1), m2(m2), count(2), c(0), myRank(myRank), rootRank(rootRank) {} -// void set_post_newtonian(const double c, const int pn_usage[7]) -// { -// this->c = c; -// std::copy(pn_usage, pn_usage+7, this->pn_usage); -// } -// void set_spins(const double spin1[3], const double spin2[3]) -// { -// std::copy(spin1, spin1+3, this->bbh_grav.spin1); -// std::copy(spin2, spin2+3, this->bbh_grav.spin2); -// } -// void set_xv(const double3& x1, const double3& x2, const double3& v1, const double3& v2) -// { -// this->x1 = x1; -// this->x2 = x2; -// this->v1 = v1; -// this->v2 = v2; -// } -// void set_softening(const double eps_old, const double eps_new) -// { -// this->eps_old = eps_old; -// this->eps_new = eps_new; -// } -// void adjust_softening( -// double& pot1, double& pot2, -// double3& acc1, double3& acc2, -// double3& jrk1, double3& jrk2); - -// void adjust_post_newtonian( -// const double dt_bh, // pn_usage should be const -// double3& acc1, double3& acc2, -// double3& jrk1, double3& jrk2); -// void write_bh_data(double time_cur, double m[], double3 x[], double3 v[], double pot[], double3 a[], double3 adot[], double dt[]); -// public: //TODO make private -// double m1, m2; -// int count; -// int myRank, rootRank; -// double eps_old, eps_new; -// double3 x1, v1, x2, v2; -// double c; -// int pn_usage[7]; -// Bbh_gravity bbh_grav; -// }; - void Black_hole_physics::adjust_softening( double& pot1, double& pot2, double3& acc1, double3& acc2, @@ -215,22 +167,12 @@ void Black_hole_physics::write_bh_data(double time_cur, double m[], double3 x[], fclose(out); } -void write_bh_nb_data(int nb, int smbh_count, double time_cur, int N, double m[], double3 x[], double3 v[]) +void Write_bh_nb_data::operator()(double time_cur) { - //int nb = config->live_smbh_neighbor_number; - // TODO fix below!!! Should be class members. - int ind_sort[30000]; - double var_sort[30000]; - //TODO you don't want and probably don't need to allocate these here. Maybe just need size nb, or maybe use as private variables. - - auto out = fopen("bh_neighbors.dat", "a"); - - /* 1st BH */ - for (int i_bh=0; i_bh < smbh_count; i_bh++) { for (int i=0; i +#include +#include #include "double3.h" struct Bbh_gravity { @@ -56,4 +58,49 @@ public: //TODO make private Bbh_gravity bbh_grav; }; -void write_bh_nb_data(int nb, int smbh_count, double time_cur, int N, double m[], double3 x[], double3 v[]); +//void write_bh_nb_data(int nb, int smbh_count, double time_cur, int N, double m[], double3 x[], double3 v[]); + +class Write_bh_nb_data { +public: + Write_bh_nb_data(int nb, int smbh_count, int N, double *m, double3 *x, double3 *v) + : nb(nb), smbh_count(smbh_count), N(N), m(m), x(x), v(v) + { + ind_sort.resize(N); + var_sort.resize(N); + out = fopen("bh_neighbors.dat", "w"); + } + ~Write_bh_nb_data() + { + fclose(out); + } + void operator()(double time_cur); +private: + int nb, smbh_count, N; + double *m; + double3 *x, *v; + std::vector ind_sort; + std::vector var_sort; + FILE *out; +}; + +class Binary_smbh_influence_sphere_output { +public: + Binary_smbh_influence_sphere_output(double factor, int N, double *m, double3 *x, double3 *v, double *pot, double *dt) + : factor(factor), m(m), x(x), v(v), pot(pot), dt(dt) + { + inf_event.assign(N, 0); + out = fopen("bbh_inf.dat", "w"); + } + + ~Binary_smbh_influence_sphere_output() + { + fclose(out); + } + void operator()(int ind_act[], int n_act, double timesteps, double time_cur); +private: + double factor; + double *m, *pot, *dt; + double3 *x, *v; + std::vector inf_event; + FILE *out; +}; \ No newline at end of file diff --git a/n_bh.c b/n_bh.c deleted file mode 100644 index 67223d9..0000000 --- a/n_bh.c +++ /dev/null @@ -1,74 +0,0 @@ -/***************************************************************************/ -/* - Coded by : Peter Berczik - Version number : 1.0 - Last redaction : 2011.II.20. 13:00 -*/ - -void calc_force_n_BH(double m1, double xx1[], double vv1[], - double m2, double xx2[], double vv2[], - double eps_BH, - double *pot_n1, double a_n1[], double adot_n1[], - double *pot_n2, double a_n2[], double adot_n2[]) -{ - -/* - INPUT - -m1 - mass of the 1 BH -xx1[0,1,2] - coordinate of the 1 BH -vv1[0,1,2] - velocity of the 1 BH - -m2 - mass of the 2 BH -xx2[0,1,2] - coordinate of the 2 BH -vv2[0,1,2] - velocity of the 2 BH - -eps_BH - force softening, can be even exactly 0.0 ! - - OUTPUT - -pot_n1 for the 1 BH -a_n1 [0,1,2] for the 1 BH -adot_n1 [0,1,2] for the 1 BH - -pot_n2 for the 2 BH -a_n2 [0,1,2] for the 2 BH -adot_n2 [0,1,2] for the 2 BH -*/ - - -int k; - -double r, r2, r3, r4, RP, x[3], v[3]; - - -for(k=0;k<3;k++) - { - x[k] = xx1[k] - xx2[k]; - v[k] = vv1[k] - vv2[k]; - } - -r2 = SQR(x[0]) + SQR(x[1]) + SQR(x[2]) + SQR(eps_BH); - -r = sqrt(r2); -r3 = r2*r; -r4 = r2*r2; - -RP = 3.0*(x[0]*v[0]+x[1]*v[1]+x[2]*v[2])/r; - -// Newton pot + acc & jerks - -*pot_n1 = -m2/r; -*pot_n2 = -m1/r; - -for(k=0;k<3;k++) - { - a_n1[k] = -m2*x[k]/r3; - a_n2[k] = m1*x[k]/r3; - - adot_n1[k] = -m2*(v[k]/r3 - RP*x[k]/r4); - adot_n2[k] = m1*(v[k]/r3 - RP*x[k]/r4); - } - -} -/***************************************************************************/ diff --git a/phigrape.cpp b/phigrape.cpp index 86d8121..da5b8d9 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -124,20 +124,6 @@ double DT_ACT_REDUCE; #endif - -/* external potential... */ - -double3 x_bh1, x_bh2, v_bh1, v_bh2; - -double pot_bh1, pot_bh2; -double3 a_bh1, adot_bh1, a_bh2, adot_bh2; - -//#include "n_bh.c" - -//double3 a_pn1[7], adot_pn1[7], a_pn2[7], adot_pn2[7]; - -//#include "pn_bh_spin.c" - #ifdef ETICS int grapite_cep_index; #endif @@ -452,76 +438,6 @@ inline double aarseth_step(const double eta, const double dt_tmp, const double3 return sqrt(eta*(a1abs*a2dot1abs+adot1abs*adot1abs)/(adot1abs*a3dot1abs+a2dot1abs*a2dot1abs)); } -void binary_smbh_influence_sphere_output(int i_bh1, int i_bh2, int ind_act[], int n_act, double timesteps, double time_cur, double factor, int inf_event[], Source_particle_list *source_particle_list) -{ - //TODO !!IMPORTANT!! only open the file IF THERE IS ANYTHING TO WRITE!!! - //TODO inf_event to be static or something? - auto out = fopen("bbh_inf.dat", "a"); - - double m_bh1 = source_particle_list->m[0]; - double m_bh2 = source_particle_list->m[1]; - double3 x_bh1 = source_particle_list->x[0]; - double3 x_bh2 = source_particle_list->x[1]; - double3 v_bh1 = source_particle_list->v[0]; - double3 v_bh2 = source_particle_list->v[1]; - - double3 x_bbhc = (m_bh1*x_bh1 + m_bh2*x_bh2)/(m_bh1 + m_bh2); - double3 v_bbhc = (m_bh1*v_bh1 + m_bh2*v_bh2)/(m_bh1 + m_bh2); - - double DR2 = (x_bh1 - x_bh2).norm2(); - double DV2 = (v_bh1 - v_bh2).norm2(); - double EB = -(m_bh1 + m_bh2) / sqrt(DR2) + 0.5 * DV2; - double SEMI_a = -0.5 * (m_bh1 + m_bh2)/EB; - double SEMI_a2 = SQR(SEMI_a); - - for (int i=0; ipot[0]; - double& pot_bh2 = source_particle_list->pot[1]; - double& m_act = source_particle_list->m[j_act]; - double3& x_act = source_particle_list->x[j_act]; - double3& v_act = source_particle_list->v[j_act]; - double& dt_act = source_particle_list->dt[j_act]; - double& pot_act = source_particle_list->pot[j_act]; - double tmp_r2 = (x_act - x_bbhc).norm2(); - - if (tmp_r2 < SEMI_a2*SQR(factor)) { - - if (inf_event[j_act] == 0) { - - fprintf(out,"INF1 %.6E %.16E %07d %07d %.6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E \n", - timesteps, time_cur, i, j_act, - sqrt(DR2), x_bbhc[0], x_bbhc[1], x_bbhc[2], v_bbhc[0], v_bbhc[1], v_bbhc[2], - m_bh1, x_bh1[0], x_bh1[1], x_bh1[2], v_bh1[0], v_bh1[1], v_bh1[2], pot_bh1, - m_bh2, x_bh2[0], x_bh2[1], x_bh2[2], v_bh2[0], v_bh2[1], v_bh2[2], pot_bh2, - sqrt(tmp_r2), - m_act, x_act[0], x_act[1], x_act[2], v_act[0], v_act[1], v_act[2], pot_act, - dt_act); - - inf_event[j_act] = 1; - } - - } else { - if (inf_event[j_act] == 1) { - fprintf(out,"INF2 %.6E %.16E %07d %07d %.6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E %.6E % .6E % .6E % .6E % .6E % .6E % .6E % .6E %.6E \n", - timesteps, time_cur, i, ind_act[i], - sqrt(DR2), x_bbhc[0], x_bbhc[1], x_bbhc[2], v_bbhc[0], v_bbhc[1], v_bbhc[2], - m_bh1, x_bh1[0], x_bh1[1], x_bh1[2], v_bh1[0], v_bh1[1], v_bh1[2], pot_bh1, - m_bh2, x_bh2[0], x_bh2[1], x_bh2[2], v_bh2[0], v_bh2[1], v_bh2[2], pot_bh2, - sqrt(tmp_r2), - m_act, x_act[0], x_act[1], x_act[2], v_act[0], v_act[1], v_act[2], pot_act, - dt_act); - } - - inf_event[j_act] = 0; - - } /* if (tmp_r2 < DR2*R_INF2) */ - - } /* i */ - fclose(out); -} int main(int argc, char *argv[]) { @@ -617,8 +533,6 @@ int main(int argc, char *argv[]) double dt_bh = config->dt_bh; if (myRank == rootRank) { - if (config->binary_smbh_influence_sphere_output) for (int i=0; ibinary_smbh_influence_sphere_output) { - out = fopen("bbh_inf.dat", "w"); - fclose(out); - } + // if (config->binary_smbh_influence_sphere_output) { + // out = fopen("bbh_inf.dat", "w"); + // fclose(out); + // } } get_CPU_time(&CPU_time_real0, &CPU_time_user0, &CPU_time_syst0); @@ -748,6 +662,10 @@ int main(int argc, char *argv[]) } black_hole_physics.set_softening(eps, config->live_smbh_custom_eps); + Binary_smbh_influence_sphere_output binary_smbh_influence_sphere_output(config->binary_smbh_influence_radius_factor, N, m, x, v, pot, dt); + + Write_bh_nb_data write_bh_nb_data(config->live_smbh_neighbor_number, config->live_smbh_count, N, m, x, v); + #ifdef ETICS grapite_read_particle_tags(N, config->grapite_mask_file_name.c_str(), myRank, n_loc); grapite_set_dt_exp(config->dt_scf); @@ -875,7 +793,7 @@ int main(int argc, char *argv[]) if (config->live_smbh_output) black_hole_physics.write_bh_data(time_cur, m, x, v, pot, a, adot, dt); /* Write BH NB data... */ - if (config->live_smbh_neighbor_output) write_bh_nb_data(config->live_smbh_neighbor_number, config->live_smbh_count, time_cur, N, m, x, v); + if (config->live_smbh_neighbor_output) write_bh_nb_data(time_cur); } /* if (myRank == rootRank) */ @@ -1122,7 +1040,7 @@ int main(int argc, char *argv[]) if (config->binary_smbh_influence_sphere_output && (myRank == rootRank)) { //TODO clean up this mass. We don't want to have all these _act arrays; they are only needed for this lame function. - binary_smbh_influence_sphere_output(i_bh1, i_bh2, ind_act, n_act, timesteps, time_cur, config->binary_smbh_influence_radius_factor, inf_event, &source_particle_list); + binary_smbh_influence_sphere_output(ind_act, n_act, timesteps, time_cur); } #ifdef TIMING @@ -1170,7 +1088,7 @@ int main(int argc, char *argv[]) if (config->live_smbh_output) black_hole_physics.write_bh_data(time_cur, m, x, v, pot, a, adot, dt); /* Write BH NB data... */ - if (config->live_smbh_neighbor_output) write_bh_nb_data(config->live_smbh_neighbor_number, config->live_smbh_count, time_cur, N, m, x, v); + if (config->live_smbh_neighbor_output) write_bh_nb_data(time_cur); } /* if (myRank == rootRank) */ From d046c189b3a56d051181d1697ce674ae52b406e5 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Wed, 29 Apr 2020 21:51:05 -0400 Subject: [PATCH 45/65] Cleaned up energy control as well as many other things --- debug.h | 143 - io.cpp | 18 +- phigrape.cpp | 385 +-- sse_sse.f | 7109 -------------------------------------------------- 4 files changed, 99 insertions(+), 7556 deletions(-) delete mode 100644 debug.h delete mode 100644 sse_sse.f diff --git a/debug.h b/debug.h deleted file mode 100644 index e307360..0000000 --- a/debug.h +++ /dev/null @@ -1,143 +0,0 @@ -/***************************************************************/ -void d_swap(double *a, double *b) -{ -register double tmp; -tmp = *a; *a = *b; *b = tmp; -} - -void i_swap(int *a, int *b) -{ -register int tmp; -tmp = *a; *a = *b; *b = tmp; -} -/***************************************************************/ - -/***************************************************************/ -void my_sort(int l, int r, double *arr, int *ind) -{ - -int i, j, cikl; -double tmp; - -i = l; j = r; -tmp = arr[(l+r)/2]; - -cikl = 1; - -while (cikl) - { - while (arr[i]> 1; - - d_swap(&arr[mid],&arr[l+1]); - i_swap(&ind[mid],&ind[l+1]); - - if (arr[l+1] > arr[ir]) - { - d_swap(&arr[l+1],&arr[ir]); - i_swap(&ind[l+1],&ind[ir]); - } - - if (arr[l] > arr[ir]) - { - d_swap(&arr[l],&arr[ir]); - i_swap(&ind[l],&ind[ir]); - } - - if (arr[l+1] > arr[l]) - { - d_swap(&arr[l+1],&arr[l]); - i_swap(&ind[l+1],&ind[l]); - } - - i = l+1; - j = ir; - a = arr[l]; - a_ind = ind[l]; - - for (;;) - { - do i++; while (arr[i] < a); - do j--; while (arr[j] > a); - if (j < i) break; - d_swap(&arr[i],&arr[j]); - i_swap(&ind[i],&ind[j]); - } - - arr[l] = arr[j]; - ind[l] = ind[j]; - arr[j] = a; - ind[j] = a_ind; - if (j >= k) ir = j-1; - if (j <= k) l = i; - - } - } -} -/***************************************************************/ - -/***************************************************************/ -/* -double lagrange_radius(double percent) -{ -int Nb; -double tmp; - -Nb = (int)(percent * N); - -my_sort(0, N-1, d, ind); - -tmp = my_select(0, N-1, Nb-1, d, ind); d[Nb-1] = tmp; - -return(tmp); -} -*/ -/***************************************************************/ diff --git a/io.cpp b/io.cpp index ea496c4..2ca64c8 100644 --- a/io.cpp +++ b/io.cpp @@ -24,7 +24,7 @@ bool is_hdf5(std::string file_name) return result; } -void ascii_read(const std::string file_name, int *step_num, int *N, double *t, double *m, double3 *x, double3 *v) +void ascii_read(const std::string file_name, int& step_num, int& N, double& t, double **m, double3 **x, double3 **v) { char rest[512]; int result; @@ -34,21 +34,25 @@ void ascii_read(const std::string file_name, int *step_num, int *N, double *t, d std::string str; std::getline(file, str); - result = sscanf(str.c_str(), "%d%s", step_num, rest); + result = sscanf(str.c_str(), "%d%s", &step_num, rest); if (result!=1) throw std::runtime_error("Error parsing line 1: expected one integer"); std::getline(file, str); - result = sscanf(str.c_str(), "%d%s", N, rest); + result = sscanf(str.c_str(), "%d%s", &N, rest); if (result!=1) throw std::runtime_error("Error parsing line 2: expected one integer"); std::getline(file, str); - result = sscanf(str.c_str(), "%lf%s", t, rest); + result = sscanf(str.c_str(), "%lf%s", &t, rest); if (result!=1) throw std::runtime_error("Error parsing line 3: expected one real number"); + *m = new double[N]; + *x = new double3[N]; + *v = new double3[N]; + int i = -1; while (std::getline(file, str)) { - if (++i > *N) throw std::runtime_error("Error parsing line " + std::to_string(i+4) + ": particle out of range"); - result = sscanf(str.c_str(), "%*s %lf %lf %lf %lf %lf %lf %lf%s", &m[i], &x[i][0], &x[i][1], &x[i][2], &v[i][0], &v[i][1], &v[i][2], rest); + if (++i > N) throw std::runtime_error("Error parsing line " + std::to_string(i+4) + ": particle out of range"); + result = sscanf(str.c_str(), "%*s %lf %lf %lf %lf %lf %lf %lf%s", &(*m)[i], &(*x)[i][0], &(*x)[i][1], &(*x)[i][2], &(*v)[i][0], &(*v)[i][1], &(*v)[i][2], rest); } file.close(); } @@ -145,7 +149,7 @@ void h5_read(const std::string file_name, int *step_num, int *N, double *t, doub void h5_write(const std::string file_name, const int step_num, const int N, const double t, const double *m, const double3 *x, const double3 *v, const double *pot, const double3 *acc, const double3 *jrk, const int extra_mode=0, const bool use_double_precision=true) { #ifdef HAS_HDF5 - hid_t file_id, group_id, attribute_id, dataset_id, dataspace_id; + hid_t file_id, group_id, attribute_id, dataspace_id; hsize_t dims[2] = {(hsize_t)N, 3}; hid_t h5_float_type; diff --git a/phigrape.cpp b/phigrape.cpp index da5b8d9..69f6d93 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -53,18 +53,6 @@ Coded by : Peter Berczik Version number : 19.04 Last redaction : 2019.04.16 12:55 *****************************************************************************/ -#include "double3.h" -#include "black_holes.h" -#include "config.h" -#include "io.h" -#include "external.h" - -Config *config; - -#ifdef ETICS -#include "grapite.h" -#endif - #define TIMING #define ETA_S_CORR 4.0 @@ -73,42 +61,37 @@ Config *config; #define DTMAXPOWER -3.0 #define DTMINPOWER -36.0 -#include -#include -#include -#include -#include -#include -#include - #include +#include +#include #include #include +#include +#include +#include +#include +#include +#include +#include "black_holes.h" +#include "config.h" +#include "double3.h" +#include "external.h" #include "grape6.h" +#include "io.h" -#include +#ifdef ETICS +#include "grapite.h" +#endif -/* Some "good" functions and constants... */ -// TODO replace with inline functions -#define MIN(a,b) (((a)<(b)) ? (a):(b) ) -#define SQR(x) ((x)*(x) ) - - -#define KB 1024 -#define MB (KB*KB) - -#define N_MAX (32*KB) - -// double L[3]; // needed in pn_bh_spin.c -// Needed for things related to BHs -#include "debug.h" +Config *config; +// These are used in the energy control, could be static but will probably be removed in the end anyway double CPU_time_real0, CPU_time_user0, CPU_time_syst0; double CPU_time_real, CPU_time_user, CPU_time_syst; #ifdef TIMING - +// TODO clean up here double CPU_tmp_real0, CPU_tmp_user0, CPU_tmp_syst0; double CPU_tmp_real, CPU_tmp_user, CPU_tmp_syst; @@ -118,14 +101,7 @@ double DT_TOT, DT_GMC_GRAV, DT_GMC_GMC_GRAV, DT_EXT_GMC_GRAV, DT_ACT_CORR, DT_ACT_LOAD, DT_STEVOL, DT_STARDISK, DT_STARDESTR; - double DT_ACT_REDUCE; - -#endif - - -#ifdef ETICS -int grapite_cep_index; #endif void get_CPU_time(double *time_real, double *time_user, double *time_syst) @@ -178,110 +154,66 @@ private: std::vector h2; }; -void calc_ext_grav(std::vector &external_gravity_components, int n_act, double3 *x_act_new, double3 *v_act_new, double *pot_act_ext, double3 *a_act_new, double3* adot_act_new) +void calc_ext_grav(std::vector &external_gravity_components, int n, double3 *x, double3 *v, double *pot, double3 *acc, double3* jrk) +// TODO should just be a class that has this pointer array as a member { #ifdef TIMING get_CPU_time(&CPU_tmp_real0, &CPU_tmp_user0, &CPU_tmp_syst0); #endif - /* Define the external potential for all active particles on all nodes */ - - std::fill(pot_act_ext, pot_act_ext+n_act, 0.); - + std::fill(pot, pot+n, 0.); for (auto component : external_gravity_components) { if (component->is_active) - component->apply(n_act, x_act_new, v_act_new, pot_act_ext, a_act_new, adot_act_new); + component->apply(n, x, v, pot, acc, jrk); } - /* For simple Plummer potential... */ - #ifdef TIMING get_CPU_time(&CPU_tmp_real, &CPU_tmp_user, &CPU_tmp_syst); DT_EXT_GRAV += (CPU_tmp_user - CPU_tmp_user0); #endif - } -void energy_contr(const double time_cur, const double timesteps, const double n_act_sum, const double g6_calls, double& rcm_sum, double& vcm_sum, double& E_tot_0, double& E_tot_corr_0, double& E_tot_corr_sd_0, int &skip_con, int N, double m[], double3 x[], double3 v[], double pot[], double pot_ext[]) +void energy_contr(const double time_cur, const double timesteps, const double n_act_sum, const double g6_calls, int N, double m[], double3 x[], double3 v[], double pot[], double pot_ext[]) { - // TODO maybe use static variables here for the previous step energy? - double E_pot = 0.0; + double E_pot = 0; for (int i=0; iinput_file_name)) { #ifndef HAS_HDF5 fprintf(stderr, "ERROR: input file is in HDF5 format, but the code was compiled without HDF5 support\n"); @@ -522,8 +371,20 @@ int main(int argc, char *argv[]) h5_read(config->input_file_name, &diskstep, &N, &time_cur, m, x, v); } else - ascii_read(config->input_file_name, &diskstep, &N, &time_cur, m, x, v); + ascii_read(config->input_file_name, diskstep, N, time_cur, &m, &x, &v); + + int *ind = new int[N]; std::iota(ind, ind+N, 0); + double3 *a = new double3[N], *adot = new double3[N]; + double *pot = new double[N], *pot_ext = new double[N], *t = new double[N], *dt = new double[N]; + + /* data for active particles */ + // x_act_new and v_act_new arrays hold the predicted position and velocity of i-particles, which is later corrected before moving into the j-particle memory. The [pot,a,adot]_act_tmp arrays hold the calculation results from each node. The [pot,a,adot]_act_new arrays hold the reduced calculation results from all nodes. + int n_act, *ind_act = new int[N]; + double *pot_act_new = new double[N], *pot_act_tmp = new double[N], *pot_act_ext = new double[N]; + double3 *x_act_new = new double3[N], *v_act_new = new double3[N], + *a_act_tmp = new double3[N], *adot_act_tmp = new double3[N], + *a_act_new = new double3[N], *adot_act_new = new double3[N]; double eps = config->eps; double eta = config->eta; @@ -558,19 +419,12 @@ int main(int argc, char *argv[]) out = fopen("bh_neighbors.dat", "w"); fclose(out); } - // if (config->binary_smbh_influence_sphere_output) { - // out = fopen("bbh_inf.dat", "w"); - // fclose(out); - // } } get_CPU_time(&CPU_time_real0, &CPU_time_user0, &CPU_time_syst0); } /* if (myRank == rootRank) */ - /* Wait to all processors to finish his works... */ - MPI_Barrier(MPI_COMM_WORLD); - double normalization_mass=1, normalization_length=1, normalization_velocity=1; if (config->ext_units_physical) { normalization_mass = 1/config->unit_mass; @@ -624,10 +478,6 @@ int main(int argc, char *argv[]) std::fill(t, t+N, time_cur); std::fill(dt, dt+N, dt_min); - /* Wait to all processors to finish his works... */ - MPI_Barrier(MPI_COMM_WORLD); - - /* some local settings for G6a boards */ int clusterid, numGPU; if (config->devices_per_node==0) { @@ -645,8 +495,8 @@ int main(int argc, char *argv[]) /* init the local GRAPEs */ g6_open(clusterid); int npipe = g6_npipes(); - g6_set_tunit(new_tunit); - g6_set_xunit(new_xunit); + g6_set_tunit(51); + g6_set_xunit(51); int n_loc = N/n_proc; Calc_self_grav calc_self_grav(N, n_loc, clusterid, npipe, eps); @@ -685,7 +535,7 @@ int main(int argc, char *argv[]) MPI_Bcast(&etics_length_scale, 1, MPI_DOUBLE, rootRank, MPI_COMM_WORLD); grapite_set_length_scale(etics_length_scale); - grapite_cep_index = grapite_get_cep_index(); + int grapite_cep_index = grapite_get_cep_index(); if (grapite_cep_index >= 0) { grapite_calc_center(N, m, (double(*)[3])x, (double(*)[3])v, xcm, vcm, xdc, vdc); x[grapite_cep_index] = xdc; @@ -695,20 +545,14 @@ int main(int argc, char *argv[]) #endif /* define the all particles as a active on all the processors for the first time grav calc. */ - calc_self_grav(time_cur, N, ind, x, v, pot_act_tmp, a_act_tmp, adot_act_tmp); - /* Wait to all processors to finish his works... */ - MPI_Barrier(MPI_COMM_WORLD); - /* Reduce the "global" vectors from "local" on all processors) */ + // TODO why won't we do the MPI_Allreduce inside the calc_self_grav function, and get rid of these _tmp arrays? MPI_Allreduce(pot_act_tmp, pot, N, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); MPI_Allreduce(a_act_tmp, a, 3*N, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); MPI_Allreduce(adot_act_tmp, adot, 3*N, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - /* Wait to all processors to finish his works... */ - MPI_Barrier(MPI_COMM_WORLD); - if (config->live_smbh_count == 2) { black_hole_physics.set_xv(x[0], x[1], v[0], v[1]); if (config->live_smbh_custom_eps >= 0) black_hole_physics.adjust_softening(pot[0], pot[1], a[0], a[1], adot[0], adot[1]); @@ -717,14 +561,8 @@ int main(int argc, char *argv[]) calc_ext_grav(external_gravity_components, N, x, v, pot_ext, a, adot); - /* Wait to all processors to finish his works... */ - MPI_Barrier(MPI_COMM_WORLD); - - /* Energy control... */ - if (myRank == rootRank) { - energy_contr(time_cur, timesteps, n_act_sum, calc_self_grav.g6_calls, rcm_sum, vcm_sum, E_tot_0, E_tot_corr_0, E_tot_corr_sd_0, skip_con, N, m, x, v, pot, pot_ext); - } /* if (myRank == rootRank) */ + if (myRank == rootRank) energy_contr(time_cur, timesteps, n_act_sum, calc_self_grav.g6_calls, N, m, x, v, pot, pot_ext); #ifdef ETICS if (config->etics_dump_coeffs && (diskstep==0)) { @@ -741,9 +579,6 @@ int main(int argc, char *argv[]) } #endif - /* Wait to all processors to finish his works... */ - MPI_Barrier(MPI_COMM_WORLD); - /* Define initial timestep for all particles on all nodes */ for (int j=0; jlive_smbh_count; i++) dt[i] = min_dt; } - /* Wait to all processors to finish his works... */ - MPI_Barrier(MPI_COMM_WORLD); - - /* load the new values for particles to the local GRAPE's */ - /* load the nj particles to the G6 */ + /* load the new values for particles to the local GRAPEs */ for (int k=0; k= t_bh) { if (myRank == rootRank) { @@ -1098,15 +898,13 @@ int main(int argc, char *argv[]) if (time_cur >= t_contr) { if (myRank == rootRank) { - energy_contr(time_cur, timesteps, n_act_sum, calc_self_grav.g6_calls, rcm_sum, vcm_sum, E_tot_0, E_tot_corr_0, E_tot_corr_sd_0, skip_con, N, m, x, v, pot, pot_ext); + energy_contr(time_cur, timesteps, n_act_sum, calc_self_grav.g6_calls, N, m, x, v, pot, pot_ext); /* write cont data */ - if (config->output_hdf5) h5_write("data.con", diskstep, N, time_cur, m, x, v, pot, a, adot, 0, true); else ascii_write("data.con", diskstep, N, time_cur, m, x, v, 16); /* possible OUT for timing !!! */ - #ifdef TIMING FILE *out = fopen("timing.dat", "a"); @@ -1168,15 +966,9 @@ int main(int argc, char *argv[]) /* close the local GRAPEs */ g6_close(clusterid); - /* Wait to all processors to finish his works... */ - MPI_Barrier(MPI_COMM_WORLD); - double g6_calls_sum; MPI_Reduce(&calc_self_grav.g6_calls, &g6_calls_sum, 1, MPI_DOUBLE, MPI_SUM, rootRank, MPI_COMM_WORLD); - /* Wait to all processors to finish his works... */ - MPI_Barrier(MPI_COMM_WORLD); - if (myRank == rootRank) { /* Write some output for the timestep annalize... */ @@ -1189,8 +981,7 @@ int main(int argc, char *argv[]) } /* if (myRank == rootRank) */ - /* Wait to all processors to finish his works... */ - MPI_Barrier(MPI_COMM_WORLD); + delete[] m; delete[] x; delete[] v; delete[] ind; delete[] a; delete[] adot; delete[] pot; delete[] pot_ext; delete[] t; delete[] dt; delete[] ind_act; delete[] pot_act_new; delete[] pot_act_tmp; delete[] x_act_new; delete[] v_act_new; delete[] a_act_tmp; delete[] adot_act_tmp; delete[] a_act_new; delete[] adot_act_new; delete[] pot_act_ext; /* Finalize the MPI work */ MPI_Finalize(); diff --git a/sse_sse.f b/sse_sse.f deleted file mode 100644 index d29b7fc..0000000 --- a/sse_sse.f +++ /dev/null @@ -1,7109 +0,0 @@ -cc// deltat.f - -*** - SUBROUTINE deltat(kw,age,tm,tn,tscls,dt,dtr) - implicit none -* - INTEGER kw - REAL*8 age,tm,tn,tscls(20) - REAL*8 dt,dtr - REAL*8 pts1,pts2,pts3 - COMMON /POINTS/ pts1,pts2,pts3 -* -* Base new time scale for changes in radius & mass on stellar type. -* - if(kw.le.1)then - dt = pts1*tm - dtr = tm - age - elseif(kw.eq.2)then - dt = pts1*(tscls(1) - tm) - dtr = tscls(1) - age - elseif(kw.eq.3)then - if(age.lt.tscls(6))then - dt = pts2*(tscls(4) - age) - else - dt = pts2*(tscls(5) - age) - endif - dtr = MIN(tscls(2),tn) - age - elseif(kw.eq.4)then - dt = pts2*tscls(3) - dtr = MIN(tn,tscls(2) + tscls(3)) - age - elseif(kw.eq.5)then - if(age.lt.tscls(9))then - dt = pts3*(tscls(7) - age) - else - dt = pts3*(tscls(8) - age) - endif - dtr = MIN(tn,tscls(13)) - age - elseif(kw.eq.6)then - if(age.lt.tscls(12))then - dt = pts3*(tscls(10) - age) - else - dt = pts3*(tscls(11) - age) - endif - dt = MIN(dt,0.005d0) - dtr = tn - age - elseif(kw.eq.7)then - dt = pts1*tm - dtr = tm - age - elseif(kw.eq.8.or.kw.eq.9)then - if(age.lt.tscls(6))then - dt = pts2*(tscls(4) - age) - else - dt = pts2*(tscls(5) - age) - endif - dtr = tn - age - else -* dt = MAX(0.1d0,age*10.d0) - dt = MAX(0.1d0,dt*10.d0) - dt = MIN(dt,5.0d+02) - dtr = dt - endif -* - RETURN - END -*** - - -cc//evolv1.f - -*** - SUBROUTINE evolv1(kw,mass,mt,r,lum,mc,rc,menv,renv,ospin, - & epoch,tm,tphys,tphysf,dtp,z,zpars,vkick,vs) -c-------------------------------------------------------------c -c -c Evolves a single star. -c Mass loss is an option. -c The timestep is not constant but determined by certain criteria. -c Plots the HRD and variables as a function of time. -c -c Written by Jarrod Hurley 26/08/97 at the Institute of -c Astronomy, Cambridge. -c -c-------------------------------------------------------------c -c -c STELLAR TYPES - KW -c -c 0 - deeply or fully convective low mass MS star -c 1 - Main Sequence star -c 2 - Hertzsprung Gap -c 3 - First Giant Branch -c 4 - Core Helium Burning -c 5 - First Asymptotic Giant Branch -c 6 - Second Asymptotic Giant Branch -c 7 - Main Sequence Naked Helium star -c 8 - Hertzsprung Gap Naked Helium star -c 9 - Giant Branch Naked Helium star -c 10 - Helium White Dwarf -c 11 - Carbon/Oxygen White Dwarf -c 12 - Oxygen/Neon White Dwarf -c 13 - Neutron Star -c 14 - Black Hole -c 15 - Massless Supernova -c -c-------------------------------------------------------------c - implicit none -* - integer kw,it,ip,jp,j,kwold,rflag - integer nv - parameter(nv=50000) -* - real*8 mass,z,aj - real*8 epoch,tphys,tphys2,tmold,tbgold - real*8 mt,tm,tn,tphysf,dtp,tsave - real*8 tscls(20),lums(10),GB(10),zpars(20) - real*8 r,lum,mc,teff,rc,menv,renv,vs(3) - real*8 ospin,jspin,djt,djmb,k2,k3,vkick - parameter(k3=0.21d0) - real*8 m0,r1,lum1,mc1,rc1,menv1,renv1,k21 - real*8 dt,dtm,dtr,dr,dtdr,dms,dml,mt2,rl - real*8 tol,tiny - parameter(tol=1.0d-10,tiny=1.0d-14) - real*8 ajhold,rm0,eps,alpha2 - parameter(eps=1.0d-06,alpha2=0.09d0) - real*8 mlwind,vrotf - external mlwind,vrotf - logical iplot,isave - REAL*8 neta,bwind,hewind,mxns - COMMON /VALUE1/ neta,bwind,hewind,mxns - REAL*8 pts1,pts2,pts3 - COMMON /POINTS/ pts1,pts2,pts3 - REAL scm(50000,14),spp(20,3) - COMMON /SINGLE/ scm,spp -* - dtm = 0.d0 - r = 0.d0 - lum = 0.d0 - mc = 0.d0 - mc1 = 0.d0 - rc = 0.d0 - rl = 0.d0 - if(ospin.le.0.d0)then - ospin = 1.0d-10 - jspin = 1.0d-10 - endif - k2 = 0.15d0 - rflag = 0 - -* -* Setup variables which control the output (if it is required). -* - ip = 0 - jp = 0 - tsave = tphys - isave = .true. - iplot = .false. - if(dtp.le.0.d0)then - iplot = .true. - isave = .false. - tsave = tphysf - elseif(dtp.gt.tphysf)then - isave = .false. - tsave = tphysf - endif -* - do 10 , j = 1,nv -* - if(neta.gt.tiny.and.j.gt.1)then -* -* Calculate mass loss from the previous timestep. -* - dt = 1.0d+06*dtm - dms = mlwind(kw,lum,r,mt,mc,rl,z)*dt - if(kw.lt.10)then - dml = mt - mc - if(dml.lt.dms)then - dtm = (dml/dms)*dtm - dms = dml - endif - endif - else - dms = 0.d0 - endif -* -* Limit to 1% mass loss. -* - if(dms.gt.0.01d0*mt)then - dtm = 0.01d0*mt*dtm/dms - dms = 0.01d0*mt - endif -* -* Calculate the rate of angular momentum loss due to magnetic braking -* and/or mass loss. -* - if(j.gt.1)then - djt = (2.d0/3.d0)*(dms/(1.0d+06*dtm))*r*r*ospin - if(mt.gt.0.35d0.and.kw.lt.10)then - djmb = 5.83d-16*menv*(r*ospin)**3/mt - djt = djt + djmb - endif - endif -* -* Update mass and time and reset epoch for a MS (and possibly a HG) star. -* - if(dms.gt.0.d0)then - mt = mt - dms - if(kw.le.2.or.kw.eq.7)then - m0 = mass - mc1 = mc - mass = mt - tmold = tm - tbgold = tscls(1) - CALL star(kw,mass,mt,tm,tn,tscls,lums,GB,zpars) - if(kw.eq.2)then - if(GB(9).lt.mc1.or.m0.gt.zpars(3))then - mass = m0 - else - epoch = tm + (tscls(1) - tm)*(ajhold-tmold)/ - & (tbgold - tmold) - epoch = tphys - epoch - endif - else - epoch = tphys - ajhold*tm/tmold - endif - endif - endif - tphys2 = tphys - tphys = tphys + dtm -* -* Find the landmark luminosities and timescales as well as setting -* the GB parameters. -* - aj = tphys - epoch - CALL star(kw,mass,mt,tm,tn,tscls,lums,GB,zpars) -* -* Find the current radius, luminosity, core mass and stellar type -* given the initial mass, current mass, metallicity and age -* - kwold = kw - CALL hrdiag(mass,aj,mt,tm,tn,tscls,lums,GB,zpars, - & r,lum,kw,mc,rc,menv,renv,k2) -* -* If mass loss has occurred and no type change then check that we -* have indeed limited the radius change to 10%. -* - if(kw.eq.kwold.and.dms.gt.0.d0.and.rflag.ne.0)then - mt2 = mt + dms - dml = dms/dtm - it = 0 - 20 dr = r - rm0 - if(ABS(dr).gt.0.1d0*rm0)then - it = it + 1 - if(it.eq.20.and.kw.eq.4) goto 30 - if(it.gt.30)then - WRITE(99,*)' DANGER1! ',it,kw,mass,dr,rm0 - WRITE(*,*)' STOP: EVOLV1 FATAL ERROR ' - CALL exit(0) - STOP - endif - dtdr = dtm/ABS(dr) - dtm = alpha2*MAX(rm0,r)*dtdr - if(it.ge.20) dtm = 0.5d0*dtm - if(dtm.lt.1.0d-07*aj) goto 30 - dms = dtm*dml - mt = mt2 - dms - if(kw.le.2.or.kw.eq.7)then - mass = mt - CALL star(kw,mass,mt,tm,tn,tscls,lums,GB,zpars) - if(kw.eq.2)then - if(GB(9).lt.mc1.or.m0.gt.zpars(3))then - mass = m0 - else - epoch = tm + (tscls(1) - tm)*(ajhold-tmold)/ - & (tbgold - tmold) - epoch = tphys2 - epoch - endif - else - epoch = tphys2 - ajhold*tm/tmold - endif - endif - tphys = tphys2 + dtm - aj = tphys - epoch - mc = mc1 - CALL star(kw,mass,mt,tm,tn,tscls,lums,GB,zpars) - CALL hrdiag(mass,aj,mt,tm,tn,tscls,lums,GB,zpars, - & r,lum,kw,mc,rc,menv,renv,k2) - goto 20 - endif - 30 continue - endif -* -* Initialize or adjust the spin of the star. -* - if(j.eq.1)then - if(tphys.lt.tiny.and.ospin.lt.0.001d0)then - ospin = 45.35d0*vrotf(mt)/r - endif - jspin = ospin*(k2*r*r*(mt-mc)+k3*rc*rc*mc) - else - jspin = MAX(1.0d-10,jspin - djt*1.0d+06*dtm) - ospin = jspin/(k2*r*r*(mt-mc)+k3*rc*rc*mc) - endif -* -* Test for changes in evolution type. -* - if(j.eq.1.or.kw.ne.kwold)then -* -* Force new NS or BH to have a one second period. -* - if(kw.eq.13.or.kw.eq.14)then - ospin = 2.0d+08 - jspin = k3*rc*rc*mc*ospin - CALL kick(kw,mass,mt,0.d0,0.d0,-1.d0,0.d0,vs) - vkick = dsqrt(vs(1)*vs(1)+vs(2)*vs(2)+vs(3)*vs(3)) - endif - jp = jp + 1 - spp(jp,1) = tphys - spp(jp,2) = float(kw) - if(kw.eq.15)then - spp(jp,3) = mass - goto 90 - else - spp(jp,3) = mt - endif - endif -* -* Record values for plotting and reset epoch. -* - epoch = tphys - aj - if((isave.and.tphys.ge.tsave).or.iplot)then - ip = ip + 1 - scm(ip,1) = tphys - scm(ip,2) = float(kw) - scm(ip,3) = mass - scm(ip,4) = mt - scm(ip,5) = log10(lum) - scm(ip,6) = log10(r) - teff = 1000.d0*((1130.d0*lum/(r**2.d0))**(1.d0/4.d0)) - scm(ip,7) = log10(teff) - scm(ip,8) = mc - scm(ip,9) = rc - scm(ip,10) = menv - scm(ip,11) = renv - scm(ip,12) = epoch - scm(ip,13) = ospin - if(isave) tsave = tsave + dtp - if(tphysf.lt.tiny)then - ip = ip + 1 - do 35 , it = 1,13 - scm(ip,it) = scm(ip-1,it) - 35 continue - endif - endif -* - if(tphys.ge.tphysf)then - jp = jp + 1 - spp(jp,1) = tphys - spp(jp,2) = float(kw) - spp(jp,3) = mt - goto 90 - endif -* -* Record radius and current age. -* - rm0 = r - ajhold = aj - if(kw.ne.kwold) kwold = kw - CALL deltat(kw,aj,tm,tn,tscls,dtm,dtr) -* -* Check for type change. -* - it = 0 - m0 = mass - if((dtr-dtm).le.tol.and.kw.le.9)then -* -* Check final radius for too large a jump. -* - aj = MAX(aj,aj*(1.d0-eps)+dtr) - mc1 = mc - CALL hrdiag(mass,aj,mt,tm,tn,tscls,lums,GB,zpars, - & r1,lum1,kw,mc1,rc1,menv1,renv1,k21) - dr = r1 - rm0 - if(ABS(dr).gt.0.1d0*rm0)then - dtm = dtr - ajhold*eps - dtdr = dtm/ABS(dr) - dtm = alpha2*MAX(r1,rm0)*dtdr - goto 40 - else - dtm = dtr - goto 50 - endif - endif -* -* Limit to a 10% increase in radius assuming no further mass loss -* and thus that the pertubation functions due to small envelope mass -* will not change the radius. -* - 40 aj = ajhold + dtm - mc1 = mc - CALL hrdiag(mass,aj,mt,tm,tn,tscls,lums,GB,zpars, - & r1,lum1,kw,mc1,rc1,menv1,renv1,k21) - dr = r1 - rm0 - it = it + 1 - if(it.eq.20.and.kw.eq.4) goto 50 - if(it.gt.30)then - WRITE(99,*)' DANGER2! ',it,kw,mass,dr,rm0 - WRITE(*,*)' STOP: EVOLV1 FATAL ERROR ' - CALL exit(0) - STOP - endif - if(ABS(dr).gt.0.1d0*rm0)then - dtdr = dtm/ABS(dr) - dtm = alpha2*MAX(rm0,r1)*dtdr - if(it.ge.20) dtm = 0.5d0*dtm - goto 40 - endif -* - 50 continue -* -* Ensure that change of type has not occurred during radius check. -* This is rare but may occur for HG stars of ZAMS mass > 50 Msun. -* - if(kw.ne.kwold)then - kw = kwold - mass = m0 - CALL star(kw,mass,mt,tm,tn,tscls,lums,GB,zpars) - endif -* -* Choose minimum of time-scale and remaining interval (> 100 yrs). -* - dtm = MAX(dtm,1.0d-07*aj) - dtm = MIN(dtm,tsave-tphys) -* - 10 continue -* - 90 continue -* - tphysf = tphys - scm(ip+1,1) = -1.0 - spp(jp+1,1) = -1.0 - if(ip.ge.nv)then - WRITE(99,*)' EVOLV1 ARRAY ERROR ',mass - WRITE(*,*)' STOP: EVOLV1 ARRAY ERROR ' - CALL exit(0) - STOP - endif -* - RETURN - END -*** - - -cc//hrdiag.f - -*** - SUBROUTINE hrdiag(mass,aj,mt,tm,tn,tscls,lums,GB,zpars, - & r,lum,kw,mc,rc,menv,renv,k2) -* -* -* H-R diagram for population I stars. -* ----------------------------------- -* -* Computes the new mass, luminosity, radius & stellar type. -* Input (MASS, AJ, TM, TN, LUMS & TSCLS) supplied by routine STAR. -* Ref: P.P. Eggleton, M.J. Fitchett & C.A. Tout (1989) Ap.J. 347, 998. -* -* Revised 27th March 1995 by C. A. Tout; -* 24th October 1995 to include metallicity; -* 14th November 1996 to include naked helium stars; -* 28th February 1997 to allow accretion induced supernovae. -* -* Revised 5th April 1997 by J. R. Hurley -* to include Z=0.001 as well as Z=0.02, convective overshooting, -* MS hook and more elaborate CHeB -* - implicit none -* - integer kw,kwp - INTEGER ceflag,tflag,ifflag,nsflag,wdflag - COMMON /FLAGS/ ceflag,tflag,ifflag,nsflag,wdflag -* - -CCC added by Long Wang & Peter Berczik 2014.10. - real*8 fallback - common /fall/fallback - - real*8 mass,aj,mt,tm,tn,tscls(20),lums(10),GB(10),zpars(20) - real*8 r,lum,mc,rc,menv,renv,k2 - real*8 mch,mlp,tiny - parameter(mch=1.44d0,mlp=12.d0,tiny=1.0d-14) - real*8 mass0,mt0,mtc - REAL*8 neta,bwind,hewind,mxns - COMMON /VALUE1/ neta,bwind,hewind,mxns -* - real*8 thook,thg,tbagb,tau,tloop,taul,tauh,tau1,tau2,dtau,texp - real*8 lx,ly,dell,alpha,beta,eta - real*8 rx,ry,delr,rzams,rtms,gamma,rmin,taumin,rg - parameter(taumin=5.0d-08) - real*8 mcmax,mcx,mcy,mcbagb,lambda - real*8 am,xx,fac,rdgen,mew,lum0,kap,zeta,ahe,aco - parameter(lum0=7.0d+04,kap=-0.5d0,ahe=4.d0,aco=16.d0) -* - real*8 thookf,tblf - real*8 lalphf,lbetaf,lnetaf,lhookf,lgbtf,lmcgbf,lzhef,lpertf - real*8 rzamsf,rtmsf,ralphf,rbetaf,rgammf,rhookf - real*8 rgbf,rminf,ragbf,rzahbf,rzhef,rhehgf,rhegbf,rpertf - real*8 mctmsf,mcgbtf,mcgbf,mcheif,mcagbf,lzahbf - external thookf,tblf - external lalphf,lbetaf,lnetaf,lhookf,lgbtf,lmcgbf,lzhef,lpertf - external rzamsf,rtmsf,ralphf,rbetaf,rgammf,rhookf - external rgbf,rminf,ragbf,rzahbf,rzhef,rhehgf,rhegbf,rpertf - external mctmsf,mcgbtf,mcgbf,mcheif,mcagbf,lzahbf -* -* -* --------------------------------------------------------------------- -* MASS Stellar mass in solar units (input: old; output: new value). -* AJ Current age in Myr. -* MT Current mass in solar units (used for R). -* TM Main sequence time. -* TN Nuclear burning time. -* TSCLS Time scale for different stages. -* LUMS Characteristic luminosity. -* GB Giant Branch parameters -* ZPARS Parameters for distinguishing various mass intervals. -* R Stellar radius in solar units. -* TE Effective temperature (suppressed). -* KW Classification type (0 - 15). -* MC Core mass. -* --------------------------------------------------------------------- -* -* -* Make evolutionary changes to stars that have not reached KW > 5. -* - -CCC added by Long Wang & Peter Berczik 2014.10. - fallback = 0.0d0 - - mass0 = mass - if(mass0.gt.100.d0) mass = 100.d0 - mt0 = mt - if(mt0.gt.100.d0) mt = 100.d0 -* - if(kw.gt.6) goto 90 -* - tbagb = tscls(2) + tscls(3) - thg = tscls(1) - tm -* - rzams = rzamsf(mass) - rtms = rtmsf(mass) -* - if(aj.lt.tscls(1))then -* -* Either on MS or HG -* - rg = rgbf(mt,lums(3)) -* - if(aj.lt.tm)then -* -* Main sequence star. -* - mc = 0.d0 - tau = aj/tm - thook = thookf(mass)*tscls(1) - zeta = 0.01d0 - tau1 = MIN(1.d0,aj/thook) - tau2 = MAX(0.d0, - & MIN(1.d0,(aj-(1.d0-zeta)*thook)/(zeta*thook))) -* - dell = lhookf(mass,zpars(1)) - dtau = tau1**2 - tau2**2 - alpha = lalphf(mass) - beta = lbetaf(mass) - eta = lnetaf(mass) - lx = LOG10(lums(2)/lums(1)) - if(tau.gt.taumin)then - xx = alpha*tau + beta*tau**eta + - & (lx - alpha - beta)*tau**2 - dell*dtau - else - xx = alpha*tau + (lx - alpha)*tau**2 - dell*dtau - endif - lum = lums(1)*10.d0**xx -* - delr = rhookf(mass,zpars(1)) - dtau = tau1**3 - tau2**3 - alpha = ralphf(mass) - beta = rbetaf(mass) - gamma = rgammf(mass) - rx = LOG10(rtms/rzams) -* Note that the use of taumin is a slightly pedantic attempt to -* avoid floating point underflow. It IS overkill! - if(tau.gt.taumin)then - xx = alpha*tau + beta*tau**10 + gamma*tau**40 + - & (rx - alpha - beta - gamma)*tau**3 - delr*dtau - else - xx = alpha*tau + (rx - alpha)*tau**3 - delr*dtau - endif - r = rzams*10.d0**xx -* - if(mass.lt.(zpars(1)-0.3d0))then - kw = 0 -* This following is given by Chris for low mass MS stars which will be -* substantially degenerate. We need the Hydrogen abundance, X, which we -* calculate from Z assuming that the helium abundance, Y, is calculated -* according to Y = 0.24 + 2*Z - rdgen = 0.0258d0*((1.d0+zpars(11))**(5.d0/3.d0))* - & (mass**(-1.d0/3.d0)) - r = MAX(rdgen,r) - else - kw = 1 - endif -* - else -* -* Star is on the HG -* - mcx = mc - if(mass.le.zpars(2))then - mc = mcgbf(lums(3),GB,lums(6)) - elseif(mass.le.zpars(3))then - mc = mcheif(mass,zpars(2),zpars(9)) - else - mc = mcheif(mass,zpars(2),zpars(10)) - endif - eta = mctmsf(mass) - tau = (aj - tm)/thg - mc = ((1.d0 - tau)*eta + tau)*mc - mc = MAX(mc,mcx) -* -* Test whether core mass has reached total mass. -* - if(mc.ge.mt)then - aj = 0.d0 - if(mass.gt.zpars(2))then -* -* Zero-age helium star -* - mc = 0.d0 - mass = mt - kw = 7 - CALL star(kw,mass,mt,tm,tn,tscls,lums,GB,zpars) - else -* -* Zero-age helium white dwarf. -* - mc = mt - mass = mt - kw = 10 - endif - else - lum = lums(2)*(lums(3)/lums(2))**tau - if(mass.le.zpars(3))then - rx = rg - else -* He-ignition and end of HG occur at Rmin - rmin = rminf(mass) - ry = ragbf(mt,lums(4),zpars(2)) - rx = MIN(rmin,ry) - if(mass.le.mlp)then - texp = log(mass/mlp)/log(zpars(3)/mlp) - rx = rg - rx = rmin*(rx/rmin)**texp - endif - tau2 = tblf(mass,zpars(2),zpars(3)) - if(tau2.lt.tiny) rx = ry - endif - r = rtms*(rx/rtms)**tau - kw = 2 - endif -* - endif -* -* Now the GB, CHeB and AGB evolution. -* - elseif(aj.lt.tscls(2))then -* -* Red Giant. -* - kw = 3 - lum = lgbtf(aj,GB(1),GB,tscls(4),tscls(5),tscls(6)) - if(mass.le.zpars(2))then -* Star has a degenerate He core which grows on the GB - mc = mcgbf(lum,GB,lums(6)) - else -* Star has a non-degenerate He core which may grow, but -* only slightly, on the GB - tau = (aj - tscls(1))/(tscls(2) - tscls(1)) - mcx = mcheif(mass,zpars(2),zpars(9)) - mcy = mcheif(mass,zpars(2),zpars(10)) - mc = mcx + (mcy - mcx)*tau - endif - r = rgbf(mt,lum) - rg = r - if(mc.ge.mt)then - aj = 0.d0 - if(mass.gt.zpars(2))then -* -* Zero-age helium star -* - mc = 0.d0 - mass = mt - kw = 7 - CALL star(kw,mass,mt,tm,tn,tscls,lums,GB,zpars) - else -* -* Zero-age helium white dwarf. -* - mc = mt - mass = mt - kw = 10 - endif - endif -* - elseif(aj.lt.tbagb)then -* -* Core helium burning star. -* - if(kw.eq.3.and.mass.le.zpars(2))then - mass = mt - CALL star(kw,mass,mt,tm,tn,tscls,lums,GB,zpars) - aj = tscls(2) - endif - if(mass.le.zpars(2))then - mcx = mcgbf(lums(4),GB,lums(6)) - else - mcx = mcheif(mass,zpars(2),zpars(10)) - endif - tau = (aj - tscls(2))/tscls(3) - mc = mcx + (mcagbf(mass) - mcx)*tau -* - if(mass.le.zpars(2))then - lx = lums(5) - ly = lums(7) - rx = rzahbf(mt,mc,zpars(2)) - rg = rgbf(mt,lx) - rmin = rg*zpars(13)**(mass/zpars(2)) - texp = MIN(MAX(0.4d0,rmin/rx),2.5d0) - ry = ragbf(mt,ly,zpars(2)) - if(rmin.lt.rx)then - taul = (log(rx/rmin))**(1.d0/3.d0) - else - rmin = rx - taul = 0.d0 - endif - tauh = (log(ry/rmin))**(1.d0/3.d0) - tau2 = taul*(tau - 1.d0) + tauh*tau - r = rmin*exp(abs(tau2)**3) - rg = rg + tau*(ry - rg) - lum = lx*(ly/lx)**(tau**texp) - elseif(mass.gt.zpars(3))then -* -* For HM stars He-ignition takes place at Rmin in the HG, and CHeB -* consists of a blue phase (before tloop) and a RG phase (after tloop). -* - tau2 = tblf(mass,zpars(2),zpars(3)) - tloop = tscls(2) + tau2*tscls(3) - rmin = rminf(mass) - rg = rgbf(mt,lums(4)) - rx = ragbf(mt,lums(4),zpars(2)) - rmin = MIN(rmin, rx) - if(mass.le.mlp) then - texp = log(mass/mlp)/log(zpars(3)/mlp) - rx = rg - rx = rmin*(rx/rmin)**texp - else - rx = rmin - end if - texp = MIN(MAX(0.4d0,rmin/rx),2.5d0) - lum = lums(4)*(lums(7)/lums(4))**(tau**texp) - if(aj.lt.tloop)then - ly = lums(4)*(lums(7)/lums(4))**(tau2**texp) - ry = ragbf(mt,ly,zpars(2)) - taul = 0.d0 - if(ABS(rmin-rx).gt.tiny)then - taul = (log(rx/rmin))**(1.d0/3.d0) - endif - tauh = 0.d0 - if(ry.gt.rmin) tauh = (log(ry/rmin))**(1.d0/3.d0) - tau = (aj - tscls(2))/(tau2*tscls(3)) - tau2 = taul*(tau - 1.d0) + tauh*tau - r = rmin*exp(abs(tau2)**3) - rg = rg + tau*(ry - rg) - else - r = ragbf(mt,lum,zpars(2)) - rg = r - end if - else -* -* For IM stars CHeB consists of a RG phase (before tloop) and a blue -* loop (after tloop). -* - tau2 = 1.d0 - tblf(mass,zpars(2),zpars(3)) - tloop = tscls(2) + tau2*tscls(3) - if(aj.lt.tloop)then - tau = (tloop - aj)/(tau2*tscls(3)) - lum = lums(5)*(lums(4)/lums(5))**(tau**3) - r = rgbf(mt,lum) - rg = r - else - lx = lums(5) - ly = lums(7) - rx = rgbf(mt,lx) - rmin = rminf(mt) - texp = MIN(MAX(0.4d0,rmin/rx),2.5d0) - ry = ragbf(mt,ly,zpars(2)) - if(rmin.lt.rx)then - taul = (log(rx/rmin))**(1.d0/3.d0) - else - rmin = rx - taul = 0.d0 - endif - tauh = (log(ry/rmin))**(1.d0/3.d0) - tau = (aj - tloop)/(tscls(3) - (tloop - tscls(2))) - tau2 = taul*(tau - 1.d0) + tauh*tau - r = rmin*exp(abs(tau2)**3) - rg = rx + tau*(ry - rx) - lum = lx*(ly/lx)**(tau**texp) - endif - endif -* -* Test whether core mass exceeds total mass. -* - if(mc.ge.mt)then -* -* Evolved MS naked helium star. -* - kw = 7 - xx = (aj - tscls(2))/tscls(3) - mass = mt - CALL star(kw,mass,mt,tm,tn,tscls,lums,GB,zpars) - aj = xx*tm - else - kw = 4 - endif -* - else -* -* Asymptotic Red Giant. -* -* On the AGB the He core mass remains constant until at Ltp it -* is caught by the C core mass and they grow together. -* - mcbagb = mcagbf(mass) - mcx = mcgbtf(tbagb,GB(8),GB,tscls(7),tscls(8),tscls(9)) - mcmax = MAX(MAX(mch,0.773d0*mcbagb-0.35d0),1.05d0*mcx) -* - if(aj.lt.tscls(13))then - mcx = mcgbtf(aj,GB(8),GB,tscls(7),tscls(8),tscls(9)) - mc = mcbagb - lum = lmcgbf(mcx,GB) - if(mt.le.mc)then -* -* Evolved naked helium star as the envelope is lost but the -* star has not completed its interior burning. The star becomes -* a post-HeMS star. -* - kw = 9 - mt = mc - mass = mt - mc = mcx - CALL star(kw,mass,mt,tm,tn,tscls,lums,GB,zpars) - if(mc.le.GB(7))then - aj = tscls(4) - (1.d0/((GB(5)-1.d0)*GB(8)*GB(4)))* - & (mc**(1.d0-GB(5))) - else - aj = tscls(5) - (1.d0/((GB(6)-1.d0)*GB(8)*GB(3)))* - & (mc**(1.d0-GB(6))) - endif - aj = MAX(aj,tm) - goto 90 - else - kw = 5 - endif - else - kw = 6 - mc = mcgbtf(aj,GB(2),GB,tscls(10),tscls(11),tscls(12)) - lum = lmcgbf(mc,GB) -* -* Approximate 3rd Dredge-up on AGB by limiting Mc. -* - lambda = MIN(0.9d0,0.3d0+0.001d0*mass**5) - tau = tscls(13) - mcx = mcgbtf(tau,GB(2),GB,tscls(10),tscls(11),tscls(12)) - mcy = mc - mc = mc - lambda*(mcy-mcx) - mcx = mc - mcmax = MIN(mt,mcmax) - endif - r = ragbf(mt,lum,zpars(2)) - rg = r -* -* Mc,x represents the C core mass and we now test whether it -* exceeds either the total mass or the maximum allowed core mass. -* - if(mcmax-mcx.lt.tiny)then - aj = 0.d0 - mc = mcmax - if(mc.lt.mch)then - if(ifflag.ge.1)then -* -* Invoke WD IFMR from HPE, 1995, MNRAS, 272, 800. -* - if(zpars(14).ge.1.0d-08)then - mc = MIN(0.36d0+0.104d0*mass,0.58d0+0.061d0*mass) - mc = MAX(0.54d0+0.042d0*mass,mc) - if(mass.lt.1.d0) mc = 0.46d0 - else - mc = MIN(0.29d0+0.178d0*mass,0.65d0+0.062d0*mass) - mc = MAX(0.54d0+0.073d0*mass,mc) - endif - mc = MIN(mch,mc) - endif -* - mt = mc - if(mcbagb.lt.1.6d0)then -* -* Zero-age Carbon/Oxygen White Dwarf -* - kw = 11 - else -* -* Zero-age Oxygen/Neon White Dwarf -* - kw = 12 - endif - mass = mt -* - else - if(mcbagb.lt.1.6d0)then -* -* Star is not massive enough to ignite C burning. -* so no remnant is left after the SN -* - kw = 15 - aj = 0.d0 - mt = 0.d0 - lum = 1.0d-10 - r = 1.0d-10 - else - if(nsflag.eq.0)then - mt = 1.17d0 + 0.09d0*mc - elseif(nsflag.ge.1)then -* -* Use NS/BH mass given by Belczynski et al. 2002, ApJ, 572, 407. -* - if(mc.lt.2.5d0) then - mcx = 0.161767d0*mc + 1.067055d0 - else - mcx = 0.314154d0*mc + 0.686088d0 - endif - - if(mc.le.5.d0) then - mt = mcx - elseif(mc.lt.7.6d0) then - mt = mcx + (mc - 5.d0)*(mt - mcx)/2.6d0 -CCC added by Long Wang & Peter Berczik 2014.10. - fallback = (mc - 5.0d0)/2.6d0 - endif -CCC added by Long Wang & Peter Berczik 2014.10. - if(mc.gt.7.6d0) fallback = 1.0d0 - - endif - mc = mt - if(mt.le.mxns)then -* -* Zero-age Neutron star -* - kw = 13 - else -* -* Zero-age Black hole -* - kw = 14 - endif - endif - endif - endif -* - endif -* - 90 continue -* - if(kw.ge.7.and.kw.le.9)then -* -* Naked Helium Star -* - rzams = rzhef(mt) - rx = rzams - if(aj.lt.tm)then -* -* Main Sequence -* - kw = 7 - tau = aj/tm - am = MAX(0.d0,0.85d0-0.08d0*mass) - lum = lums(1)*(1.d0+0.45d0*tau+am*tau**2) - am = MAX(0.d0,0.4d0-0.22d0*LOG10(mt)) - r = rx*(1.d0+am*(tau-tau**6)) - rg = rx -* Star has no core mass and hence no memory of its past -* which is why we subject mass and mt to mass loss for -* this phase. - mc = 0.d0 - if(mt.lt.zpars(10)) kw = 10 - else -* -* Helium Shell Burning -* - kw = 8 - lum = lgbtf(aj,GB(8),GB,tscls(4),tscls(5),tscls(6)) - r = rhehgf(mt,lum,rx,lums(2)) - rg = rhegbf(lum) - if(r.ge.rg)then - kw = 9 - r = rg - endif - mc = mcgbf(lum,GB,lums(6)) - mtc = MIN(mt,1.45d0*mt-0.31d0) - mcmax = MIN(mtc,MAX(mch,0.773d0*mass-0.35d0)) - if(mcmax-mc.lt.tiny)then - aj = 0.d0 - mc = mcmax - if(mc.lt.mch)then - if(mass.lt.1.6d0)then -* -* Zero-age Carbon/Oxygen White Dwarf -* - mt = MAX(mc,(mc+0.31d0)/1.45d0) - kw = 11 - else -* -* Zero-age Oxygen/Neon White Dwarf -* - mt = mc - kw = 12 - endif - mass = mt - else - if(mass.lt.1.6d0)then -* -* Star is not massive enough to ignite C burning. -* so no remnant is left after the SN -* - kw = 15 - aj = 0.d0 - mt = 0.d0 - lum = 1.0d-10 - r = 1.0d-10 - else - if(nsflag.eq.0)then - mt = 1.17d0 + 0.09d0*mc - elseif(nsflag.ge.1)then - if(mc.lt.2.5d0)then - mcx = 0.161767d0*mc + 1.067055d0 - else - mcx = 0.314154d0*mc + 0.686088d0 - endif - if(mc.le.5.d0)then - mt = mcx - elseif(mc.lt.7.6d0)then - mt = mcx + (mc - 5.d0)*(mt - mcx)/2.6d0 - endif - endif - mc = mt - if(mt.le.mxns)then -* -* Zero-age Neutron star -* - kw = 13 - else -* -* Zero-age Black hole -* - kw = 14 - endif - endif - endif - endif - endif - endif -* - if(kw.ge.10.and.kw.le.12)then -* -* White dwarf. -* - mc = mt - if(mc.ge.mch)then -* -* Accretion induced supernova with no remnant -* unless WD is ONe in which case we assume a NS -* of minimum mass is the remnant. -* - if(kw.eq.12)then - kw = 13 - aj = 0.d0 - mt = 1.3d0 - else - kw = 15 - aj = 0.d0 - mt = 0.d0 - lum = 1.0d-10 - r = 1.0d-10 - endif - else -* - if(kw.eq.10)then - xx = ahe - else - xx = aco - endif -* - if(wdflag.eq.0)then -* -* Mestel cooling -* - lum = 635.d0*mt*zpars(14)/(xx*(aj+0.1d0))**1.4d0 -* - elseif(wdflag.ge.1)then -* -* modified-Mestel cooling -* - if(aj.lt.9000.0)then - lum = 300.d0*mt*zpars(14)/(xx*(aj+0.1d0))**1.18d0 - else - fac = (9000.1d0*xx)**5.3d0 - lum = 300.d0*fac*mt*zpars(14)/(xx*(aj+0.1d0))**6.48d0 - endif -* - endif -* - r = 0.0115d0*SQRT(MAX(1.48204d-06,(mch/mt)**(2.d0/3.d0) - & - (mt/mch)**(2.d0/3.d0))) - r = MIN(0.1d0,r) - if(mt.lt.0.0005d0) r = 0.09d0 - if(mt.lt.0.000005d0) r = 0.009d0 -* - endif - endif -* - if(kw.eq.13)then -* -* Neutron Star. -* - mc = mt - if(mc.gt.mxns)then -* -* Accretion induced Black Hole? -* - kw = 14 - aj = 0.d0 - else - lum = 0.02d0*(mt**0.67d0)/(MAX(aj,0.1d0))**2 - r = 1.4d-05 - endif - endif -* - if(kw.eq.14)then -* -* Black hole -* - mc = mt - lum = 1.0d-10 - r = 4.24d-06*mt - endif -* -* Calculate the core radius and the luminosity and radius of the -* remnant that the star will become. -* - tau = 0.d0 - if(kw.le.1.or.kw.eq.7)then - rc = 0.d0 - elseif(kw.le.3)then - if(mass.gt.zpars(2))then - lx = lzhef(mc) - rx = rzhef(mc) - rc = rx - else - if(wdflag.eq.0)then - lx = 635.d0*mc*zpars(14)/((ahe*0.1d0)**1.4d0) - elseif(wdflag.ge.1)then - lx = 300.d0*mc*zpars(14)/((ahe*0.1d0)**1.18d0) - endif - rx = 0.0115d0*SQRT(MAX(1.48204d-06, - & (mch/mc)**(2.d0/3.d0)-(mc/mch)**(2.d0/3.d0))) - rc = 5.d0*rx - endif - elseif(kw.eq.4)then - tau = (aj - tscls(2))/tscls(3) - kwp = 7 - CALL star(kwp,mc,mc,tm,tn,tscls,lums,GB,zpars) - am = MAX(0.d0,0.85d0-0.08d0*mc) - lx = lums(1)*(1.d0+0.45d0*tau+am*tau**2) - rx = rzhef(mc) - am = MAX(0.d0,0.4d0-0.22d0*LOG10(mc)) - rx = rx*(1.d0+am*(tau-tau**6)) - CALL star(kw,mass,mt,tm,tn,tscls,lums,GB,zpars) - rc = rx - elseif(kw.eq.5)then - kwp = 9 - if(tn.gt.tbagb) tau = 3.d0*(aj-tbagb)/(tn-tbagb) - CALL star(kwp,mc,mc,tm,tn,tscls,lums,GB,zpars) - lx = lmcgbf(mcx,GB) - if(tau.lt.1.d0) lx = lums(2)*(lx/lums(2))**tau - rx = rzhef(mc) - rx = MIN(rhehgf(mc,lx,rx,lums(2)),rhegbf(lx)) - CALL star(kw,mass,mt,tm,tn,tscls,lums,GB,zpars) - rc = rx - elseif(kw.le.9)then - if(wdflag.eq.0)then - lx = 635.d0*mc*zpars(14)/((aco*0.1d0)**1.4d0) - elseif(wdflag.ge.1)then - lx = 300.d0*mc*zpars(14)/((aco*0.1d0)**1.18d0) - endif - rx = 0.0115d0*SQRT(MAX(1.48204d-06, - & (mch/mc)**(2.d0/3.d0) - (mc/mch)**(2.d0/3.d0))) - rc = 5.d0*rx - else - rc = r - menv = 1.0d-10 - renv = 1.0d-10 - k2 = 0.21d0 - endif -* -* Perturb the luminosity and radius due to small envelope mass. -* - if(kw.ge.2.and.kw.le.9.and.kw.ne.7)then - mew = ((mt-mc)/mt)*MIN(5.d0,MAX(1.2d0,(lum/lum0)**kap)) - if(kw.ge.8) mew = ((mtc-mc)/mtc)*5.d0 - if(mew.lt.1.d0)then - xx = lpertf(mt,mew) - lum = lx*(lum/lx)**xx - if(r.le.rx)then - xx = 0.d0 - else - xx = rpertf(mt,mew,r,rx) - endif - r = rx*(r/rx)**xx - endif - rc = MIN(rc,r) - endif -* -* Calculate mass and radius of convective envelope, and envelope -* gyration radius. -* - if(kw.lt.10)then - CALL mrenv(kw,mass,mt,mc,lum,r,rc,aj,tm,lums(2),lums(3), - & lums(4),rzams,rtms,rg,menv,renv,k2) - endif -* - if(mass.gt.99.99d0)then - mass = mass0 - endif - if(mt.gt.99.99d0)then - mt = mt0 - endif -* - return - end -*** - -cc//kick.f - -*** - SUBROUTINE kick(kw,m1,m1n,m2,ecc,sep,jorb,vs) - implicit none -* - integer kw,k - INTEGER idum - COMMON /VALUE3/ idum - INTEGER idum2,iy,ir(32) - COMMON /RAND3/ idum2,iy,ir - integer bhflag - real*8 m1,m2,m1n,ecc,sep,jorb,ecc2 - real*8 pi,twopi,gmrkm,yearsc,rsunkm - parameter(yearsc=3.1557d+07,rsunkm=6.96d+05) - real*8 mm,em,dif,der,del,r - real*8 u1,u2,vk,v(4),s,theta,phi - real*8 sphi,cphi,stheta,ctheta,salpha,calpha - real*8 vr,vr2,vk2,vn2,hn2 - real*8 mu,cmu,vs(3),v1,v2,mx1,mx2 - real*8 sigma - COMMON /VALUE4/ sigma,bhflag - real ran3,xx - external ran3 - -CCC added by Long Wang & Peter Berczik 2014.10. - real*8 fallback - common /fall/fallback - -* - do k = 1,3 - vs(k) = 0.d0 - enddo -* if(kw.eq.14.and.bhflag.eq.0) goto 95 -* - pi = ACOS(-1.d0) - twopi = 2.d0*pi - -* Conversion factor to ensure velocities are in km/s using mass and -* radius in solar units. - gmrkm = 1.906125d+05 - -* -* Find the initial separation by randomly choosing a mean anomaly. - if(sep.gt.0.d0.and.ecc.ge.0.d0)then - xx = RAN3(idum) - mm = xx*twopi - em = mm - 2 dif = em - ecc*SIN(em) - mm - if(ABS(dif/mm).le.1.0d-04) goto 3 - der = 1.d0 - ecc*COS(em) - del = dif/der - em = em - del - goto 2 - 3 continue - r = sep*(1.d0 - ecc*COS(em)) -* -* Find the initial relative velocity vector. - salpha = SQRT((sep*sep*(1.d0-ecc*ecc))/(r*(2.d0*sep-r))) - calpha = (-1.d0*ecc*SIN(em))/SQRT(1.d0-ecc*ecc*COS(em)*COS(em)) - vr2 = gmrkm*(m1+m2)*(2.d0/r - 1.d0/sep) - vr = SQRT(vr2) - else - vr = 0.d0 - vr2 = 0.d0 - salpha = 0.d0 - calpha = 0.d0 - endif -* -* Generate Kick Velocity using Maxwellian Distribution (Phinney 1992). -* Use Henon's method for pairwise components (Douglas Heggie 22/5/97). - do 20 k = 1,2 - u1 = RAN3(idum) - u2 = RAN3(idum) - -* Generate two velocities from polar coordinates S & THETA. - s = sigma*SQRT(-2.d0*LOG(1.d0 - u1)) - theta = twopi*u2 - v(2*k-1) = s*COS(theta) - v(2*k) = s*SIN(theta) - 20 continue - - vk2 = v(1)**2 + v(2)**2 + v(3)**2 - vk = SQRT(vk2) - -CCC added by Long Wang & Peter Berczik 2014.10. - if(kw.eq.14) then - vk = vk*(1.0d0-fallback) - vk2 = vk*vk - endif - - if((kw.eq.14.and.bhflag.eq.0).or.kw.lt.0)then - vk2 = 0.d0 - vk = 0.d0 - if(kw.lt.0) kw = 13 - endif - - sphi = -1.d0 + 2.d0*u1 - phi = ASIN(sphi) - cphi = COS(phi) - stheta = SIN(theta) - ctheta = COS(theta) - -* WRITE(66,*)' KICK VK PHI THETA ',vk,phi,theta - if(sep.le.0.d0.or.ecc.lt.0.d0) goto 90 -* -* Determine the magnitude of the new relative velocity. - vn2 = vk2+vr2-2.d0*vk*vr*(ctheta*cphi*salpha-stheta*cphi*calpha) - -* Calculate the new semi-major axis. - sep = 2.d0/r - vn2/(gmrkm*(m1n+m2)) - sep = 1.d0/sep - -* if(sep.le.0.d0)then -* ecc = 1.1d0 -* goto 90 -* endif - -* Determine the magnitude of the cross product of the separation vector -* and the new relative velocity. - - v1 = vk2*sphi*sphi - v2 = (vk*ctheta*cphi-vr*salpha)**2 - hn2 = r*r*(v1 + v2) - -* Calculate the new eccentricity. - ecc2 = 1.d0 - hn2/(gmrkm*sep*(m1n+m2)) - ecc2 = MAX(ecc2,0.d0) - ecc = SQRT(ecc2) - -* Calculate the new orbital angular momentum taking care to convert -* hn to units of Rsun^2/yr. - jorb = (m1n*m2/(m1n+m2))*SQRT(hn2)*(yearsc/rsunkm) - -* Determine the angle between the new and old orbital angular -* momentum vectors. - cmu = (vr*salpha-vk*ctheta*cphi)/SQRT(v1 + v2) - mu = ACOS(cmu) - -* Calculate the components of the velocity of the new centre-of-mass. - 90 continue - - if(ecc.le.1.0)then -* Calculate the components of the velocity of the new centre-of-mass. - mx1 = vk*m1n/(m1n+m2) - mx2 = vr*(m1-m1n)*m2/((m1n+m2)*(m1+m2)) - vs(1) = mx1*ctheta*cphi + mx2*salpha - vs(2) = mx1*stheta*cphi + mx2*calpha - vs(3) = mx1*sphi - else -* Calculate the relative hyperbolic velocity at infinity (simple method). - sep = r/(ecc-1.d0) -* cmu = SQRT(ecc-1.d0) -* mu = ATAN(cmu) - mu = ACOS(1.d0/ecc) - vr2 = gmrkm*(m1n+m2)/sep - vr = SQRT(vr2) - vs(1) = vr*SIN(mu) - vs(2) = vr*COS(mu) - vs(3) = 0.d0 - ecc = MIN(ecc,99.99d0) - endif -* - 95 continue -* - RETURN - END -*** - -cc//mlwind.f - -*** - real*8 FUNCTION mlwind(kw,lum,r,mt,mc,rl,z) - implicit none - integer kw - real*8 lum,r,mt,mc,rl,z - real*8 dml,dms,dmt,p0,x,mew,lum0,kap,neta,bwind,hewind,mxns - parameter(lum0=7.0d+04,kap=-0.5d0) - common /value1/ neta,bwind,hewind,mxns -* -* Calculate stellar wind mass loss. -* -* Apply mass loss of Nieuwenhuijzen & de Jager, A&A, 1990, 231, 134, -* for massive stars over the entire HRD. - dms = 0.d0 - if(lum.gt.4000.d0)then - x = MIN(1.d0,(lum-4000.d0)/500.d0) - dms = 9.6d-15*x*(r**0.81d0)*(lum**1.24d0)*(mt**0.16d0) - dms = dms*(z/0.02d0)**(1.d0/2.d0) - endif - if(kw.ge.2.and.kw.le.9)then -* 'Reimers' mass loss - dml = neta*4.0d-13*r*lum/mt - if(rl.gt.0.d0) dml = dml*(1.d0 + bwind*(MIN(0.5d0,(r/rl)))**6) -* Apply mass loss of Vassiliadis & Wood, ApJ, 1993, 413, 641, -* for high pulsation periods on AGB. - if(kw.eq.5.or.kw.eq.6)then - p0 = -2.07d0 - 0.9d0*log10(mt) + 1.94d0*log10(r) - p0 = 10.d0**p0 - p0 = MIN(p0,2000.d0) - dmt = -11.4d0+0.0125d0*(p0-100.d0*MAX(mt-2.5d0,0.d0)) - dmt = 10.d0**dmt - dmt = 1.d0*MIN(dmt,1.36d-09*lum) - dml = MAX(dml,dmt) - endif - if(kw.gt.6)then - dms = MAX(dml,1.0d-13*hewind*lum**(3.d0/2.d0)) - else - dms = MAX(dml,dms) - mew = ((mt-mc)/mt)*MIN(5.d0,MAX(1.2d0,(lum/lum0)**kap)) -* reduced WR-like mass loss for small H-envelope mass - if(mew.lt.1.d0)then - dml = 1.0d-13*lum**(3.d0/2.d0)*(1.d0 - mew) - dms = MAX(dml,dms) - end if -* LBV-like mass loss beyond the Humphreys-Davidson limit. - x = 1.0d-5*r*sqrt(lum) - if(lum.gt.6.0d+05.and.x.gt.1.d0)then - dml = 0.1d0*(x-1.d0)**3*(lum/6.0d+05-1.d0) - dms = dms + dml - endif - endif - endif -* - mlwind = dms -* - return - end -*** - - -cc//mrenv.f - -*** - SUBROUTINE mrenv(kw,mass,mt,mc,lum,rad,rc,aj,tm,ltms,lbgb,lhei, - & rzams,rtms,rg,menv,renv,k2e) - implicit none - integer kw - real*8 mass,mt,mc,lum,rad,rc,aj,tm - real*8 k2e,menv,menvg,menvt,menvz,renv,renvg,renvt,renvz - real*8 A,B,C,D,E,F,x,y - real*8 k2bgb,k2g,k2z,logm,logmt,lbgb,ltms,lhei,rg,rtms,rzams - real*8 teff,tebgb,tetms,tau,tauenv,tautms -* -* A function to estimate the mass and radius of the convective envelope, -* as well as the gyration radius of the envelope. -* N.B. Valid only for Z=0.02! -* -* The following input is needed from HRDIAG: -* kw = stellar type -* mass = zero-age stellar mass -* mt = actual mass -* mc = core mass (not really needed, can also be done outside subroutine) -* lum = luminosity -* rad = radius -* rc = core radius (not really needed...) -* aj = age -* tm = main-sequence lifetime -* ltms = luminosity at TMS, lums(2) -* lbgb = luminosity at BGB, lums(3) -* lhei = luminosity at He ignition, lums(4) -* rzams = radius at ZAMS -* rtms = radius at TMS -* rg = giant branch or Hayashi track radius, approporaite for the type. -* For kw=1 or 2 this is radius at BGB, and for kw=4 either GB or -* AGB radius at present luminosity. -* - logm = log10(mass) - A = MIN(0.81d0,MAX(0.68d0,0.68d0+0.4d0*logm)) - C = MAX(-2.5d0,MIN(-1.5d0,-2.5d0+5.d0*logm)) - D = -0.1d0 - E = 0.025d0 -* -* Zero-age and BGB values of k^2. -* - k2z = MIN(0.21d0,MAX(0.09d0-0.27d0*logm,0.037d0+0.033d0*logm)) - if(logm.gt.1.3d0) k2z = k2z - 0.055d0*(logm-1.3d0)**2 - k2bgb = MIN(0.15d0,MIN(0.147d0+0.03d0*logm,0.162d0-0.04d0*logm)) -* - if(kw.ge.3.and.kw.le.6)then -* -* Envelope k^2 for giant-like stars; this will be modified for non-giant -* CHeB stars or small envelope mass below. -* Formula is fairly accurate for both FGB and AGB stars if M <= 10, and -* gives reasonable values for higher masses. Mass dependence is on actual -* rather than ZA mass, expected to work for mass-losing stars (but not -* tested!). The slightly complex appearance is to insure continuity at -* the BGB, which depends on the ZA mass. -* - logmt = log10(mt) - F = 0.208d0 + 0.125d0*logmt - 0.035d0*logmt**2 - B = 1.0d+04*mt**(3.d0/2.d0)/(1.d0+0.1d0*mt**(3.d0/2.d0)) - x = ((lum-lbgb)/B)**2 - y = (F - 0.033d0*log10(lbgb))/k2bgb - 1.d0 - k2g = (F - 0.033d0*log10(lum) + 0.4d0*x)/(1.d0+y*(lbgb/lum)+x) - elseif(kw.eq.9)then -* -* Rough fit for for HeGB stars... -* - B = 3.0d+04*mt**(3.d0/2.d0) - x = (MAX(0.d0,lum/B-0.5d0))**2 - k2g = (k2bgb + 0.4d0*x)/(1.d0 + 0.4d0*x) - else - k2g = k2bgb - endif -* - if(kw.le.2)then - menvg = 0.5d0 - renvg = 0.65d0 - elseif(kw.eq.3.and.lum.lt.3.d0*lbgb)then -* -* FGB stars still close to the BGB do not yet have a fully developed CE. -* - x = MIN(3.d0,lhei/lbgb) - tau = MAX(0.d0,MIN(1.d0,(x-lum/lbgb)/(x-1.d0))) - menvg = 1.d0 - 0.5d0*tau**2 - renvg = 1.d0 - 0.35d0*tau**2 - else - menvg = 1.d0 - renvg = 1.d0 - endif -* - if(rad.lt.rg)then -* -* Stars not on the Hayashi track: MS and HG stars, non-giant CHeB stars, -* HeMS and HeHG stars, as well as giants with very small envelope mass. -* - - if(kw.le.6)then -* -* Envelope k^2 fitted for MS and HG stars. -* Again, pretty accurate for M <= 10 but less so for larger masses. -* [Note that this represents the whole star on the MS, so there is a -* discontinuity in stellar k^2 between MS and HG - okay for stars with a -* MS hook but low-mass stars should preferably be continous...] -* -* For other types of star not on the Hayashi track we use the same fit as -* for HG stars, this is not very accurate but has the correct qualitative -* behaviour. For CheB stars this is an overestimate because they appear -* to have a more centrally concentrated envelope than HG stars. -* - k2e = (k2z-E)*(rad/rzams)**C + E*(rad/rzams)**D - elseif(kw.eq.7)then -* Rough fit for naked He MS stars. - tau = aj/tm - k2e = 0.08d0 - 0.03d0*tau - elseif(kw.le.9)then -* Rough fit for HeHG stars. - k2e = 0.08d0*rzams/rad - endif -* -* tauenv measures proximity to the Hayashi track in terms of Teff. -* If tauenv>0 then an appreciable convective envelope is present, and -* k^2 needs to be modified. -* - if(kw.le.2)then - teff = sqrt(sqrt(lum)/rad) - tebgb = sqrt(sqrt(lbgb)/rg) - tauenv = MAX(0.d0,MIN(1.d0,(tebgb/teff-A)/(1.d0-A))) - else - tauenv = MAX(0.d0,MIN(1.d0,(sqrt(rad/rg)-A)/(1.d0-A))) - endif -* - if(tauenv.gt.0.d0)then - menv = menvg*tauenv**5 - renv = renvg*tauenv**(5.d0/4.d0) - if(kw.le.1)then -* Zero-age values for CE mass and radius. - x = MAX(0.d0,MIN(1.d0,(0.1d0-logm)/0.55d0)) - menvz = 0.18d0*x + 0.82d0*x**5 - renvz = 0.4d0*x**(1.d0/4.d0) + 0.6d0*x**10 - y = 2.d0 + 8.d0*x -* Values for CE mass and radius at start of the HG. - tetms = sqrt(sqrt(ltms)/rtms) - tautms = MAX(0.d0,MIN(1.d0,(tebgb/tetms-A)/(1.d0-A))) - menvt = menvg*tautms**5 - renvt = renvg*tautms**(5.d0/4.d0) -* Modified expressions during MS evolution. - tau = aj/tm - if(tautms.gt.0.d0)then - menv = menvz + tau**y*menv*(menvt - menvz)/menvt - renv = renvz + tau**y*renv*(renvt - renvz)/renvt - else - menv = 0.d0 - renv = 0.d0 - endif - k2e = k2e + tau**y*tauenv**3*(k2g - k2e) - else - k2e = k2e + tauenv**3*(k2g - k2e) - endif - else - menv = 0.d0 - renv = 0.d0 - endif - else -* -* All other stars should be true giants. -* - menv = menvg - renv = renvg - k2e = k2g - endif -* - menv = menv*(mt - mc) - renv = renv*(rad - rc) - menv = MAX(menv,1.0d-10) - renv = MAX(renv,1.0d-10) -* - return - end -*** - - -cc//ran3.f - -*** - REAL FUNCTION ran3(IDUM) -* -* Random number generator from Numerical Recipes, Press et al. pg 272. -* - IMPLICIT NONE - INTEGER j,k,im1,im2,imm1,ia1,ia2,iq1,iq2,ir1,ir2,ntab,ndiv - PARAMETER(im1=2147483563,im2=2147483399,ia1=40014,ia2=40692) - PARAMETER(iq1=53668,iq2=52774,ir1=12211,ir2=3791,ntab=32) - INTEGER idum - INTEGER idum2,iy,ir(ntab) - COMMON /RAND3/ idum2,iy,ir - DATA idum2/123456789/, iy/0/, ir/ntab*0/ - REAL am -* - am = 1.0/float(im1) - imm1 = im1 - 1 - ndiv = 1 + imm1/ntab -* - if(idum.le.0)then - idum = MAX(-idum,1) - idum2 = idum - do 11 , j = ntab+8,1,-1 - k = idum/iq1 - idum = ia1*(idum-k*iq1)-k*ir1 - if(idum.lt.0) idum = idum + im1 - if(j.le.ntab) ir(j) = idum - 11 continue - iy = ir(1) - endif - k = idum/iq1 - idum = ia1*(idum-k*iq1)-k*ir1 - if(idum.lt.0) idum = idum + im1 - k = idum2/iq2 - idum2 = ia2*(idum2-k*iq2)-k*ir2 - if(idum2.lt.0) idum2 = idum2 + im2 - j = 1 + iy/ndiv - iy = ir(j) - idum2 - ir(j) = idum - if(iy.lt.1) iy = iy + imm1 - ran3 = am*iy -* - RETURN - END -*** - - - -cc//star.f - -*** - SUBROUTINE star(kw,mass,mt,tm,tn,tscls,lums,GB,zpars) -* -* -* Stellar luminosity & evolution time. -* ------------------------------------ -* - implicit none -* - integer kw -* - real*8 mass,mt,tm,tn,tscls(20),lums(10),GB(10),zpars(20) - real*8 tgb,tbagb,mch,mcmax,mc1,mc2,mcbagb,dx,am - real*8 lambda,tau,mtc,mass0 - parameter(mch=1.44d0) -* - real*8 lzamsf,lzahbf,lzhef - real*8 tbgbf,thookf,tHef,themsf,mcgbf,mcagbf,mcheif,mcgbtf - real*8 ltmsf,lbgbf,lHeIf,lHef,lbagbf,lmcgbf - external lzamsf,lzahbf,lzhef - external tbgbf,thookf,tHef,themsf,mcgbf,mcagbf,mcheif,mcgbtf - external ltmsf,lbgbf,lHeIf,lHef,lbagbf,lmcgbf -* -* Computes the characteristic luminosities at different stages (LUMS), -* and various timescales (TSCLS). -* Ref: P.P. Eggleton, M.J. Fitchett & C.A. Tout (1989) Ap.J. 347, 998. -* -* Revised 27th March 1995 by C. A. Tout -* and 24th October 1995 to include metallicity -* and 13th December 1996 to include naked helium stars -* -* Revised 5th April 1997 by J. R. Hurley -* to include Z=0.001 as well as Z=0.02, convective overshooting, -* MS hook and more elaborate CHeB. It now also sets the Giant -* Branch parameters relevant to the mass of the star. -* -* ------------------------------------------------------------ -* Times: 1; BGB 2; He ignition 3; He burning -* 4; Giant t(inf1) 5; Giant t(inf2) 6; Giant t(Mx) -* 7; FAGB t(inf1) 8; FAGB t(inf2) 9; FAGB t(Mx) -* 10; SAGB t(inf1) 11; SAGB t(inf2) 12; SAGB t(Mx) -* 13; TP 14; t(Mcmax) -* -* LUMS: 1; ZAMS 2; End MS 3; BGB -* 4; He ignition 5; He burning 6; L(Mx) -* 7; BAGB 8; TP -* -* GB: 1; effective A(H) 2; A(H,He) 3; B -* 4; D 5; p 6; q -* 7; Mx 8; A(He) 9; Mc,BGB -* -* ------------------------------------------------------------ -* -* - mass0 = mass - if(mass0.gt.100.d0) mass = 100.d0 -* - if(kw.ge.7.and.kw.le.9) goto 90 - if(kw.ge.10) goto 95 -* -* MS and BGB times -* - tscls(1) = tbgbf(mass) - tm = MAX(zpars(8),thookf(mass))*tscls(1) -* -* Zero- and terminal age main sequence luminosity -* - lums(1) = lzamsf(mass) - lums(2) = ltmsf(mass) -* -* Set the GB parameters -* - GB(1) = MAX(-4.8d0,MIN(-5.7d0+0.8d0*mass,-4.1d0+0.14d0*mass)) - GB(1) = 10.d0**GB(1) - GB(2) = 1.27d-05 - GB(8) = 8.0d-05 - GB(3) = MAX(3.0d+04,500.d0 + 1.75d+04*mass**0.6d0) - if(mass.le.2.0)then - GB(4) = zpars(6) - GB(5) = 6.d0 - GB(6) = 3.d0 - elseif(mass.lt.2.5)then - dx = zpars(6) - (0.975d0*zpars(6) - 0.18d0*2.5d0) - GB(4) = zpars(6) - dx*(mass - 2.d0)/(0.5d0) - GB(5) = 6.d0 - (mass - 2.d0)/(0.5d0) - GB(6) = 3.d0 - (mass - 2.d0)/(0.5d0) - else - GB(4) = MAX(-1.d0,0.5d0*zpars(6) - 0.06d0*mass) - GB(4) = MAX(GB(4),0.975d0*zpars(6) - 0.18d0*mass) - GB(5) = 5.d0 - GB(6) = 2.d0 - endif - GB(4) = 10.d0**GB(4) - GB(7) = (GB(3)/GB(4))**(1.d0/(GB(5)-GB(6))) -* -* Change in slope of giant L-Mc relation. - lums(6) = GB(4)*GB(7)**GB(5) -* -* HeI ignition luminosity - lums(4) = lHeIf(mass,zpars(2)) - lums(7) = lbagbf(mass,zpars(2)) -* - if(mass.lt.0.1d0.and.kw.le.1)then - tscls(2) = 1.1d0*tscls(1) - tscls(3) = 0.1d0*tscls(1) - lums(3) = lbgbf(mass) - goto 96 - endif -* - if(mass.le.zpars(3))then -* Base of the giant branch luminosity - lums(3) = lbgbf(mass) -* Set GB timescales - tscls(4) = tscls(1) + (1.d0/((GB(5)-1.d0)*GB(1)*GB(4)))* - & ((GB(4)/lums(3))**((GB(5)-1.d0)/GB(5))) - tscls(6) = tscls(4) - (tscls(4) - tscls(1))*((lums(3)/lums(6)) - & **((GB(5)-1.d0)/GB(5))) - tscls(5) = tscls(6) + (1.d0/((GB(6)-1.d0)*GB(1)*GB(3)))* - & ((GB(3)/lums(6))**((GB(6)-1.d0)/GB(6))) -* Set Helium ignition time - if(lums(4).le.lums(6))then - tscls(2) = tscls(4) - (1.d0/((GB(5)-1.d0)*GB(1)*GB(4)))* - & ((GB(4)/lums(4))**((GB(5)-1.d0)/GB(5))) - else - tscls(2) = tscls(5) - (1.d0/((GB(6)-1.d0)*GB(1)*GB(3)))* - & ((GB(3)/lums(4))**((GB(6)-1.d0)/GB(6))) - endif - tgb = tscls(2) - tscls(1) - if(mass.le.zpars(2))then - mc1 = mcgbf(lums(4),GB,lums(6)) - mc2 = mcagbf(mass) - lums(5) = lzahbf(mass,mc1,zpars(2)) - tscls(3) = tHef(mass,mc1,zpars(2)) - else - lums(5) = lHef(mass)*lums(4) - tscls(3) = tHef(mass,1.d0,zpars(2))*tscls(1) - endif - else -* Note that for M>zpars(3) there is no GB as the star goes from -* HG -> CHeB -> AGB. So in effect tscls(1) refers to the time of -* Helium ignition and not the BGB. - tscls(2) = tscls(1) - tscls(3) = tHef(mass,1.d0,zpars(2))*tscls(1) -* This now represents the luminosity at the end of CHeB, ie. BAGB - lums(5) = lums(7) -* We set lums(3) to be the luminosity at the end of the HG - lums(3) = lums(4) - endif -* -* Set the core mass at the BGB. -* - if(mass.le.zpars(2))then - GB(9) = mcgbf(lums(3),GB,lums(6)) - elseif(mass.le.zpars(3))then - GB(9) = mcheif(mass,zpars(2),zpars(9)) - else - GB(9) = mcheif(mass,zpars(2),zpars(10)) - endif -* -* FAGB time parameters -* - tbagb = tscls(2) + tscls(3) - tscls(7) = tbagb + (1.d0/((GB(5)-1.d0)*GB(8)*GB(4)))* - & ((GB(4)/lums(7))**((GB(5)-1.d0)/GB(5))) - tscls(9) = tscls(7) - (tscls(7) - tbagb)*((lums(7)/lums(6)) - & **((GB(5)-1.d0)/GB(5))) - tscls(8) = tscls(9) + (1.d0/((GB(6)-1.d0)*GB(8)*GB(3)))* - & ((GB(3)/lums(6))**((GB(6)-1.d0)/GB(6))) -* -* Now to find Ltp and ttp using Mc,He,tp -* - mcbagb = mcagbf(mass) - mc1 = mcbagb - if(mc1.ge.0.8d0.and.mc1.lt.2.25d0)then -* The star undergoes dredge-up at Ltp causing a decrease in Mc,He - mc1 = 0.44d0*mc1 + 0.448d0 - endif - lums(8) = lmcgbf(mc1,GB) - if(mc1.le.GB(7))then - tscls(13) = tscls(7) - (1.d0/((GB(5)-1.d0)*GB(8)*GB(4)))* - & (mc1**(1.d0-GB(5))) - else - tscls(13) = tscls(8) - (1.d0/((GB(6)-1.d0)*GB(8)*GB(3)))* - & (mc1**(1.d0-GB(6))) - endif -* -* SAGB time parameters -* - if(mc1.le.GB(7))then - tscls(10) = tscls(13) + (1.d0/((GB(5)-1.d0)*GB(2)*GB(4)))* - & ((GB(4)/lums(8))**((GB(5)-1.d0)/GB(5))) - tscls(12) = tscls(10) - (tscls(10) - tscls(13))* - & ((lums(8)/lums(6))**((GB(5)-1.d0)/GB(5))) - tscls(11) = tscls(12) + (1.d0/((GB(6)-1.d0)*GB(2)*GB(3)))* - & ((GB(3)/lums(6))**((GB(6)-1.d0)/GB(6))) - else - tscls(10) = tscls(7) - tscls(12) = tscls(9) - tscls(11) = tscls(13) + (1.d0/((GB(6)-1.d0)*GB(2)*GB(3)))* - & ((GB(3)/lums(8))**((GB(6)-1.d0)/GB(6))) - endif -* -* Get an idea of when Mc,C = Mc,C,max on the AGB - tau = tscls(2) + tscls(3) - mc2 = mcgbtf(tau,GB(8),GB,tscls(7),tscls(8),tscls(9)) - mcmax = MAX(MAX(mch,0.773d0*mcbagb - 0.35d0),1.05d0*mc2) -* - if(mcmax.le.mc1)then - if(mcmax.le.GB(7))then - tscls(14) = tscls(7) - (1.d0/((GB(5)-1.d0)*GB(8)*GB(4)))* - & (mcmax**(1.d0-GB(5))) - else - tscls(14) = tscls(8) - (1.d0/((GB(6)-1.d0)*GB(8)*GB(3)))* - & (mcmax**(1.d0-GB(6))) - endif - else -* Star is on SAGB and we need to increase mcmax if any 3rd -* dredge-up has occurred. - lambda = MIN(0.9d0,0.3d0+0.001d0*mass**5) - mcmax = (mcmax - lambda*mc1)/(1.d0 - lambda) - if(mcmax.le.GB(7))then - tscls(14) = tscls(10) - (1.d0/((GB(5)-1.d0)*GB(2)*GB(4)))* - & (mcmax**(1.d0-GB(5))) - else - tscls(14) = tscls(11) - (1.d0/((GB(6)-1.d0)*GB(2)*GB(3)))* - & (mcmax**(1.d0-GB(6))) - endif - endif - tscls(14) = MAX(tbagb,tscls(14)) - if(mass.ge.100.d0)then - tn = tscls(2) - goto 100 - endif -* -* Calculate the nuclear timescale - the time of exhausting -* nuclear fuel without further mass loss. -* This means we want to find when Mc = Mt which defines Tn and will -* be used in determining the timestep required. Note that after some -* stars reach Mc = Mt there will be a Naked Helium Star lifetime -* which is also a nuclear burning period but is not included in Tn. -* - if(ABS(mt-mcbagb).lt.1.0d-14.and.kw.lt.5)then - tn = tbagb - else -* Note that the only occurence of Mc being double-valued is for stars -* that have a dredge-up. If Mt = Mc where Mc could be the value taken -* from CHeB or from the AGB we need to check the current stellar type. - if(mt.gt.mcbagb.or.(mt.ge.mc1.and.kw.gt.4))then - if(kw.eq.6)then - lambda = MIN(0.9d0,0.3d0+0.001d0*mass**5) - mc1 = (mt - lambda*mc1)/(1.d0 - lambda) - else - mc1 = mt - endif - if(mc1.le.GB(7))then - tn = tscls(10) - (1.d0/((GB(5)-1.d0)*GB(2)*GB(4)))* - & (mc1**(1.d0-GB(5))) - else - tn = tscls(11) - (1.d0/((GB(6)-1.d0)*GB(2)*GB(3)))* - & (mc1**(1.d0-GB(6))) - endif - else - if(mass.gt.zpars(3))then - mc1 = mcheif(mass,zpars(2),zpars(10)) - if(mt.le.mc1)then - tn = tscls(2) - else - tn = tscls(2) + tscls(3)*((mt - mc1)/(mcbagb - mc1)) - endif - elseif(mass.le.zpars(2))then - mc1 = mcgbf(lums(3),GB,lums(6)) - mc2 = mcgbf(lums(4),GB,lums(6)) - if(mt.le.mc1)then - tn = tscls(1) - elseif(mt.le.mc2)then - if(mt.le.GB(7))then - tn = tscls(4) - (1.d0/((GB(5)-1.d0)*GB(1)*GB(4)))* - & (mt**(1.d0-GB(5))) - else - tn = tscls(5) - (1.d0/((GB(6)-1.d0)*GB(1)*GB(3)))* - & (mt**(1.d0-GB(6))) - endif - else - tn = tscls(2) + tscls(3)*((mt - mc2)/(mcbagb - mc2)) - endif - else - mc1 = mcheif(mass,zpars(2),zpars(9)) - mc2 = mcheif(mass,zpars(2),zpars(10)) - if(mt.le.mc1)then - tn = tscls(1) - elseif(mt.le.mc2)then - tn = tscls(1) + tgb*((mt - mc1)/(mc2 - mc1)) - else - tn = tscls(2) + tscls(3)*((mt - mc2)/(mcbagb - mc2)) - endif - endif - endif - endif - tn = MIN(tn,tscls(14)) -* - goto 100 -* - 90 continue -* -* Calculate Helium star Main Sequence lifetime. -* - tm = themsf(mass) - tscls(1) = tm -* -* Zero- and terminal age Helium star main sequence luminosity -* - lums(1) = lzhef(mass) - am = MAX(0.d0,0.85d0-0.08d0*mass) - lums(2) = lums(1)*(1.d0+0.45d0+am) -* -* Set the Helium star GB parameters -* - GB(8) = 8.0d-05 - GB(3) = 4.1d+04 - GB(4) = 5.5d+04/(1.d0+0.4d0*mass**4) - GB(5) = 5.d0 - GB(6) = 3.d0 - GB(7) = (GB(3)/GB(4))**(1.d0/(GB(5)-GB(6))) -* Change in slope of giant L-Mc relation. - lums(6) = GB(4)*GB(7)**GB(5) -* -*** Set Helium star GB timescales -* - mc1 = mcgbf(lums(2),GB,lums(6)) - tscls(4) = tm + (1.d0/((GB(5)-1.d0)*GB(8)*GB(4)))* - & mc1**(1.d0-GB(5)) - tscls(6) = tscls(4) - (tscls(4) - tm)*((GB(7)/mc1) - & **(1.d0-GB(5))) - tscls(5) = tscls(6) + (1.d0/((GB(6)-1.d0)*GB(8)*GB(3)))* - & GB(7)**(1.d0-GB(6)) -* -* Get an idea of when Mc = MIN(Mt,Mc,C,max) on the GB - mtc = MIN(mt,1.45d0*mt-0.31d0) - if(mtc.le.0.d0) mtc = mt - mcmax = MIN(mtc,MAX(mch,0.773d0*mass-0.35d0)) - if(mcmax.le.GB(7))then - tscls(14) = tscls(4) - (1.d0/((GB(5)-1.d0)*GB(8)*GB(4)))* - & (mcmax**(1.d0-GB(5))) - else - tscls(14) = tscls(5) - (1.d0/((GB(6)-1.d0)*GB(8)*GB(3)))* - & (mcmax**(1.d0-GB(6))) - endif - tscls(14) = MAX(tscls(14),tm) - tn = tscls(14) -* - goto 100 -* - 95 continue - tm = 1.0d+10 - tscls(1) = tm - 96 continue - tn = 1.0d+10 -* - 100 continue - mass = mass0 -* - return - end -*** - - -cc//zcnsts.f - -*** - SUBROUTINE zcnsts(z,zpars) -* - implicit none - integer kw -* - real*8 z,zpars(20) - real*8 tm,tn,tscls(20),lums(10),GB(10) - real*8 lzs,dlzs,lz,lzd,dum1,m1,m2,rr,rb,mhefl,lhefl,thefl,lx - real*8 tbgbf,thef,lbagbf,lheif,lhef,lzahbf - real*8 rgbf,ragbf,rminf,mcgbf - external tbgbf,thef,lbagbf,lheif,lhef,lzahbf - external rgbf,ragbf,rminf,mcgbf -* -cc// include 'zdata.h' - -* -* Initialization data set for fitting formulae. -* ----------------------------------------------------------- -* - real*8 xz(76),xt(31),xl(72),xr(119),xg(112),xh(99) -* -* data for Lzams(1->35) and Rzams(36->76) -* - data xz / - & 3.970417d-01, -3.2913574d-01, 3.4776688d-01, 3.7470851d-01, - & 9.011915d-02, - & 8.527626d+00,-2.441225973d+01, 5.643597107d+01, 3.706152575d+01, - & 5.4562406d+00, - & 2.5546d-04, -1.23461d-03, -2.3246d-04, 4.5519d-04, - & 1.6176d-04, - & 5.432889d+00, -8.62157806d+00, 1.344202049d+01, - & 1.451584135d+01, 3.39793084d+00, - & 5.563579d+00,-1.032345224d+01, 1.944322980d+01, - & 1.897361347d+01, 4.16903097d+00, - & 7.8866060d-01, -2.90870942d+00, 6.54713531d+00, - & 4.05606657d+00, 5.3287322d-01, - & 5.86685d-03, -1.704237d-02, 3.872348d-02, 2.570041d-02, - & 3.83376d-03, - & 1.715359d+00, 6.2246212d-01, -9.2557761d-01, -1.16996966d+00, - & -3.0631491d-01, - & 6.597788d+00, -4.2450044d-01,-1.213339427d+01,-1.073509484d+01, - & -2.51487077d+00, - & 1.008855000d+01, -7.11727086d+00,-3.167119479d+01, - & -2.424848322d+01,-5.33608972d+00, - & 1.012495d+00, 3.2699690d-01, -9.23418d-03, -3.876858d-02, - & -4.12750d-03, - & 7.490166d-02, 2.410413d-02, 7.233664d-02, 3.040467d-02, - & 1.97741d-03, 1.077422d-02, - & 3.082234d+00, 9.447205d-01, -2.15200882d+00, -2.49219496d+00, - & -6.3848738d-01, - & 1.784778d+01, -7.4534569d+00,-4.896066856d+01,-4.005386135d+01, - & -9.09331816d+00, - & 2.2582d-04, -1.86899d-03, 3.88783d-03, 1.42402d-03,-7.671d-05/ -* -* data for Tbgb(1->17) and Thook(18->31) -* - data xt /1.593890d+03, 2.053038d+03, 1.231226d+03, - & 2.327785d+02, 2.706708d+03, 1.483131d+03, - & 5.772723d+02, 7.411230d+01, 1.466143d+02, - & -1.048442d+02,-6.795374d+01,-1.391127d+01, - & 4.141960d-02, 4.564888d-02, 2.958542d-02, - & 5.571483d-03, 3.426349d-01, - & 1.949814d+01, 1.758178d+00,-6.008212d+00, - & -4.470533d+00, 4.903830d+00, 5.212154d-02, - & 3.166411d-02,-2.750074d-03,-2.271549d-03, - & 1.312179d+00,-3.294936d-01, 9.231860d-02, - & 2.610989d-02, 8.073972d-01/ -* -* data for Ltms(1->27), Lalpha(28->43), Lbeta(44->56) and Lhook(57->72) -* - data xl /1.031538d+00,-2.434480d-01, 7.732821d+00, - & 6.460705d+00, 1.374484d+00, 1.043715d+00, - & -1.577474d+00,-5.168234d+00,-5.596506d+00, - & -1.299394d+00, 7.859573d+02,-8.542048d+00, - & -2.642511d+01,-9.585707d+00, 3.858911d+03, - & 2.459681d+03,-7.630093d+01,-3.486057d+02, - & -4.861703d+01, 2.888720d+02, 2.952979d+02, - & 1.850341d+02, 3.797254d+01, 7.196580d+00, - & 5.613746d-01, 3.805871d-01, 8.398728d-02, - & 2.321400d-01, 1.828075d-03,-2.232007d-02, - & -3.378734d-03, 1.163659d-02, 3.427682d-03, - & 1.421393d-03,-3.710666d-03, 1.048020d-02, - & -1.231921d-02,-1.686860d-02,-4.234354d-03, - & 1.555590d+00,-3.223927d-01,-5.197429d-01, - & -1.066441d-01, - & 3.855707d-01,-6.104166d-01, 5.676742d+00, - & 1.060894d+01, 5.284014d+00, 3.579064d-01, - & -6.442936d-01, 5.494644d+00, 1.054952d+01, - & 5.280991d+00, 9.587587d-01, 8.777464d-01, - & 2.017321d-01, - & 1.910302d-01, 1.158624d-01, 3.348990d-02, - & 2.599706d-03, 3.931056d-01, 7.277637d-02, - & -1.366593d-01,-4.508946d-02, 3.267776d-01, - & 1.204424d-01, 9.988332d-02, 2.455361d-02, - & 5.990212d-01, 5.570264d-02, 6.207626d-02, - & 1.777283d-02/ -* -* data for Rtms(1->40), Ralpha(41->64), Rbeta(65->83), Rgamma(84->103) -* and Rhook(104->119) -* - data xr /2.187715d-01,-2.154437d+00,-3.768678d+00, - & -1.975518d+00,-3.021475d-01, 1.466440d+00, - & 1.839725d+00, 6.442199d+00, 4.023635d+00, - & 6.957529d-01, 2.652091d+01, 8.178458d+01, - & 1.156058d+02, 7.633811d+01, 1.950698d+01, - & 1.472103d+00,-2.947609d+00,-3.312828d+00, - & -9.945065d-01, 3.071048d+00,-5.679941d+00, - & -9.745523d+00,-3.594543d+00,-8.672073d-02, - & 2.617890d+00, 1.019135d+00,-3.292551d-02, - & -7.445123d-02, 1.075567d-02, 1.773287d-02, - & 9.610479d-03, 1.732469d-03, 1.476246d+00, - & 1.899331d+00, 1.195010d+00, 3.035051d-01, - & 5.502535d+00,-6.601663d-02, 9.968707d-02, - & 3.599801d-02, - & 4.907546d-01,-1.683928d-01,-3.108742d-01, - & -7.202918d-02, 4.537070d+00,-4.465455d+00, - & -1.612690d+00,-1.623246d+00, 1.796220d+00, - & 2.814020d-01, 1.423325d+00, 3.421036d-01, - & 2.256216d+00, 3.773400d-01, 1.537867d+00, - & 4.396373d-01, 1.564231d-03, 1.653042d-03, - & -4.439786d-03,-4.951011d-03,-1.216530d-03, - & 5.210157d+00,-4.143695d+00,-2.120870d+00, - & 1.071489d+00,-1.164852d-01,-8.623831d-02, - & -1.582349d-02, 7.108492d-01, 7.935927d-01, - & 3.926983d-01, 3.622146d-02, 3.478514d+00, - & -2.585474d-02,-1.512955d-02,-2.833691d-03, - & 3.969331d-03, 4.539076d-03, 1.720906d-03, - & 1.897857d-04, 9.132108d-01,-1.653695d-01, - & 3.636784d-02, - & 1.192334d-02, 1.083057d-02, 1.230969d+00, - & 1.551656d+00,-1.668868d-01, 5.818123d-01, - & -1.105027d+01,-1.668070d+01, 7.615495d-01, - & 1.068243d-01,-2.011333d-01,-9.371415d-02, - & -1.015564d-01,-2.161264d-01,-5.182516d-02, - & -3.868776d-01,-5.457078d-01,-1.463472d-01, - & 9.409838d+00, 1.522928d+00, - & 7.330122d-01, 5.192827d-01, 2.316416d-01, - & 8.346941d-03, 1.172768d+00,-1.209262d-01, - & -1.193023d-01,-2.859837d-02, 3.982622d-01, - & -2.296279d-01,-2.262539d-01,-5.219837d-02, - & 3.571038d+00,-2.223625d-02,-2.611794d-02, - & -6.359648d-03/ -* -* data for Lbgb(1->24), Lbagb(25->44), Rgb(45->66), Ragb(67->100), -* Mchei(101->102) and Mcbagb(103->112) -* - data xg /9.511033d+01, 6.819618d+01,-1.045625d+01, - & -1.474939d+01, 3.113458d+01, 1.012033d+01, - & -4.650511d+00,-2.463185d+00, 1.413057d+00, - & 4.578814d-01,-6.850581d-02,-5.588658d-02, - & 3.910862d+01, 5.196646d+01, 2.264970d+01, - & 2.873680d+00, 4.597479d+00,-2.855179d-01, - & 2.709724d-01, 6.682518d+00, 2.827718d-01, - & -7.294429d-02, 4.637345d+00, 9.301992d+00, - & 1.626062d+02,-1.168838d+01,-5.498343d+00, - & 3.336833d-01,-1.458043d-01,-2.011751d-02, - & 7.425137d+01, 1.790236d+01, 3.033910d+01, - & 1.018259d+01, 9.268325d+02,-9.739859d+01, - & -7.702152d+01,-3.158268d+01, 1.127018d+01, - & 1.622158d+00,-1.443664d+00,-9.474699d-01, - & 2.474401d+00, 3.892972d-01, - & 9.960283d-01, 8.164393d-01, 2.383830d+00, - & 2.223436d+00, 8.638115d-01, 1.231572d-01, - & 2.561062d-01, 7.072646d-02,-5.444596d-02, - & -5.798167d-02,-1.349129d-02, 1.157338d+00, - & 1.467883d+00, 4.299661d+00, 3.130500d+00, - & 6.992080d-01, 1.640687d-02, 4.022765d-01, - & 3.050010d-01, 9.962137d-01, 7.914079d-01, - & 1.728098d-01, - & 1.125124d+00, 1.306486d+00, 3.622359d+00, - & 2.601976d+00, 3.031270d-01,-1.343798d-01, - & 3.349489d-01, 4.531269d-03, 1.131793d-01, - & 2.300156d-01, 7.632745d-02, 1.467794d+00, - & 2.798142d+00, 9.455580d+00, 8.963904d+00, - & 3.339719d+00, 4.426929d-01, 4.658512d-01, - & 2.597451d-01, 9.048179d-01, 7.394505d-01, - & 1.607092d-01, 1.110866d+00, 9.623856d-01, - & 2.735487d+00, 2.445602d+00, 8.826352d-01, - & 1.140142d-01,-1.584333d-01,-1.728865d-01, - & -4.461431d-01,-3.925259d-01,-1.276203d-01, - & -1.308728d-02, - & 9.796164d-02, 1.350554d+00, - & 1.445216d-01,-6.180219d-02, 3.093878d-02, - & 1.567090d-02, 1.304129d+00, 1.395919d-01, - & 4.142455d-03,-9.732503d-03, 5.114149d-01, - & -1.160850d-02/ -* -* data for Lhei(1->14), Lhe(15->25) Rmin(26->43), The(44->65), -* Tbl(66->79), Lzahb(80->87) and Rzahb(88->99) -* - data xh /2.751631d+03, 3.557098d+02, - & -3.820831d-02, 5.872664d-02, 1.5d+01, - & 1.071738d+02,-8.970339d+01,-3.949739d+01, - & 7.348793d+02,-1.531020d+02,-3.793700d+01, - & 9.219293d+00,-2.005865d+00,-5.561309d-01, - & 2.917412d+00, 1.575290d+00, 5.751814d-01, - & 6.371760d-01, 3.880523d-01, 4.916389d+00, - & 2.862149d+00, 7.844850d-01, 3.629118d+00, - & -9.112722d-01, 1.042291d+00, - & 1.609901d+01, 7.391573d+00, 2.277010d+01, - & 8.334227d+00, 1.747500d-01, 6.271202d-02, - & -2.324229d-02,-1.844559d-02, 2.752869d+00, - & 2.729201d-02, 4.996927d-01, 2.496551d-01, - & -9.138012d-02,-3.671407d-01, 3.518506d+00, - & 1.112440d+00,-4.556216d-01,-2.179426d-01, - & 1.314955d+02, 2.009258d+01,-5.143082d-01, - & -1.379140d+00, 1.823973d+01,-3.074559d+00, - & -4.307878d+00, 1.5d1, - & 2.327037d+00, 2.403445d+00, 1.208407d+00, - & 2.087263d-01, 1.079113d-01, 1.762409d-02, - & 1.096601d-02, 3.058818d-03, 2.327409d+00, - & 6.901582d-01,-2.158431d-01,-1.084117d-01, - & 1.997378d+00,-8.126205d-01, - & 2.214315d+00,-1.975747d+00, 4.805428d-01, - & 2.471620d+00,-5.401682d+00, 3.247361d+00, - & 5.072525d+00, 1.146189d+01, 6.961724d+00, - & 1.316965d+00, 5.139740d+00, 1.127733d+00, - & 2.344416d-01,-3.793726d-01, - & 5.496045d+01,-1.289968d+01, 6.385758d+00, - & 1.832694d+00,-5.766608d-02, 5.696128d-02, - & 1.211104d+02, 1.647903d+00, - & 2.063983d+00, 7.363827d-01, 2.654323d-01, - & -6.140719d-02, 2.214088d+02, 2.187113d+02, - & 1.170177d+01,-2.635340d+01, 2.003160d+00, - & 9.388871d-01, 9.656450d-01, 2.362266d-01/ -* -*** - - real*8 msp(200),gbp(200),c(5) - common /MSCFF/ msp - common /GBCFF/ gbp - data c /3.040581d-01, 8.049509d-02, 8.967485d-02, - & 8.780198d-02, 2.219170d-02/ -* -* ------------------------------------------------------------ -* -* zpars: 1; M below which hook doesn't appear on MS, Mhook. -* 2; M above which He ignition occurs non-degenerately, Mhef. -* 3; M above which He ignition occurs on the HG, Mfgb. -* 4; M below which C/O ignition doesn't occur, Mup. -* 5; M above which C ignites in the centre, Mec. -* 6; value of log D for M<= zpars(3) -* 7; value of x for Rgb propto M^(-x) -* 8; value of x for tMS = MAX(tHOOK,x*tBGB) -* 9; constant for McHeIf when computing Mc,BGB, mchefl. -* 10; constant for McHeIf when computing Mc,HeI, mchefl. -* 11; hydrogen abundance. -* 12; helium abundance. -* 13; constant x in rmin = rgb*x**y used by LM CHeB. -* 14; z**0.4 to be used for WD L formula. -* -* ------------------------------------------------------------ -* - lzs = log10(z/0.02d0) - dlzs = 1.d0/(z*log(10.d0)) - lz = log10(z) - lzd = lzs + 1.d0 -* - zpars(1) = 1.0185d0 + lzs*(0.16015d0 + lzs*0.0892d0) - zpars(2) = 1.995d0 + lzs*(0.25d0 + lzs*0.087d0) - zpars(3) = 16.5d0*z**0.06d0/(1.d0 + (1.0d-04/z)**1.27d0) - zpars(4) = MAX(6.11044d0 + 1.02167d0*lzs, 5.d0) - zpars(5) = zpars(4) + 1.8d0 - zpars(6) = 5.37d0 + lzs*0.135d0 - zpars(7) = c(1) + lzs*(c(2) + lzs*(c(3) + lzs*(c(4) + lzs*c(5)))) - zpars(8) = MAX(0.95d0,MAX(0.95d0-(10.d0/3.d0)*(z-0.01d0), - & MIN(0.99d0,0.98d0-(100.d0/7.d0)*(z-0.001d0)))) -*** -* Lzams - msp(1) = xz(1)+lzs*(xz(2)+lzs*(xz(3)+lzs*(xz(4)+lzs*xz(5)))) - msp(2) = xz(6)+lzs*(xz(7)+lzs*(xz(8)+lzs*(xz(9)+lzs*xz(10)))) - msp(3) = xz(11)+lzs*(xz(12)+lzs*(xz(13)+lzs*(xz(14)+lzs*xz(15)))) - msp(4) = xz(16)+lzs*(xz(17)+lzs*(xz(18)+lzs*(xz(19)+lzs*xz(20)))) - msp(5) = xz(21)+lzs*(xz(22)+lzs*(xz(23)+lzs*(xz(24)+lzs*xz(25)))) - msp(6) = xz(26)+lzs*(xz(27)+lzs*(xz(28)+lzs*(xz(29)+lzs*xz(30)))) - msp(7) = xz(31)+lzs*(xz(32)+lzs*(xz(33)+lzs*(xz(34)+lzs*xz(35)))) -* Rzams - msp(8) = xz(36)+lzs*(xz(37)+lzs*(xz(38)+lzs*(xz(39)+lzs*xz(40)))) - msp(9) = xz(41)+lzs*(xz(42)+lzs*(xz(43)+lzs*(xz(44)+lzs*xz(45)))) - msp(10) = xz(46)+lzs*(xz(47)+lzs*(xz(48)+lzs*(xz(49)+lzs*xz(50)))) - msp(11) = xz(51)+lzs*(xz(52)+lzs*(xz(53)+lzs*(xz(54)+lzs*xz(55)))) - msp(12) = xz(56)+lzs*(xz(57)+lzs*(xz(58)+lzs*(xz(59)+lzs*xz(60)))) - msp(13) = xz(61) - msp(14) = xz(62)+lzs*(xz(63)+lzs*(xz(64)+lzs*(xz(65)+lzs*xz(66)))) - msp(15) = xz(67)+lzs*(xz(68)+lzs*(xz(69)+lzs*(xz(70)+lzs*xz(71)))) - msp(16) = xz(72)+lzs*(xz(73)+lzs*(xz(74)+lzs*(xz(75)+lzs*xz(76)))) -* Tbgb - msp(17) = xt(1)+lzs*(xt(2)+lzs*(xt(3)+lzs*xt(4))) - msp(18) = xt(5)+lzs*(xt(6)+lzs*(xt(7)+lzs*xt(8))) - msp(19) = xt(9)+lzs*(xt(10)+lzs*(xt(11)+lzs*xt(12))) - msp(20) = xt(13)+lzs*(xt(14)+lzs*(xt(15)+lzs*xt(16))) - msp(21) = xt(17) -* dTbgb/dz - msp(117) = dlzs*(xt(2)+lzs*(2.d0*xt(3)+3.d0*lzs*xt(4))) - msp(118) = dlzs*(xt(6)+lzs*(2.d0*xt(7)+3.d0*lzs*xt(8))) - msp(119) = dlzs*(xt(10)+lzs*(2.d0*xt(11)+3.d0*lzs*xt(12))) - msp(120) = dlzs*(xt(14)+lzs*(2.d0*xt(15)+3.d0*lzs*xt(16))) -* Thook - msp(22) = xt(18)+lzs*(xt(19)+lzs*(xt(20)+lzs*xt(21))) - msp(23) = xt(22) - msp(24) = xt(23)+lzs*(xt(24)+lzs*(xt(25)+lzs*xt(26))) - msp(25) = xt(27)+lzs*(xt(28)+lzs*(xt(29)+lzs*xt(30))) - msp(26) = xt(31) -* Ltms - msp(27) = xl(1)+lzs*(xl(2)+lzs*(xl(3)+lzs*(xl(4)+lzs*xl(5)))) - msp(28) = xl(6)+lzs*(xl(7)+lzs*(xl(8)+lzs*(xl(9)+lzs*xl(10)))) - msp(29) = xl(11)+lzs*(xl(12)+lzs*(xl(13)+lzs*xl(14))) - msp(30) = xl(15)+lzs*(xl(16)+lzs*(xl(17)+lzs*(xl(18)+lzs*xl(19)))) - msp(27) = msp(27)*msp(30) - msp(28) = msp(28)*msp(30) - msp(31) = xl(20)+lzs*(xl(21)+lzs*(xl(22)+lzs*xl(23))) - msp(32) = xl(24)+lzs*(xl(25)+lzs*(xl(26)+lzs*xl(27))) -* Lalpha - m2 = 2.d0 - msp(33) = xl(28)+lzs*(xl(29)+lzs*(xl(30)+lzs*xl(31))) - msp(34) = xl(32)+lzs*(xl(33)+lzs*(xl(34)+lzs*xl(35))) - msp(35) = xl(36)+lzs*(xl(37)+lzs*(xl(38)+lzs*xl(39))) - msp(36) = xl(40)+lzs*(xl(41)+lzs*(xl(42)+lzs*xl(43))) - msp(37) = MAX(0.9d0,1.1064d0+lzs*(0.415d0+0.18d0*lzs)) - msp(38) = MAX(1.d0,1.19d0+lzs*(0.377d0+0.176d0*lzs)) - if(z.gt.0.01d0)then - msp(37) = MIN(msp(37),1.d0) - msp(38) = MIN(msp(38),1.1d0) - endif - msp(39) = MAX(0.145d0,0.0977d0-lzs*(0.231d0+0.0753d0*lzs)) - msp(40) = MIN(0.24d0+lzs*(0.18d0+0.595d0*lzs),0.306d0+0.053d0*lzs) - msp(41) = MIN(0.33d0+lzs*(0.132d0+0.218d0*lzs), - & 0.3625d0+0.062d0*lzs) - msp(42) = (msp(33)+msp(34)*m2**msp(36))/ - & (m2**0.4d0+msp(35)*m2**1.9d0) -* Lbeta - msp(43) = xl(44)+lzs*(xl(45)+lzs*(xl(46)+lzs*(xl(47)+lzs*xl(48)))) - msp(44) = xl(49)+lzs*(xl(50)+lzs*(xl(51)+lzs*(xl(52)+lzs*xl(53)))) - msp(45) = xl(54)+lzs*(xl(55)+lzs*xl(56)) - msp(46) = MIN(1.4d0,1.5135d0+0.3769d0*lzs) - msp(46) = MAX(0.6355d0-0.4192d0*lzs,MAX(1.25d0,msp(46))) -* Lhook - msp(47) = xl(57)+lzs*(xl(58)+lzs*(xl(59)+lzs*xl(60))) - msp(48) = xl(61)+lzs*(xl(62)+lzs*(xl(63)+lzs*xl(64))) - msp(49) = xl(65)+lzs*(xl(66)+lzs*(xl(67)+lzs*xl(68))) - msp(50) = xl(69)+lzs*(xl(70)+lzs*(xl(71)+lzs*xl(72))) - msp(51) = MIN(1.4d0,1.5135d0+0.3769d0*lzs) - msp(51) = MAX(0.6355d0-0.4192d0*lzs,MAX(1.25d0,msp(51))) -* Rtms - msp(52) = xr(1)+lzs*(xr(2)+lzs*(xr(3)+lzs*(xr(4)+lzs*xr(5)))) - msp(53) = xr(6)+lzs*(xr(7)+lzs*(xr(8)+lzs*(xr(9)+lzs*xr(10)))) - msp(54) = xr(11)+lzs*(xr(12)+lzs*(xr(13)+lzs*(xr(14)+lzs*xr(15)))) - msp(55) = xr(16)+lzs*(xr(17)+lzs*(xr(18)+lzs*xr(19))) - msp(56) = xr(20)+lzs*(xr(21)+lzs*(xr(22)+lzs*xr(23))) - msp(52) = msp(52)*msp(54) - msp(53) = msp(53)*msp(54) - msp(57) = xr(24) - msp(58) = xr(25)+lzs*(xr(26)+lzs*(xr(27)+lzs*xr(28))) - msp(59) = xr(29)+lzs*(xr(30)+lzs*(xr(31)+lzs*xr(32))) - msp(60) = xr(33)+lzs*(xr(34)+lzs*(xr(35)+lzs*xr(36))) - msp(61) = xr(37)+lzs*(xr(38)+lzs*(xr(39)+lzs*xr(40))) -* - msp(62) = MAX(0.097d0-0.1072d0*(lz+3.d0),MAX(0.097d0,MIN(0.1461d0, - & 0.1461d0+0.1237d0*(lz+2.d0)))) - msp(62) = 10.d0**msp(62) - m2 = msp(62) + 0.1d0 - msp(63) = (msp(52)+msp(53)*msp(62)**msp(55))/ - & (msp(54)+msp(62)**msp(56)) - msp(64) = (msp(57)*m2**3+msp(58)*m2**msp(61)+ - & msp(59)*m2**(msp(61)+1.5d0))/(msp(60)+m2**5) -* Ralpha - msp(65) = xr(41)+lzs*(xr(42)+lzs*(xr(43)+lzs*xr(44))) - msp(66) = xr(45)+lzs*(xr(46)+lzs*(xr(47)+lzs*xr(48))) - msp(67) = xr(49)+lzs*(xr(50)+lzs*(xr(51)+lzs*xr(52))) - msp(68) = xr(53)+lzs*(xr(54)+lzs*(xr(55)+lzs*xr(56))) - msp(69) = xr(57)+lzs*(xr(58)+lzs*(xr(59)+lzs*(xr(60)+lzs*xr(61)))) - msp(70) = MAX(0.9d0,MIN(1.d0,1.116d0+0.166d0*lzs)) - msp(71) = MAX(1.477d0+0.296d0*lzs,MIN(1.6d0,-0.308d0-1.046d0*lzs)) - msp(71) = MAX(0.8d0,MIN(0.8d0-2.d0*lzs,msp(71))) - msp(72) = xr(62)+lzs*(xr(63)+lzs*xr(64)) - msp(73) = MAX(0.065d0,0.0843d0-lzs*(0.0475d0+0.0352d0*lzs)) - msp(74) = 0.0736d0+lzs*(0.0749d0+0.04426d0*lzs) - if(z.lt.0.004d0) msp(74) = MIN(0.055d0,msp(74)) - msp(75) = MAX(0.091d0,MIN(0.121d0,0.136d0+0.0352d0*lzs)) - msp(76) = (msp(65)*msp(71)**msp(67))/(msp(66) + msp(71)**msp(68)) - if(msp(70).gt.msp(71))then - msp(70) = msp(71) - msp(75) = msp(76) - endif -* Rbeta - msp(77) = xr(65)+lzs*(xr(66)+lzs*(xr(67)+lzs*xr(68))) - msp(78) = xr(69)+lzs*(xr(70)+lzs*(xr(71)+lzs*xr(72))) - msp(79) = xr(73)+lzs*(xr(74)+lzs*(xr(75)+lzs*xr(76))) - msp(80) = xr(77)+lzs*(xr(78)+lzs*(xr(79)+lzs*xr(80))) - msp(81) = xr(81)+lzs*(xr(82)+lzs*lzs*xr(83)) - if(z.gt.0.01d0) msp(81) = MAX(msp(81),0.95d0) - msp(82) = MAX(1.4d0,MIN(1.6d0,1.6d0+lzs*(0.764d0+0.3322d0*lzs))) -* Rgamma - msp(83) = MAX(xr(84)+lzs*(xr(85)+lzs*(xr(86)+lzs*xr(87))), - & xr(96)+lzs*(xr(97)+lzs*xr(98))) - msp(84) = MIN(0.d0,xr(88)+lzs*(xr(89)+lzs*(xr(90)+lzs*xr(91)))) - msp(84) = MAX(msp(84),xr(99)+lzs*(xr(100)+lzs*xr(101))) - msp(85) = xr(92)+lzs*(xr(93)+lzs*(xr(94)+lzs*xr(95))) - msp(85) = MAX(0.d0,MIN(msp(85),7.454d0+9.046d0*lzs)) - msp(86) = MIN(xr(102)+lzs*xr(103),MAX(2.d0,-13.3d0-18.6d0*lzs)) - msp(87) = MIN(1.5d0,MAX(0.4d0,2.493d0+1.1475d0*lzs)) - msp(88) = MAX(1.d0,MIN(1.27d0,0.8109d0-0.6282d0*lzs)) - msp(88) = MAX(msp(88),0.6355d0-0.4192d0*lzs) - msp(89) = MAX(5.855420d-02,-0.2711d0-lzs*(0.5756d0+0.0838d0*lzs)) -* Rhook - msp(90) = xr(104)+lzs*(xr(105)+lzs*(xr(106)+lzs*xr(107))) - msp(91) = xr(108)+lzs*(xr(109)+lzs*(xr(110)+lzs*xr(111))) - msp(92) = xr(112)+lzs*(xr(113)+lzs*(xr(114)+lzs*xr(115))) - msp(93) = xr(116)+lzs*(xr(117)+lzs*(xr(118)+lzs*xr(119))) - msp(94) = MIN(1.25d0, - & MAX(1.1d0,1.9848d0+lzs*(1.1386d0+0.3564d0*lzs))) - msp(95) = 0.063d0 + lzs*(0.0481d0 + 0.00984d0*lzs) - msp(96) = MIN(1.3d0,MAX(0.45d0,1.2d0+2.45d0*lzs)) -* Lneta - if(z.gt.0.0009d0)then - msp(97) = 10.d0 - else - msp(97) = 20.d0 - endif -* Lbgb - gbp(1) = xg(1)+lzs*(xg(2)+lzs*(xg(3)+lzs*xg(4))) - gbp(2) = xg(5)+lzs*(xg(6)+lzs*(xg(7)+lzs*xg(8))) - gbp(3) = xg(9)+lzs*(xg(10)+lzs*(xg(11)+lzs*xg(12))) - gbp(4) = xg(13)+lzs*(xg(14)+lzs*(xg(15)+lzs*xg(16))) - gbp(5) = xg(17)+lzs*(xg(18)+lzs*xg(19)) - gbp(6) = xg(20)+lzs*(xg(21)+lzs*xg(22)) - gbp(3) = gbp(3)**gbp(6) - gbp(7) = xg(23) - gbp(8) = xg(24) -* Lbagb -* set gbp(16) = 1.d0 until it is reset later with an initial -* call to Lbagbf using mass = zpars(2) and mhefl = 0.0 - gbp(9) = xg(25) + lzs*(xg(26) + lzs*xg(27)) - gbp(10) = xg(28) + lzs*(xg(29) + lzs*xg(30)) - gbp(11) = 15.d0 - gbp(12) = xg(31)+lzs*(xg(32)+lzs*(xg(33)+lzs*xg(34))) - gbp(13) = xg(35)+lzs*(xg(36)+lzs*(xg(37)+lzs*xg(38))) - gbp(14) = xg(39)+lzs*(xg(40)+lzs*(xg(41)+lzs*xg(42))) - gbp(15) = xg(43)+lzs*xg(44) - gbp(12) = gbp(12)**gbp(15) - gbp(14) = gbp(14)**gbp(15) - gbp(16) = 1.d0 -* Rgb - gbp(17) = -4.6739d0-0.9394d0*lz - gbp(17) = 10.d0**gbp(17) - gbp(17) = MAX(gbp(17),-0.04167d0+55.67d0*z) - gbp(17) = MIN(gbp(17),0.4771d0-9329.21d0*z**2.94d0) - gbp(18) = MIN(0.54d0,0.397d0+lzs*(0.28826d0+0.5293d0*lzs)) - gbp(19) = MAX(-0.1451d0,-2.2794d0-lz*(1.5175d0+0.254d0*lz)) - gbp(19) = 10.d0**gbp(19) - if(z.gt.0.004d0)then - gbp(19) = MAX(gbp(19),0.7307d0+14265.1d0*z**3.395d0) - endif - gbp(20) = xg(45)+lzs*(xg(46)+lzs*(xg(47)+lzs*(xg(48)+ - & lzs*(xg(49)+lzs*xg(50))))) - gbp(21) = xg(51)+lzs*(xg(52)+lzs*(xg(53)+lzs*(xg(54)+lzs*xg(55)))) - gbp(22) = xg(56)+lzs*(xg(57)+lzs*(xg(58)+lzs*(xg(59)+ - & lzs*(xg(60)+lzs*xg(61))))) - gbp(23) = xg(62)+lzs*(xg(63)+lzs*(xg(64)+lzs*(xg(65)+lzs*xg(66)))) -* Ragb - gbp(24) = MIN(0.99164d0-743.123d0*z**2.83d0, - & 1.0422d0+lzs*(0.13156d0+0.045d0*lzs)) - gbp(25) = xg(67)+lzs*(xg(68)+lzs*(xg(69)+lzs*(xg(70)+ - & lzs*(xg(71)+lzs*xg(72))))) - gbp(26) = xg(73)+lzs*(xg(74)+lzs*(xg(75)+lzs*(xg(76)+lzs*xg(77)))) - gbp(27) = xg(78)+lzs*(xg(79)+lzs*(xg(80)+lzs*(xg(81)+ - & lzs*(xg(82)+lzs*xg(83))))) - gbp(28) = xg(84)+lzs*(xg(85)+lzs*(xg(86)+lzs*(xg(87)+lzs*xg(88)))) - gbp(29) = xg(89)+lzs*(xg(90)+lzs*(xg(91)+lzs*(xg(92)+ - & lzs*(xg(93)+lzs*xg(94))))) - gbp(30) = xg(95)+lzs*(xg(96)+lzs*(xg(97)+lzs*(xg(98)+ - & lzs*(xg(99)+lzs*xg(100))))) - m1 = zpars(2) - 0.2d0 - gbp(31) = gbp(29) + gbp(30)*m1 - gbp(32) = MIN(gbp(25)/zpars(2)**gbp(26),gbp(27)/zpars(2)**gbp(28)) -* Mchei - gbp(33) = xg(101)**4 - gbp(34) = xg(102)*4.d0 -* Mcagb - gbp(35) = xg(103)+lzs*(xg(104)+lzs*(xg(105)+lzs*xg(106))) - gbp(36) = xg(107)+lzs*(xg(108)+lzs*(xg(109)+lzs*xg(110))) - gbp(37) = xg(111)+lzs*xg(112) - gbp(35) = gbp(35)**4 - gbp(36) = gbp(36)*4.d0 - gbp(37) = gbp(37)**4 -* Lhei -* set gbp(41) = -1.d0 until it is reset later with an initial -* call to Lheif using mass = zpars(2) and mhefl = 0.0 - gbp(38) = xh(1)+lzs*xh(2) - gbp(39) = xh(3)+lzs*xh(4) - gbp(40) = xh(5) - gbp(41) = -1.d0 - gbp(42) = xh(6)+lzs*(xh(7)+lzs*xh(8)) - gbp(43) = xh(9)+lzs*(xh(10)+lzs*xh(11)) - gbp(44) = xh(12)+lzs*(xh(13)+lzs*xh(14)) - gbp(42) = gbp(42)**2 - gbp(44) = gbp(44)**2 -* Lhe - gbp(45) = xh(15)+lzs*(xh(16)+lzs*xh(17)) - if(lzs.gt.-1.d0)then - gbp(46) = 1.d0 - xh(19)*(lzs+1.d0)**xh(18) - else - gbp(46) = 1.d0 - endif - gbp(47) = xh(20)+lzs*(xh(21)+lzs*xh(22)) - gbp(48) = xh(23)+lzs*(xh(24)+lzs*xh(25)) - gbp(45) = gbp(45)**gbp(48) - gbp(47) = gbp(47)**gbp(48) - gbp(46) = gbp(46)/zpars(3)**0.1d0+(gbp(46)*gbp(47)-gbp(45))/ - & zpars(3)**(gbp(48)+0.1d0) -* Rmin - gbp(49) = xh(26)+lzs*(xh(27)+lzs*(xh(28)+lzs*xh(29))) - gbp(50) = xh(30)+lzs*(xh(31)+lzs*(xh(32)+lzs*xh(33))) - gbp(51) = xh(34)+lzs*(xh(35)+lzs*(xh(36)+lzs*xh(37))) - gbp(52) = 5.d0+xh(38)*z**xh(39) - gbp(53) = xh(40)+lzs*(xh(41)+lzs*(xh(42)+lzs*xh(43))) - gbp(49) = gbp(49)**gbp(53) - gbp(51) = gbp(51)**(2.d0*gbp(53)) -* The -* set gbp(57) = -1.d0 until it is reset later with an initial -* call to Thef using mass = zpars(2), mc = 0.0 and mhefl = 0.0 - gbp(54) = xh(44)+lzs*(xh(45)+lzs*(xh(46)+lzs*xh(47))) - gbp(55) = xh(48)+lzs*(xh(49)+lzs*xh(50)) - gbp(55) = MAX(gbp(55),1.d0) - gbp(56) = xh(51) - gbp(57) = -1.d0 - gbp(58) = xh(52)+lzs*(xh(53)+lzs*(xh(54)+lzs*xh(55))) - gbp(59) = xh(56)+lzs*(xh(57)+lzs*(xh(58)+lzs*xh(59))) - gbp(60) = xh(60)+lzs*(xh(61)+lzs*(xh(62)+lzs*xh(63))) - gbp(61) = xh(64)+lzs*xh(65) - gbp(58) = gbp(58)**gbp(61) - gbp(60) = gbp(60)**5 -* Tbl - dum1 = zpars(2)/zpars(3) - gbp(62) = xh(66)+lzs*xh(67) - gbp(62) = -gbp(62)*log10(dum1) - gbp(63) = xh(68) - if(lzd.gt.0.d0) then - gbp(64) = 1.d0-lzd*(xh(69)+lzd*(xh(70)+lzd*xh(71))) - else - gbp(64) = 1.d0 - end if - gbp(65) = 1.d0-gbp(64)*dum1**gbp(63) - gbp(66) = 1.d0 - lzd*(xh(77) + lzd*(xh(78) + lzd*xh(79))) - gbp(67) = xh(72) + lzs*(xh(73) + lzs*(xh(74) + lzs*xh(75))) - gbp(68) = xh(76) -* Lzahb - gbp(69) = xh(80) + lzs*(xh(81) + lzs*xh(82)) - gbp(70) = xh(83) + lzs*(xh(84) + lzs*xh(85)) - gbp(71) = 15.d0 - gbp(72) = xh(86) - gbp(73) = xh(87) -* Rzahb - gbp(75) = xh(88) + lzs*(xh(89) + lzs*(xh(90) + lzs*xh(91))) - gbp(76) = xh(92) + lzs*(xh(93) + lzs*(xh(94) + lzs*xh(95))) - gbp(77) = xh(96) + lzs*(xh(97) + lzs*(xh(98) + lzs*xh(99))) -*** -* finish Lbagb - mhefl = 0.d0 - lx = lbagbf(zpars(2),mhefl) - gbp(16) = lx -* finish LHeI - dum1 = 0.d0 - lhefl = lheif(zpars(2),mhefl) - gbp(41) = (gbp(38)*zpars(2)**gbp(39)-lhefl)/ - & (EXP(zpars(2)*gbp(40))*lhefl) -* finish THe - thefl = thef(zpars(2),dum1,mhefl)*tbgbf(zpars(2)) - gbp(57) = (thefl-gbp(54))/(gbp(54)*EXP(gbp(56)*zpars(2))) -* finish Tblf - rb = ragbf(zpars(3),lheif(zpars(3),zpars(2)),mhefl) - rr = 1.d0 - rminf(zpars(3))/rb - rr = MAX(rr,1.0d-12) - gbp(66) = gbp(66)/(zpars(3)**gbp(67)*rr**gbp(68)) -* finish Lzahb - gbp(74) = lhefl*lHef(zpars(2)) -*** - kw = 0 - tm = 0.d0 - tn = 0.d0 - CALL star(kw,zpars(2),zpars(2),tm,tn,tscls,lums,GB,zpars) - zpars(9) = mcgbf(lums(3),GB,lums(6)) - zpars(10) = mcgbf(lums(4),GB,lums(6)) -* set the hydrogen and helium abundances - zpars(11) = 0.76d0 - 3.d0*z - zpars(12) = 0.24d0 + 2.d0*z -* set constant for low-mass CHeB stars - zpars(13) = rminf(zpars(2))/ - & rgbf(zpars(2),lzahbf(zpars(2),zpars(9),zpars(2))) -* - zpars(14) = z**0.4d0 -* - return - end -*** - - -cc//zfuncs.f - -*** - real*8 FUNCTION lzamsf(m) - implicit none - real*8 m,mx,a(200) - common /MSCFF/ a -* -* A function to evaluate Lzams -* ( from Tout et al., 1996, MNRAS, 281, 257 ). -* - mx = SQRT(m) - lzamsf = (a(1)*m**5*mx + a(2)*m**11)/ - & (a(3) + m**3 + a(4)*m**5 + a(5)*m**7 + - & a(6)*m**8 + a(7)*m**9*mx) -* - return - end -*** - real*8 FUNCTION rzamsf(m) - implicit none - real*8 m,mx,a(200) - common /MSCFF/ a -* -* A function to evaluate Rzams -* ( from Tout et al., 1996, MNRAS, 281, 257 ). -* - mx = SQRT(m) - rzamsf = ((a(8)*m**2 + a(9)*m**6)*mx + a(10)*m**11 + - & (a(11) + a(12)*mx)*m**19)/ - & (a(13) + a(14)*m**2 + - & (a(15)*m**8 + m**18 + a(16)*m**19)*mx) -* - return - end -*** - real*8 FUNCTION tbgbf(m) - implicit none - real*8 m,a(200) - common /MSCFF/ a -* -* A function to evaluate the lifetime to the BGB or to -* Helium ignition if no FGB exists. -* (JH 24/11/97) -* - tbgbf = (a(17) + a(18)*m**4 + a(19)*m**(11.d0/2.d0) + m**7)/ - & (a(20)*m**2 + a(21)*m**7) -* - return - end -*** - real*8 FUNCTION tbgbdf(m) - implicit none - real*8 m,mx,f,df,g,dg,a(200) - common /MSCFF/ a -* -* A function to evaluate the derivitive of the lifetime to the BGB -* (or to Helium ignition if no FGB exists) wrt mass. -* (JH 24/11/97) -* - mx = SQRT(m) - f = a(17) + a(18)*m**4 + a(19)*m**5*mx + m**7 - df = 4.d0*a(18)*m**3 + 5.5d0*a(19)*m**4*mx + 7.d0*m**6 - g = a(20)*m**2 + a(21)*m**7 - dg = 2.d0*a(20)*m + 7.d0*a(21)*m**6 - tbgbdf = (df*g - f*dg)/(g*g) -* - return - end -*** - real*8 FUNCTION tbgdzf(m) - implicit none - real*8 m,mx,f,df,g,dg,a(200) - common /MSCFF/ a -* -* A function to evaluate the derivitive of the lifetime to the BGB -* (or to Helium ignition if no FGB exists) wrt Z. -* (JH 14/12/98) -* - mx = m**5*SQRT(m) - f = a(17) + a(18)*m**4 + a(19)*mx + m**7 - df = a(117) + a(118)*m**4 + a(119)*mx - g = a(20)*m**2 + a(21)*m**7 - dg = a(120)*m**2 - tbgdzf = (df*g - f*dg)/(g*g) -* - return - end -*** - real*8 FUNCTION thookf(m) - implicit none - real*8 m,a(200) - common /MSCFF/ a -* -* A function to evaluate the lifetime to the end of the MS -* hook ( for those models that have one ) as a fraction of -* the lifetime to the BGB -* Note that this function is only valid for M > Mhook. -* (JH 24/11/97) -* - thookf = 1.d0 - 0.01d0*MAX(a(22)/m**a(23),a(24)+a(25)/m**a(26)) - thookf = MAX(thookf,0.5d0) -* - return - end -*** - real*8 FUNCTION ltmsf(m) - implicit none - real*8 m,a(200) - common /MSCFF/ a -* -* A function to evaluate the luminosity at the end of the MS -* (JH 24/11/97) -* - ltmsf = (a(27)*m**3 + a(28)*m**4 + a(29)*m**(a(32)+1.8d0))/ - & (a(30) + a(31)*m**5 + m**a(32)) -* - return - end -*** - real*8 FUNCTION lalphf(m) - implicit none - real*8 m,mcut,a(200) - common /MSCFF/ a -* -* A function to evaluate the Luminosity alpha coefficent. -* (JH 24/11/97) -* - mcut = 2.d0 - if(m.ge.mcut)then - lalphf = (a(33) + a(34)*m**a(36))/(m**0.4d0 + a(35)*m**1.9d0) - else - if(m.le.0.5d0)then - lalphf = a(39) - elseif(m.le.0.7d0)then - lalphf = a(39) + ((0.3d0 - a(39))/0.2d0)*(m - 0.5d0) - elseif(m.le.a(37))then - lalphf = 0.3d0 + ((a(40)-0.3d0)/(a(37)-0.7d0))*(m - 0.7d0) - elseif(m.le.a(38))then - lalphf = a(40) + ((a(41)-a(40))/(a(38)-a(37)))*(m - a(37)) - else - lalphf = a(41) + ((a(42)-a(41))/(mcut-a(38)))*(m - a(38)) - endif - endif -* - return - end -*** - real*8 FUNCTION lbetaf(m) - implicit none - real*8 m,a1,a(200) - common /MSCFF/ a -* -* A function to evaluate the Luminosity beta coefficent. -* (JH 24/11/97) -* - lbetaf = a(43) - a(44)*m**a(45) - lbetaf = MAX(lbetaf,0.d0) - if(m.gt.a(46).and.lbetaf.gt.0.d0)then - a1 = a(43) - a(44)*a(46)**a(45) - lbetaf = a1 - 10.d0*a1*(m - a(46)) - lbetaf = MAX(lbetaf,0.d0) - endif -* - return - end -*** - real*8 FUNCTION lnetaf(m) - implicit none - real*8 m,a(200) - common /MSCFF/ a -* -* A function to evaluate the Luminosity neta exponent. -* (JH 24/11/97) -* - if(m.le.1.d0)then - lnetaf = 10.d0 - elseif(m.ge.1.1d0)then - lnetaf = 20.d0 - else - lnetaf = 10.d0 + 100.d0*(m - 1.d0) - endif - lnetaf = MIN(lnetaf,a(97)) -* - return - end -*** - real*8 FUNCTION lhookf(m,mhook) - implicit none - real*8 m,mhook,a2,a(200) - common /MSCFF/ a -* -* A function to evalute the luminosity at the start of -* the MS hook ( for those stars that have one ). -* Note that this function is only valid for M > Mhook. -* (JH 24/11/97) -* - if(m.le.mhook)then - lhookf = 0.d0 - elseif(m.ge.a(51))then - lhookf = MIN(a(47)/m**a(48),a(49)/m**a(50)) - else - a2 = MIN(a(47)/a(51)**a(48),a(49)/a(51)**a(50)) - lhookf = a2*((m-mhook)/(a(51)-mhook))**0.4d0 - endif -* - return - end -*** - real*8 FUNCTION rtmsf(m) - implicit none - real*8 m,m2,rchk,a(200) - common /MSCFF/ a - real*8 rzamsf - external rzamsf -* -* A function to evaluate the radius at the end of the MS -* Note that a safety check is added to ensure Rtms > Rzams -* when extrapolating the function to low masses. -* (JH 24/11/97) -* - m2 = a(62) + 0.1d0 - if(m.le.a(62))then - rchk = 1.5d0*rzamsf(m) - rtmsf = MAX(rchk,(a(52) + a(53)*m**a(55))/(a(54) + m**a(56))) - elseif(m.ge.m2)then - rtmsf = (a(57)*m**3+a(58)*m**a(61)+a(59)*m**(a(61)+1.5d0))/ - & (a(60) + m**5) - else - rtmsf = a(63) + ((a(64) - a(63))/0.1d0)*(m - a(62)) - endif -* - return - end -*** - real*8 FUNCTION ralphf(m) - implicit none - real*8 m,a5,a(200) - common /MSCFF/ a -* -* A function to evaluate the radius alpha coefficent. -* (JH 24/11/97) -* - if(m.le.0.5d0)then - ralphf = a(73) - elseif(m.le.0.65d0)then - ralphf = a(73) + ((a(74) - a(73))/0.15d0)*(m - 0.5d0) - elseif(m.le.a(70))then - ralphf = a(74) + ((a(75)-a(74))/(a(70)-0.65d0))*(m - 0.65d0) - elseif(m.le.a(71))then - ralphf = a(75) + ((a(76) - a(75))/(a(71) - a(70)))*(m - a(70)) - elseif(m.le.a(72))then - ralphf = (a(65)*m**a(67))/(a(66) + m**a(68)) - else - a5 = (a(65)*a(72)**a(67))/(a(66) + a(72)**a(68)) - ralphf = a5 + a(69)*(m - a(72)) - endif -* - return - end -*** - real*8 FUNCTION rbetaf(m) - implicit none - real*8 m,m2,m3,b2,b3,a(200) - common /MSCFF/ a -* -* A function to evaluate the radius beta coefficent. -* (JH 24/11/97) -* - m2 = 2.d0 - m3 = 16.d0 - if(m.le.1.d0)then - rbetaf = 1.06d0 - elseif(m.le.a(82))then - rbetaf = 1.06d0 + ((a(81)-1.06d0)/(a(82)-1.d0))*(m-1.d0) - elseif(m.le.m2)then - b2 = (a(77)*m2**(7.d0/2.d0))/(a(78) + m2**a(79)) - rbetaf = a(81) + ((b2-a(81))/(m2-a(82)))*(m-a(82)) - elseif(m.le.m3)then - rbetaf = (a(77)*m**(7.d0/2.d0))/(a(78) + m**a(79)) - else - b3 = (a(77)*m3**(7.d0/2.d0))/(a(78) + m3**a(79)) - rbetaf = b3 + a(80)*(m - m3) - endif - rbetaf = rbetaf - 1.d0 -* - return - end -*** - real*8 FUNCTION rgammf(m) - implicit none - real*8 m,m1,b1,a(200) - common /MSCFF/ a -* -* A function to evaluate the radius gamma coefficent. -* (JH 24/11/97) -* - m1 = 1.d0 - if(m.gt.(a(88)+0.1d0))then - rgammf = 0.d0 - else - b1 = MAX(0.d0,a(83) + a(84)*(m1-a(85))**a(86)) - if(m.le.m1)then - rgammf = a(83) + a(84)*ABS(m-a(85))**a(86) - elseif(m.le.a(88))then - rgammf = b1 + (a(89) - b1)*((m - m1)/(a(88) - m1))**a(87) - else - if(a(88).gt.m1) b1 = a(89) - rgammf = b1 - 10.d0*b1*(m - a(88)) - endif - rgammf = MAX(rgammf,0.d0) - endif -* - return - end -*** - real*8 FUNCTION rhookf(m,mhook) - implicit none - real*8 m,mhook,m2,b2,a(200) - common /MSCFF/ a -* -* A function to evalute the radius at the start of -* the MS hook ( for those stars that have one ). -* Note that this function is only valid for M > Mhook. -* (JH 24/11/97) -* - if(m.le.mhook)then - rhookf = 0.d0 - elseif(m.le.a(94))then - rhookf = a(95)*SQRT((m-mhook)/(a(94)-mhook)) - elseif(m.le.2.d0)then - m2 = 2.d0 - b2 = (a(90) + a(91)*m2**(7.d0/2.d0))/ - & (a(92)*m2**3 + m2**a(93)) - 1.d0 - rhookf = a(95) + (b2-a(95))*((m-a(94))/(m2-a(94)))**a(96) - else - rhookf = (a(90) + a(91)*m**(7.d0/2.d0))/ - & (a(92)*m**3 + m**a(93)) - 1.d0 - endif -* - return - end -*** - real*8 FUNCTION lbgbf(m) - real*8 m,a(200) - common /GBCFF/ a -* -* A function to evaluate the luminosity at the end of the -* FGB ( for those models that have one ) -* Note that this function is only valid for LM & IM stars -* (JH 24/11/97) -* - lbgbf = (a(1)*m**a(5) + a(2)*m**a(8))/ - & (a(3) + a(4)*m**a(7) + m**a(6)) -* - return - end -*** - real*8 FUNCTION lbgbdf(m) - real*8 m,a(200) - real*8 f,df,g,dg - common /GBCFF/ a -* -* A function to evaluate the derivitive of the Lbgb function. -* Note that this function is only valid for LM & IM stars -* (JH 24/11/97) -* - f = a(1)*m**a(5) + a(2)*m**a(8) - df = a(5)*a(1)*m**(a(5)-1.d0) + a(8)*a(2)*m**(a(8)-1.d0) - g = a(3) + a(4)*m**a(7) + m**a(6) - dg = a(7)*a(4)*m**(a(7)-1.d0) + a(6)*m**(a(6)-1.d0) -* - lbgbdf = (df*g - f*dg)/(g*g) -* - return - end -*** - real*8 FUNCTION lbagbf(m,mhefl) - implicit none - real*8 m,mhefl,a4,a(200) - common /GBCFF/ a -* -* A function to evaluate the BAGB luminosity. (OP 21/04/98) -* Continuity between LM and IM functions is ensured by setting -* gbp(16) = lbagbf(mhefl,0.0) with gbp(16) = 1.0. -* - a4 = (a(9)*mhefl**a(10) - a(16))/(exp(mhefl*a(11))*a(16)) -* - if(m.lt.mhefl)then - lbagbf = a(9)*m**a(10)/(1.d0 + a4*exp(m*a(11))) - else - lbagbf = (a(12) + a(13)*m**(a(15)+1.8d0))/(a(14) + m**a(15)) - endif -* - return - end -*** - real*8 FUNCTION rgbf(m,lum) - implicit none - real*8 m,lum,a1,a(200) - common /GBCFF/ a -* -* A function to evaluate radius on the GB. -* (JH 24/11/97) -* - a1 = MIN(a(20)/m**a(21),a(22)/m**a(23)) - rgbf = a1*(lum**a(18) + a(17)*lum**a(19)) -* - return - end -*** - real*8 FUNCTION rgbdf(m,lum) - implicit none - real*8 m,lum,a1,a(200) - common /GBCFF/ a -* -* A function to evaluate radius derivitive on the GB (as f(L)). -* (JH 24/11/97) -* - a1 = MIN(a(20)/m**a(21),a(22)/m**a(23)) - rgbdf = a1*(a(18)*lum**(a(18)-1.d0) + - & a(17)*a(19)*lum**(a(19)-1.d0)) -* - return - end -*** - real*8 FUNCTION ragbf(m,lum,mhelf) - implicit none - real*8 m,lum,mhelf,m1,a1,a4,xx,a(200) - common /GBCFF/ a -* -* A function to evaluate radius on the AGB. -* (JH 24/11/97) -* - m1 = mhelf - 0.2d0 - if(m.ge.mhelf)then - xx = a(24) - elseif(m.ge.m1)then - xx = 1.d0 + 5.d0*(a(24)-1.d0)*(m-m1) - else - xx = 1.d0 - endif - a4 = xx*a(19) - if(m.le.m1)then - a1 = a(29) + a(30)*m - elseif(m.ge.mhelf)then - a1 = MIN(a(25)/m**a(26),a(27)/m**a(28)) - else - a1 = a(31) + 5.d0*(a(32)-a(31))*(m-m1) - endif -* - ragbf = a1*(lum**a(18) + a(17)*lum**a4) -* - return - end -*** - real*8 FUNCTION ragbdf(m,lum,mhelf) - implicit none - real*8 m,lum,mhelf,m1,a1,a4,xx,a(200) - common /GBCFF/ a -* -* A function to evaluate radius derivitive on the AGB (as f(L)). -* (JH 24/11/97) -* - m1 = mhelf - 0.2d0 - if(m.ge.mhelf)then - xx = a(24) - elseif(m.ge.m1)then - xx = 1.d0 + 5.d0*(a(24)-1.d0)*(m-m1) - else - xx = 1.d0 - endif - a4 = xx*a(19) - if(m.le.m1)then - a1 = a(29) + a(30)*m - elseif(m.ge.mhelf)then - a1 = MIN(a(25)/m**a(26),a(27)/m**a(28)) - else - a1 = a(31) + 5.d0*(a(32)-a(31))*(m-m1) - endif -* - ragbdf = a1*(a(18)*lum**(a(18)-1.d0) + - & a(17)*a4*lum**(a4-1.d0)) -* - return - end -*** - real*8 FUNCTION mctmsf(m) - implicit none - real*8 m,m525 -* -* A function to evaluate core mass at the end of the MS as a -* fraction of the BGB value, i.e. this must be multiplied by -* the BGB value (see below) to give the actual core mass (JH 5/9/99) -* - m525 = m**(21.d0/4.d0) - mctmsf = (1.586d0 + m525)/(2.434d0 + 1.02d0*m525) -* - return - end -*** - real*8 FUNCTION mcheif(m,mhefl,mchefl) - implicit none - real*8 m,mhefl,mchefl,mcbagb,a3,a(200) - common /GBCFF/ a - real*8 mcagbf - external mcagbf -* -* A function to evaluate core mass at BGB or He ignition -* (depending on mchefl) for IM & HM stars (OP 25/11/97) -* - mcbagb = mcagbf(m) - a3 = mchefl**4 - a(33)*mhefl**a(34) - mcheif = MIN(0.95d0*mcbagb,(a3 + a(33)*m**a(34))**(1.d0/4.d0)) -* - return - end -*** - real*8 FUNCTION mheif(mc,mhefl,mchefl) - implicit none - real*8 mc,mhefl,mchefl,m1,m2,a3,a(200) - common /GBCFF/ a - real*8 mbagbf - external mbagbf -* -* A function to evaluate mass at BGB or He ignition -* (depending on mchefl) for IM & HM stars by inverting -* mcheif -* - m1 = mbagbf(mc/0.95d0) - a3 = mchefl**4 - a(33)*mhefl**a(34) - m2 = ((mc**4 - a3)/a(33))**(1.d0/a(34)) - mheif = MAX(m1,m2) -* - return - end -*** - real*8 FUNCTION mcagbf(m) - implicit none - real*8 m,a(200) - common /GBCFF/ a -* -* A function to evaluate core mass at the BAGB (OP 25/11/97) -* - mcagbf = (a(37) + a(35)*m**a(36))**(1.d0/4.d0) -* - return - end -*** - real*8 FUNCTION mbagbf(mc) - implicit none - real*8 mc,mc4,a(200) - common /GBCFF/ a -* -* A function to evaluate mass at the BAGB by inverting mcagbf. -* - mc4 = mc**4 - if(mc4.gt.a(37))then - mbagbf = ((mc4 - a(37))/a(35))**(1.d0/a(36)) - else - mbagbf = 0.d0 - endif -* - return - end -*** - real*8 FUNCTION mcgbtf(t,A,GB,tinf1,tinf2,tx) - implicit none - real*8 t,A,GB(10),tinf1,tinf2,tx -* -* A function to evaluate Mc given t for GB, AGB and NHe stars -* - if(t.le.tx)then - mcgbtf = ((GB(5)-1.d0)*A*GB(4)*(tinf1 - t))** - & (1.d0/(1.d0-GB(5))) - else - mcgbtf = ((GB(6)-1.d0)*A*GB(3)*(tinf2 - t))** - & (1.d0/(1.d0-GB(6))) - endif -* - return - end -*** - real*8 FUNCTION lgbtf(t,A,GB,tinf1,tinf2,tx) - implicit none - real*8 t,A,GB(10),tinf1,tinf2,tx -* -* A function to evaluate L given t for GB, AGB and NHe stars -* - if(t.le.tx)then - lgbtf = GB(4)*(((GB(5)-1.d0)*A*GB(4)*(tinf1 - t))** - & (GB(5)/(1.d0-GB(5)))) - else - lgbtf = GB(3)*(((GB(6)-1.d0)*A*GB(3)*(tinf2 - t))** - & (GB(6)/(1.d0-GB(6)))) - endif -* - return - end -*** - real*8 FUNCTION mcgbf(lum,GB,lx) - implicit none - real*8 lum,GB(10),lx -* -* A function to evaluate Mc given L for GB, AGB and NHe stars -* - if(lum.le.lx)then - mcgbf = (lum/GB(4))**(1.d0/GB(5)) - else - mcgbf = (lum/GB(3))**(1.d0/GB(6)) - endif -* - return - end -*** - real*8 FUNCTION lmcgbf(mc,GB) - implicit none - real*8 mc,GB(10) -* -* A function to evaluate L given Mc for GB, AGB and NHe stars -* - if(mc.le.GB(7))then - lmcgbf = GB(4)*(mc**GB(5)) - else - lmcgbf = GB(3)*(mc**GB(6)) - endif -* - return - end -*** - real*8 FUNCTION lHeIf(m,mhefl) - implicit none - real*8 m,mhefl,a(200) - common /GBCFF/ a -* -* A function to evaluate He-ignition luminosity (OP 24/11/97) -* Continuity between the LM and IM functions is ensured with a first -* call setting lhefl = lHeIf(mhefl,0.0) -* - if(m.lt.mhefl)then - lHeIf = a(38)*m**a(39)/(1.d0 + a(41)*EXP(m*a(40))) - else - lHeIf = (a(42) + a(43)*m**3.8d0)/(a(44) + m**2) - endif -* - return - end -*** - real*8 FUNCTION lHef(m) - implicit none - real*8 m,a(200) - common /GBCFF/ a -* -* A function to evaluate the ratio LHe,min/LHeI (OP 20/11/97) -* Note that this function is everywhere <= 1, and is only valid -* for IM stars -* - lHef = (a(45) + a(46)*m**(a(48)+0.1d0))/(a(47) + m**a(48)) -* - return - end -*** - real*8 FUNCTION rminf(m) - implicit none - real*8 m,mx,a(200) - common /GBCFF/ a -* -* A function to evaluate the minimum radius during He-burning -* for IM & HM stars (OP 20/11/97) -* - mx = m**a(53) - rminf = (a(49)*m + (a(50)*m)**a(52)*mx)/(a(51) + mx) -* - return - end -*** - real*8 FUNCTION tHef(m,mc,mhefl) - implicit none - real*8 m,mc,mhefl,mm,a(200) - common /GBCFF/ a - real*8 themsf - external themsf -* -* A function to evaluate the He-burning lifetime. (OP 26/11/97) -* For IM & HM stars, tHef is relative to tBGB. -* Continuity between LM and IM stars is ensured by setting -* thefl = tHef(mhefl,0.0,,0.0), and the call to themsf ensures -* continuity between HB and NHe stars as Menv -> 0. -* - if(m.le.mhefl)then - mm = MAX((mhefl - m)/(mhefl - mc),1.0d-12) - tHef = (a(54) + (themsf(mc) - a(54))*mm**a(55))* - & (1.d0 + a(57)*EXP(m*a(56))) - else - mm = m**5 - tHef = (a(58)*m**a(61) + a(59)*mm)/(a(60) + mm) - endif -* - return - end -*** - real*8 FUNCTION tblf(m,mhefl,mfgb) - implicit none - real*8 m,mhefl,mfgb,mr,m1,m2,r1,a(200) - common /GBCFF/ a - real*8 lheif,rminf,ragbf - external lheif,rminf,ragbf -* -* A function to evaluate the blue-loop fraction of the He-burning -* lifetime for IM & HM stars (OP 28/01/98) -* - mr = mhefl/mfgb - if(m.le.mfgb) then - m1 = m/mfgb - m2 = log10(m1)/log10(mr) - m2 = max(m2,1.0d-12) - tblf = a(64)*m1**a(63) + a(65)*m2**a(62) - else - r1 = 1.d0 - rminf(m)/ragbf(m,lheif(m,mhefl),mhefl) - r1 = max(r1,1.0d-12) - tblf = a(66)*m**a(67)*r1**a(68) - end if - tblf = MIN(1.d0,MAX(0.d0,tblf)) - if(tblf.lt.1.0d-10) tblf = 0.d0 -* - return - end -*** - real*8 FUNCTION lzahbf(m,mc,mhefl) - implicit none - real*8 m,mc,mhefl,mm,a4,a5,a(200) - common /GBCFF/ a - real*8 lzhef - external lzhef -* -* A function to evaluate the ZAHB luminosity for LM stars. (OP 28/01/98) -* Continuity with LHe,min for IM stars is ensured by setting -* lx = lHeif(mhefl,z,0.0,1.0)*lHef(mhefl,z,mfgb), and the call to lzhef -* ensures continuity between the ZAHB and the NHe-ZAMS as Menv -> 0. -* - a5 = lzhef(mc) - a4 = (a(69) + a5 - a(74))/((a(74) - a5)*exp(a(71)*mhefl)) - mm = MAX((m-mc)/(mhefl - mc),1.0d-12) - lzahbf = a5 + (1.d0 + a(72))*a(69)*mm**a(70)/ - & ((1.d0 + a(72)*mm**a(73))*(1.d0 + a4*EXP(m*a(71)))) -* - return - end -*** - real*8 FUNCTION rzahbf(m,mc,mhefl) - implicit none - real*8 m,mc,mhefl,rx,ry,mm,f,a(200) - common /GBCFF/ a - real*8 rzhef,rgbf,lzahbf -* -* A function to evaluate the ZAHB radius for LM stars. (OP 28/01/98) -* Continuity with R(LHe,min) for IM stars is ensured by setting -* lx = lHeif(mhefl,z,0.0,1.0)*lHef(mhefl,z,mfgb), and the call to rzhef -* ensures continuity between the ZAHB and the NHe-ZAMS as Menv -> 0. -* - rx = rzhef(mc) - ry = rgbf(m,lzahbf(m,mc,mhefl)) - mm = MAX((m-mc)/(mhefl - mc),1.0d-12) - f = (1.d0 + a(76))*mm**a(75)/(1.d0 + a(76)*mm**a(77)) - rzahbf = (1.d0 - f)*rx + f*ry -* - return - end -*** - real*8 FUNCTION lzhef(m) - implicit none - real*8 m,m15 -* -* A function to evaluate Naked Helium star 'ZAMS' luminosity -* - m15 = m*SQRT(m) - lzhef = 1.5262d+04*m**(41.d0/4.d0)/ - & (0.0469d0 + m**6*(31.18d0 + m15*(29.54d0 + m15))) -* - return - end -*** - real*8 FUNCTION rzhef(m) - implicit none - real*8 m -* -* A function to evaluate Helium star 'ZAMS' radius -* - rzhef = 0.2391d0*m**4.6d0/(0.0065d0 + (0.162d0 + m)*m**3) -* - return - end -*** - real*8 FUNCTION themsf(m) - implicit none - real*8 m -* -* A function to evaluate Helium star main sequence lifetime -* - themsf = (0.4129d0 + 18.81d0*m**4 + 1.853d0*m**6)/m**(13.d0/2.d0) -* - return - end -*** - real*8 FUNCTION rhehgf(m,lum,rx,lx) - implicit none - real*8 m,lum,rx,lx,cm -* -* A function to evaluate Helium star radius on the Hertzsprung gap -* from its mass and luminosity. -* - cm = 2.0d-03*m**(5.d0/2.d0)/(2.d0 + m**5) - rhehgf = rx*(lum/lx)**0.2d0 + 0.02d0*(EXP(cm*lum) - EXP(cm*lx)) -* - return - end -*** - real*8 FUNCTION rhegbf(lum) - implicit none - real*8 lum -* -* A function to evaluate Helium star radius on the giant branch. -* - rhegbf = 0.08d0*lum**(3.d0/4.d0) -* - return - end -*** - real*8 FUNCTION lpertf(m,mew) - implicit none - real*8 m,mew - real*8 b,c -* -* A function to obtain the exponent that perturbs luminosity. -* - b = 0.002d0*MAX(1.d0,2.5d0/m) - c = 3.d0 - lpertf = ((1.d0 + b**c)*((mew/b)**c))/(1.d0+(mew/b)**c) -* - return - end -*** - real*8 FUNCTION rpertf(m,mew,r,rc) - implicit none - real*8 m,mew,r,rc - real*8 a,b,c,q,fac,facmax -* -* A function to obtain the exponent that perturbs radius. -* - if(mew.le.0.d0)then - rpertf = 0.d0 - else - a = 0.1d0 - b = 0.006d0*MAX(1.d0,2.5d0/m) - c = 3.d0 - q = log(r/rc) - fac = a/q - facmax = -14.d0/log10(mew) - fac = MIN(fac,facmax) - rpertf = ((1.d0 + b**c)*((mew/b)**c)*(mew**fac))/ - & (1.d0+(mew/b)**c) - endif -* - return - end -*** - real*8 FUNCTION vrotf(m) - implicit none - real*8 m -* - vrotf = 330.d0*m**3.3d0/(15.d0 + m**3.45d0) -* - return - end -*** - real*8 FUNCTION celamf(kw,m,lum,rad,rzams,menv,fac) - implicit none - integer kw - real*8 m,lum,rad,rzams,menv,fac - real*8 lam1,lam2,m1,logm,logl - real*8 aa,bb,cc,dd -* -* A function to estimate lambda for common-envelope. -* - if(fac.ge.0.d0)then -* -* No fits yet for naked He stars... -* - if(kw.gt.6)then - celamf = 0.5d0 - goto 90 - endif -* - if(menv.gt.0.d0)then -* Formulae for giant-like stars; also used for HG and CHeB stars close -* to the Hayashi track. - logl = log10(lum) - logm = log10(m) - if(kw.le.5)then - m1 = m - if(kw.gt.3) m1 = 100.d0 - lam1 = 3.d0/(2.4d0 + 1.d0/m1**(3.d0/2.d0)) - 0.15d0*logl - lam1 = MIN(lam1,0.8d0) - else - lam1 = -3.5d0 - 0.75d0*logm + logl - endif - if(kw.gt.3)then - lam2 = MIN(0.9d0,0.58d0 + 0.75d0*logm) - 0.08d0*logl - if(kw.lt.6)then - lam1 = MIN(lam2,lam1) - else - lam1 = MAX(lam2,lam1) - lam1 = MIN(lam1,1.d0) - endif - endif - lam1 = 2.d0*lam1 - if(fac.gt.0.d0)then -* Use a fraction FAC of the ionization energy in the energy balance. - if(kw.le.3)then - aa = MIN(1.2d0*(logm - 0.25d0)**2 - 0.7d0,-0.5d0) - else - aa = MAX(-0.2d0 - logm,-0.5d0) - endif - bb = MAX(3.d0 - 5.d0*logm,1.5d0) - cc = MAX(3.7d0 + 1.6d0*logm,3.3d0 + 2.1d0*logm) - lam2 = aa + ATAN(bb*(cc - logl)) - if(kw.le.3)then - dd = MAX(0.d0,MIN(0.15d0,0.15d0 - 0.25d0*logm)) - lam2 = lam2 + dd*(logl - 2.d0) - endif - lam2 = MAX(lam2,1.d-2) - lam2 = MAX(1.d0/lam2,lam1) - if(fac.ge.1.d0)then - lam1 = lam2 - else - lam1 = lam1 + fac*(lam2 - lam1) - endif - endif - endif -* - if(menv.lt.1.d0)then -* Formula for HG stars; also reasonable for CHeB stars in blue loop. - lam2 = 0.42d0*(rzams/rad)**0.4d0 -* Alternatively: -* lam2 = 0.3d0*(rtms/rad)**0.4d0 - lam2 = 2.d0*lam2 - endif -* - if(menv.le.0.d0)then - celamf = lam2 - elseif(menv.ge.1.d0)then - celamf = lam1 - else -* Interpolate between HG and GB values depending on conv. envelope mass. - celamf = lam2 + sqrt(menv)*(lam1 - lam2) - endif -* - 90 continue -* - else - celamf = -1.d0*fac - endif -* - return - end -*** - - -cc//comenv.f - -*** - SUBROUTINE COMENV(M01,M1,MC1,AJ1,JSPIN1,KW1, - & M02,M2,MC2,AJ2,JSPIN2,KW2, - & ZPARS,ECC,SEP,JORB,COEL) -* -* Common Envelope Evolution. -* -* Author : C. A. Tout -* Date : 18th September 1996 -* -* Redone : J. R. Hurley -* Date : 7th July 1998 -* - IMPLICIT NONE -* - INTEGER KW1,KW2,KW - INTEGER KTYPE(0:14,0:14) - COMMON /TYPES/ KTYPE - INTEGER ceflag,tflag,ifflag,nsflag,wdflag - COMMON /FLAGS/ ceflag,tflag,ifflag,nsflag,wdflag -* - REAL*8 M01,M1,MC1,AJ1,JSPIN1,R1,L1,K21 - REAL*8 M02,M2,MC2,AJ2,JSPIN2,R2,L2,K22,MC22 - REAL*8 TSCLS1(20),TSCLS2(20),LUMS(10),GB(10),TM1,TM2,TN,ZPARS(20) - REAL*8 EBINDI,EBINDF,EORBI,EORBF,ECIRC,SEPF,SEPL,MF,XX - REAL*8 CONST,DELY,DERI,DELMF,MC3,FAGE1,FAGE2 - REAL*8 ECC,SEP,JORB,TB,OORB,OSPIN1,OSPIN2,TWOPI - REAL*8 RC1,RC2,Q1,Q2,RL1,RL2,LAMB1,LAMB2 - REAL*8 MENV,RENV,MENVD,RZAMS,VS(3) - REAL*8 AURSUN,K3,ALPHA1,LAMBDA - PARAMETER (AURSUN = 214.95D0,K3 = 0.21D0) - COMMON /VALUE2/ ALPHA1,LAMBDA - LOGICAL COEL - REAL*8 CELAMF,RL,RZAMSF - EXTERNAL CELAMF,RL,RZAMSF -* -* Common envelope evolution - entered only when KW1 = 2, 3, 4, 5, 6, 8 or 9. -* -* For simplicity energies are divided by -G. -* - TWOPI = 2.D0*ACOS(-1.D0) - COEL = .FALSE. -* -* Obtain the core masses and radii. -* - KW = KW1 - CALL star(KW1,M01,M1,TM1,TN,TSCLS1,LUMS,GB,ZPARS) - CALL hrdiag(M01,AJ1,M1,TM1,TN,TSCLS1,LUMS,GB,ZPARS, - & R1,L1,KW1,MC1,RC1,MENV,RENV,K21) - OSPIN1 = JSPIN1/(K21*R1*R1*(M1-MC1)+K3*RC1*RC1*MC1) - MENVD = MENV/(M1-MC1) - RZAMS = RZAMSF(M01) - LAMB1 = CELAMF(KW,M01,L1,R1,RZAMS,MENVD,LAMBDA) - KW = KW2 - CALL star(KW2,M02,M2,TM2,TN,TSCLS2,LUMS,GB,ZPARS) - CALL hrdiag(M02,AJ2,M2,TM2,TN,TSCLS2,LUMS,GB,ZPARS, - & R2,L2,KW2,MC2,RC2,MENV,RENV,K22) - OSPIN2 = JSPIN2/(K22*R2*R2*(M2-MC2)+K3*RC2*RC2*MC2) -* -* Calculate the binding energy of the giant envelope (multiplied by lambda). -* - EBINDI = M1*(M1-MC1)/(LAMB1*R1) -* -* If the secondary star is also giant-like add its envelopes's energy. -* - EORBI = M1*M2/(2.D0*SEP) - IF(KW2.GE.2.AND.KW2.LE.9.AND.KW2.NE.7)THEN - MENVD = MENV/(M2-MC2) - RZAMS = RZAMSF(M02) - LAMB2 = CELAMF(KW,M02,L2,R2,RZAMS,MENVD,LAMBDA) - EBINDI = EBINDI + M2*(M2-MC2)/(LAMB2*R2) -* -* Calculate the initial orbital energy -* - IF(CEFLAG.NE.3) EORBI = MC1*MC2/(2.D0*SEP) - ELSE - IF(CEFLAG.NE.3) EORBI = MC1*M2/(2.D0*SEP) - ENDIF -* -* Allow for an eccentric orbit. -* - ECIRC = EORBI/(1.D0 - ECC*ECC) -* -* Calculate the final orbital energy without coalescence. -* - EORBF = EORBI + EBINDI/ALPHA1 -* -* If the secondary is on the main sequence see if it fills its Roche lobe. -* - IF(KW2.LE.1.OR.KW2.EQ.7)THEN - SEPF = MC1*M2/(2.D0*EORBF) - Q1 = MC1/M2 - Q2 = 1.D0/Q1 - RL1 = RL(Q1) - RL2 = RL(Q2) - IF(RC1/RL1.GE.R2/RL2)THEN -* -* The helium core of a very massive star of type 4 may actually fill -* its Roche lobe in a wider orbit with a very low-mass secondary. -* - IF(RC1.GT.RL1*SEPF)THEN - COEL = .TRUE. - SEPL = RC1/RL1 - ENDIF - ELSE - IF(R2.GT.RL2*SEPF)THEN - COEL = .TRUE. - SEPL = R2/RL2 - ENDIF - ENDIF - IF(COEL)THEN -* - KW = KTYPE(KW1,KW2) - 100 - MC3 = MC1 - IF(KW2.EQ.7.AND.KW.EQ.4) MC3 = MC3 + M2 -* -* Coalescence - calculate final binding energy. -* - EORBF = MAX(MC1*M2/(2.D0*SEPL),EORBI) - EBINDF = EBINDI - ALPHA1*(EORBF - EORBI) - ELSE -* -* Primary becomes a black hole, neutron star, white dwarf or helium star. -* - MF = M1 - M1 = MC1 - CALL star(KW1,M01,M1,TM1,TN,TSCLS1,LUMS,GB,ZPARS) - CALL hrdiag(M01,AJ1,M1,TM1,TN,TSCLS1,LUMS,GB,ZPARS, - & R1,L1,KW1,MC1,RC1,MENV,RENV,K21) - IF(KW1.GE.13)THEN - CALL kick(KW1,MF,M1,M2,ECC,SEPF,JORB,VS) - IF(ECC.GT.1.D0) GOTO 30 - ENDIF - ENDIF - ELSE -* -* Degenerate or giant secondary. Check if the least massive core fills its -* Roche lobe. -* - SEPF = MC1*MC2/(2.D0*EORBF) - Q1 = MC1/MC2 - Q2 = 1.D0/Q1 - RL1 = RL(Q1) - RL2 = RL(Q2) - IF(RC1/RL1.GE.RC2/RL2)THEN - IF(RC1.GT.RL1*SEPF)THEN - COEL = .TRUE. - SEPL = RC1/RL1 - ENDIF - ELSE - IF(RC2.GT.RL2*SEPF)THEN - COEL = .TRUE. - SEPL = RC2/RL2 - ENDIF - ENDIF -* - IF(COEL)THEN -* -* If the secondary was a neutron star or black hole the outcome -* is an unstable Thorne-Zytkow object that leaves only the core. -* - SEPF = 0.D0 - IF(KW2.GE.13)THEN - MC1 = MC2 - M1 = MC1 - MC2 = 0.D0 - M2 = 0.D0 - KW1 = KW2 - KW2 = 15 - AJ1 = 0.D0 -* -* The envelope mass is not required in this case. -* - GOTO 30 - ENDIF -* - KW = KTYPE(KW1,KW2) - 100 - MC3 = MC1 + MC2 -* -* Calculate the final envelope binding energy. -* - EORBF = MAX(MC1*MC2/(2.D0*SEPL),EORBI) - EBINDF = EBINDI - ALPHA1*(EORBF - EORBI) -* -* Check if we have the merging of two degenerate cores and if so -* then see if the resulting core will survive or change form. -* - IF(KW1.EQ.6.AND.(KW2.EQ.6.OR.KW2.GE.11))THEN - CALL dgcore(KW1,KW2,KW,MC1,MC2,MC3,EBINDF) - ENDIF - IF(KW1.LE.3.AND.M01.LE.ZPARS(2))THEN - IF((KW2.GE.2.AND.KW2.LE.3.AND.M02.LE.ZPARS(2)).OR. - & KW2.EQ.10)THEN - CALL dgcore(KW1,KW2,KW,MC1,MC2,MC3,EBINDF) - IF(KW.GE.10)THEN - KW1 = KW - M1 = MC3 - MC1 = MC3 - IF(KW.LT.15) M01 = MC3 - AJ1 = 0.D0 - MC2 = 0.D0 - M2 = 0.D0 - KW2 = 15 - GOTO 30 - ENDIF - ENDIF - ENDIF -* - ELSE -* -* The cores do not coalesce - assign the correct masses and ages. -* - MF = M1 - M1 = MC1 - CALL star(KW1,M01,M1,TM1,TN,TSCLS1,LUMS,GB,ZPARS) - CALL hrdiag(M01,AJ1,M1,TM1,TN,TSCLS1,LUMS,GB,ZPARS, - & R1,L1,KW1,MC1,RC1,MENV,RENV,K21) - IF(KW1.GE.13)THEN - CALL kick(KW1,MF,M1,M2,ECC,SEPF,JORB,VS) - IF(ECC.GT.1.D0) GOTO 30 - ENDIF - MF = M2 - KW = KW2 - M2 = MC2 - CALL star(KW2,M02,M2,TM2,TN,TSCLS2,LUMS,GB,ZPARS) - CALL hrdiag(M02,AJ2,M2,TM2,TN,TSCLS2,LUMS,GB,ZPARS, - & R2,L2,KW2,MC2,RC2,MENV,RENV,K22) - IF(KW2.GE.13.AND.KW.LT.13)THEN - CALL kick(KW2,MF,M2,M1,ECC,SEPF,JORB,VS) - IF(ECC.GT.1.D0) GOTO 30 - ENDIF - ENDIF - ENDIF -* - IF(COEL)THEN - MC22 = MC2 - IF(KW.EQ.4.OR.KW.EQ.7)THEN -* If making a helium burning star calculate the fractional age -* depending on the amount of helium that has burnt. - IF(KW1.LE.3)THEN - FAGE1 = 0.D0 - ELSEIF(KW1.GE.6)THEN - FAGE1 = 1.D0 - ELSE - FAGE1 = (AJ1 - TSCLS1(2))/(TSCLS1(13) - TSCLS1(2)) - ENDIF - IF(KW2.LE.3.OR.KW2.EQ.10)THEN - FAGE2 = 0.D0 - ELSEIF(KW2.EQ.7)THEN - FAGE2 = AJ2/TM2 - MC22 = M2 - ELSEIF(KW2.GE.6)THEN - FAGE2 = 1.D0 - ELSE - FAGE2 = (AJ2 - TSCLS2(2))/(TSCLS2(13) - TSCLS2(2)) - ENDIF - ENDIF - ENDIF -* -* Now calculate the final mass following coelescence. This requires a -* Newton-Raphson iteration. -* - IF(COEL)THEN -* -* Calculate the orbital spin just before coalescence. -* - TB = (SEPL/AURSUN)*SQRT(SEPL/(AURSUN*(MC1+MC2))) - OORB = TWOPI/TB -* - XX = 1.D0 + ZPARS(7) - IF(EBINDF.LE.0.D0)THEN - MF = MC3 - GOTO 20 - ELSE - CONST = ((M1+M2)**XX)*(M1-MC1+M2-MC22)*EBINDF/EBINDI - ENDIF -* -* Initial Guess. -* - MF = MAX(MC1 + MC22,(M1 + M2)*(EBINDF/EBINDI)**(1.D0/XX)) - 10 DELY = (MF**XX)*(MF - MC1 - MC22) - CONST -* IF(ABS(DELY/MF**(1.D0+XX)).LE.1.0D-02) GOTO 20 - IF(ABS(DELY/MF).LE.1.0D-03) GOTO 20 - DERI = MF**ZPARS(7)*((1.D0+XX)*MF - XX*(MC1 + MC22)) - DELMF = DELY/DERI - MF = MF - DELMF - GOTO 10 -* -* Set the masses and separation. -* - 20 IF(MC22.EQ.0.D0) MF = MAX(MF,MC1+M2) - M2 = 0.D0 - M1 = MF - KW2 = 15 -* -* Combine the core masses. -* - IF(KW.EQ.2)THEN - CALL star(KW,M1,M1,TM2,TN,TSCLS2,LUMS,GB,ZPARS) - IF(GB(9).GE.MC1)THEN - M01 = M1 - AJ1 = TM2 + (TSCLS2(1) - TM2)*(AJ1-TM1)/(TSCLS1(1) - TM1) - CALL star(KW,M01,M1,TM1,TN,TSCLS1,LUMS,GB,ZPARS) - ENDIF - ELSEIF(KW.EQ.7)THEN - M01 = M1 - CALL star(KW,M01,M1,TM1,TN,TSCLS1,LUMS,GB,ZPARS) - AJ1 = TM1*(FAGE1*MC1 + FAGE2*MC22)/(MC1 + MC22) - ELSEIF(KW.EQ.4.OR.MC2.GT.0.D0.OR.KW.NE.KW1)THEN - IF(KW.EQ.4) AJ1 = (FAGE1*MC1 + FAGE2*MC22)/(MC1 + MC22) - MC1 = MC1 + MC2 - MC2 = 0.D0 -* -* Obtain a new age for the giant. -* - CALL gntage(MC1,M1,KW,ZPARS,M01,AJ1) - CALL star(KW,M01,M1,TM1,TN,TSCLS1,LUMS,GB,ZPARS) - ENDIF - CALL hrdiag(M01,AJ1,M1,TM1,TN,TSCLS1,LUMS,GB,ZPARS, - & R1,L1,KW,MC1,RC1,MENV,RENV,K21) - JSPIN1 = OORB*(K21*R1*R1*(M1-MC1)+K3*RC1*RC1*MC1) - KW1 = KW - ECC = 0.D0 - ELSE -* -* Check if any eccentricity remains in the orbit by first using -* energy to circularise the orbit before removing angular momentum. -* (note this should not be done in case of CE SN ... fix). -* - IF(EORBF.LT.ECIRC)THEN - ECC = SQRT(1.D0 - EORBF/ECIRC) - ELSE - ECC = 0.D0 - ENDIF -* -* Set both cores in co-rotation with the orbit on exit of CE, -* - TB = (SEPF/AURSUN)*SQRT(SEPF/(AURSUN*(M1+M2))) - OORB = TWOPI/TB - JORB = M1*M2/(M1+M2)*SQRT(1.D0-ECC*ECC)*SEPF*SEPF*OORB -* JSPIN1 = OORB*(K21*R1*R1*(M1-MC1)+K3*RC1*RC1*MC1) -* JSPIN2 = OORB*(K22*R2*R2*(M2-MC2)+K3*RC2*RC2*MC2) -* -* or, leave the spins of the cores as they were on entry. -* Tides will deal with any synchronization later. -* - JSPIN1 = OSPIN1*(K21*R1*R1*(M1-MC1)+K3*RC1*RC1*MC1) - JSPIN2 = OSPIN2*(K22*R2*R2*(M2-MC2)+K3*RC2*RC2*MC2) - ENDIF - 30 SEP = SEPF - RETURN - END -*** - - -cc//corerd.f - -*** - REAL*8 FUNCTION CORERD(KW,MC,M0,MFLASH) -* -* A function to determine the radius of the core of a giant-like star. -* NOTE: this is out of date so rc should be obtained using HRDIAG! -* It is still OK to use but bear in mind that the core radius calculated -* for non-degenerate giant cores is only a rough estimate. -* -* Author : C. A. Tout -* Date : 26th February 1997 -* Updated 6/1/98 by J. Hurley -* - IMPLICIT NONE - INTEGER KW - REAL*8 MC,MCH,M0,MFLASH - PARAMETER (MCH = 1.44d0) -* -* First do the black holes and neutron stars. -* - IF(KW.EQ.14)THEN - CORERD = 4.24d-06*MC - ELSEIF(KW.EQ.13)THEN - CORERD = 1.4d-05 -* -* Main sequence stars. -* - ELSEIF(KW.LE.1.OR.KW.EQ.7)THEN - CORERD = 0.d0 -* -* Core-helium-burning stars, FAGB stars and non-degenerate giant cores. -* - ELSEIF(KW.EQ.4.OR.KW.EQ.5.OR.(KW.LE.3.AND.M0.GT.MFLASH))THEN - CORERD = 0.2239d0*MC**0.62d0 -* -* The degenerate giants and white dwarfs. -* - ELSE - CORERD = 0.0115d0*SQRT(MAX(1.48204d-06,(MCH/MC)**(2.d0/3.d0) - & - (MC/MCH)**(2.d0/3.d0))) -* -* Degenerate giants have hot subdwarf cores. -* - IF(KW.LE.9) CORERD = 5.d0*CORERD - ENDIF -* - RETURN - END -*** - - - -cc//dgcore.f - -*** - SUBROUTINE dgcore(kw1,kw2,kw3,m1,m2,m3,ebinde) -* -* A routine to determine the outcome of a collision or coalescence -* of two degenerate cores. -* Entered with kw1,kw2 = 2 or 3 with M <= Mflash, 6, 10, 11 or 12 -* - implicit none -* - integer kw1,kw2,kw3 -* - real*8 m1,m2,m3,ebinde - real*8 r1,r2,r3,mhe,mc,mne,ebindi,ebindf,deleb,de,enuc - real*8 temp,x,y,m0,mflash - real*8 cvhe,cvc,cvne - parameter(cvhe=3.1d+07,cvc=8.27d+06,cvne=7.44d+06) - real*8 ehe,ec,ene - parameter(ehe=5.812d+17,ec=2.21d+17,ene=2.06d+17) - real*8 the,tc,gmr,mch - parameter(the=1.0d+08,tc=1.0d+09,gmr=1.906d+15,mch=1.44d0) -* - real*8 corerd - external corerd -* -* Calculate the core radii setting m0 < mflash using dummy values as we -* know it to be true if kw = 2 or 3. - m0 = 1.d0 - mflash = 2.d0 - r1 = corerd(kw1,m1,m0,mflash) - r2 = corerd(kw2,m2,m0,mflash) - r3 = corerd(kw3,m3,m0,mflash) -* Calculate the initial binding energy of the two seperate cores and the -* difference between this and the final binding energy of the new core. - ebindi = m1*m1/r1 + m2*m2/r2 - ebindf = m3*m3/r3 - deleb = ABS(ebindi - ebindf) -* If an envelope is present reduce its binding energy by the amount -* of energy liberated by the coalescence. - ebinde = MAX(0.d0,ebinde - deleb) - if(kw1.gt.3) goto 90 -* Distribute the mass into core mass groups where mhe represents Helium -* core mass, mc represents Carbon core mass and mne represents a Neon -* core mass or any mass that is all converted Carbon. - mhe = 0.d0 - mc = 0.d0 - mne = 0.d0 - if(kw1.le.3.or.kw1.eq.10)then - mhe = mhe + m1 - elseif(kw1.eq.12)then - mne = mne + m1 - else - mc = mc + m1 - endif - if(kw2.le.3.or.kw2.eq.10)then - mhe = mhe + m2 - elseif(kw2.eq.12)then - mne = mne + m2 - else - mc = mc + m2 - endif -* Calculate the temperature generated by the merging of the cores. - temp = (deleb/(cvhe*mhe+cvc*mc+cvne*mne))*gmr -* -* To decide if He is converted to C we use: -* 3He4 -> C12 , T > 10^8 K , 7.274 Mev released, -* to decide if C is converted further we use: -* 2C12 -> Ne20 + alpha , T > 10^9 K , 4.616 Mev released. -* and to decide if O is converted further we use: -* 2O16 -> P31 + p , T > 10^9 K , 7.677 Mev released. -* To obtain the heat capacity of an O/Ne WD and to gain an idea of the -* energy released from the further processing of an O/Ne WD we use: -* 2Ne20 + gamma -> O16 + Mg24 +gamma , T > 10^9 K , 4.583 Mev released. -* For a CO core the composition is assumed to be 20% C, 80% O and for -* an ONe core 80% O, 20% Ne. -* -* Decide if conversion of elements can take place. -* if(temp.gt.the)then - x = 1.d0 -* else -* x = 0.d0 -* endif -* if(temp.gt.tc)then -* y = 1.d0 -* else - y = 0.d0 -* endif -* Calculate the nuclear energy generated from any element conversion. - enuc = (x*ehe*mhe + y*(ec*mc + ene*mne))/gmr -* Calculate the difference between the binding energy of the star -* (core + envelope) and the nuclear energy. The new star will be -* destroyed in a SN if dE < 0. - de = (ebindf + ebinde) - enuc -* If the star survives and an envelope is present then reduce the -* envelope binding energy by the amount of liberated nuclear energy. -* The envelope will not survive if its binding energy is reduced to <= 0. - if(de.ge.0.d0) ebinde = MAX(0.d0,ebinde - enuc) -* Now determine the final evolution state of the merged core. - if(de.lt.0.d0) kw3 = 15 - if(kw3.eq.3)then - if(x.gt.0.5d0)then - kw3 = 6 - elseif(ebinde.le.0.d0)then - kw3 = 10 - endif - elseif(kw3.eq.4)then - if(x.gt.0.5d0)then - kw3 = 6 - elseif(ebinde.le.0.d0)then - kw3 = 7 - endif - endif - if(kw3.eq.6.and.y.lt.0.5d0)then - if(ebinde.le.0.d0) kw3 = 11 - elseif(kw3.eq.6.and.y.gt.0.5d0)then - if(ebinde.le.0.d0) kw3 = 12 - endif - if(kw3.eq.10.and.x.gt.0.5d0) kw3 = 11 - if(kw3.eq.11.and.y.gt.0.5d0) kw3 = 12 - if(kw3.ge.10.and.kw3.le.12.and.m3.ge.mch) kw3 = 15 -* - if(kw3.eq.15) m3 = 0.d0 - 90 continue -* - return - end -*** - - -cc//evolv2.f - -*** - SUBROUTINE evolv2(kstar,mass0,mass,rad,lumin,massc,radc, - & menv,renv,ospin,epoch,tms, - & tphys,tphysf,dtp,z,zpars,tb,ecc,vkick) - implicit none -*** -* -* B I N A R Y -* *********** -* -* Roche lobe overflow. -* -------------------- -* -* Developed by Jarrod Hurley, IOA, Cambridge. -* ......................................................... -* -* Advice by Christopher Tout, Onno Pols & Sverre Aarseth. -* ++++++++++++++++++++++++++++++++++++++++++++++++++ -* -* Adapted from Aarseth's code 21st September 1996. -* Fully revised on 27th November 1996 to remove vestiges of N-body code and -* incorporate corrections. -* Fully revised on 1st April 1998 to include new stellar evolution formulae -* and associated binary evolution changes. -* Fully revised on 4th July 1998 to include eccentricity, tidal -* circularization, wind accretion, velocity kicks for supernovae and all -* associated orbital momentum changes. -* Revised on 31st October 2000 to upgrade restrictions imposed on the -* timestep owing to magnetic braking and orbital angular momentum changes. -* -*** -* -* See Tout et al., 1997, MNRAS, 291, 732 for a description of many of the -* processes in this code as well as the relevant references mentioned -* within the code. -* -* Reference for the stellar evolution formulae is Hurley, Pols & Tout, -* 2000, MNRAS, 315, 543 (SSE paper). -* Reference for the binary evolution algorithm is Hurley, Tout & Pols, -* 2002, MNRAS, 329, 897 (BSE paper). -* -*** -* -* March 2001 * -* Changes since version 3, i.e. since production of Paper3: -* -* 1) The Eddington limit flag (on/off) has been replaced by an -* Eddington limit multiplicative factor (eddfac). So if you -* want to neglect the Eddington limit you would set eddfac -* to a large value. -* -* 2) To determine whether material transferred during RLOF forms -* an accretion disk around the secondary or hits the secondary -* in a direct stream we calculate a minimum radial distance, rmin, -* of the mass stream from the secondary. This is taken from eq.(1) -* of Ulrich & Burger (1976, ApJ, 206, 509) which they fitted to -* the calculations of Lubow & Shu (1974, ApJ, 198, 383). -* If rmin is less than the radius of the secondary then an -* accretion disk is not formed. -* Note that the formula for rmin given by Ulrich & Burger is valid -* for all q whereas that given by Nelemans et al. (2001, A&A, -* submitted) in their eq.(6) is only valid for q < 1 where -* they define q = Mdonor/Maccretor, i.e. DD systems. -* -* 3) The changes to orbital and spin angular momentum owing to -* RLOF mass transfer have been improved, and an new input option -* now exists. -* When mass is lost from the system during RLOF there are now -* three choices as to how the orbital angular momentum is -* affected: a) the lost material carries with it a fraction -* gamma of the orbital angular momentum, i.e. -* dJorb = gamma*dm*a^2*omega_orb; b) the material carries with it -* the specific angular momentum of the primary, i.e. -* dJorb = dm*a_1^2*omega_orb; or c) assume the material is lost -* from the system as if a wind from the secondary, i.e. -* dJorb = dm*a_2^2*omega_orb. -* The parameter gamma is an input option. -* Choice c) is used if the mass transfer is super-Eddington -* or the system is experiencing novae eruptions. -* In all other cases choice a) is used if gamma > 0.0, b) if -* gamma = -1.0 and c) is used if gamma = -2.0. -* The primary spin angular momentum is reduced by an amount -* dm1*r_1^2*omega_1 when an amount of mass dm1 is transferred -* from the primary. -* If the secondary accretes through a disk then its spin -* angular momentum is altered by assuming that the material -* falls onto the star from the inner edge of a Keplerian -* disk and that the system is in a steady state, i.e. -* an amount dm2*SQRT(G*m_2*r_2). -* If there is no accretion disk then we calculate the angular -* momentum of the transferred material by using the radius at -* at which the disk would have formed (rdisk = 1.7*rmin, see -* Ulrich & Burger 1976) if allowed, i.e. the angular momentum -* of the inner Lagrangian point, and add this directly to -* the secondary, i.e. an amount dm2*SQRT(G*m_2*rdisk). -* Total angular momentum is conserved in this model. -* -* 4) Now using q_crit = 3.0 for MS-MS Roche systems (previously we -* had nothing). This corresponds roughly to R proportional to M^5 -* which should be true for the majority of the MS (varies from -* (M^17 -> M^2). If q > q_crit then contact occurs. -* For CHeB primaries we also take q_crit = 3.0 and allow -* common-envelope to occur if this is exceeded. -* -* 5) The value of lambda used in calculations of the envelope binding -* energy for giants in common-envelope is now variable (see function -* in zfuncs). The lambda function has been fitted by Onno to detailed -* models ... he will write about this soon! -* -* 6) Note that eq.42 in the paper is missing a SQRT around the -* MR^2/a^5 part. This needs to be corrected in any code update -* paper with a thanks to Jeremy Sepinsky (student at NorthWestern). -* It is ok in the code. -* -* March 2003 * -* New input options added: -* -* ifflag - for the mass of a WD you can choose to use the mass that -* results from the evolution algorithm (basically a competition -* between core-mass growth and envelope mass-loss) or use the IFMR -* proposed by Han, Podsiadlowski & Eggleton, 1995, MNRAS, 272, 800 -* [>0 activates HPE IFMR]. -* -* wdflag - for the cooling of WDs you can choose to use either the standard -* Mestel cooling law (see SSE paper) or a modified-Mestel law that -* is better matched to detailed models (provided by Brad Hansen -* ... see Hurley & Shara, 2003, ApJ, May 20, in press) -* [>0 activates modified-Mestel]. -* -* bhflag - choose whether or not black holes should get velocity kicks -* at formation -* [0= no kick; >0 kick]. -* -* nsflag - for the mass of neutron stars and black holes you can use either -* the SSE prescription or the prescription presented by -* Belczynski et al. 2002, ApJ, 572, 407 who found that SSE was -* underestimating the masses of these stars. In either case you also -* need to set the maximum NS mass (mxns) for the prescription -* [0= SSE, mxns=1.8; >0 Belczynski, mxns=3.0]. -* -* Sept 2004 * -* Input options added/changed: -* -* ceflag - set to 3 this uses de Kool (or Podsiadlowski) CE prescription, -* other options, such as Yungelson, could be added as well. -* -* hewind - factor to control the amount of He star mass-loss, i.e. -* 1.0e-13*hewind*L^(2/3) gives He star mass-loss. -* -* -* ++++++++++++++++++++++++++++++++++++++++++++++++++ -*** -* - INTEGER loop,iter,intpol,k,ip,jp,j1,j2 - PARAMETER(loop=20000) - INTEGER kstar(2),kw,kst,kw1,kw2,kmin,kmax - INTEGER ktype(0:14,0:14) - COMMON /TYPES/ ktype - INTEGER ceflag,tflag,ifflag,nsflag,wdflag - COMMON /FLAGS/ ceflag,tflag,ifflag,nsflag,wdflag -* - REAL*8 km,km0,tphys,tphys0,dtm0,tphys00 - REAL*8 tphysf,dtp,tsave - REAL*8 aj(2),aj0(2),epoch(2),tms(2),tbgb(2),tkh(2),dtmi(2) - REAL*8 mass0(2),mass(2),massc(2),menv(2),mass00(2),mcxx(2) - REAL*8 rad(2),rol(2),rol0(2),rdot(2),radc(2),renv(2),radx(2) - REAL*8 lumin(2),k2str(2),q(2),dms(2),dmr(2),dmt(2),vkick(2) - REAL*8 dml,vorb2,vwind2,omv2,ivsqm,lacc,vs(3) - REAL*8 sep,dr,tb,dme,tdyn,taum,dm1,dm2,dmchk,qc,dt,pd,rlperi - REAL*8 m1ce,m2ce,mch,tmsnew,dm22,mew - PARAMETER(mch=1.44d0) - REAL*8 yeardy,aursun - PARAMETER(yeardy=365.24d0,aursun=214.95d0) - REAL*8 acc1,tiny - PARAMETER(acc1=3.920659d+08,tiny=1.0d-14) - REAL*8 ecc,ecc1,tc,tcirc,ttid,ecc2,omecc2,sqome2,sqome3,sqome5 - REAL*8 f1,f2,f3,f4,f5,f,raa2,raa6,eqspin,rg2,tcqr - REAL*8 k3,mr23yr,twopi - PARAMETER(k3=0.21d0,mr23yr=0.4311d0) - REAL*8 jspin(2),ospin(2),jorb,oorb,jspbru,ospbru - REAL*8 delet,delet1,dspint(2),djspint(2),djtx(2) - REAL*8 dtj,djorb,djgr,djmb,djt,djtt,rmin,rdisk - REAL*8 neta,bwind,hewind,mxns - COMMON /VALUE1/ neta,bwind,hewind,mxns - REAL*8 beta,xi,acc2,epsnov,eddfac,gamma - COMMON /VALUE5/ beta,xi,acc2,epsnov,eddfac,gamma -* - REAL*8 z,tm,tn,m0,mt,rm,lum,mc,rc,me,re,k2,age,dtm,dtr - REAL*8 tscls(20),lums(10),GB(10),zpars(20) - REAL*8 zero,ngtv,ngtv2,mt2,rrl1,rrl2,mcx,teff1,teff2 - REAL*8 mass1i,mass2i,tbi,ecci - LOGICAL coel,com,prec,inttry,change,snova,sgl,bsymb,esymb,bss - LOGICAL supedd,novae,disk - LOGICAL isave,iplot - REAL*8 rl,mlwind,vrotf,corerd - EXTERNAL rl,mlwind,vrotf,corerd - REAL bcm(50000,34),bpp(80,10) - COMMON /BINARY/ bcm,bpp -* -* Save the initial state. -* - mass1i = mass0(1) - mass2i = mass0(2) - tbi = tb - ecci = ecc -* - zero = 0.d0 - ngtv = -1.d0 - ngtv2 = -2.d0 - twopi = 2.d0*ACOS(-1.d0) -* -* Initialize the parameters. -* - kmin = 1 - kmax = 2 - sgl = .false. - mt2 = MIN(mass(1),mass(2)) - kst = 0 -* - if(mt2.lt.tiny.or.tb.le.0.d0)then - sgl = .true. - if(mt2.lt.tiny)then - mt2 = 0.d0 - if(mass(1).lt.tiny)then - if(tphys.lt.tiny)then - mass0(1) = 0.01d0 - mass(1) = mass0(1) - kst = 1 - else - kmin = 2 - lumin(1) = 1.0d-10 - rad(1) = 1.0d-10 - massc(1) = 0.d0 - dmt(1) = 0.d0 - dmr(1) = 0.d0 - endif - ospin(1) = 1.0d-10 - jspin(1) = 1.0d-10 - else - if(tphys.lt.tiny)then - mass0(2) = 0.01d0 - mass(2) = mass0(2) - kst = 2 - else - kmax = 1 - lumin(2) = 1.0d-10 - rad(2) = 1.0d-10 - massc(2) = 0.d0 - dmt(2) = 0.d0 - dmr(2) = 0.d0 - endif - ospin(2) = 1.0d-10 - jspin(2) = 1.0d-10 - endif - endif - ecc = -1.d0 - tb = 0.d0 - sep = 1.0d+10 - oorb = 0.d0 - jorb = 0.d0 - if(ospin(1).lt.0.0) ospin(1) = 1.0d-10 - if(ospin(2).lt.0.0) ospin(2) = 1.0d-10 - q(1) = 1.0d+10 - q(2) = 1.0d+10 - rol(1) = 1.0d+10 - rol(2) = 1.0d+10 - else - tb = tb/yeardy - sep = aursun*(tb*tb*(mass(1) + mass(2)))**(1.d0/3.d0) - oorb = twopi/tb - jorb = mass(1)*mass(2)/(mass(1)+mass(2)) - & *SQRT(1.d0-ecc*ecc)*sep*sep*oorb - if(ospin(1).lt.0.d0) ospin(1) = oorb - if(ospin(2).lt.0.d0) ospin(2) = oorb - endif -* - do 500 , k = kmin,kmax - age = tphys - epoch(k) - CALL star(kstar(k),mass0(k),mass(k),tm,tn,tscls,lums,GB,zpars) - CALL hrdiag(mass0(k),age,mass(k),tm,tn,tscls,lums,GB,zpars, - & rm,lum,kstar(k),mc,rc,me,re,k2) - aj(k) = age - epoch(k) = tphys - age - rad(k) = rm - lumin(k) = lum - massc(k) = mc - radc(k) = rc - menv(k) = me - renv(k) = re - k2str(k) = k2 - tms(k) = tm - tbgb(k) = tscls(1) -* - if(tphys.lt.tiny.and.ospin(k).le.0.001d0)then - ospin(k) = 45.35d0*vrotf(mass(k))/rm - endif - jspin(k) = ospin(k)*(k2*rm*rm*(mass(k)-mc)+k3*rc*rc*mc) - if(.not.sgl)then - q(k) = mass(k)/mass(3-k) - rol(k) = rl(q(k))*sep - endif - rol0(k) = rol(k) - dmr(k) = 0.d0 - dmt(k) = 0.d0 - djspint(k) = 0.d0 - dtmi(k) = 1.0d+06 -* - 500 continue -* - if(mt2.lt.tiny)then - sep = 0.d0 - if(kst.gt.0)then - mass0(kst) = 0.d0 - mass(kst) = 0.d0 - kmin = 3 - kst - kmax = kmin - endif - endif -* -* On the first entry the previous timestep is zero to prevent mass loss. -* - dtm = 0.d0 - delet = 0.d0 - djorb = 0.d0 - bss = .false. -* -* Setup variables which control the output (if it is required). -* - ip = 0 - jp = 0 - tsave = tphys - isave = .true. - iplot = .false. - if(dtp.le.0.d0)then - iplot = .true. - isave = .false. - tsave = tphysf - elseif(dtp.gt.tphysf)then - isave = .false. - tsave = tphysf - endif - if(tphys.ge.tphysf) goto 140 -* - 4 iter = 0 - intpol = 0 - inttry = .false. - change = .false. - prec = .false. - snova = .false. - coel = .false. - com = .false. - bsymb = .false. - esymb = .false. - tphys0 = tphys - ecc1 = ecc - j1 = 1 - j2 = 2 - if(kstar(1).ge.10.and.kstar(1).le.14) dtmi(1) = 0.01d0 - if(kstar(2).ge.10.and.kstar(2).le.14) dtmi(2) = 0.01d0 - dm1 = 0.d0 - dm2 = 0.d0 -* - 5 kw1 = kstar(1) - kw2 = kstar(2) -* - dt = 1.0d+06*dtm - eqspin = 0.d0 - djtt = 0.d0 -* - if(intpol.eq.0.and.ABS(dtm).gt.tiny.and..not.sgl)then - vorb2 = acc1*(mass(1)+mass(2))/sep - ivsqm = 1.d0/SQRT(1.d0-ecc*ecc) - do 501 , k = 1,2 -* -* Calculate wind mass loss from the previous timestep. -* - if(neta.gt.tiny)then - rlperi = rol(k)*(1.d0-ecc) - dmr(k) = mlwind(kstar(k),lumin(k),rad(k),mass(k), - & massc(k),rlperi,z) -* -* Calculate how much of wind mass loss from companion will be -* accreted (Boffin & Jorissen, A&A 1988, 205, 155). -* - vwind2 = 2.d0*beta*acc1*mass(k)/rad(k) - omv2 = (1.d0 + vorb2/vwind2)**(3.d0/2.d0) - dmt(3-k) = ivsqm*acc2*dmr(k)*((acc1*mass(3-k)/vwind2)**2) - & /(2.d0*sep*sep*omv2) - dmt(3-k) = MIN(dmt(3-k),0.8d0*dmr(k)) - else - dmr(k) = 0.d0 - dmt(3-k) = 0.d0 - endif - 501 continue -* -* Diagnostic for Symbiotic-type stars. -* - if(neta.gt.tiny.and..not.esymb)then - lacc = 3.14d+07*mass(j2)*dmt(j2)/rad(j2) - lacc = lacc/lumin(j1) - if((lacc.gt.0.01d0.and..not.bsymb).or. - & (lacc.lt.0.01d0.and.bsymb))then - jp = MIN(80,jp + 1) - bpp(jp,1) = tphys - bpp(jp,2) = mass(1) - bpp(jp,3) = mass(2) - bpp(jp,4) = float(kstar(1)) - bpp(jp,5) = float(kstar(2)) - bpp(jp,6) = sep - bpp(jp,7) = ecc - bpp(jp,8) = rad(1)/rol(1) - bpp(jp,9) = rad(2)/rol(2) - if(bsymb)then - bpp(jp,10) = 13.0 - esymb = .true. - else - bpp(jp,10) = 12.0 - bsymb = .true. - endif - endif - endif -* -* Calculate orbital angular momentum change due to wind mass loss. -* - ecc2 = ecc*ecc - omecc2 = 1.d0 - ecc2 - sqome2 = SQRT(omecc2) -* - djorb = ((dmr(1)+q(1)*dmt(1))*mass(2)*mass(2) + - & (dmr(2)+q(2)*dmt(2))*mass(1)*mass(1))* - & sep*sep*sqome2*oorb/(mass(1)+mass(2))**2 - delet = ecc*(dmt(1)*(0.5d0/mass(1) + 1.d0/(mass(1)+mass(2))) + - & dmt(2)*(0.5d0/mass(2) + 1.d0/(mass(1)+mass(2)))) -* -* For very close systems include angular momentum loss owing to -* gravitational radiation. -* - if(sep.le.10.d0)then - djgr = 8.315d-10*mass(1)*mass(2)*(mass(1)+mass(2))/ - & (sep*sep*sep*sep) - f1 = (19.d0/6.d0) + (121.d0/96.d0)*ecc2 - sqome5 = sqome2**5 - delet1 = djgr*ecc*f1/sqome5 - djgr = djgr*jorb*(1.d0+0.875d0*ecc2)/sqome5 - djorb = djorb + djgr - delet = delet + delet1 - endif -* - do 502 , k = 1,2 -* -* Calculate change in the intrinsic spin of the star. -* - djtx(k) = (2.d0/3.d0)*xi*dmt(k)*rad(3-k)*rad(3-k)*ospin(3-k) - djspint(k) = (2.d0/3.d0)*(dmr(k)*rad(k)*rad(k)*ospin(k)) - - & djtx(k) -* -* Include magnetic braking for stars that have appreciable convective -* envelopes. This includes MS stars with M < 1.25, HG stars near the GB -* and giants. MB is not allowed for fully convective MS stars. -* - if(mass(k).gt.0.35d0.and.kstar(k).lt.10)then - djmb = 5.83d-16*menv(k)*(rad(k)*ospin(k))**3/mass(k) - djspint(k) = djspint(k) + djmb -* -* Limit to a 3% angular momentum change for the star owing to MB. -* This is found to work best with the maximum iteration of 20000, -* i.e. does not create an excessive number of iterations, while not -* affecting the evolution outcome when compared with a 2% restriction. -* - if(djmb.gt.tiny)then - dtj = 0.03d0*jspin(k)/ABS(djmb) - dt = MIN(dt,dtj) - endif - endif -* -* Calculate circularization, orbital shrinkage and spin up. -* - dspint(k) = 0.d0 - if(((kstar(k).le.9.and.rad(k).ge.0.01d0*rol(k)).or. - & (kstar(k).ge.10.and.k.eq.j1)).and.tflag.gt.0)then -* - raa2 = (rad(k)/sep)**2 - raa6 = raa2**3 -* -* Hut's polynomials. -* - f5 = 1.d0+ecc2*(3.d0+ecc2*0.375d0) - f4 = 1.d0+ecc2*(1.5d0+ecc2*0.125d0) - f3 = 1.d0+ecc2*(3.75d0+ecc2*(1.875d0+ecc2*7.8125d-02)) - f2 = 1.d0+ecc2*(7.5d0+ecc2*(5.625d0+ecc2*0.3125d0)) - f1 = 1.d0+ecc2*(15.5d0+ecc2*(31.875d0+ecc2*(11.5625d0 - & +ecc2*0.390625d0))) -* - if((kstar(k).eq.1.and.mass(k).ge.1.25d0).or. - & kstar(k).eq.4.or.kstar(k).eq.7)then -* -* Radiative damping (Zahn, 1977, A&A, 57, 383 and 1975, A&A, 41, 329). -* - tc = 1.592d-09*(mass(k)**2.84d0) - f = 1.9782d+04*SQRT((mass(k)*rad(k)*rad(k))/sep**5)* - & tc*(1.d0+q(3-k))**(5.d0/6.d0) - tcqr = f*q(3-k)*raa6 - rg2 = k2str(k) - elseif(kstar(k).le.9)then -* -* Convective damping (Hut, 1981, A&A, 99, 126). -* - tc = mr23yr*(menv(k)*renv(k)*(rad(k)-0.5d0*renv(k))/ - & (3.d0*lumin(k)))**(1.d0/3.d0) - ttid = twopi/(1.0d-10 + ABS(oorb - ospin(k))) - f = MIN(1.d0,(ttid/(2.d0*tc)**2)) - tcqr = 2.d0*f*q(3-k)*raa6*menv(k)/(21.d0*tc*mass(k)) - rg2 = (k2str(k)*(mass(k)-massc(k)))/mass(k) - else -* -* Degenerate damping (Campbell, 1984, MNRAS, 207, 433) -* - f = 7.33d-09*(lumin(k)/mass(k))**(5.d0/7.d0) - tcqr = f*q(3-k)*q(3-k)*raa2*raa2/(1.d0+q(3-k)) - rg2 = k3 - endif -* -* Circularization. -* - sqome3 = sqome2**3 - delet1 = 27.d0*tcqr*(1.d0+q(3-k))*raa2*(ecc/sqome2**13)* - & (f3 - (11.d0/18.d0)*sqome3*f4*ospin(k)/oorb) - tcirc = ecc/(ABS(delet1) + 1.0d-20) - delet = delet + delet1 -* -* Spin up of star. -* - dspint(k) = (3.d0*q(3-k)*tcqr/(rg2*omecc2**6))* - & (f2*oorb - sqome3*f5*ospin(k)) -* -* Calculate the equilibrium spin at which no angular momentum -* can be transferred. -* - eqspin = oorb*f2/(sqome3*f5) -* -* Calculate angular momentum change for the star owing to tides. -* - djt = (k2str(k)*(mass(k)-massc(k))*rad(k)*rad(k) + - & k3*massc(k)*radc(k)*radc(k))*dspint(k) - if(kstar(k).le.6.or.ABS(djt)/jspin(k).gt.0.1d0)then - djtt = djtt + djt - endif - endif - 502 continue -* -* Limit to 2% orbital angular momentum change. -* - djtt = djtt + djorb - if(ABS(djtt).gt.tiny)then - dtj = 0.02d0*jorb/ABS(djtt) - dt = MIN(dt,dtj) - endif - dtm = dt/1.0d+06 -* - elseif(ABS(dtm).gt.tiny.and.sgl)then - do 503 , k = kmin,kmax - if(neta.gt.tiny)then - rlperi = 0.d0 - dmr(k) = mlwind(kstar(k),lumin(k),rad(k),mass(k), - & massc(k),rlperi,z) - else - dmr(k) = 0.d0 - endif - dmt(k) = 0.d0 - djspint(k) = (2.d0/3.d0)*dmr(k)*rad(k)*rad(k)*ospin(k) - if(mass(k).gt.0.35d0.and.kstar(k).lt.10)then - djmb = 5.83d-16*menv(k)*(rad(k)*ospin(k))**3/mass(k) - djspint(k) = djspint(k) + djmb - if(djmb.gt.tiny)then - dtj = 0.03d0*jspin(k)/ABS(djmb) - dt = MIN(dt,dtj) - endif - endif - 503 continue - dtm = dt/1.0d+06 - endif -* - do 504 , k = kmin,kmax -* - dms(k) = (dmr(k) - dmt(k))*dt - if(kstar(k).lt.10)then - dml = mass(k) - massc(k) - if(dml.lt.dms(k))then - dml = MAX(dml,2.d0*tiny) - dtm = (dml/dms(k))*dtm - if(k.eq.2) dms(1) = dms(1)*dml/dms(2) - dms(k) = dml - dt = 1.0d+06*dtm - endif -* -* Limit to 1% mass loss. -* - if(dms(k).gt.0.01d0*mass(k))then - dtm = 0.01d0*mass(k)*dtm/dms(k) - if(k.eq.2) dms(1) = dms(1)*0.01d0*mass(2)/dms(2) - dms(k) = 0.01d0*mass(k) - dt = 1.0d+06*dtm - endif - endif -* - 504 continue -* -* Update mass and intrinsic spin (checking that the star is not spun -* past the equilibrium) and reset epoch for a MS (and possibly a HG) star. -* - do 505 , k = kmin,kmax -* - if(eqspin.gt.0.d0.and.ABS(dspint(k)).gt.tiny)then - if(intpol.eq.0)then - if(dspint(k).ge.0.d0)then - dspint(k) = MIN(dspint(k),(eqspin-ospin(k))/dt) - else - dspint(k) = MAX(dspint(k),(eqspin-ospin(k))/dt) - endif - djt = (k2str(k)*(mass(k)-massc(k))*rad(k)*rad(k) + - & k3*massc(k)*radc(k)*radc(k))*dspint(k) - djorb = djorb + djt - djspint(k) = djspint(k) - djt - endif - endif -* - jspin(k) = MAX(1.0d-10,jspin(k) - djspint(k)*dt) -* -* Ensure that the star does not spin up beyond break-up. -* - ospbru = twopi*SQRT(mass(k)*aursun**3/rad(k)**3) - jspbru = (k2str(k)*(mass(k)-massc(k))*rad(k)*rad(k) + - & k3*massc(k)*radc(k)*radc(k))*ospbru - if(jspin(k).gt.jspbru.and.ABS(dtm).gt.tiny)then - mew = 1.d0 - if(djtx(k).gt.0.d0)then - mew = MIN(mew,(jspin(k) - jspbru)/djtx(k)) - endif - jspin(k) = jspbru -* If excess material should not be accreted, activate next line. -* dms(k) = dms(k) + (1.d0 - mew)*dmt(k)*dt - endif -* - if(ABS(dms(k)).gt.tiny)then - mass(k) = mass(k) - dms(k) - if(kstar(k).le.2.or.kstar(k).eq.7)then - m0 = mass0(k) - mass0(k) = mass(k) - CALL star(kstar(k),mass0(k),mass(k),tm,tn,tscls, - & lums,GB,zpars) - if(kstar(k).eq.2)then - if(GB(9).lt.massc(k).or.m0.gt.zpars(3))then - mass0(k) = m0 - else - epoch(k) = tm + (tscls(1) - tm)*(aj(k)-tms(k))/ - & (tbgb(k) - tms(k)) - epoch(k) = tphys - epoch(k) - endif - else - epoch(k) = tphys - aj(k)*tm/tms(k) - endif - endif - endif -* - 505 continue -* - if(.not.sgl)then -* - ecc1 = ecc1 - delet*dt - ecc = MAX(ecc1,0.d0) - if(ecc.lt.1.0d-10) ecc = 0.d0 -* - if(ecc.ge.1.d0) goto 135 -* - jorb = jorb - djorb*dt - sep = (mass(1) + mass(2))*jorb*jorb/ - & ((mass(1)*mass(2)*twopi)**2*aursun**3*(1.d0-ecc*ecc)) - tb = (sep/aursun)*SQRT(sep/(aursun*(mass(1)+mass(2)))) - oorb = twopi/tb - endif -* -* Advance the time. -* - if(intpol.eq.0)then - tphys0 = tphys - dtm0 = dtm - endif - tphys = tphys + dtm -* - do 6 , k = kmin,kmax -* -* Acquire stellar parameters (M, R, L, Mc & K*) at apparent evolution age. -* - age = tphys - epoch(k) - aj0(k) = age - kw = kstar(k) - m0 = mass0(k) - mt = mass(k) - mc = massc(k) - if(intpol.eq.0) mcxx(k) = mc - if(intpol.gt.0) mc = mcxx(k) - mass00(k) = m0 -* -* Masses over 100Msun should probably not be trusted in the -* evolution formulae. -* - if(mt.gt.100.d0)then - WRITE(99,*)' MASS EXCEEDED ',mass1i,mass2i,tbi,ecci,mt - goto 140 - endif -* - CALL star(kw,m0,mt,tm,tn,tscls,lums,GB,zpars) - CALL hrdiag(m0,age,mt,tm,tn,tscls,lums,GB,zpars, - & rm,lum,kw,mc,rc,me,re,k2) -* - if(kw.ne.15)then - ospin(k) = jspin(k)/(k2*(mt-mc)*rm*rm+k3*mc*rc*rc) - endif -* -* At this point there may have been a supernova. -* - if(kw.ne.kstar(k).and.kstar(k).le.12.and. - & (kw.eq.13.or.kw.eq.14))then - if(sgl)then - CALL kick(kw,mass(k),mt,0.d0,0.d0,-1.d0,0.d0,vs) - vkick(k) = dsqrt(vs(1)*vs(1)+vs(2)*vs(2)+vs(3)*vs(3)) - else - CALL kick(kw,mass(k),mt,mass(3-k),ecc,sep,jorb,vs) - vkick(k) = dsqrt(vs(1)*vs(1)+vs(2)*vs(2)+vs(3)*vs(3)) - if(ecc.gt.1.d0)then - kstar(k) = kw - mass(k) = mt - epoch(k) = tphys - age - goto 135 - endif - tb = (sep/aursun)*SQRT(sep/(aursun*(mt+mass(3-k)))) - oorb = twopi/tb - endif - snova = .true. - endif -* - if(kw.ne.kstar(k))then - change = .true. - mass(k) = mt - dtmi(k) = 0.01d0 - if(kw.eq.15)then - kstar(k) = kw - goto 135 - endif - mass0(k) = m0 - epoch(k) = tphys - age - if(kw.gt.6.and.kstar(k).le.6)then - bsymb = .false. - esymb = .false. - endif - endif -* -* Force new NS or BH to have a second period. -* - if(kstar(k).eq.13.or.kstar(k).eq.14)then - if(tphys-epoch(k).lt.tiny)then - ospin(k) = 2.0d+08 - jspin(k) = k3*rc*rc*mc*ospin(k) - endif - endif -* -* Set radius derivative for later interpolation. -* - if(ABS(dtm).gt.tiny)then - rdot(k) = ABS(rm - rad(k))/dtm - else - rdot(k) = 0.d0 - endif -* -* Base new time scale for changes in radius & mass on stellar type. -* - dt = dtmi(k) - CALL deltat(kw,age,tm,tn,tscls,dt,dtr) -* -* Choose minimum of time-scale and remaining interval. -* - dtmi(k) = MIN(dt,dtr) -* -* Save relevent solar quantities. -* - aj(k) = age - kstar(k) = kw - rad(k) = rm - lumin(k) = lum - massc(k) = mc - radc(k) = rc - menv(k) = me - renv(k) = re - k2str(k) = k2 - tms(k) = tm - tbgb(k) = tscls(1) -* -* Check for blue straggler formation. -* - if(kw.le.1.and.tm.lt.tphys.and..not.bss)then - bss = .true. - jp = MIN(80,jp + 1) - bpp(jp,1) = tphys - bpp(jp,2) = mass(1) - bpp(jp,3) = mass(2) - bpp(jp,4) = float(kstar(1)) - bpp(jp,5) = float(kstar(2)) - bpp(jp,6) = sep - bpp(jp,7) = ecc - bpp(jp,8) = rad(1)/rol(1) - bpp(jp,9) = rad(2)/rol(2) - bpp(jp,10) = 14.0 - endif -* - 6 continue -* - if(.not.sgl)then -* -* Determine the mass ratios. -* - do 506 , k = 1,2 - q(k) = mass(k)/mass(3-k) - 506 continue -* -* Determine the Roche lobe radii and adjust the radius derivative. -* - do 507 , k = 1,2 - rol(k) = rl(q(k))*sep - if(ABS(dtm).gt.tiny)then - rdot(k) = rdot(k) + (rol(k) - rol0(k))/dtm - rol0(k) = rol(k) - endif - 507 continue - else - do 508 , k = kmin,kmax - rol(k) = 10000.d0*rad(k) - 508 continue - endif -* - if((tphys.lt.tiny.and.ABS(dtm).lt.tiny.and. - & (mass2i.lt.0.1d0.or..not.sgl)).or.snova)then - jp = MIN(80,jp + 1) - bpp(jp,1) = tphys - bpp(jp,2) = mass(1) - bpp(jp,3) = mass(2) - bpp(jp,4) = float(kstar(1)) - bpp(jp,5) = float(kstar(2)) - bpp(jp,6) = sep - bpp(jp,7) = ecc - bpp(jp,8) = rad(1)/rol(1) - bpp(jp,9) = rad(2)/rol(2) - bpp(jp,10) = 1.0 - if(snova)then - bpp(jp,10) = 2.0 - dtm = 0.d0 - goto 4 - endif - endif -* - if((isave.and.tphys.ge.tsave).or.iplot)then - if(sgl.or.(rad(1).lt.rol(1).and.rad(2).lt.rol(2)). - & or.tphys.lt.tiny)then - ip = ip + 1 - bcm(ip,1) = tphys - bcm(ip,2) = float(kstar(1)) - bcm(ip,3) = mass0(1) - bcm(ip,4) = mass(1) - bcm(ip,5) = log10(lumin(1)) - bcm(ip,6) = log10(rad(1)) - teff1 = 1000.d0*((1130.d0*lumin(1)/ - & (rad(1)**2.d0))**(1.d0/4.d0)) - bcm(ip,7) = log10(teff1) - bcm(ip,8) = massc(1) - bcm(ip,9) = radc(1) - bcm(ip,10) = menv(1) - bcm(ip,11) = renv(1) - bcm(ip,12) = epoch(1) - bcm(ip,13) = ospin(1) - bcm(ip,14) = dmt(1) - dmr(1) - bcm(ip,15) = rad(1)/rol(1) - bcm(ip,16) = float(kstar(2)) - bcm(ip,17) = mass0(2) - bcm(ip,18) = mass(2) - bcm(ip,19) = log10(lumin(2)) - bcm(ip,20) = log10(rad(2)) - teff2 = 1000.d0*((1130.d0*lumin(2)/ - & (rad(2)**2.d0))**(1.d0/4.d0)) - bcm(ip,21) = log10(teff2) - bcm(ip,22) = massc(2) - bcm(ip,23) = radc(2) - bcm(ip,24) = menv(2) - bcm(ip,25) = renv(2) - bcm(ip,26) = epoch(2) - bcm(ip,27) = ospin(2) - bcm(ip,28) = dmt(2) - dmr(2) - bcm(ip,29) = rad(2)/rol(2) - bcm(ip,30) = tb - bcm(ip,31) = sep - bcm(ip,32) = ecc - if(isave) tsave = tsave + dtp - endif - endif -* -* If not interpolating set the next timestep. -* - if(intpol.eq.0)then - dtm = MAX(1.0d-07*tphys,MIN(dtmi(1),dtmi(2))) - dtm = MIN(dtm,tsave-tphys) - if(iter.eq.0) dtm0 = dtm - endif - if(sgl) goto 98 -* -* Set j1 to the donor - the primary -* and j2 to the accretor - the secondary. -* - if(intpol.eq.0)then - if(rad(1)/rol(1).ge.rad(2)/rol(2))then - j1 = 1 - j2 = 2 - else - j1 = 2 - j2 = 1 - endif - endif -* -* Test whether Roche lobe overflow has begun. -* - if(rad(j1).gt.rol(j1))then -* -* Interpolate back until the primary is just filling its Roche lobe. -* - if(rad(j1).ge.1.002d0*rol(j1))then - if(intpol.eq.0) tphys00 = tphys - intpol = intpol + 1 - if(iter.eq.0) goto 7 - if(inttry) goto 7 - if(intpol.ge.100)then - WRITE(99,*)' INTPOL EXCEEDED ',mass1i,mass2i,tbi,ecci - goto 140 - endif - dr = rad(j1) - 1.001d0*rol(j1) - if(ABS(rdot(j1)).lt.tiny.or.prec)then - goto 7 - endif - dtm = -dr/ABS(rdot(j1)) - if(ABS(tphys0-tphys).gt.tiny) dtm = MAX(dtm,tphys0-tphys) - if(kstar(1).ne.kw1)then - kstar(1) = kw1 - mass0(1) = mass00(1) - epoch(1) = tphys - aj0(1) - endif - if(kstar(2).ne.kw2)then - kstar(2) = kw2 - mass0(2) = mass00(2) - epoch(2) = tphys - aj0(2) - endif - change = .false. - else -* -* Enter Roche lobe overflow -* - if(tphys.ge.tphysf) goto 140 - goto 7 - endif - else -* -* Check if already interpolating. -* - if(intpol.gt.0)then - intpol = intpol + 1 - if(intpol.ge.80)then - inttry = .true. - endif - if(ABS(rdot(j1)).lt.tiny)then - prec = .true. - dtm = 1.0d-07*tphys - else - dr = rad(j1) - 1.001d0*rol(j1) - dtm = -dr/ABS(rdot(j1)) - endif - if((tphys+dtm).ge.tphys00)then -* -* If this occurs then most likely the star is a high mass type 4 -* where the radius can change very sharply or possibly there is a -* discontinuity in the radius as a function of time and HRDIAG -* needs to be checked! -* - dtm = 0.5d0*(tphys00 - tphys0) - dtm = MAX(dtm,1.0d-10) - prec = .true. - endif - tphys0 = tphys - endif - endif -* -* Check for collision at periastron. -* - pd = sep*(1.d0 - ecc) - if(pd.lt.(rad(1)+rad(2)).and.intpol.eq.0) goto 130 -* -* Go back for the next step or interpolation. -* - 98 continue - if(tphys.ge.tphysf.and.intpol.eq.0) goto 140 - if(change)then - change = .false. - jp = MIN(80,jp + 1) - bpp(jp,1) = tphys - bpp(jp,2) = mass(1) - bpp(jp,3) = mass(2) - bpp(jp,4) = float(kstar(1)) - bpp(jp,5) = float(kstar(2)) - bpp(jp,6) = sep - bpp(jp,7) = ecc - bpp(jp,8) = rad(1)/rol(1) - bpp(jp,9) = rad(2)/rol(2) - bpp(jp,10) = 2.0 - endif -* - iter = iter + 1 -* - if(iter.ge.loop)then - WRITE(99,*)' MAXIMUM ITER EXCEEDED ',mass1i,mass2i,tbi,ecci - goto 140 - endif - goto 5 -* -* Set the nuclear timescale in years and slow-down factor. -* - 7 km0 = dtm0*1.0d+03/tb - if(km0.lt.tiny) km0 = 0.5d0 -* -* Force co-rotation of primary and orbit to ensure that the tides do not -* lead to unstable Roche (not currently used). -* -* if(ospin(j1).gt.1.05d0*oorb)then -* ospin(j1) = oorb -* jspin(j1) = (k2str(j1)*rad(j1)*rad(j1)*(mass(j1)-massc(j1))+ -* & k3*radc(j1)*radc(j1)*massc(j1))*ospin(j1) -* endif -* - iter = 0 - coel = .false. - change = .false. - radx(j1) = MAX(radc(j1),rol(j1)) - radx(j2) = rad(j2) -* - jp = MIN(80,jp + 1) - bpp(jp,1) = tphys - bpp(jp,2) = mass(1) - bpp(jp,3) = mass(2) - bpp(jp,4) = float(kstar(1)) - bpp(jp,5) = float(kstar(2)) - bpp(jp,6) = sep - bpp(jp,7) = ecc - bpp(jp,8) = rad(1)/rol(1) - bpp(jp,9) = rad(2)/rol(2) - bpp(jp,10) = 3.0 -* - if(iplot.and.tphys.gt.tiny)then - ip = ip + 1 - bcm(ip,1) = tphys - bcm(ip,2) = float(kstar(1)) - bcm(ip,3) = mass0(1) - bcm(ip,4) = mass(1) - bcm(ip,5) = log10(lumin(1)) - bcm(ip,6) = log10(rad(1)) - teff1 = 1000.d0*((1130.d0*lumin(1)/ - & (rad(1)**2.d0))**(1.d0/4.d0)) - bcm(ip,7) = log10(teff1) - bcm(ip,8) = massc(1) - bcm(ip,9) = radc(1) - bcm(ip,10) = menv(1) - bcm(ip,11) = renv(1) - bcm(ip,12) = epoch(1) - bcm(ip,13) = ospin(1) - bcm(ip,14) = 0.0 - bcm(ip,15) = rad(1)/rol(1) - bcm(ip,16) = float(kstar(2)) - bcm(ip,17) = mass0(2) - bcm(ip,18) = mass(2) - bcm(ip,19) = log10(lumin(2)) - bcm(ip,20) = log10(rad(2)) - teff2 = 1000.d0*((1130.d0*lumin(2)/ - & (rad(2)**2.d0))**(1.d0/4.d0)) - bcm(ip,21) = log10(teff2) - bcm(ip,22) = massc(2) - bcm(ip,23) = radc(2) - bcm(ip,24) = menv(2) - bcm(ip,25) = renv(2) - bcm(ip,26) = epoch(2) - bcm(ip,27) = ospin(2) - bcm(ip,28) = 0.0 - bcm(ip,29) = rad(2)/rol(2) - bcm(ip,30) = tb - bcm(ip,31) = sep - bcm(ip,32) = ecc - endif -* -* Eddington limit for accretion on to the secondary in one orbit. -* - 8 dme = 2.08d-03*eddfac*(1.d0/(1.d0 + zpars(11)))*rad(j2)*tb - supedd = .false. - novae = .false. - disk = .false. -* -* Determine whether the transferred material forms an accretion -* disk around the secondary or hits the secondary in a direct -* stream, by using eq.(1) of Ulrich & Burger (1976, ApJ, 206, 509) -* fitted to the calculations of Lubow & Shu (1974, ApJ, 198, 383). -* -* if(kstar(j2).ge.10) disk = .true. - rmin = 0.0425d0*sep*(q(j2)*(1.d0+q(j2)))**(1.d0/4.d0) - if(rmin.gt.rad(j2)) disk = .true. -* -* Kelvin-Helmholtz time from the modified classical expression. -* - do 13 , k = 1,2 - tkh(k) = 1.0d+07*mass(k)/(rad(k)*lumin(k)) - if(kstar(k).le.1.or.kstar(k).eq.7.or.kstar(k).ge.10)then - tkh(k) = tkh(k)*mass(k) - else - tkh(k) = tkh(k)*(mass(k) - massc(k)) - endif - 13 continue -* -* Dynamical timescale for the primary. -* - tdyn = 5.05d-05*SQRT(rad(j1)**3/mass(j1)) -* -* Identify special cases. -* - if(kstar(j1).eq.2)then - qc = 4.d0 - elseif(kstar(j1).eq.3.or.kstar(j1).eq.5.or.kstar(j1).eq.6)then -* qc = (1.67d0-zpars(7)+2.d0*(massc(j1)/mass(j1))**5)/2.13d0 -* Alternatively use condition of Hjellming & Webbink, 1987, ApJ, 318, 794. - qc = 0.362 + 1.0/(3.0*(1.0 - massc(j1)/mass(j1))) -* Or allow all cases to avoid common-envelope. -* qc = 100.d0 - elseif(kstar(j1).eq.8.or.kstar(j1).eq.9)then - qc = 0.784d0 - else - qc = 3.d0 - endif -* - if(kstar(j1).eq.0.and.q(j1).gt.0.695d0)then -* -* This will be dynamical mass transfer of a similar nature to -* common-envelope evolution. The result is always a single -* star placed in *2. -* - taum = SQRT(tkh(j1)*tdyn) - dm1 = mass(j1) - if(kstar(j2).le.1)then -* -* Restrict accretion to thermal timescale of secondary. -* - dm2 = taum/tkh(j2)*dm1 - mass(j2) = mass(j2) + dm2 -* -* Rejuvenate if the star is still on the main sequence. -* - mass0(j2) = mass(j2) - CALL star(kstar(j2),mass0(j2),mass(j2),tmsnew,tn, - & tscls,lums,GB,zpars) -* If the star has no convective core then the effective age decreases, -* otherwise it will become younger still. - if(mass(j2).lt.0.35d0.or.mass(j2).gt.1.25d0)then - aj(j2) = tmsnew/tms(j2)*aj(j2)*(mass(j2) - dm2)/mass(j2) - else - aj(j2) = tmsnew/tms(j2)*aj(j2) - endif - epoch(j2) = tphys - aj(j2) - elseif(kstar(j2).le.6)then -* -* Add all the material to the giant's envelope. -* - dm2 = dm1 - mass(j2) = mass(j2) + dm2 - if(kstar(j2).eq.2)then - mass0(j2) = mass(j2) - CALL star(kstar(j2),mass0(j2),mass(j2),tmsnew,tn,tscls, - & lums,GB,zpars) - aj(j2) = tmsnew + tscls(1)*(aj(j2)-tms(j2))/tbgb(j2) - epoch(j2) = tphys - aj(j2) - endif - elseif(kstar(j2).le.12)then -* -* Form a new giant envelope. -* - dm2 = dm1 - kst = ktype(kstar(j1),kstar(j2)) - if(kst.gt.100) kst = kst - 100 - if(kst.eq.4)then - aj(j2) = aj(j2)/tms(j2) - massc(j2) = mass(j2) - endif -* -* Check for planets or low-mass WDs. -* - if((kstar(j2).eq.10.and.mass(j2).lt.0.05d0).or. - & (kstar(j2).ge.11.and.mass(j2).lt.0.5d0))then - kst = kstar(j1) - mass(j1) = mass(j2) + dm2 - mass(j2) = 0.d0 - else - mass(j2) = mass(j2) + dm2 - CALL gntage(massc(j2),mass(j2),kst,zpars, - & mass0(j2),aj(j2)) - epoch(j2) = tphys - aj(j2) - endif - kstar(j2) = kst - else -* -* The neutron star or black hole simply accretes at the Eddington rate. -* - dm2 = MIN(dme*taum/tb,dm1) - if(dm2.lt.dm1) supedd = .true. - mass(j2) = mass(j2) + dm2 - endif - coel = .true. - if(mass(j2).gt.0.d0)then - mass(j1) = 0.d0 - kstar(j1) = 15 - else - kstar(j1) = kstar(j2) - kstar(j2) = 15 - endif - goto 135 - elseif(((ABS(ABS(2*kstar(j1)-11)-3).eq.2.or.kstar(j1).eq.9). - & and.(q(j1).gt.qc.or.radx(j1).le.radc(j1))).or. - & (kstar(j1).eq.2.and.q(j1).gt.qc).or. - & (kstar(j1).eq.4.and.q(j1).gt.qc))then -* -* Common-envelope evolution. -* - m1ce = mass(j1) - m2ce = mass(j2) - CALL comenv(mass0(j1),mass(j1),massc(j1),aj(j1),jspin(j1), - & kstar(j1),mass0(j2),mass(j2),massc(j2),aj(j2), - & jspin(j2),kstar(j2),zpars,ecc,sep,jorb,coel) -* - jp = MIN(80,jp + 1) - bpp(jp,1) = tphys - bpp(jp,2) = mass(1) - if(kstar(1).eq.15) bpp(jp,2) = mass0(1) - bpp(jp,3) = mass(2) - if(kstar(2).eq.15) bpp(jp,3) = mass0(2) - bpp(jp,4) = float(kstar(1)) - bpp(jp,5) = float(kstar(2)) - bpp(jp,6) = sep - bpp(jp,7) = ecc - bpp(jp,8) = rad(1)/rol(1) - bpp(jp,9) = rad(2)/rol(2) - bpp(jp,10) = 7.0 -* - epoch(j1) = tphys - aj(j1) - if(coel)then - com = .true. - goto 135 - endif - epoch(j2) = tphys - aj(j2) - if(ecc.gt.1.d0)then - if(kstar(1).ge.13)then - rc = corerd(kstar(1),mass(1),mass(1),zpars(2)) - ospin(1) = jspin(1)/(k3*rc*rc*mass(1)) - endif - if(kstar(2).ge.13)then - rc = corerd(kstar(2),mass(2),mass(2),zpars(2)) - ospin(2) = jspin(2)/(k3*rc*rc*mass(2)) - endif - goto 135 - endif -* -* Next step should be made without changing the time. -* - dm1 = m1ce - mass(j1) - dm2 = mass(j2) - m2ce - dm22 = dm2 - dtm = 0.d0 -* -* Reset orbital parameters as separation may have changed. -* - tb = (sep/aursun)*SQRT(sep/(aursun*(mass(1)+mass(2)))) - oorb = twopi/tb - elseif(kstar(j1).ge.10.and.kstar(j1).le.12.and. - & q(j1).gt.0.628d0)then -* -* Dynamic transfer from a white dwarf. Secondary will have KW > 9. -* - taum = SQRT(tkh(j1)*tdyn) - dm1 = mass(j1) - if(eddfac.lt.10.d0)then - dm2 = MIN(dme*taum/tb,dm1) - if(dm2.lt.dm1) supedd = .true. - else - dm2 = dm1 - endif - mass(j2) = mass(j2) + dm2 -* - if(kstar(j1).eq.10.and.kstar(j2).eq.10)then -* -* Assume the energy released by ignition of the triple-alpha reaction -* is enough to destroy the star. -* - kstar(j2) = 15 - mass(j2) = 0.d0 - elseif(kstar(j1).eq.10.or.kstar(j2).eq.10)then -* -* Should be helium overflowing onto a CO or ONe core in which case the -* helium swells up to form a giant envelope so a HeGB star is formed. -* Allowance for the rare case of CO or ONe flowing onto He is made. -* - kst = 9 - if(kstar(j2).eq.10) massc(j2) = dm2 - CALL gntage(massc(j2),mass(j2),kst,zpars,mass0(j2),aj(j2)) - kstar(j2) = kst - epoch(j2) = tphys - aj(j2) - elseif(kstar(j2).le.12)then - mass0(j2) = mass(j2) - if(kstar(j1).eq.12.and.kstar(j2).eq.11)then -* -* Mixture of ONe and CO will result in an ONe product. -* - kstar(j2) = 12 - endif - endif - kstar(j1) = 15 - mass(j1) = 0.d0 -* -* Might be a supernova that destroys the system. -* - if(kstar(j2).le.11.and.mass(j2).gt.mch)then - kstar(j2) = 15 - mass(j2) = 0.d0 - endif - coel = .true. - goto 135 - elseif(kstar(j1).eq.13)then -* -* Gamma ray burster? -* - dm1 = mass(j1) - mass(j1) = 0.d0 - kstar(j1) = 15 - dm2 = dm1 - mass(j2) = mass(j2) + dm2 - kstar(j2) = 14 - coel = .true. - goto 135 - elseif(kstar(j1).eq.14)then -* -* Both stars are black holes. Let them merge quietly. -* - dm1 = mass(j1) - mass(j1) = 0.d0 - kstar(j1) = 15 - dm2 = dm1 - mass(j2) = mass(j2) + dm2 - coel = .true. - goto 135 - else -* -* Mass transfer in one Kepler orbit. -* - dm1 = 3.0d-06*tb*(LOG(rad(j1)/rol(j1))**3)* - & MIN(mass(j1),5.d0)**2 - if(kstar(j1).eq.2)then - mew = (mass(j1) - massc(j1))/mass(j1) - dm1 = MAX(mew,0.01d0)*dm1 - elseif(kstar(j1).ge.10)then -* dm1 = dm1*1.0d+03/MAX(rad(j1),1.0d-04) - dm1 = dm1*1.0d+03*mass(j1)/MAX(rad(j1),1.0d-04) - endif - kst = kstar(j2) -* -* Possibly mass transfer needs to be reduced if primary is rotating -* faster than the orbit (not currently implemented). -* -* spnfac = MIN(3.d0,MAX(ospin(j1)/oorb,1.d0)) -* dm1 = dm1/spnfac**2 -* -* Limit mass transfer to the thermal rate for remaining giant-like stars -* and to the dynamical rate for all others. -* - if(kstar(j1).ge.2.and.kstar(j1).le.9.and.kstar(j1).ne.7)then -*** -* JH_temp ... this may be good for HG RLOF?? -* if(kstar(j1).eq.2)then -* mew = rad(j1)/rol(j1) - 1.d0 -* mew = 2.d0*mew -* dm1 = dm1*10.d0**mew -* endif -*** - dm1 = MIN(dm1,mass(j1)*tb/tkh(j1)) - elseif(rad(j1).gt.10.d0*rol(j1).or.(kstar(j1).le.1.and. - & kstar(j2).le.1.and.q(j1).gt.qc))then -* -* Allow the stars to merge with the product in *1. -* - m1ce = mass(j1) - m2ce = mass(j2) - CALL mix(mass0,mass,aj,kstar,zpars) - dm1 = m1ce - mass(j1) - dm2 = mass(j2) - m2ce -* -* Next step should be made without changing the time. -* - dtm = 0.d0 - epoch(1) = tphys - aj(1) - coel = .true. - goto 135 - else - dm1 = MIN(dm1,mass(j1)*tb/tdyn) - endif -* -* Calculate wind mass loss from the stars during one orbit. -* - vorb2 = acc1*(mass(1)+mass(2))/sep - ivsqm = 1.d0/SQRT(1.d0-ecc*ecc) - do 14 , k = 1,2 - if(neta.gt.tiny)then - rlperi = rol(k)*(1.d0-ecc) - dmr(k) = mlwind(kstar(k),lumin(k),radx(k), - & mass(k),massc(k),rlperi,z) - vwind2 = 2.d0*beta*acc1*mass(k)/radx(k) - omv2 = (1.d0 + vorb2/vwind2)**(3.d0/2.d0) - dmt(3-k) = ivsqm*acc2*dmr(k)*((acc1*mass(3-k)/vwind2)**2) - & /(2.d0*sep*sep*omv2) - dmt(3-k) = MIN(dmt(3-k),dmr(k)) - else - dmr(k) = 0.d0 - dmt(3-k) = 0.d0 - endif - 14 continue -* - do 15 , k = 1,2 - dms(k) = (dmr(k)-dmt(k))*tb - 15 continue -* -* Increase time-scale to relative mass loss of 0.5% but not more than twice. -* KM is the number of orbits for the timestep. -* - km = MIN(2.d0*km0,5.0d-03/ - & MAX(ABS(dm1+dms(j1))/mass(j1),dms(j2)/mass(j2))) - km0 = km -* -* Modify time-step & mass loss terms by speed-up factor. -* - dt = km*tb - dtm = dt/1.0d+06 -* -* Take the stellar evolution timestep into account but don't let it -* be overly restrictive for long lived phases. -* - if(iter.le.1000) dtm = MIN(dtm,dtmi(1),dtmi(2)) - dtm = MIN(dtm,tsave-tphys) - dt = dtm*1.0d+06 - km = dt/tb -* -* Decide between accreted mass by secondary and/or system mass loss. -* - taum = mass(j2)/dm1*tb - if(kstar(j2).le.2.or.kstar(j2).eq.4)then -* -* Limit according to the thermal timescale of the secondary. -* - dm2 = MIN(1.d0,10.d0*taum/tkh(j2))*dm1 - elseif(kstar(j2).ge.7.and.kstar(j2).le.9)then -* -* Naked helium star secondary swells up to a core helium burning star -* or SAGB star unless the primary is also a helium star. -* - if(kstar(j1).ge.7)then - dm2 = MIN(1.d0,10.d0*taum/tkh(j2))*dm1 - else - dm2 = dm1 - dmchk = dm2 - 1.05d0*dms(j2) - if(dmchk.gt.0.d0.and.dm2/mass(j2).gt.1.0d-04)then - kst = MIN(6,2*kstar(j2)-10) - if(kst.eq.4)then - aj(j2) = aj(j2)/tms(j2) - mcx = mass(j2) - else - mcx = massc(j2) - endif - mt2 = mass(j2) + km*(dm2 - dms(j2)) - CALL gntage(mcx,mt2,kst,zpars,mass0(j2),aj(j2)) - epoch(j2) = tphys + dtm - aj(j2) -* - jp = MIN(80,jp + 1) - bpp(jp,1) = tphys - bpp(jp,2) = mass(j1) - bpp(jp,3) = mt2 - bpp(jp,4) = float(kstar(j1)) - bpp(jp,5) = float(kst) - bpp(jp,6) = sep - bpp(jp,7) = ecc - bpp(jp,8) = rad(1)/rol(1) - bpp(jp,9) = rad(2)/rol(2) - bpp(jp,10) = 8.0 - if(j1.eq.2)then - bpp(jp,2) = mt2 - bpp(jp,3) = mass(j1) - bpp(jp,4) = float(kst) - bpp(jp,5) = float(kstar(j1)) - endif -* - endif - endif - elseif(kstar(j1).le.6.and. - & (kstar(j2).ge.10.and.kstar(j2).le.12))then -* -* White dwarf secondary. -* - if(dm1/tb.lt.2.71d-07)then - if(dm1/tb.lt.1.03d-07)then -* -* Accrete until a nova explosion blows away most of the accreted material. -* - novae = .true. - dm2 = MIN(dm1,dme) - if(dm2.lt.dm1) supedd = .true. - dm22 = epsnov*dm2 - else -* -* Steady burning at the surface -* - dm2 = dm1 - endif - else -* -* Make a new giant envelope. -* - dm2 = dm1 -* -* Check for planets or low-mass WDs. -* - if((kstar(j2).eq.10.and.mass(j2).lt.0.05d0).or. - & (kstar(j2).ge.11.and.mass(j2).lt.0.5d0))then - kst = kstar(j2) - else - kst = MIN(6,3*kstar(j2)-27) - mt2 = mass(j2) + km*(dm2 - dms(j2)) - CALL gntage(massc(j2),mt2,kst,zpars,mass0(j2),aj(j2)) - epoch(j2) = tphys + dtm - aj(j2) -* - jp = MIN(80,jp + 1) - bpp(jp,1) = tphys - bpp(jp,2) = mass(j1) - bpp(jp,3) = mt2 - bpp(jp,4) = float(kstar(j1)) - bpp(jp,5) = float(kst) - bpp(jp,6) = sep - bpp(jp,7) = ecc - bpp(jp,8) = rad(1)/rol(1) - bpp(jp,9) = rad(2)/rol(2) - bpp(jp,10) = 8.0 - if(j1.eq.2)then - bpp(jp,2) = mt2 - bpp(jp,3) = mass(j1) - bpp(jp,4) = float(kst) - bpp(jp,5) = float(kstar(j1)) - endif -* - endif -* - endif - elseif(kstar(j2).ge.10)then -* -* Impose the Eddington limit. -* - dm2 = MIN(dm1,dme) - if(dm2.lt.dm1) supedd = .true. -* - else -* -* We have a giant whose envelope can absorb any transferred material. -* - dm2 = dm1 - endif - if(.not.novae) dm22 = dm2 -* - if(kst.ge.10.and.kst.le.12)then - mt2 = mass(j2) + km*(dm22 - dms(j2)) - if(kstar(j1).le.10.and.kst.eq.10.and.mt2.ge.0.7d0)then -* -* HeWD can only accrete helium-rich material up to a mass of 0.7 when -* it is destroyed in a possible Type 1a SN. -* - mass(j1) = mass(j1) - km*(dm1 + dms(j1)) - mass(j2) = 0.d0 - kstar(j2) = 15 - goto 135 - elseif(kstar(j1).le.10.and.kst.ge.11)then -* -* CO and ONeWDs accrete helium-rich material until the accumulated -* material exceeds a mass of 0.15 when it ignites. For a COWD with -* mass less than 0.95 the system will be destroyed as an ELD in a -* possible Type 1a SN. COWDs with mass greater than 0.95 and ONeWDs -* will survive with all the material converted to ONe (JH 30/09/99). -* -** Now changed to an ELD for all COWDs when 0.15 accreted (JH 11/01/00). -* - if((mt2-mass0(j2)).ge.0.15d0)then - if(kst.eq.11)then - mass(j1) = mass(j1) - km*(dm1 + dms(j1)) - mass(j2) = 0.d0 - kstar(j2) = 15 - goto 135 - endif - mass0(j2) = mt2 - endif - else - mass0(j2) = mt2 - endif -* -* If the Chandrasekhar limit is exceeded for a white dwarf then destroy -* the white dwarf in a supernova. If the WD is ONe then a neutron star -* will survive the supernova and we let HRDIAG take care of this when -* the stars are next updated. -* - if(kst.eq.10.or.kst.eq.11)then - if(mt2.ge.mch)then - dm1 = mch - mass(j2) + km*dms(j2) - mass(j1) = mass(j1) - dm1 - km*dms(j1) - mass(j2) = 0.d0 - kstar(j2) = 15 - goto 135 - endif - endif - endif -* -* Modify mass loss terms by speed-up factor. -* - dm1 = km*dm1 - dm2 = km*dm2 - dm22 = km*dm22 - dme = km*dme -* -* Calculate orbital angular momentum change due to system mass loss. -* - djorb = ((dmr(1)+q(1)*dmt(1))*mass(2)*mass(2) + - & (dmr(2)+q(2)*dmt(2))*mass(1)*mass(1))/ - & (mass(1)+mass(2))**2 - djorb = djorb*dt -* -* For super-Eddington mass transfer rates, for gamma = -2.0, -* and for novae systems, assume that material is lost from -* the system as if a wind from the secondary. -* If gamma = -1.0 then assume the lost material carries with it -* the specific angular momentum of the primary and for all -* gamma > 0.0 assume that it takes away a fraction gamma of -* the orbital angular momentum. -* - if(supedd.or.novae.or.gamma.lt.-1.5d0)then - djorb = djorb + (dm1 - dm22)*mass(j1)*mass(j1)/ - & (mass(1)+mass(2))**2 - elseif(gamma.ge.0.d0)then - djorb = djorb + gamma*(dm1 - dm2) - else - djorb = djorb + (dm1 - dm2)*mass(j2)*mass(j2)/ - & (mass(1)+mass(2))**2 - endif -* - ecc2 = ecc*ecc - omecc2 = 1.d0 - ecc2 - sqome2 = SQRT(omecc2) -* - djorb = djorb*sep*sep*sqome2*oorb - delet = 0.d0 -* -* For very close systems include angular momentum loss mechanisms. -* - if(sep.le.10.d0)then - djgr = 8.315d-10*mass(1)*mass(2)*(mass(1)+mass(2))/ - & (sep*sep*sep*sep) - f1 = (19.d0/6.d0) + (121.d0/96.d0)*ecc2 - sqome5 = sqome2**5 - delet1 = djgr*ecc*f1/sqome5 - djgr = djgr*jorb*(1.d0+0.875d0*ecc2)/sqome5 - djorb = djorb + djgr*dt - delet = delet + delet1*dt - endif -* - do 602 , k = 1,2 -* - dms(k) = km*dms(k) - if(kstar(k).lt.10) dms(k) = MIN(dms(k),mass(k) - massc(k)) -* -* Calculate change in the intrinsic spin of the star. -* - djspint(k) = (2.d0/3.d0)*(dmr(k)*radx(k)*radx(k)*ospin(k) - - & xi*dmt(k)*radx(3-k)*radx(3-k)*ospin(3-k)) - djspint(k) = djspint(k)*dt -* - if(mass(k).gt.0.35d0.and.kstar(k).lt.10)then - djmb = 5.83d-16*menv(k)*(rad(k)*ospin(k))**3/mass(k) - djspint(k) = djspint(k) + djmb*dt - endif -* - 602 continue -* -* Adjust the spin angular momentum of each star owing to mass transfer -* and conserve total angular momentum. -* - djt = dm1*radx(j1)*radx(j1)*ospin(j1) - djspint(j1) = djspint(j1) + djt - djorb = djorb - djt - if(disk)then -* -* Alter spin of the degenerate secondary by assuming that material -* falls onto the star from the inner edge of a Keplerian accretion -* disk and that the system is in a steady state. -* - djt = dm2*twopi*aursun*SQRT(aursun*mass(j2)*radx(j2)) - djspint(j2) = djspint(j2) - djt - djorb = djorb + djt -* - else -* -* No accretion disk. -* Calculate the angular momentum of the transferred material by -* using the radius of the disk (see Ulrich & Burger) that would -* have formed if allowed. -* - rdisk = 1.7d0*rmin - djt = dm2*twopi*aursun*SQRT(aursun*mass(j2)*rdisk) - djspint(j2) = djspint(j2) - djt - djorb = djorb + djt -* - endif - djtx(2) = djt -* -* Adjust the secondary spin if a nova eruption has occurred. -* - if(novae)then - djt = (dm2 - dm22)*radx(j2)*radx(j2)*ospin(j2) - djspint(j2) = djspint(j2) + djt - djtx(2) = djtx(2) - djt - endif -* -* Calculate circularization, orbital shrinkage and spin up. -* - do 603 , k = 1,2 -* - dspint(k) = 0.d0 - if(((kstar(k).le.9.and.rad(k).ge.0.01d0*rol(k)).or. - & (kstar(k).ge.10.and.k.eq.j1)).and.tflag.gt.0)then -* - raa2 = (radx(k)/sep)**2 - raa6 = raa2**3 -* - f5 = 1.d0+ecc2*(3.d0+ecc2*0.375d0) - f4 = 1.d0+ecc2*(1.5d0+ecc2*0.125d0) - f3 = 1.d0+ecc2*(3.75d0+ecc2*(1.875d0+ecc2*7.8125d-02)) - f2 = 1.d0+ecc2*(7.5d0+ecc2*(5.625d0+ecc2*0.3125d0)) - f1 = 1.d0+ecc2*(15.5d0+ecc2*(31.875d0+ecc2*(11.5625d0 - & +ecc2*0.390625d0))) -* - if((kstar(k).eq.1.and.mass(k).ge.1.25d0).or. - & kstar(k).eq.4.or.kstar(k).eq.7)then - tc = 1.592d-09*(mass(k)**2.84d0) - f = 1.9782d+04*SQRT((mass(k)*radx(k)*radx(k))/sep**5)* - & tc*(1.d0+q(3-k))**(5.d0/6.d0) - tcqr = f*q(3-k)*raa6 - rg2 = k2str(k) - elseif(kstar(k).le.9)then - renv(k) = MIN(renv(k),radx(k)-radc(k)) - renv(k) = MAX(renv(k),1.0d-10) - tc = mr23yr*(menv(k)*renv(k)*(radx(k)-0.5d0*renv(k))/ - & (3.d0*lumin(k)))**(1.d0/3.d0) - ttid = twopi/(1.0d-10 + ABS(oorb - ospin(k))) - f = MIN(1.d0,(ttid/(2.d0*tc)**2)) - tcqr = 2.d0*f*q(3-k)*raa6*menv(k)/(21.d0*tc*mass(k)) - rg2 = (k2str(k)*(mass(k)-massc(k)))/mass(k) - else - f = 7.33d-09*(lumin(k)/mass(k))**(5.d0/7.d0) - tcqr = f*q(3-k)*q(3-k)*raa2*raa2/(1.d0+q(3-k)) - rg2 = k3 - endif - sqome3 = sqome2**3 - delet1 = 27.d0*tcqr*(1.d0+q(3-k))*raa2*(ecc/sqome2**13)* - & (f3 - (11.d0/18.d0)*sqome3*f4*ospin(k)/oorb) - tcirc = ecc/(ABS(delet1) + 1.0d-20) - delet = delet + delet1*dt - dspint(k) = (3.d0*q(3-k)*tcqr/(rg2*omecc2**6))* - & (f2*oorb - sqome3*f5*ospin(k)) - eqspin = oorb*f2/(sqome3*f5) - if(dt.gt.0.d0)then - if(dspint(k).ge.0.d0)then - dspint(k) = MIN(dt*dspint(k),eqspin-ospin(k))/dt - else - dspint(k) = MAX(dt*dspint(k),eqspin-ospin(k))/dt - endif - endif - djt = (k2str(k)*(mass(k)-massc(k))*radx(k)*radx(k) + - & k3*massc(k)*radc(k)*radc(k))*dspint(k) - djorb = djorb + djt*dt - djspint(k) = djspint(k) - djt*dt -* - endif -* - jspin(k) = MAX(1.0d-10,jspin(k) - djspint(k)) -* -* Ensure that the star does not spin up beyond break-up, and transfer -* the excess angular momentum back to the orbit. -* - ospbru = twopi*SQRT(mass(k)*aursun**3/radx(k)**3) - jspbru = (k2str(k)*(mass(k)-massc(k))*radx(k)*radx(k) + - & k3*massc(k)*radc(k)*radc(k))*ospbru - if(jspin(k).gt.jspbru)then - mew = 1.d0 - if(djtx(2).gt.0.d0)then - mew = MIN(mew,(jspin(k) - jspbru)/djtx(2)) - endif - djorb = djorb - (jspin(k) - jspbru) - jspin(k) = jspbru -* If excess material should not be accreted, activate next line. -* dm22 = (1.d0 - mew)*dm22 - endif -* - 603 continue -* -* Update the masses. -* - kstar(j2) = kst - mass(j1) = mass(j1) - dm1 - dms(j1) - if(kstar(j1).le.1.or.kstar(j1).eq.7) mass0(j1) = mass(j1) - mass(j2) = mass(j2) + dm22 - dms(j2) - if(kstar(j2).le.1.or.kstar(j2).eq.7) mass0(j2) = mass(j2) -* -* For a HG star check if the initial mass can be reduced. -* - if(kstar(j1).eq.2.and.mass0(j1).le.zpars(3))then - m0 = mass0(j1) - mass0(j1) = mass(j1) - CALL star(kstar(j1),mass0(j1),mass(j1),tmsnew,tn,tscls, - & lums,GB,zpars) - if(GB(9).lt.massc(j1))then - mass0(j1) = m0 - endif - endif - if(kstar(j2).eq.2.and.mass0(j2).le.zpars(3))then - m0 = mass0(j2) - mass0(j2) = mass(j2) - CALL star(kstar(j2),mass0(j2),mass(j2),tmsnew,tn,tscls, - & lums,GB,zpars) - if(GB(9).lt.massc(j2))then - mass0(j2) = m0 - endif - endif -* - ecc = ecc - delet - ecc = MAX(ecc,0.d0) - if(ecc.lt.1.0d-10) ecc = 0.d0 -* - if(ecc.ge.1.d0) goto 135 -* -* Ensure that Jorb does not become negative which could happen if the -* primary overfills its Roche lobe initially. In this case we simply -* allow contact to occur. -* - jorb = MAX(1.d0,jorb - djorb) - sep = (mass(1) + mass(2))*jorb*jorb/ - & ((mass(1)*mass(2)*twopi)**2*aursun**3*(1.d0-ecc*ecc)) - tb = (sep/aursun)*SQRT(sep/(aursun*(mass(1)+mass(2)))) - oorb = twopi/tb -* - endif -* -* Always rejuvenate the secondary and age the primary if they are on -* the main sequence. -* - if(kstar(j1).le.2.or.kstar(j1).eq.7)then - CALL star(kstar(j1),mass0(j1),mass(j1),tmsnew,tn,tscls, - & lums,GB,zpars) - if(kstar(j1).eq.2)then - aj(j1) = tmsnew + (tscls(1) - tmsnew)*(aj(j1)-tms(j1))/ - & (tbgb(j1) - tms(j1)) - else - aj(j1) = tmsnew/tms(j1)*aj(j1) - endif - epoch(j1) = tphys - aj(j1) - endif -* - if(kstar(j2).le.2.or.kstar(j2).eq.7)then - CALL star(kstar(j2),mass0(j2),mass(j2),tmsnew,tn,tscls, - & lums,GB,zpars) - if(kstar(j2).eq.2)then - aj(j2) = tmsnew + (tscls(1) - tmsnew)*(aj(j2)-tms(j2))/ - & (tbgb(j2) - tms(j2)) - elseif((mass(j2).lt.0.35d0.or.mass(j2).gt.1.25d0). - & and.kstar(j2).ne.7)then - aj(j2) = tmsnew/tms(j2)*aj(j2)*(mass(j2) - dm22)/mass(j2) - else - aj(j2) = tmsnew/tms(j2)*aj(j2) - endif - epoch(j2) = tphys - aj(j2) - endif -* -* Obtain the stellar parameters for the next step. -* - tphys = tphys + dtm - do 90 , k = 1,2 - age = tphys - epoch(k) - m0 = mass0(k) - mt = mass(k) - mc = massc(k) -* -* Masses over 100Msun should probably not be trusted in the -* evolution formulae. -* - if(mt.gt.100.d0)then - WRITE(99,*)' MASS EXCEEDED ',mass1i,mass2i,tbi,ecci,mt - goto 140 - endif - kw = kstar(k) - CALL star(kw,m0,mt,tm,tn,tscls,lums,GB,zpars) - CALL hrdiag(m0,age,mt,tm,tn,tscls,lums,GB,zpars, - & rm,lum,kw,mc,rc,me,re,k2) -* -* Check for a supernova and correct the semi-major axis if so. -* - if(kw.ne.kstar(k).and.kstar(k).le.12.and. - & (kw.eq.13.or.kw.eq.14))then - dms(k) = mass(k) - mt - CALL kick(kw,mass(k),mt,mass(3-k),ecc,sep,jorb,vs) - vkick(k) = dsqrt(vs(1)*vs(1)+vs(2)*vs(2)+vs(3)*vs(3)) - if(ecc.gt.1.d0)then - kstar(k) = kw - mass(k) = mt - epoch(k) = tphys - age - goto 135 - endif - tb = (sep/aursun)*SQRT(sep/(aursun*(mt+mass(3-k)))) - oorb = twopi/tb - endif - if(kw.ne.kstar(k))then - change = .true. - if((kw.eq.13.or.kw.eq.14).and.kstar(k).le.12)then - snova = .true. - endif - mass(k) = mt - if(kw.eq.15)then - kstar(k) = kw - goto 135 - endif - mass0(k) = m0 - epoch(k) = tphys - age - endif -* -* Determine stellar evolution timescale for nuclear burning types. -* - if(kw.le.9)then - CALL deltat(kw,age,tm,tn,tscls,dt,dtr) - dtmi(k) = MIN(dt,dtr) -* dtmi(k) = dtr - dtmi(k) = MAX(1.0d-07,dtmi(k)) - else - dtmi(k) = 1.0d+10 - endif -* dtmi(k) = MAX((tn-age),1.0d-07) -* -* Save relevent solar quantities. -* - aj(k) = age - kstar(k) = kw - rad(k) = rm - radx(k) = rm - lumin(k) = lum - massc(k) = mc - radc(k) = rc - menv(k) = me - renv(k) = re - k2str(k) = k2 - tms(k) = tm - tbgb(k) = tscls(1) -* -* Check for blue straggler formation. -* - if(kw.le.1.and.tm.lt.tphys.and..not.bss)then - bss = .true. - jp = MIN(80,jp + 1) - bpp(jp,1) = tphys - bpp(jp,2) = mass(1) - bpp(jp,3) = mass(2) - bpp(jp,4) = float(kstar(1)) - bpp(jp,5) = float(kstar(2)) - bpp(jp,6) = sep - bpp(jp,7) = ecc - bpp(jp,8) = rad(1)/rol(1) - bpp(jp,9) = rad(2)/rol(2) - bpp(jp,10) = 14.0 - endif -* - 90 continue -* - do 100 , k = 1,2 - q(k) = mass(k)/mass(3-k) - rol(k) = rl(q(k))*sep - 100 continue - if(rad(j1).gt.rol(j1)) radx(j1) = MAX(radc(j1),rol(j1)) - do 110 , k = 1,2 - ospin(k) = jspin(k)/(k2str(k)*(mass(k)-massc(k))*radx(k)* - & radx(k) + k3*massc(k)*radc(k)*radc(k)) - 110 continue -* - if((isave.and.tphys.ge.tsave).or.iplot)then - ip = ip + 1 - bcm(ip,1) = tphys - bcm(ip,2) = float(kstar(1)) - bcm(ip,3) = mass0(1) - bcm(ip,4) = mass(1) - bcm(ip,5) = log10(lumin(1)) - bcm(ip,6) = log10(rad(1)) - teff1 = 1000.d0*((1130.d0*lumin(1)/ - & (rad(1)**2.d0))**(1.d0/4.d0)) - bcm(ip,7) = log10(teff1) - bcm(ip,8) = massc(1) - bcm(ip,9) = radc(1) - bcm(ip,10) = menv(1) - bcm(ip,11) = renv(1) - bcm(ip,12) = epoch(1) - bcm(ip,13) = ospin(1) - bcm(ip,15) = rad(1)/rol(1) - bcm(ip,16) = float(kstar(2)) - bcm(ip,17) = mass0(2) - bcm(ip,18) = mass(2) - bcm(ip,19) = log10(lumin(2)) - bcm(ip,20) = log10(rad(2)) - teff2 = 1000.d0*((1130.d0*lumin(2)/ - & (rad(2)**2.d0))**(1.d0/4.d0)) - bcm(ip,21) = log10(teff2) - bcm(ip,22) = massc(2) - bcm(ip,23) = radc(2) - bcm(ip,24) = menv(2) - bcm(ip,25) = renv(2) - bcm(ip,26) = epoch(2) - bcm(ip,27) = ospin(2) - bcm(ip,29) = rad(2)/rol(2) - bcm(ip,30) = tb - bcm(ip,31) = sep - bcm(ip,32) = ecc - dt = MAX(dtm,1.0d-12)*1.0d+06 - if(j1.eq.1)then - bcm(ip,14) = (-1.0*dm1 - dms(1))/dt - bcm(ip,28) = (dm2 - dms(2))/dt - else - bcm(ip,14) = (dm2 - dms(1))/dt - bcm(ip,28) = (-1.0*dm1 - dms(2))/dt - endif - if(isave) tsave = tsave + dtp - endif -* - if(tphys.ge.tphysf) goto 140 -* - if(change)then - change = .false. - jp = MIN(80,jp + 1) - bpp(jp,1) = tphys - bpp(jp,2) = mass(1) - bpp(jp,3) = mass(2) - bpp(jp,4) = float(kstar(1)) - bpp(jp,5) = float(kstar(2)) - bpp(jp,6) = sep - bpp(jp,7) = ecc - bpp(jp,8) = rad(1)/rol(1) - bpp(jp,9) = rad(2)/rol(2) - bpp(jp,10) = 2.0 - endif -* -* Test whether the primary still fills its Roche lobe. -* - if(rad(j1).gt.rol(j1).and..not.snova)then -* -* Test for a contact system -* - if(rad(j2).gt.rol(j2)) goto 130 - iter = iter + 1 - goto 8 - else - jp = MIN(80,jp + 1) - bpp(jp,1) = tphys - bpp(jp,2) = mass(1) - bpp(jp,3) = mass(2) - bpp(jp,4) = float(kstar(1)) - bpp(jp,5) = float(kstar(2)) - bpp(jp,6) = sep - bpp(jp,7) = ecc - bpp(jp,8) = rad(1)/rol(1) - bpp(jp,9) = rad(2)/rol(2) - bpp(jp,10) = 4.0 - dtm = 0.d0 - goto 4 - endif -* - 130 continue -* -* Contact system. -* - coel = .true. -* -* If *1 or *2 is giant-like this will be common-envelope evolution. -* - m1ce = mass(j1) - m2ce = mass(j2) - rrl1 = MIN(999.999d0,rad(1)/rol(1)) - rrl2 = MIN(999.999d0,rad(2)/rol(2)) -* - jp = MIN(80,jp + 1) - bpp(jp,1) = tphys - bpp(jp,2) = mass(1) - bpp(jp,3) = mass(2) - bpp(jp,4) = float(kstar(1)) - bpp(jp,5) = float(kstar(2)) - bpp(jp,6) = sep - bpp(jp,7) = ecc - bpp(jp,8) = rrl1 - bpp(jp,9) = rrl2 - bpp(jp,10) = 5.0 -* - if(kstar(j1).ge.2.and.kstar(j1).le.9.and.kstar(j1).ne.7)then - CALL comenv(mass0(j1),mass(j1),massc(j1),aj(j1),jspin(j1), - & kstar(j1),mass0(j2),mass(j2),massc(j2),aj(j2), - & jspin(j2),kstar(j2),zpars,ecc,sep,jorb,coel) - com = .true. - elseif(kstar(j2).ge.2.and.kstar(j2).le.9.and.kstar(j2).ne.7)then - CALL comenv(mass0(j2),mass(j2),massc(j2),aj(j2),jspin(j2), - & kstar(j2),mass0(j1),mass(j1),massc(j1),aj(j1), - & jspin(j1),kstar(j1),zpars,ecc,sep,jorb,coel) - com = .true. - else - CALL mix(mass0,mass,aj,kstar,zpars) - endif - if(com)then - jp = MIN(80,jp + 1) - bpp(jp,1) = tphys - bpp(jp,2) = mass(1) - if(kstar(1).eq.15) bpp(jp,2) = mass0(1) - bpp(jp,3) = mass(2) - if(kstar(2).eq.15) bpp(jp,3) = mass0(2) - bpp(jp,4) = float(kstar(1)) - bpp(jp,5) = float(kstar(2)) - bpp(jp,6) = sep - bpp(jp,7) = ecc - rrl1 = MIN(rrl1,0.99d0) - rrl2 = MIN(rrl2,0.99d0) - bpp(jp,8) = rrl1 - bpp(jp,9) = rrl2 - bpp(jp,10) = 7.0 - endif - epoch(1) = tphys - aj(1) - epoch(2) = tphys - aj(2) - if(.not.coel)then -* -* Next step should be made without changing the time. -* - if(ecc.gt.1.d0)then - if(kstar(1).ge.13)then - rc = corerd(kstar(1),mass(1),mass(1),zpars(2)) - ospin(1) = jspin(1)/(k3*rc*rc*mass(1)) - endif - if(kstar(2).ge.13)then - rc = corerd(kstar(2),mass(2),mass(2),zpars(2)) - ospin(2) = jspin(2)/(k3*rc*rc*mass(2)) - endif - goto 135 - endif - dtm = 0.d0 -* -* Reset orbital parameters as separation may have changed. -* - tb = (sep/aursun)*SQRT(sep/(aursun*(mass(1)+mass(2)))) - oorb = twopi/tb - goto 4 - endif -* - 135 continue -* - sgl = .true. - if(kstar(1).ne.15.or.kstar(2).ne.15)then - if(com)then - com = .false. - else - jp = MIN(80,jp + 1) - bpp(jp,1) = tphys - bpp(jp,2) = mass(1) - if(kstar(1).eq.15) bpp(jp,2) = mass0(1) - bpp(jp,3) = mass(2) - if(kstar(2).eq.15) bpp(jp,3) = mass0(2) - bpp(jp,4) = float(kstar(1)) - bpp(jp,5) = float(kstar(2)) - bpp(jp,6) = zero - bpp(jp,7) = zero - bpp(jp,8) = zero - bpp(jp,9) = ngtv - if(coel)then - bpp(jp,10) = 6.0 - elseif(ecc.gt.1.d0)then -* -* Binary dissolved by a supernova or tides. -* - bpp(jp,6) = sep - bpp(jp,7) = ecc - bpp(jp,9) = ngtv2 - bpp(jp,10) = 11.0 - else - bpp(jp,10) = 9.0 - endif - endif - if(kstar(2).eq.15)then - kmax = 1 - rol(2) = -1.d0*rad(2) - dtmi(2) = tphysf - elseif(kstar(1).eq.15)then - kmin = 2 - rol(1) = -1.d0*rad(1) - dtmi(1) = tphysf - endif - ecc = -1.d0 - sep = 0.d0 - dtm = 0.d0 - coel = .false. - goto 4 - endif -* - 140 continue -* - if(com)then - com = .false. - else - jp = MIN(80,jp + 1) - bpp(jp,1) = tphys - bpp(jp,2) = mass(1) - if(kstar(1).eq.15.and.bpp(jp-1,4).lt.15.0)then - bpp(jp,2) = mass0(1) - endif - bpp(jp,3) = mass(2) - if(kstar(2).eq.15.and.bpp(jp-1,5).lt.15.0)then - bpp(jp,3) = mass0(2) - endif - bpp(jp,4) = float(kstar(1)) - bpp(jp,5) = float(kstar(2)) - bpp(jp,6) = zero - bpp(jp,7) = zero - bpp(jp,8) = zero - if(coel)then - bpp(jp,9) = ngtv - bpp(jp,10) = 6.0 - elseif(kstar(1).eq.15.and.kstar(2).eq.15)then -* -* Cases of accretion induced supernova or single star supernova. -* No remnant is left in either case. -* - bpp(jp,9) = ngtv2 - bpp(jp,10) = 9.0 - else - bpp(jp,6) = sep - bpp(jp,7) = ecc - bpp(jp,8) = rad(1)/rol(1) - bpp(jp,9) = rad(2)/rol(2) - bpp(jp,10) = 10.0 - endif - endif -* - if((isave.and.tphys.ge.tsave).or.iplot)then - ip = ip + 1 - bcm(ip,1) = tphys - bcm(ip,2) = float(kstar(1)) - bcm(ip,3) = mass0(1) - bcm(ip,4) = mass(1) - bcm(ip,5) = log10(lumin(1)) - bcm(ip,6) = log10(rad(1)) - teff1 = 1000.d0*((1130.d0*lumin(1)/ - & (rad(1)**2.d0))**(1.d0/4.d0)) - bcm(ip,7) = log10(teff1) - bcm(ip,8) = massc(1) - bcm(ip,9) = radc(1) - bcm(ip,10) = menv(1) - bcm(ip,11) = renv(1) - bcm(ip,12) = epoch(1) - bcm(ip,13) = ospin(1) - bcm(ip,15) = rad(1)/rol(1) - bcm(ip,16) = float(kstar(2)) - bcm(ip,17) = mass0(2) - bcm(ip,18) = mass(2) - bcm(ip,19) = log10(lumin(2)) - bcm(ip,20) = log10(rad(2)) - teff2 = 1000.d0*((1130.d0*lumin(2)/ - & (rad(2)**2.d0))**(1.d0/4.d0)) - bcm(ip,21) = log10(teff2) - bcm(ip,22) = massc(2) - bcm(ip,23) = radc(2) - bcm(ip,24) = menv(2) - bcm(ip,25) = renv(2) - bcm(ip,26) = epoch(2) - bcm(ip,27) = ospin(2) - bcm(ip,29) = rad(2)/rol(2) - bcm(ip,30) = tb - bcm(ip,31) = sep - bcm(ip,32) = ecc - dt = MAX(dtm,1.0d-12)*1.0d+06 - if(j1.eq.1)then - bcm(ip,14) = (-1.0*dm1 - dms(1))/dt - bcm(ip,28) = (dm2 - dms(2))/dt - else - bcm(ip,14) = (dm2 - dms(1))/dt - bcm(ip,28) = (-1.0*dm1 - dms(2))/dt - endif - if(isave) tsave = tsave + dtp - if(tphysf.le.0.d0)then - ip = ip + 1 - do 145 , k = 1,32 - bcm(ip,k) = bcm(ip-1,k) - 145 continue - endif - endif -* - tphysf = tphys - if(sgl)then - if(ecc.ge.0.d0.and.ecc.le.1.d0) ecc = -1.d0 - tb = -1.d0 - endif - tb = tb*yeardy - if(jp.ge.80)then - WRITE(99,*)' EVOLV2 ARRAY ERROR ',mass1i,mass2i,tbi,ecci - WRITE(*,*)' STOP: EVOLV2 ARRAY ERROR ' - CALL exit(0) - STOP - elseif(jp.ge.40)then - WRITE(99,*)' EVOLV2 ARRAY WARNING ',mass1i,mass2i,tbi,ecci,jp - endif - bcm(ip+1,1) = -1.0 - bpp(jp+1,1) = -1.0 -* - RETURN - END -*** - - -cc//gntage.f - -*** - SUBROUTINE gntage(mc,mt,kw,zpars,m0,aj) -* -* A routine to determine the age of a giant from its core mass and type. -* -* Author : C. A. Tout -* Date : 24th September 1996 -* Revised: 21st February 1997 to include core-helium-burning stars -* -* Rewritten: 2nd January 1998 by J. R. Hurley to be compatible with -* the new evolution routines and to include new stellar -* types. -* - implicit none -* - integer kw - integer j,jmax - parameter(jmax=30) -* - real*8 mc,mt,m0,aj,tm,tn - real*8 tscls(20),lums(10),GB(10),zpars(20) - real*8 mmin,mmax,mmid,dm,f,fmid,dell,derl,lum - real*8 macc,lacc,tiny - parameter(macc=0.00001d0,lacc=0.0001d0,tiny=1.0d-14) - real*8 mcx,mcy -* - real*8 mcheif,mcagbf,mheif,mbagbf,mcgbf,lmcgbf,lbgbf,lbgbdf - external mcheif,mcagbf,mheif,mbagbf,mcgbf,lmcgbf,lbgbf,lbgbdf -* -* This should only be entered with KW = 3, 4, 5, 6 or 9 -* -* First we check that we don't have a CheB star -* with too small a core mass. - if(kw.eq.4)then -* Set the minimum CHeB core mass using M = Mflash - mcy = mcheif(zpars(2),zpars(2),zpars(10)) - if(mc.le.mcy) kw = 3 -* if(mc.le.mcy) WRITE(66,*)' GNTAGE4: changed to 3' - endif -* -* Next we check that we don't have a GB star for M => Mfgb - if(kw.eq.3)then -* Set the maximum GB core mass using M = Mfgb - mcy = mcheif(zpars(3),zpars(2),zpars(9)) - if(mc.ge.mcy)then - kw = 4 - aj = 0.d0 -* WRITE(66,*)' GNTAGE3: changed to 4' - endif - endif -* - if(kw.eq.6)then -* -* We try to start the star from the start of the SAGB by -* setting Mc = Mc,TP. -* - mcy = 0.44d0*2.25d0 + 0.448d0 - if(mc.gt.mcy)then -* A type 6 with this sized core mass cannot exist as it should -* already have become a NS or BH as a type 5. -* We set it up so that it will. - mcx = (mc + 0.35d0)/0.773d0 - elseif(mc.ge.0.8d0)then - mcx = (mc - 0.448d0)/0.44d0 - else - mcx = mc - endif - m0 = mbagbf(mcx) - if(m0.lt.tiny)then -* Carbon core mass is less then the minimum for the start of SAGB. -* This must be the case of a low-mass C/O or O/Ne WD with only a -* very small envelope added or possibly the merger of a helium star -* with a main sequence star. We will set m0 = mt and then reset the -* core mass to allow for some helium to be added to the C/O core. - kw = 14 -* WRITE(66,*)' GNTAGE6: changed to 4' - else - CALL star(kw,m0,mt,tm,tn,tscls,lums,GB,zpars) - aj = tscls(13) - endif - endif -* - if(kw.eq.5)then -* -* We fit a Helium core mass at the base of the AGB. -* - m0 = mbagbf(mc) - if(m0.lt.tiny)then -* Helium core mass is less then the BAGB minimum. - kw = 14 -* WRITE(66,*)' GNTAGE5: changed to 4' - else - CALL star(kw,m0,mt,tm,tn,tscls,lums,GB,zpars) - aj = tscls(2) + tscls(3) - endif - endif -* -* - if(kw.eq.4)then -* -* The supplied age is actually the fractional age, fage, of CHeB lifetime -* that has been completed, ie. 0 <= aj <= 1. -* - if(aj.lt.0.d0.or.aj.gt.1.d0)then -* WRITE(99,*)' FATAL ERROR! GNTAGE4: fage out of bounds ' -* WRITE(99,*)' FAGE ',aj -* WRITE(*,*)' STOP: FATAL ERROR ' -* CALL exit(0) -* STOP - aj = 0.d0 - endif -* Get the minimum, fage=1, and maximum, fage=0, allowable masses - mcy = mcagbf(zpars(2)) - if(mc.ge.mcy)then - mmin = mbagbf(mc) - else - mmin = zpars(2) - endif - mmax = mheif(mc,zpars(2),zpars(10)) - if(aj.lt.tiny)then - m0 = mmax - goto 20 - elseif(aj.ge.1.d0)then - m0 = mmin - goto 20 - endif -* Use the bisection method to find m0 - fmid = (1.d0-aj)*mcheif(mmax,zpars(2),zpars(10)) + - & aj*mcagbf(mmax) - mc - f = (1.d0-aj)*mcheif(mmin,zpars(2),zpars(10)) + - & aj*mcagbf(mmin) - mc - if(f*fmid.ge.0.d0)then -* This will probably occur if mc is just greater than the minimum -* allowed mass for a CHeB star and fage > 0. - kw = 3 -* WRITE(66,*)' GNTAGE4: changed to 3' - goto 90 - endif - m0 = mmin - dm = mmax - mmin - do 10 , j = 1,jmax - dm = 0.5d0*dm - mmid = m0 + dm - fmid = (1.d0-aj)*mcheif(mmid,zpars(2),zpars(10)) + - & aj*mcagbf(mmid) - mc - if(fmid.lt.0.d0) m0 = mmid - if(ABS(dm).lt.macc.or.ABS(fmid).lt.tiny) goto 20 - if(j.eq.jmax)then -* WRITE(99,*)' FATAL ERROR! GNTAGE4: root not found ' -* WRITE(*,*)' STOP: FATAL ERROR ' -* CALL exit(0) -* STOP - m0 = mt - aj = 0.d0 - endif - 10 continue - 20 continue -* - CALL star(kw,m0,mt,tm,tn,tscls,lums,GB,zpars) - aj = tscls(2) + aj*tscls(3) -* - endif -* - 90 continue -* - if(kw.eq.3)then -* -* First we double check that we don't have a GB star for M => Mfgb - mcy = mcheif(zpars(3),zpars(2),zpars(9)) - if(mc.ge.mcy)then -* WRITE(99,*)' GNTAGE3: star too big for GB ' -* WRITE(*,*)' STOP: FATAL ERROR ' -* CALL exit(0) -* STOP - mc = 0.99d0*mcy - endif -* Next we find an m0 so as to place the star at the BGB - mcx = mcheif(zpars(2),zpars(2),zpars(9)) - if(mc.gt.mcx)then - m0 = mheif(mc,zpars(2),zpars(9)) - else -* Use Newton-Raphson to find m0 from Lbgb - m0 = zpars(2) - CALL star(kw,m0,mt,tm,tn,tscls,lums,GB,zpars) - lum = lmcgbf(mc,GB) - j = 0 - 30 continue - dell = lbgbf(m0) - lum - if(ABS(dell/lum).le.lacc) goto 40 - derl = lbgbdf(m0) - m0 = m0 - dell/derl - j = j + 1 - if(j.eq.jmax)then -* WRITE(99,*)' FATAL ERROR! GNTAGE3: root not found ' -* WRITE(*,*)' STOP: FATAL ERROR ' -* CALL exit(0) -* STOP - m0 = zpars(2) - m0 = MAX(m0,mt) - goto 40 - endif - goto 30 - 40 continue - endif - CALL star(kw,m0,mt,tm,tn,tscls,lums,GB,zpars) - aj = tscls(1) + 1.0d-06*(tscls(2) - tscls(1)) -* - endif -* - if(kw.eq.8.or.kw.eq.9)then -* -* We make a post-MS naked helium star. -* To make things easier we put the star at the TMS point -* so it actually begins as type 8. -* - kw = 8 - mmin = mc - CALL star(kw,mmin,mc,tm,tn,tscls,lums,GB,zpars) - mcx = mcgbf(lums(2),GB,lums(6)) - if(mcx.ge.mc)then -* WRITE(99,*)' FATAL ERROR! GNTAGE9: mmin too big ' -* WRITE(*,*)' STOP: FATAL ERROR ' -* CALL exit(0) -* STOP - m0 = mt - goto 80 - endif - f = mcx - mc - mmax = mt - do 50 , j = 1,jmax - CALL star(kw,mmax,mc,tm,tn,tscls,lums,GB,zpars) - mcy = mcgbf(lums(2),GB,lums(6)) - if(mcy.gt.mc) goto 60 - mmax = 2.d0*mmax - if(j.eq.jmax)then -* WRITE(99,*)' FATAL ERROR! GNTAGE9: mmax not found ' -* WRITE(*,*)' STOP: FATAL ERROR ' -* CALL exit(0) -* STOP - m0 = mt - goto 80 - endif - 50 continue - 60 continue - fmid = mcy - mc -* Use the bisection method to find m0 - if(f*fmid.ge.0.d0)then -* WRITE(99,*)' FATAL ERROR! GNTAGE9: root not bracketed ' -* WRITE(*,*)' STOP: FATAL ERROR ' -* CALL exit(0) -* STOP - m0 = mt - goto 80 - endif - m0 = mmin - dm = mmax - mmin - do 70 , j = 1,jmax - dm = 0.5d0*dm - mmid = m0 + dm - CALL star(kw,mmid,mc,tm,tn,tscls,lums,GB,zpars) - mcy = mcgbf(lums(2),GB,lums(6)) - fmid = mcy - mc - if(fmid.lt.0.d0) m0 = mmid - if(ABS(dm).lt.macc.or.ABS(fmid).lt.tiny) goto 80 - if(j.eq.jmax)then -* WRITE(99,*)' FATAL ERROR! GNTAGE9: root not found ' -* WRITE(*,*)' STOP: FATAL ERROR ' -* CALL exit(0) -* STOP - m0 = mt - goto 80 - endif - 70 continue - 80 continue -* - CALL star(kw,m0,mt,tm,tn,tscls,lums,GB,zpars) - aj = tm + 1.0d-10*tm -* - endif -* - if(kw.eq.14)then -* - kw = 4 - m0 = mt - mcy = mcagbf(m0) - aj = mc/mcy - CALL star(kw,m0,mt,tm,tn,tscls,lums,GB,zpars) - if(m0.le.zpars(2))then - mcx = mcgbf(lums(4),GB,lums(6)) - else - mcx = mcheif(m0,zpars(2),zpars(10)) - end if - mc = mcx + (mcy - mcx)*aj - aj = tscls(2) + aj*tscls(3) - endif -* - RETURN - END -*** - - - -cc//instar.f - -*** - SUBROUTINE instar -* -* -* Initialization of collision matrix. -* ------------------------ -* - implicit none - integer i,j,ktype(0:14,0:14) - common /TYPES/ ktype -* -* Initialize stellar collision matrix. -* - ktype(0,0) = 1 - do 10 , j = 1,6 - ktype(0,j) = j - ktype(1,j) = j - 10 continue - ktype(0,7) = 4 - ktype(1,7) = 4 - do 15 , j = 8,12 - if(j.ne.10)then - ktype(0,j) = 6 - else - ktype(0,j) = 3 - endif - ktype(1,j) = ktype(0,j) - 15 continue - ktype(2,2) = 3 - do 20 , i = 3,14 - ktype(i,i) = i - 20 continue - ktype(5,5) = 4 - ktype(7,7) = 1 - ktype(10,10) = 15 - ktype(13,13) = 14 - do 25 , i = 2,5 - do 30 j = i+1,12 - ktype(i,j) = 4 - 30 continue - 25 continue - ktype(2,3) = 3 - ktype(2,6) = 5 - ktype(2,10) = 3 - ktype(2,11) = 5 - ktype(2,12) = 5 - ktype(3,6) = 5 - ktype(3,10) = 3 - ktype(3,11) = 5 - ktype(3,12) = 5 - ktype(6,7) = 4 - ktype(6,8) = 6 - ktype(6,9) = 6 - ktype(6,10) = 5 - ktype(6,11) = 6 - ktype(6,12) = 6 - ktype(7,8) = 8 - ktype(7,9) = 9 - ktype(7,10) = 7 - ktype(7,11) = 9 - ktype(7,12) = 9 - ktype(8,9) = 9 - ktype(8,10) = 7 - ktype(8,11) = 9 - ktype(8,12) = 9 - ktype(9,10) = 7 - ktype(9,11) = 9 - ktype(9,12) = 9 - ktype(10,11) = 9 - ktype(10,12) = 9 - ktype(11,12) = 12 - do 35 , i = 0,12 - ktype(i,13) = 13 - ktype(i,14) = 14 - 35 continue - ktype(13,14) = 14 -* -* Increase common-envelope cases by 100. - do 40 , i = 0,9 - do 45 , j = i,14 - if(i.le.1.or.i.eq.7)then - if(j.ge.2.and.j.le.9.and.j.ne.7)then - ktype(i,j) = ktype(i,j) + 100 - endif - else - ktype(i,j) = ktype(i,j) + 100 - endif - 45 continue - 40 continue -* -* Assign the remaining values by symmetry. - do 50 , i = 1,14 - do 55 , j = 0,i-1 - ktype(i,j) = ktype(j,i) - 55 continue - 50 continue -* - return - end -*** - - -cc//mix.f - -*** - SUBROUTINE MIX(M0,M,AJ,KS,ZPARS) -* -* Author : J. R. Hurley -* Date : 7th July 1998 -* -* Evolution parameters for mixed star. -* ------------------------------------ -* - implicit none -* - INTEGER KS(2),I1,I2,K1,K2,KW,ICASE - INTEGER KTYPE(0:14,0:14) - COMMON /TYPES/ KTYPE - REAL*8 M0(2),M(2),AJ(2),ZPARS(20) - REAL*8 TSCLS(20),LUMS(10),GB(10),TMS1,TMS2,TMS3,TN - REAL*8 M01,M02,M03,M1,M2,M3,AGE1,AGE2,AGE3,MC3,MCH - PARAMETER(MCH=1.44D0) - REAL*8 NETA,BWIND,HEWIND,MXNS - COMMON /VALUE1/ NETA,BWIND,HEWIND,MXNS -* -* -* Define global indices with body #I1 being most evolved. - IF(KS(1).GE.KS(2))THEN - I1 = 1 - I2 = 2 - ELSE - I1 = 2 - I2 = 1 - END IF -* -* Specify case index for collision treatment. - K1 = KS(I1) - K2 = KS(I2) - ICASE = KTYPE(K1,K2) -* if(icase.gt.100) WRITE(66,*)' MIX ERROR ICASE>100 ',icase,k1,k2 -* -* Determine evolution time scales for first star. - M01 = M0(I1) - M1 = M(I1) - AGE1 = AJ(I1) - CALL star(K1,M01,M1,TMS1,TN,TSCLS,LUMS,GB,ZPARS) -* -* Obtain time scales for second star. - M02 = M0(I2) - M2 = M(I2) - AGE2 = AJ(I2) - CALL star(K2,M02,M2,TMS2,TN,TSCLS,LUMS,GB,ZPARS) -* -* Check for planetary systems - defined as HeWDs and low-mass WDs! - IF(K1.EQ.10.AND.M1.LT.0.05)THEN - ICASE = K2 - IF(K2.LE.1)THEN - ICASE = 1 - AGE1 = 0.D0 - ENDIF - ELSEIF(K1.GE.11.AND.M1.LT.0.5.AND.ICASE.EQ.6)THEN - ICASE = 9 - ENDIF - IF(K2.EQ.10.AND.M2.LT.0.05)THEN - ICASE = K1 - IF(K1.LE.1)THEN - ICASE = 1 - AGE2 = 0.D0 - ENDIF - ENDIF -* -* Specify total mass. - M3 = M1 + M2 - M03 = M01 + M02 - KW = ICASE - AGE3 = 0.d0 -* -* Restrict merged stars to masses less than 100 Msun. - IF(M3.GE.100.D0)THEN - M3 = 99.D0 - M03 = MIN(M03,M3) - ENDIF -* -* Evaluate apparent age and other parameters. -* - IF(ICASE.EQ.1)THEN -* Specify new age based on complete mixing. - IF(K1.EQ.7) KW = 7 - CALL star(KW,M03,M3,TMS3,TN,TSCLS,LUMS,GB,ZPARS) - AGE3 = 0.1d0*TMS3*(AGE1*M1/TMS1 + AGE2*M2/TMS2)/M3 - ELSEIF(ICASE.EQ.3.OR.ICASE.EQ.6.OR.ICASE.EQ.9)THEN - MC3 = M1 - CALL gntage(MC3,M3,KW,ZPARS,M03,AGE3) - ELSEIF(ICASE.EQ.4)THEN - MC3 = M1 - AGE3 = AGE1/TMS1 - CALL gntage(MC3,M3,KW,ZPARS,M03,AGE3) - ELSEIF(ICASE.EQ.7)THEN - CALL star(KW,M03,M3,TMS3,TN,TSCLS,LUMS,GB,ZPARS) - AGE3 = TMS3*(AGE2*M2/TMS2)/M3 - ELSEIF(ICASE.LE.12)THEN -* Ensure that a new WD has the initial mass set correctly. - M03 = M3 - IF(ICASE.LT.12.AND.M3.GE.MCH)THEN - M3 = 0.D0 - KW = 15 - ENDIF - ELSEIF(ICASE.EQ.13.OR.ICASE.EQ.14)THEN -* Set unstable Thorne-Zytkow object with fast mass loss of envelope -* unless the less evolved star is a WD, NS or BH. - IF(K2.LT.10)THEN - M03 = M1 - M3 = M1 - ENDIF - IF(ICASE.EQ.13.AND.M3.GT.MXNS) KW = 14 - ELSEIF(ICASE.EQ.15)THEN - M3 = 0.D0 - ELSEIF(ICASE.GT.100)THEN -* Common envelope case which should only be used after COMENV. - KW = K1 - AGE3 = AGE1 - M3 = M1 - M03 = M01 - ELSE -* This should not be reached. - KW = 1 - M03 = M3 - ENDIF -* -* Put the result in *1. -* - KS(1) = KW - KS(2) = 15 - M(1) = M3 - M(2) = 0.D0 - M0(1) = M03 - AJ(1) = AGE3 -* - RETURN - END -*** - - - -cc//rl.f - - -*** - REAL*8 FUNCTION RL(Q) - IMPLICIT NONE - REAL*8 Q,P -* -* A function to evaluate R_L/a(q), Eggleton 1983. -* - P = Q**(1.d0/3.d0) - RL = 0.49d0*P*P/(0.6d0*P*P + LOG(1.d0+P)) -* - RETURN - END -*** - - From 2f8f8c582c00f78c6fe1634c315f507ebf4b5619 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Fri, 1 May 2020 00:27:41 -0400 Subject: [PATCH 46/65] Attempting to get fast active search working --- io.h | 2 +- phigrape.cpp | 155 +++++++++++++++++++++++++++++++-------------------- 2 files changed, 97 insertions(+), 60 deletions(-) diff --git a/io.h b/io.h index 1baa152..770a0f5 100644 --- a/io.h +++ b/io.h @@ -5,7 +5,7 @@ bool is_hdf5(std::string file_name); // This function is implemented independently of the HDF5 library -void ascii_read(const std::string file_name, int *step_num, int *N, double *t, double *m, double3 *x, double3 *v); +void ascii_read(const std::string file_name, int& step_num, int& N, double& t, double **m, double3 **x, double3 **v); void ascii_write(const std::string file_name, const int step_num, const int N, const double t, const double *m, const double3 *x, const double3 *v, int precision=10); diff --git a/phigrape.cpp b/phigrape.cpp index 69f6d93..8d176d8 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -82,7 +82,9 @@ Last redaction : 2019.04.16 12:55 #ifdef ETICS #include "grapite.h" +//#define ACT_DEF_GRAPITE #endif +const bool act_def_grapite = true; Config *config; @@ -248,42 +250,44 @@ public: double get_minimum_time(const double t[], const double dt[]) { double min_t_loc, min_t; -#ifdef ACT_DEF_GRAPITE - min_t_loc = grapite_get_minimum_time(); -#else - min_t_loc = t[myRank*n_loc]+dt[myRank*n_loc]; - for (int j=myRank*n_loc+1; j<(myRank+1)*n_loc; j++) { - double tmp = t[j] + dt[j]; - if (tmp < min_t_loc) min_t_loc = tmp; + if (act_def_grapite) { + min_t_loc = grapite_get_minimum_time(); + printf("gggggggggggg min_t_loc=%.10e\n", min_t_loc); + } else { + min_t_loc = t[myRank*n_loc]+dt[myRank*n_loc]; + for (int j=myRank*n_loc+1; j<(myRank+1)*n_loc; j++) { + double tmp = t[j] + dt[j]; + if (tmp < min_t_loc) min_t_loc = tmp; + } } -#endif /* Reduce the "global" min_t from min_t_loc "local" on all processors) */ MPI_Allreduce(&min_t_loc, &min_t, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD); return min_t; } void get_active_indices(const double min_t, const double t[], const double dt[], int ind_act[], int *n_act) +#warning refrence not pointer { -#ifdef ACT_DEF_GRAPITE - int n_act_loc; - grapite_active_search(min_t, ind_act_loc, &n_act_loc); - if (myRank > 0) - for (int i=0; i 0) + for (int i=0; ilive_smbh_count; + if (n_bh>0) { + if (act_def_grapite) { + int act_def_grapite_bh_count = 0; + int i_bh[n_bh]; + for (int i=0; ilive_smbh_count > 0) { - i_bh1 = 0; - i_bh2 = 1; - } -#endif + printf("now finding i_bh1=%d and i_bh2=%d\n", i_bh1, i_bh2); + if (++printouts >= 10) return 0; + + + +// #if defined(ACT_DEF_GRAPITE) && (defined(ADD_BH1) || defined(ADD_BH2)) + +// #ifdef ADD_BH1 +// #define ACT_DEF_GRAPITE_NUMBH 1 +// #else +// #define ACT_DEF_GRAPITE_NUMBH 2 +// #endif + +// int act_def_grapite_bh_count = 0; +// for (i=0; ilive_smbh_count) break; +// } +// if (i==n_act) { +// fprintf(stderr, "ERROR: black holes were not found in the active particle list"); +// return -1; +// } +// #else +// if (config->live_smbh_count > 0) { +// i_bh1 = 0; +// i_bh2 = 1; +// } +// #endif #ifdef TIMING get_CPU_time(&CPU_tmp_real, &CPU_tmp_user, &CPU_tmp_syst); From 1a438449a8e283549d1ebfb3446f083a4eef155a Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Fri, 1 May 2020 20:41:12 -0400 Subject: [PATCH 47/65] Now fast active search works, and can be controlled from config file --- config.cpp | 1 + config.h | 1 + phigrape.conf | 16 +++++--- phigrape.cpp | 110 +++++++++++++++----------------------------------- 4 files changed, 44 insertions(+), 84 deletions(-) diff --git a/config.cpp b/config.cpp index 6223df7..9a7b9ce 100644 --- a/config.cpp +++ b/config.cpp @@ -233,6 +233,7 @@ Config::Config(std::string file_name) grapite_mask_file_name = get_parameter(dictionary, "grapite_mask_file_name", "grapite.mask"); etics_dump_coeffs = get_parameter(dictionary, "etics_dump_coeffs", false); grapite_active_search = get_parameter(dictionary, "grapite_active_search", false); + grapite_dev_exec_threshold = get_parameter(dictionary, "grapite_dev_exec_threshold", 32); #endif error_checking(); diff --git a/config.h b/config.h index 875d626..9305e34 100644 --- a/config.h +++ b/config.h @@ -57,6 +57,7 @@ public: std::string grapite_mask_file_name; bool etics_dump_coeffs; bool grapite_active_search; + int grapite_dev_exec_threshold; #endif private: diff --git a/phigrape.conf b/phigrape.conf index 3c7411b..13080de 100644 --- a/phigrape.conf +++ b/phigrape.conf @@ -31,7 +31,7 @@ eta = 0.01 # processes on a machine with a single device, set the value to 1 and use the # mpirun utility (or whatever is used in your job scheduler) to launch as many # processes as you like. -devices_per_node = 1 +#devices_per_node = 1 ########## @@ -168,7 +168,7 @@ devices_per_node = 1 # always included. #pn_usage = {1, 1, 1, 1, 0, 0, 0} -# The speed of light in N-body units [default: 500] +# The speed of light in N-body units #pn_c = 477.12 # The spin vectors of the two SMBHs. Only define these if the last component of @@ -188,22 +188,26 @@ devices_per_node = 1 dt_scf = 0.015625 # Name of the mask file for GRAPite [default: grapite.mask] -grapite_mask_file_name = grapite.mask +#grapite_mask_file_name = grapite.mask # Whether to write to disk a list of SCF coefficients at every dt_disk. [default: false] -etics_dump_coeffs = true +#etics_dump_coeffs = true # Whether to use an alternative procedure for active particle search that is # available in the GRAPite library. This requires the number of particles in # each MPI process to be exactly divisible by 32. This can substantially # accelerate the calculation in some circumstances [default: false] -grapite_active_search = true +#grapite_active_search = true +# If the number of active particles in a particular bunch is bigger than this +# threshold, then the execution is on the GPU, otherwise on the CPU. When the +# active bunch is small, the overhead of calculating the SCF gravity on the GPU +# makes the operation more expensive than if it is done on the CPU. [default: 32] +#grapite_dev_exec_threshold = 512 # TODO ######## # etics dump mode -# threshold for execution on device for grapite # scaling parameter override diff --git a/phigrape.cpp b/phigrape.cpp index 8d176d8..548468e 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -82,9 +82,7 @@ Last redaction : 2019.04.16 12:55 #ifdef ETICS #include "grapite.h" -//#define ACT_DEF_GRAPITE #endif -const bool act_def_grapite = true; Config *config; @@ -250,10 +248,12 @@ public: double get_minimum_time(const double t[], const double dt[]) { double min_t_loc, min_t; - if (act_def_grapite) { +#ifdef ETICS + if (config->grapite_active_search) { min_t_loc = grapite_get_minimum_time(); - printf("gggggggggggg min_t_loc=%.10e\n", min_t_loc); - } else { + } else +#endif + { min_t_loc = t[myRank*n_loc]+dt[myRank*n_loc]; for (int j=myRank*n_loc+1; j<(myRank+1)*n_loc; j++) { double tmp = t[j] + dt[j]; @@ -264,10 +264,10 @@ public: MPI_Allreduce(&min_t_loc, &min_t, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD); return min_t; } - void get_active_indices(const double min_t, const double t[], const double dt[], int ind_act[], int *n_act) -#warning refrence not pointer + void get_active_indices(const double min_t, const double t[], const double dt[], int ind_act[], int& n_act) { - if (act_def_grapite) { +#ifdef ETICS + if (config->grapite_active_search) { int n_act_loc; grapite_active_search(min_t, ind_act_loc, &n_act_loc); if (myRank > 0) @@ -275,17 +275,19 @@ public: ind_act_loc[i] += myRank*n_loc; int n_act_arr[256], displs[256]; // Assuming maximum of 256 processes... seems safe. MPI_Allgather(&n_act_loc, 1, MPI_INT, n_act_arr, 1, MPI_INT, MPI_COMM_WORLD); - *n_act = n_act_arr[0]; + n_act = n_act_arr[0]; for (int i=1; igrapite_dev_exec_threshold); +#endif + int n_loc = N/n_proc; Calc_self_grav calc_self_grav(N, n_loc, clusterid, npipe, eps); Active_search active_search(myRank, n_proc, n_loc, N); @@ -674,7 +678,6 @@ int main(int argc, char *argv[]) #endif double min_t = active_search.get_minimum_time(t, dt); - printf("zzzzzzzzzzzzzzzzz %.10e\n", min_t); #ifdef TIMING get_CPU_time(&CPU_tmp_real, &CPU_tmp_user, &CPU_tmp_syst); @@ -685,75 +688,26 @@ int main(int argc, char *argv[]) get_CPU_time(&CPU_tmp_real0, &CPU_tmp_user0, &CPU_tmp_syst0); #endif - active_search.get_active_indices(min_t, t, dt, ind_act, &n_act); + active_search.get_active_indices(min_t, t, dt, ind_act, n_act); -// TODO deal with it below -// #ifdef ACT_DEF_GRAPITE -// #error please fix here -// #endif - - static int printouts = 0; + int i_bh1=0, i_bh2=1; +#ifdef ETICS int n_bh = config->live_smbh_count; - if (n_bh>0) { - if (act_def_grapite) { - int act_def_grapite_bh_count = 0; - int i_bh[n_bh]; - for (int i=0; igrapite_active_search && (n_bh>0)) { + int act_def_grapite_bh_count = 0; + int i_bh[n_bh]; + for (int i=0; i= 10) return 0; +#endif - -// #if defined(ACT_DEF_GRAPITE) && (defined(ADD_BH1) || defined(ADD_BH2)) - -// #ifdef ADD_BH1 -// #define ACT_DEF_GRAPITE_NUMBH 1 -// #else -// #define ACT_DEF_GRAPITE_NUMBH 2 -// #endif - -// int act_def_grapite_bh_count = 0; -// for (i=0; ilive_smbh_count) break; -// } -// if (i==n_act) { -// fprintf(stderr, "ERROR: black holes were not found in the active particle list"); -// return -1; -// } -// #else -// if (config->live_smbh_count > 0) { -// i_bh1 = 0; -// i_bh2 = 1; -// } -// #endif - #ifdef TIMING get_CPU_time(&CPU_tmp_real, &CPU_tmp_user, &CPU_tmp_syst); DT_ACT_DEF2 += (CPU_tmp_user - CPU_tmp_user0); From 329dd2ca4dee9a1d8178ade6242dd7b2d6d9de41 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Sat, 9 May 2020 18:21:01 -0400 Subject: [PATCH 48/65] New timing, moved MPI reduction into function call, started converting some of the pointers into std::vectors --- black_holes.cpp | 18 +-- black_holes.h | 9 +- io.cpp | 4 +- io.h | 2 +- phigrape.cpp | 367 ++++++++++-------------------------------------- 5 files changed, 88 insertions(+), 312 deletions(-) diff --git a/black_holes.cpp b/black_holes.cpp index 0db9a13..4f5ffce 100644 --- a/black_holes.cpp +++ b/black_holes.cpp @@ -99,7 +99,7 @@ void Black_hole_physics::adjust_post_newtonian( jrk2 += jrk2_corr; } -void Black_hole_physics::write_bh_data(double time_cur, double m[], double3 x[], double3 v[], double pot[], double3 a[], double3 adot[], double dt[]) +void Black_hole_physics::write_bh_data(double time_cur, double m[], double3 x[], double3 v[], const std::vector& pot, double3 a[], double3 adot[], double dt[]) { // This function logs data on the black hole(s). It uses both external data // (the arguments to this function) and optionall internal data to this @@ -195,7 +195,7 @@ void Write_bh_nb_data::operator()(double time_cur) fflush(out); } -void Binary_smbh_influence_sphere_output::operator()(int ind_act[], int n_act, double timesteps, double time_cur) +void Binary_smbh_influence_sphere_output::operator()(const std::vector& ind_act, int n_act, double timesteps, double time_cur) { double m_bh1 = m[0]; double m_bh2 = m[1]; @@ -216,13 +216,13 @@ void Binary_smbh_influence_sphere_output::operator()(int ind_act[], int n_act, d for (int i=0; i& pot, double3 a[], double3 adot[], double dt[]); public: //TODO make private double m1, m2; int count; @@ -85,7 +85,7 @@ private: class Binary_smbh_influence_sphere_output { public: - Binary_smbh_influence_sphere_output(double factor, int N, double *m, double3 *x, double3 *v, double *pot, double *dt) + Binary_smbh_influence_sphere_output(double factor, int N, double *m, double3 *x, double3 *v, const std::vector& pot, double *dt) : factor(factor), m(m), x(x), v(v), pot(pot), dt(dt) { inf_event.assign(N, 0); @@ -96,10 +96,11 @@ public: { fclose(out); } - void operator()(int ind_act[], int n_act, double timesteps, double time_cur); + void operator()(const std::vector& ind_act, int n_act, double timesteps, double time_cur); private: double factor; - double *m, *pot, *dt; + const std::vector& pot; + double *m, /**pot,*/ *dt; double3 *x, *v; std::vector inf_event; FILE *out; diff --git a/io.cpp b/io.cpp index 2ca64c8..3a1b086 100644 --- a/io.cpp +++ b/io.cpp @@ -146,7 +146,7 @@ void h5_read(const std::string file_name, int *step_num, int *N, double *t, doub #endif } -void h5_write(const std::string file_name, const int step_num, const int N, const double t, const double *m, const double3 *x, const double3 *v, const double *pot, const double3 *acc, const double3 *jrk, const int extra_mode=0, const bool use_double_precision=true) +void h5_write(const std::string file_name, const int step_num, const int N, const double t, const double *m, const double3 *x, const double3 *v, const std::vector& pot, const double3 *acc, const double3 *jrk, const int extra_mode=0, const bool use_double_precision=true) { #ifdef HAS_HDF5 hid_t file_id, group_id, attribute_id, dataspace_id; @@ -181,7 +181,7 @@ void h5_write(const std::string file_name, const int step_num, const int N, cons bool write_pot = (extra_mode ) & 1; bool write_acc = (extra_mode >> 1) & 1; bool write_jrk = (extra_mode >> 2) & 1; - if (write_pot) write_dataset("POT", 1, (double*)pot); + if (write_pot) write_dataset("POT", 1, (double*)pot.data()); if (write_acc) write_dataset("ACC", 2, (double*)acc); if (write_jrk) write_dataset("JRK", 2, (double*)jrk); diff --git a/io.h b/io.h index 770a0f5..8e8d2ad 100644 --- a/io.h +++ b/io.h @@ -12,5 +12,5 @@ void ascii_write(const std::string file_name, const int step_num, const int N, c void h5_read(const std::string file_name, int *step_num, int *N, double *t, double m[], double3 x[], double3 v[]); // In case the code is compiled without HDF5 support, the implementation of this function just throws an error -void h5_write(const std::string file_name, const int step_num, const int N, const double t, const double *m, const double3 *x, const double3 *v, const double *pot, const double3 *acc, const double3 *jrk, const int write_mode=0, const bool use_double_precision=true); +void h5_write(const std::string file_name, const int step_num, const int N, const double t, const double *m, const double3 *x, const double3 *v, const std::vector& pot, const double3 *acc, const double3 *jrk, const int write_mode=0, const bool use_double_precision=true); // In case the code is compiled without HDF5 support, the implementation of this function just throws an error diff --git a/phigrape.cpp b/phigrape.cpp index 548468e..f8cc761 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -1,60 +1,3 @@ -/***************************************************************************** -File Name : "phi-GRAPE/GPU.c" // BH (1 || 2) + ACC + EJECT - : -Contents : N-body code with integration by individual block time step - : together with the parallel using of GRAPE6a board's. - : - : Added the GPU support via SAPPORO library. - : - : Normalization to the physical units!!! - : - : External Potential added - : Plummer-Kuzmin: Bulge, Disk, Halo - : Kharchenko+Andreas... - : - : SC extra POT for Bek SC test runs... - : - : Rebuced to the Single BH -> Plummer - : Andreas+Fazeel... - : - : Stellar evolution added - : Stellar lifetimes: Raiteri, Villata & Navarro (1996) - : IMS mass loss: van den Hoeg & Groenewegen (1997) - : - : STARDESTR_EXT: Tidal disruption of stars by external BH... - : Chingis, Denis & Maxim... - : - : STARDESTR: Tidal disruption of stars by BH... - : Jose, Li Shuo & Shiyan Zhong - : - : STARDISK: Drag force... - : Chingis, Denis & Maxim... - : - : STARDISK: variable hz = HZ*(R/R_crit) up to R_crit... - : Taras, Andreas... - : - : Live BH (1 || 2) + ACC + EJECT... - : Li Shuo & Shiyan Zhong - : - : dt_min for BH (1 || 2)... - : - : added the PN calculus for the BBH - : PN0, PN1, PN2, PN2.5 (coded on the base of - : Gabor Kupi original routine) - : - : added the "name" array... - : - : added the GMC's calculus (GMC on CPU; GMC2 on GPU) - : for Alexey SC runs... and also for Fazeel Zurich runs... - : - : CPU_TIMELIMIT added for the Julich MW cluster runs... - : -Coded by : Peter Berczik -Version number : 19.04 -Last redaction : 2019.04.16 12:55 -*****************************************************************************/ -#define TIMING - #define ETA_S_CORR 4.0 #define ETA_BH_CORR 4.0 @@ -62,6 +5,7 @@ Last redaction : 2019.04.16 12:55 #define DTMINPOWER -36.0 #include +#include #include #include #include @@ -85,47 +29,24 @@ Last redaction : 2019.04.16 12:55 #endif Config *config; +//chrono::steady_clock::time_point walltime_start; -// These are used in the energy control, could be static but will probably be removed in the end anyway -double CPU_time_real0, CPU_time_user0, CPU_time_syst0; -double CPU_time_real, CPU_time_user, CPU_time_syst; - -#ifdef TIMING -// TODO clean up here -double CPU_tmp_real0, CPU_tmp_user0, CPU_tmp_syst0; -double CPU_tmp_real, CPU_tmp_user, CPU_tmp_syst; - -double DT_TOT, - DT_ACT_DEF1, DT_ACT_DEF2, DT_ACT_DEF3, DT_ACT_PRED, - DT_ACT_GRAV, DT_EXT_GRAV, - DT_GMC_GRAV, DT_GMC_GMC_GRAV, DT_EXT_GMC_GRAV, - DT_ACT_CORR, DT_ACT_LOAD, - DT_STEVOL, DT_STARDISK, DT_STARDESTR; -double DT_ACT_REDUCE; -#endif - -void get_CPU_time(double *time_real, double *time_user, double *time_syst) -{ - struct rusage xxx; - double sec_u, microsec_u, sec_s, microsec_s; - struct timeval tv; - - getrusage(RUSAGE_SELF,&xxx); - - sec_u = xxx.ru_utime.tv_sec; - sec_s = xxx.ru_stime.tv_sec; - - microsec_u = xxx.ru_utime.tv_usec; - microsec_s = xxx.ru_stime.tv_usec; - - *time_user = sec_u + microsec_u * 1.0E-06; - *time_syst = sec_s + microsec_s * 1.0E-06; - - gettimeofday(&tv, NULL); - *time_real = tv.tv_sec + 1.0E-06 * tv.tv_usec; - - *time_user = *time_real; +namespace std::chrono { +struct Timer { + void start() + { + t_start = steady_clock::now(); + } + void stop() + { + t_stop = steady_clock::now(); + time = duration_cast(t_stop - t_start).count()*1E-9; + } + double time; // seconds + steady_clock::time_point t_start, t_stop; +}; } +std::chrono::Timer timer; class Calc_self_grav { public: @@ -133,49 +54,49 @@ public: : g6_calls(0), n_loc(n_loc), clusterid(clusterid), npipe(npipe), eps2(eps*eps) { h2.assign(N, eps2); + pot_loc.resize(N); + acc_loc.resize(N); + jrk_loc.resize(N); } - void operator()(const double t, const int n_act, int ind_act[], const double3 x_act[], const double3 v_act[], - double pot[], double3 acc[], double3 jrk[]) + void operator()(const double t, const int n_act, std::vector& ind_act, const double3 x_act[], const double3 v_act[], + std::vector& pot, double3 acc[], double3 jrk[]) { g6_set_ti(clusterid, t); for (int i=0; i h2; + std::vector pot_loc; // the _loc variables are for this node only. + std::vector acc_loc, jrk_loc; }; void calc_ext_grav(std::vector &external_gravity_components, int n, double3 *x, double3 *v, double *pot, double3 *acc, double3* jrk) // TODO should just be a class that has this pointer array as a member { -#ifdef TIMING - get_CPU_time(&CPU_tmp_real0, &CPU_tmp_user0, &CPU_tmp_syst0); -#endif - std::fill(pot, pot+n, 0.); for (auto component : external_gravity_components) { if (component->is_active) component->apply(n, x, v, pot, acc, jrk); } - -#ifdef TIMING - get_CPU_time(&CPU_tmp_real, &CPU_tmp_user, &CPU_tmp_syst); - DT_EXT_GRAV += (CPU_tmp_user - CPU_tmp_user0); -#endif } -void energy_contr(const double time_cur, const double timesteps, const double n_act_sum, const double g6_calls, int N, double m[], double3 x[], double3 v[], double pot[], double pot_ext[]) +void energy_contr(const double time_cur, const double timesteps, const double n_act_sum, const double g6_calls, int N, double m[], double3 x[], double3 v[], const std::vector& pot, double pot_ext[]) { - double E_pot = 0; + double E_pot = 0; for (int i=0; iinput_file_name)) { @@ -377,18 +298,19 @@ int main(int argc, char *argv[]) else ascii_read(config->input_file_name, diskstep, N, time_cur, &m, &x, &v); - int *ind = new int[N]; - std::iota(ind, ind+N, 0); + std::vector ind(N); + std::iota(begin(ind), end(ind), 0); double3 *a = new double3[N], *adot = new double3[N]; - double *pot = new double[N], *pot_ext = new double[N], *t = new double[N], *dt = new double[N]; + std::vector pot(N); + double *pot_ext = new double[N], *t = new double[N], *dt = new double[N]; /* data for active particles */ - // x_act_new and v_act_new arrays hold the predicted position and velocity of i-particles, which is later corrected before moving into the j-particle memory. The [pot,a,adot]_act_tmp arrays hold the calculation results from each node. The [pot,a,adot]_act_new arrays hold the reduced calculation results from all nodes. - int n_act, *ind_act = new int[N]; - double *pot_act_new = new double[N], *pot_act_tmp = new double[N], *pot_act_ext = new double[N]; - double3 *x_act_new = new double3[N], *v_act_new = new double3[N], - *a_act_tmp = new double3[N], *adot_act_tmp = new double3[N], - *a_act_new = new double3[N], *adot_act_new = new double3[N]; + int n_act; + std::vector ind_act(N); + std::vector pot_act_new(N); + double *pot_act_ext = new double[N]; + double3 *x_act_new = new double3[N], *v_act_new = new double3[N], + *a_act_new = new double3[N], *adot_act_new = new double3[N]; double eps = config->eps; double eta = config->eta; @@ -411,10 +333,6 @@ int main(int argc, char *argv[]) if ((diskstep == 0) && (time_cur == 0)) { FILE *out = fopen("contr.dat", "w"); fclose(out); -#ifdef TIMING - out = fopen("timing.dat", "w"); - fclose(out); -#endif if (config->live_smbh_output && (config->live_smbh_count > 0)) { out = fopen("bh.dat", "w"); fclose(out); @@ -424,9 +342,6 @@ int main(int argc, char *argv[]) fclose(out); } } - - get_CPU_time(&CPU_time_real0, &CPU_time_user0, &CPU_time_syst0); - } /* if (myRank == rootRank) */ double normalization_mass=1, normalization_length=1, normalization_velocity=1; @@ -531,7 +446,6 @@ int main(int argc, char *argv[]) #endif /* load the nj particles to the G6 */ - for (int k=0; k= 0) { + double3 xcm, vcm, xdc, vdc; grapite_calc_center(N, m, (double(*)[3])x, (double(*)[3])v, xcm, vcm, xdc, vdc); x[grapite_cep_index] = xdc; v[grapite_cep_index] = vdc; @@ -553,13 +468,7 @@ int main(int argc, char *argv[]) #endif /* define the all particles as a active on all the processors for the first time grav calc. */ - calc_self_grav(time_cur, N, ind, x, v, pot_act_tmp, a_act_tmp, adot_act_tmp); - - /* Reduce the "global" vectors from "local" on all processors) */ - // TODO why won't we do the MPI_Allreduce inside the calc_self_grav function, and get rid of these _tmp arrays? - MPI_Allreduce(pot_act_tmp, pot, N, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - MPI_Allreduce(a_act_tmp, a, 3*N, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - MPI_Allreduce(adot_act_tmp, adot, 3*N, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + calc_self_grav(time_cur, N, ind, x, v, pot, a, adot); if (config->live_smbh_count == 2) { black_hole_physics.set_xv(x[0], x[1], v[0], v[1]); @@ -580,6 +489,7 @@ int main(int argc, char *argv[]) } if (grapite_cep_index >= 0) { + double3 xcm, vcm, xdc, vdc; grapite_calc_center(N, m, (double(*)[3])x, (double(*)[3])v, xcm, vcm, xdc, vdc); x[grapite_cep_index] = xdc; v[grapite_cep_index] = vdc; @@ -588,7 +498,6 @@ int main(int argc, char *argv[]) #endif /* Define initial timestep for all particles on all nodes */ - for (int j=0; jlive_smbh_output) black_hole_physics.write_bh_data(time_cur, m, x, v, pot, a, adot, dt); @@ -636,60 +543,19 @@ int main(int argc, char *argv[]) } /* if (myRank == rootRank) */ - /* Get the Starting time on rootRank */ - - if (myRank == rootRank) { - get_CPU_time(&CPU_time_real0, &CPU_time_user0, &CPU_time_syst0); - get_CPU_time(&CPU_time_real, &CPU_time_user, &CPU_time_syst); - } /* if (myRank == rootRank) */ - timesteps = 0.0; // Why won't those two be long long instead of double + should include the zeroth step n_act_sum = 0.0; -#ifdef TIMING - DT_TOT = 0.0; - - DT_ACT_DEF1 = 0.0; - DT_ACT_DEF2 = 0.0; - DT_ACT_DEF3 = 0.0; - DT_ACT_PRED = 0.0; - DT_ACT_GRAV = 0.0; - DT_EXT_GRAV = 0.0; - DT_EXT_GMC_GRAV = 0.0; - DT_GMC_GMC_GRAV = 0.0; - DT_ACT_CORR = 0.0; - DT_ACT_LOAD = 0.0; - - DT_STEVOL = 0.0; - DT_STARDISK = 0.0; - DT_STARDESTR = 0.0; - - DT_ACT_REDUCE = 0.0; -#endif - /* The main integration loop */ - while (time_cur <= t_end) { - /* Define the minimal time and the active particles on all the nodes (exclude the ZERO masses!!!) */ - -#ifdef TIMING - get_CPU_time(&CPU_tmp_real0, &CPU_tmp_user0, &CPU_tmp_syst0); -#endif - + /* Define the minimal time and the active particles on all the nodes */ double min_t = active_search.get_minimum_time(t, dt); -#ifdef TIMING - get_CPU_time(&CPU_tmp_real, &CPU_tmp_user, &CPU_tmp_syst); - DT_ACT_DEF1 += (CPU_tmp_user - CPU_tmp_user0); -#endif - -#ifdef TIMING - get_CPU_time(&CPU_tmp_real0, &CPU_tmp_user0, &CPU_tmp_syst0); -#endif - - active_search.get_active_indices(min_t, t, dt, ind_act, n_act); + /* Get indices of all particles that will be active in this bunch */ + active_search.get_active_indices(min_t, t, dt, ind_act.data(), n_act); + /* Find the BH(s) indices in the active list */ int i_bh1=0, i_bh2=1; #ifdef ETICS int n_bh = config->live_smbh_count; @@ -707,18 +573,7 @@ int main(int argc, char *argv[]) } #endif - -#ifdef TIMING - get_CPU_time(&CPU_tmp_real, &CPU_tmp_user, &CPU_tmp_syst); - DT_ACT_DEF2 += (CPU_tmp_user - CPU_tmp_user0); -#endif - /* predict the active particles positions etc... on all the nodes */ - -#ifdef TIMING - get_CPU_time(&CPU_tmp_real0, &CPU_tmp_user0, &CPU_tmp_syst0); -#endif - for (int i=0; ilive_smbh_count == 2) { black_hole_physics.set_xv(x_act_new[i_bh1], x_act_new[i_bh2], v_act_new[i_bh1], v_act_new[i_bh2]); @@ -765,19 +592,12 @@ int main(int argc, char *argv[]) if (config->binary_smbh_pn) black_hole_physics.adjust_post_newtonian(dt[i_bh1], a_act_new[i_bh1], a_act_new[i_bh2], adot_act_new[i_bh1], adot_act_new[i_bh2]); } + /* Calculate gravity on active particles due to external forces */ calc_ext_grav(external_gravity_components, n_act, x_act_new, v_act_new, pot_act_ext, a_act_new, adot_act_new); /* correct the active particles positions etc... on all the nodes */ - -#ifdef TIMING - get_CPU_time(&CPU_tmp_real0, &CPU_tmp_user0, &CPU_tmp_syst0); -#endif - double min_dt = dt_max; for (int i=0; ilive_smbh_count > 0) { if (config->live_smbh_count>=1) dt[0] = min_dt; if (config->live_smbh_count==2) dt[1] = min_dt; - } if (config->binary_smbh_influence_sphere_output && (myRank == rootRank)) { @@ -835,41 +653,22 @@ int main(int argc, char *argv[]) binary_smbh_influence_sphere_output(ind_act, n_act, timesteps, time_cur); } -#ifdef TIMING - get_CPU_time(&CPU_tmp_real, &CPU_tmp_user, &CPU_tmp_syst); - DT_ACT_CORR += (CPU_tmp_user - CPU_tmp_user0); -#endif - /* load the new values for active particles to the local GRAPE's */ - -#ifdef TIMING - get_CPU_time(&CPU_tmp_real0, &CPU_tmp_user0, &CPU_tmp_syst0); -#endif - for (int i=0; i= t_contr) { if (myRank == rootRank) { - energy_contr(time_cur, timesteps, n_act_sum, calc_self_grav.g6_calls, N, m, x, v, pot, pot_ext); - /* write cont data */ if (config->output_hdf5) h5_write("data.con", diskstep, N, time_cur, m, x, v, pot, a, adot, 0, true); else ascii_write("data.con", diskstep, N, time_cur, m, x, v, 16); - - /* possible OUT for timing !!! */ -#ifdef TIMING - FILE *out = fopen("timing.dat", "a"); - - DT_TOT = DT_ACT_DEF1 + DT_ACT_DEF2 + DT_ACT_DEF3 + DT_ACT_PRED + - DT_ACT_GRAV + DT_EXT_GRAV + DT_GMC_GRAV + - DT_GMC_GMC_GRAV + DT_EXT_GMC_GRAV + - DT_ACT_CORR + DT_ACT_LOAD + - DT_STEVOL + DT_STARDISK + DT_STARDESTR + - DT_ACT_REDUCE; - - fprintf(out,"%.8E \t %.6E \t %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f \t %.3f \t %.8E %.8E %.8E \t %.8E %.8E %.8E \n", - time_cur, DT_TOT, - 100.0*DT_ACT_DEF1/DT_TOT, 100.0*DT_ACT_DEF2/DT_TOT, 100.0*DT_ACT_DEF3/DT_TOT, 100.0*DT_ACT_PRED/DT_TOT, - 100.0*DT_ACT_GRAV/DT_TOT, 100.0*DT_EXT_GRAV/DT_TOT, 100.0*DT_GMC_GRAV/DT_TOT, - 100.0*DT_GMC_GMC_GRAV/DT_TOT, 100.0*DT_EXT_GMC_GRAV/DT_TOT, - 100.0*DT_ACT_CORR/DT_TOT, 100.0*DT_ACT_LOAD/DT_TOT, - 100.0*DT_STEVOL/DT_TOT, 100.0*DT_STARDISK/DT_TOT, 100.0*DT_STARDESTR/DT_TOT, - 100.0*DT_ACT_REDUCE/DT_TOT, - CPU_time_real-CPU_time_real0, CPU_time_user-CPU_time_user0, CPU_time_syst-CPU_time_syst0, - timesteps, n_act_sum, 57.0*N*n_act_sum/(CPU_time_user-CPU_time_user0)/1.0E+09); - - fclose(out); -#endif - } /* if (myRank == rootRank) */ #ifdef ETICS - // We are /inside/ a control step, so all particles must be synchronized; we can safely calculate their density centre. The acceleration and jerk currently in the memory are for the predicted position of the CEP, by calling grapite_calc_center we "correct" the position and velocity, but not the gravity at that point. + // We are /inside/ a control step, so all particles must be + // synchronized; we can safely calculate their density centre. The + // acceleration and jerk currently in the memory are for the + // predicted position of the CEP, by calling grapite_calc_center we + // "correct" the position and velocity, but not the gravity at that + // point. if (grapite_cep_index >= 0) { + double3 xcm, vcm, xdc, vdc; grapite_calc_center(N, m, (double(*)[3])x, (double(*)[3])v, xcm, vcm, xdc, vdc); x[grapite_cep_index] = xdc; v[grapite_cep_index] = vdc; @@ -955,24 +732,22 @@ int main(int argc, char *argv[]) } /* while (time_cur < t_end) */ /* close the local GRAPEs */ + timer.stop(); g6_close(clusterid); double g6_calls_sum; MPI_Reduce(&calc_self_grav.g6_calls, &g6_calls_sum, 1, MPI_DOUBLE, MPI_SUM, rootRank, MPI_COMM_WORLD); - if (myRank == rootRank) { - /* Write some output for the timestep annalize... */ - printf("\n"); printf("timesteps = %.0f Total sum of integrated part. = %.0f g6_calls on all nodes = %.0f \n", timesteps, n_act_sum, g6_calls_sum); printf("\n"); - printf("Real Speed = %.3f GFlops \n", 57.0*N*n_act_sum/(CPU_time_user-CPU_time_user0)/1.0E+09); + printf("Real Speed = %.3f GFlops \n", 57.0*N*n_act_sum/(timer.time)/1.0E+09); fflush(stdout); - } /* if (myRank == rootRank) */ - delete[] m; delete[] x; delete[] v; delete[] ind; delete[] a; delete[] adot; delete[] pot; delete[] pot_ext; delete[] t; delete[] dt; delete[] ind_act; delete[] pot_act_new; delete[] pot_act_tmp; delete[] x_act_new; delete[] v_act_new; delete[] a_act_tmp; delete[] adot_act_tmp; delete[] a_act_new; delete[] adot_act_new; delete[] pot_act_ext; + delete config; + delete[] m; delete[] x; delete[] v; delete[] a; delete[] adot; delete[] pot_ext; delete[] t; delete[] dt; delete[] x_act_new; delete[] v_act_new; delete[] a_act_new; delete[] adot_act_new; delete[] pot_act_ext; /* Finalize the MPI work */ MPI_Finalize(); From 747f9f9d8951c3efac0b0c313fa9fdaa5f44f1f1 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Tue, 27 Oct 2020 23:55:55 -0400 Subject: [PATCH 49/65] Moved config to inside main and changed several arrays into vectors --- TODO.md | 6 +- black_holes.cpp | 2 +- black_holes.h | 19 +++--- external.h | 3 +- io.cpp | 20 +++--- io.h | 6 +- phigrape.cpp | 167 ++++++++++++++++++++++++------------------------ 7 files changed, 115 insertions(+), 108 deletions(-) diff --git a/TODO.md b/TODO.md index a81190a..2cceccc 100644 --- a/TODO.md +++ b/TODO.md @@ -1,7 +1,11 @@ TODO ==== -* Get rid of all global variables. +* Make the reamining arrays vectors or smart pointers. + +* Memory bug when reading HDF5? x and v not allocated. + +* Get rid of all global variables. Including config. * Break main() into smaller chunks; operations that are timed should become independent functions. diff --git a/black_holes.cpp b/black_holes.cpp index 4f5ffce..c14b970 100644 --- a/black_holes.cpp +++ b/black_holes.cpp @@ -99,7 +99,7 @@ void Black_hole_physics::adjust_post_newtonian( jrk2 += jrk2_corr; } -void Black_hole_physics::write_bh_data(double time_cur, double m[], double3 x[], double3 v[], const std::vector& pot, double3 a[], double3 adot[], double dt[]) +void Black_hole_physics::write_bh_data(double time_cur, const std::vector &m, const std::vector &x, const std::vector &v, const std::vector &pot, double3 a[], double3 adot[], double dt[]) { // This function logs data on the black hole(s). It uses both external data // (the arguments to this function) and optionall internal data to this diff --git a/black_holes.h b/black_holes.h index 3d15efa..402a628 100644 --- a/black_holes.h +++ b/black_holes.h @@ -46,7 +46,7 @@ public: const double dt_bh, // pn_usage should be const double3& acc1, double3& acc2, double3& jrk1, double3& jrk2); - void write_bh_data(double time_cur, double m[], double3 x[], double3 v[], const std::vector& pot, double3 a[], double3 adot[], double dt[]); + void write_bh_data(double time_cur, const std::vector &m, const std::vector &x, const std::vector &v, const std::vector &pot, double3 a[], double3 adot[], double dt[]); public: //TODO make private double m1, m2; int count; @@ -58,11 +58,9 @@ public: //TODO make private Bbh_gravity bbh_grav; }; -//void write_bh_nb_data(int nb, int smbh_count, double time_cur, int N, double m[], double3 x[], double3 v[]); - class Write_bh_nb_data { public: - Write_bh_nb_data(int nb, int smbh_count, int N, double *m, double3 *x, double3 *v) + Write_bh_nb_data(int nb, int smbh_count, int N, const std::vector &m, const std::vector &x, const std::vector &v) : nb(nb), smbh_count(smbh_count), N(N), m(m), x(x), v(v) { ind_sort.resize(N); @@ -76,8 +74,8 @@ public: void operator()(double time_cur); private: int nb, smbh_count, N; - double *m; - double3 *x, *v; + const std::vector &m; + const std::vector &x, &v; std::vector ind_sort; std::vector var_sort; FILE *out; @@ -85,7 +83,7 @@ private: class Binary_smbh_influence_sphere_output { public: - Binary_smbh_influence_sphere_output(double factor, int N, double *m, double3 *x, double3 *v, const std::vector& pot, double *dt) + Binary_smbh_influence_sphere_output(double factor, int N, const std::vector &m, const std::vector &x, const std::vector &v, const std::vector &pot, double *dt) : factor(factor), m(m), x(x), v(v), pot(pot), dt(dt) { inf_event.assign(N, 0); @@ -99,9 +97,10 @@ public: void operator()(const std::vector& ind_act, int n_act, double timesteps, double time_cur); private: double factor; - const std::vector& pot; - double *m, /**pot,*/ *dt; - double3 *x, *v; + const std::vector &pot; + const std::vector &m; + double /**pot,*/ *dt; + const std::vector &x, &v; std::vector inf_event; FILE *out; }; \ No newline at end of file diff --git a/external.h b/external.h index aedcab5..08d989f 100644 --- a/external.h +++ b/external.h @@ -1,9 +1,10 @@ #pragma once +#include #include "double3.h" class External_gravity { public: - void apply(const int n_act, const double3 x[], const double3 v[], double pot[], double3 a[], double3 adot[]) + void apply(const int n_act, const std::vector &x, const std::vector &v, double pot[], double3 a[], double3 adot[]) { for (int i=0; iset_coordinates(x[i], v[i]); diff --git a/io.cpp b/io.cpp index 3a1b086..6bc8e5f 100644 --- a/io.cpp +++ b/io.cpp @@ -24,7 +24,7 @@ bool is_hdf5(std::string file_name) return result; } -void ascii_read(const std::string file_name, int& step_num, int& N, double& t, double **m, double3 **x, double3 **v) +void ascii_read(const std::string file_name, int &step_num, int &N, double& t, std::vector &m, std::vector &x, std::vector &v) { char rest[512]; int result; @@ -45,19 +45,19 @@ void ascii_read(const std::string file_name, int& step_num, int& N, double& t, d result = sscanf(str.c_str(), "%lf%s", &t, rest); if (result!=1) throw std::runtime_error("Error parsing line 3: expected one real number"); - *m = new double[N]; - *x = new double3[N]; - *v = new double3[N]; + m.resize(N); + x.resize(N); + v.resize(N); int i = -1; while (std::getline(file, str)) { if (++i > N) throw std::runtime_error("Error parsing line " + std::to_string(i+4) + ": particle out of range"); - result = sscanf(str.c_str(), "%*s %lf %lf %lf %lf %lf %lf %lf%s", &(*m)[i], &(*x)[i][0], &(*x)[i][1], &(*x)[i][2], &(*v)[i][0], &(*v)[i][1], &(*v)[i][2], rest); + result = sscanf(str.c_str(), "%*s %lf %lf %lf %lf %lf %lf %lf%s", &m[i], &(x[i].x), &(x[i].y), &(x[i].z), &(v[i].x), &(v[i].y), &(v[i].z), rest); } file.close(); } -void ascii_write(const std::string file_name, const int step_num, const int N, const double t, const double *m, const double3 *x, const double3 *v, int precision=10) +void ascii_write(const std::string file_name, const int step_num, const int N, const double t, const std::vector &m, const std::vector &x, const std::vector &v, int precision=10) { auto file = std::ofstream(file_name); if (!file.is_open()) throw std::runtime_error("Cannot open file for output"); @@ -146,7 +146,7 @@ void h5_read(const std::string file_name, int *step_num, int *N, double *t, doub #endif } -void h5_write(const std::string file_name, const int step_num, const int N, const double t, const double *m, const double3 *x, const double3 *v, const std::vector& pot, const double3 *acc, const double3 *jrk, const int extra_mode=0, const bool use_double_precision=true) +void h5_write(const std::string file_name, const int step_num, const int N, const double t, std::vector &m, std::vector &x, std::vector &v, const std::vector &pot, const double3 *acc, const double3 *jrk, const int extra_mode=0, const bool use_double_precision=true) { #ifdef HAS_HDF5 hid_t file_id, group_id, attribute_id, dataspace_id; @@ -174,9 +174,9 @@ void h5_write(const std::string file_name, const int step_num, const int N, cons H5Sclose(dataspace_id); }; - write_dataset("MASS", 1, (double*)m); - write_dataset("X", 2, (double*)x); - write_dataset("V", 2, (double*)v); + write_dataset("MASS", 1, m.data()); + write_dataset("X", 2, (double*)x.data()); + write_dataset("V", 2, (double*)v.data()); bool write_pot = (extra_mode ) & 1; bool write_acc = (extra_mode >> 1) & 1; diff --git a/io.h b/io.h index 8e8d2ad..874ca27 100644 --- a/io.h +++ b/io.h @@ -5,12 +5,12 @@ bool is_hdf5(std::string file_name); // This function is implemented independently of the HDF5 library -void ascii_read(const std::string file_name, int& step_num, int& N, double& t, double **m, double3 **x, double3 **v); +void ascii_read(const std::string file_name, int &step_num, int &N, double &t, std::vector &m, std::vector &x, std::vector &v); -void ascii_write(const std::string file_name, const int step_num, const int N, const double t, const double *m, const double3 *x, const double3 *v, int precision=10); +void ascii_write(const std::string file_name, const int step_num, const int N, const double t, const std::vector &m, const std::vector &x, const std::vector &v, int precision=10); void h5_read(const std::string file_name, int *step_num, int *N, double *t, double m[], double3 x[], double3 v[]); // In case the code is compiled without HDF5 support, the implementation of this function just throws an error -void h5_write(const std::string file_name, const int step_num, const int N, const double t, const double *m, const double3 *x, const double3 *v, const std::vector& pot, const double3 *acc, const double3 *jrk, const int write_mode=0, const bool use_double_precision=true); +void h5_write(const std::string file_name, const int step_num, const int N, const double t, std::vector &m, std::vector &x, std::vector &v, const std::vector &pot, const double3 *acc, const double3 *jrk, const int extra_mode=0, const bool use_double_precision=true); // In case the code is compiled without HDF5 support, the implementation of this function just throws an error diff --git a/phigrape.cpp b/phigrape.cpp index f8cc761..0d5b4dd 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -28,7 +28,6 @@ #include "grapite.h" #endif -Config *config; //chrono::steady_clock::time_point walltime_start; namespace std::chrono { @@ -58,7 +57,7 @@ public: acc_loc.resize(N); jrk_loc.resize(N); } - void operator()(const double t, const int n_act, std::vector& ind_act, const double3 x_act[], const double3 v_act[], + void operator()(const double t, const int n_act, std::vector &ind_act, std::vector &x_act, std::vector &v_act, std::vector& pot, double3 acc[], double3 jrk[]) { g6_set_ti(clusterid, t); @@ -84,7 +83,7 @@ private: std::vector acc_loc, jrk_loc; }; -void calc_ext_grav(std::vector &external_gravity_components, int n, double3 *x, double3 *v, double *pot, double3 *acc, double3* jrk) +void calc_ext_grav(std::vector &external_gravity_components, int n, const std::vector &x, const std::vector &v, double *pot, double3 *acc, double3* jrk) // TODO should just be a class that has this pointer array as a member { std::fill(pot, pot+n, 0.); @@ -94,7 +93,7 @@ void calc_ext_grav(std::vector &external_gravity_components, } } -void energy_contr(const double time_cur, const double timesteps, const double n_act_sum, const double g6_calls, int N, double m[], double3 x[], double3 v[], const std::vector& pot, double pot_ext[]) +void energy_contr(const double time_cur, const double timesteps, const double n_act_sum, const double g6_calls, int N, const std::vector &m, const std::vector &x, const std::vector &v, const std::vector &pot, double pot_ext[]) { double E_pot = 0; for (int i=0; igrapite_active_search) { + if (grapite_active_search_flag) { min_t_loc = grapite_get_minimum_time(); } else #endif @@ -188,7 +187,7 @@ public: void get_active_indices(const double min_t, const double t[], const double dt[], int ind_act[], int& n_act) { #ifdef ETICS - if (config->grapite_active_search) { + if (grapite_active_search_flag) { int n_act_loc; grapite_active_search(min_t, ind_act_loc, &n_act_loc); if (myRank > 0) @@ -215,6 +214,7 @@ public: private: int myRank, n_proc, n_loc, N; int *ind_act_loc; + bool grapite_active_search_flag; }; inline void calc_high_derivatives(const double dt_tmp, const double3 a_old, const double3 a_new, const double3 a1_old, const double3 a1_new, double3& a2, double3& a3) @@ -254,6 +254,9 @@ inline double aarseth_step(const double eta, const double dt, const double3 a, c int main(int argc, char *argv[]) { + /* read the input parameters */ + const Config config("phigrape.conf"); + timer.start(); double timesteps=0.0, n_act_sum=0.0; @@ -280,23 +283,21 @@ int main(int argc, char *argv[]) /* Print the Rank and the names of processors */ printf("Rank of the processor %03d on %s \n", myRank, processor_name); - /* read the input parameters */ - config = new Config("phigrape.conf"); - int diskstep, N; double time_cur; // The memory for m, x, and v is allocated inside h5_read or ascii_read - double *m; - double3 *x, *v; - if (is_hdf5(config->input_file_name)) { + //double *m; + std::vector m; + std::vector x, v; + if (is_hdf5(config.input_file_name)) { #ifndef HAS_HDF5 fprintf(stderr, "ERROR: input file is in HDF5 format, but the code was compiled without HDF5 support\n"); return -1; #endif - h5_read(config->input_file_name, &diskstep, &N, &time_cur, m, x, v); + h5_read(config.input_file_name, &diskstep, &N, &time_cur, m.data(), x.data(), v.data()); } else - ascii_read(config->input_file_name, diskstep, N, time_cur, &m, &x, &v); + ascii_read(config.input_file_name, diskstep, N, time_cur, m, x, v); std::vector ind(N); std::iota(begin(ind), end(ind), 0); @@ -308,16 +309,16 @@ int main(int argc, char *argv[]) int n_act; std::vector ind_act(N); std::vector pot_act_new(N); + std::vector x_act_new(N), v_act_new(N); double *pot_act_ext = new double[N]; - double3 *x_act_new = new double3[N], *v_act_new = new double3[N], - *a_act_new = new double3[N], *adot_act_new = new double3[N]; + double3 *a_act_new = new double3[N], *adot_act_new = new double3[N]; - double eps = config->eps; - double eta = config->eta; - double t_end = config->t_end; - double dt_disk = config->dt_disk; - double dt_contr = config->dt_contr; - double dt_bh = config->dt_bh; + double eps = config.eps; + double eta = config.eta; + double t_end = config.t_end; + double dt_disk = config.dt_disk; + double dt_contr = config.dt_contr; + double dt_bh = config.dt_bh; if (myRank == rootRank) { printf("\n"); @@ -333,11 +334,11 @@ int main(int argc, char *argv[]) if ((diskstep == 0) && (time_cur == 0)) { FILE *out = fopen("contr.dat", "w"); fclose(out); - if (config->live_smbh_output && (config->live_smbh_count > 0)) { + if (config.live_smbh_output && (config.live_smbh_count > 0)) { out = fopen("bh.dat", "w"); fclose(out); } - if ((config->live_smbh_neighbor_output) && (config->live_smbh_count > 0)) { + if ((config.live_smbh_neighbor_output) && (config.live_smbh_count > 0)) { out = fopen("bh_neighbors.dat", "w"); fclose(out); } @@ -345,16 +346,16 @@ int main(int argc, char *argv[]) } /* if (myRank == rootRank) */ double normalization_mass=1, normalization_length=1, normalization_velocity=1; - if (config->ext_units_physical) { - normalization_mass = 1/config->unit_mass; - normalization_length = 1000/config->unit_length; - normalization_velocity = 1.52484071426404437233e+01*sqrt(config->unit_length/config->unit_mass); + if (config.ext_units_physical) { + normalization_mass = 1/config.unit_mass; + normalization_length = 1000/config.unit_length; + normalization_velocity = 1.52484071426404437233e+01*sqrt(config.unit_length/config.unit_mass); } - Plummer ext_bulge(config->ext_m_bulge*normalization_mass, config->ext_b_bulge*normalization_length); - Miyamoto_Nagai ext_disk(config->ext_m_disk*normalization_mass, config->ext_a_disk*normalization_length, config->ext_b_disk*normalization_length); - Plummer ext_halo_plummer(config->ext_m_halo_plummer*normalization_mass, config->ext_b_halo_plummer*normalization_length); - Logarithmic_halo ext_log_halo(config->ext_log_halo_v*normalization_velocity, config->ext_log_halo_r*normalization_length); - Dehnen ext_dehnen(config->ext_dehnen_m*normalization_mass, config->ext_dehnen_r*normalization_length, config->ext_dehnen_gamma); + Plummer ext_bulge(config.ext_m_bulge*normalization_mass, config.ext_b_bulge*normalization_length); + Miyamoto_Nagai ext_disk(config.ext_m_disk*normalization_mass, config.ext_a_disk*normalization_length, config.ext_b_disk*normalization_length); + Plummer ext_halo_plummer(config.ext_m_halo_plummer*normalization_mass, config.ext_b_halo_plummer*normalization_length); + Logarithmic_halo ext_log_halo(config.ext_log_halo_v*normalization_velocity, config.ext_log_halo_r*normalization_length); + Dehnen ext_dehnen(config.ext_dehnen_m*normalization_mass, config.ext_dehnen_r*normalization_length, config.ext_dehnen_gamma); std::vector external_gravity_components; external_gravity_components.push_back(&ext_bulge); @@ -371,11 +372,11 @@ int main(int argc, char *argv[]) } if (has_external_gravity) printf("External Potential: \n\n"); - if (ext_bulge.is_active) printf("m_bulge = %.4E b_bulge = %.4E\n", config->ext_m_bulge*normalization_mass, config->ext_b_bulge*normalization_length); - if (ext_disk.is_active) printf("m_disk = %.4E a_disk = %.4E b_disk = %.4E\n", config->ext_m_disk*normalization_mass, config->ext_a_disk*normalization_length, config->ext_b_disk*normalization_length); - if (ext_halo_plummer.is_active) printf("m_halo = %.4E b_halo = %.4E\n", config->ext_m_halo_plummer*normalization_mass, config->ext_b_halo_plummer*normalization_length); - if (ext_log_halo.is_active) printf("v_halo = %.6E r_halo = %.6E \n", config->ext_log_halo_v*normalization_velocity, config->ext_log_halo_r*normalization_length); - if (ext_dehnen.is_active) printf("m_ext = %.6E r_ext = %.6E \t g_ext = %.3E \n", config->ext_dehnen_m*normalization_mass, config->ext_dehnen_r*normalization_length, config->ext_dehnen_gamma); + if (ext_bulge.is_active) printf("m_bulge = %.4E b_bulge = %.4E\n", config.ext_m_bulge*normalization_mass, config.ext_b_bulge*normalization_length); + if (ext_disk.is_active) printf("m_disk = %.4E a_disk = %.4E b_disk = %.4E\n", config.ext_m_disk*normalization_mass, config.ext_a_disk*normalization_length, config.ext_b_disk*normalization_length); + if (ext_halo_plummer.is_active) printf("m_halo = %.4E b_halo = %.4E\n", config.ext_m_halo_plummer*normalization_mass, config.ext_b_halo_plummer*normalization_length); + if (ext_log_halo.is_active) printf("v_halo = %.6E r_halo = %.6E \n", config.ext_log_halo_v*normalization_velocity, config.ext_log_halo_r*normalization_length); + if (ext_dehnen.is_active) printf("m_ext = %.6E r_ext = %.6E \t g_ext = %.3E \n", config.ext_dehnen_m*normalization_mass, config.ext_dehnen_r*normalization_length, config.ext_dehnen_gamma); printf("\n"); fflush(stdout); @@ -399,13 +400,13 @@ int main(int argc, char *argv[]) /* some local settings for G6a boards */ int clusterid, numGPU; - if (config->devices_per_node==0) { + if (config.devices_per_node==0) { MPI_Comm shmcomm; MPI_Comm_split_type(MPI_COMM_WORLD, MPI_COMM_TYPE_SHARED, 0, MPI_INFO_NULL, &shmcomm); MPI_Comm_size(shmcomm, &numGPU); MPI_Comm_rank(shmcomm, &clusterid); } else { - numGPU = config->devices_per_node; + numGPU = config.devices_per_node; clusterid = myRank % numGPU; } printf("Rank of the processor %03d : Number of GPUs %01d : Cluster ID %01d \n", myRank, numGPU, clusterid); @@ -418,30 +419,33 @@ int main(int argc, char *argv[]) g6_set_xunit(51); #ifdef ETICS - grapite_set_dev_exec_threshold(config->grapite_dev_exec_threshold); + grapite_set_dev_exec_threshold(config.grapite_dev_exec_threshold); + bool grapite_active_search_flag = config.grapite_active_search; +#else + bool grapite_active_search_flag = false; #endif int n_loc = N/n_proc; Calc_self_grav calc_self_grav(N, n_loc, clusterid, npipe, eps); - Active_search active_search(myRank, n_proc, n_loc, N); + Active_search active_search(myRank, n_proc, n_loc, N, grapite_active_search_flag); Black_hole_physics black_hole_physics; - if (config->live_smbh_count == 1) + if (config.live_smbh_count == 1) black_hole_physics = Black_hole_physics(m[0], 0, myRank, rootRank); - else if (config->live_smbh_count == 2) + else if (config.live_smbh_count == 2) black_hole_physics = Black_hole_physics(m[0], m[1], myRank, rootRank); - if (config->binary_smbh_pn) { - black_hole_physics.set_post_newtonian(config->pn_c, config->pn_usage.data()); - if (config->pn_usage[6]) black_hole_physics.set_spins(config->smbh1_spin.data(), config->smbh2_spin.data()); + if (config.binary_smbh_pn) { + black_hole_physics.set_post_newtonian(config.pn_c, config.pn_usage.data()); + if (config.pn_usage[6]) black_hole_physics.set_spins(config.smbh1_spin.data(), config.smbh2_spin.data()); } - black_hole_physics.set_softening(eps, config->live_smbh_custom_eps); + black_hole_physics.set_softening(eps, config.live_smbh_custom_eps); - Binary_smbh_influence_sphere_output binary_smbh_influence_sphere_output(config->binary_smbh_influence_radius_factor, N, m, x, v, pot, dt); + Binary_smbh_influence_sphere_output binary_smbh_influence_sphere_output(config.binary_smbh_influence_radius_factor, N, m, x, v, pot, dt); - Write_bh_nb_data write_bh_nb_data(config->live_smbh_neighbor_number, config->live_smbh_count, N, m, x, v); + Write_bh_nb_data write_bh_nb_data(config.live_smbh_neighbor_number, config.live_smbh_count, N, m, x, v); #ifdef ETICS - grapite_read_particle_tags(N, config->grapite_mask_file_name.c_str(), myRank, n_loc); - grapite_set_dt_exp(config->dt_scf); + grapite_read_particle_tags(N, config.grapite_mask_file_name.c_str(), myRank, n_loc); + grapite_set_dt_exp(config.dt_scf); grapite_set_t_exp(time_cur); #endif @@ -470,10 +474,10 @@ int main(int argc, char *argv[]) /* define the all particles as a active on all the processors for the first time grav calc. */ calc_self_grav(time_cur, N, ind, x, v, pot, a, adot); - if (config->live_smbh_count == 2) { + if (config.live_smbh_count == 2) { black_hole_physics.set_xv(x[0], x[1], v[0], v[1]); - if (config->live_smbh_custom_eps >= 0) black_hole_physics.adjust_softening(pot[0], pot[1], a[0], a[1], adot[0], adot[1]); - if (config->binary_smbh_pn) black_hole_physics.adjust_post_newtonian(dt[0], a[0], a[1], adot[0], adot[1]); + if (config.live_smbh_custom_eps >= 0) black_hole_physics.adjust_softening(pot[0], pot[1], a[0], a[1], adot[0], adot[1]); + if (config.binary_smbh_pn) black_hole_physics.adjust_post_newtonian(dt[0], a[0], a[1], adot[0], adot[1]); } calc_ext_grav(external_gravity_components, N, x, v, pot_ext, a, adot); @@ -482,7 +486,7 @@ int main(int argc, char *argv[]) if (myRank == rootRank) energy_contr(time_cur, timesteps, n_act_sum, calc_self_grav.g6_calls, N, m, x, v, pot, pot_ext); #ifdef ETICS - if (config->etics_dump_coeffs && (diskstep==0)) { + if (config.etics_dump_coeffs && (diskstep==0)) { char out_fname[256]; sprintf(out_fname, "coeffs.%06d.%02d.dat", 0, myRank); grapite_dump(out_fname, 2); @@ -515,7 +519,7 @@ int main(int argc, char *argv[]) dt[j] = dt_tmp; - if (config->dt_min_warning && (myRank == 0)) { + if (config.dt_min_warning && (myRank == 0)) { if (dt[j] == dt_min) { printf("!!! Warning0: dt = dt_min = %.6E \t ind = %07d \n", dt[j], ind[j]); fflush(stdout); @@ -523,9 +527,9 @@ int main(int argc, char *argv[]) } } /* j */ - if (config->live_smbh_count > 0) { + if (config.live_smbh_count > 0) { double min_dt = *std::min_element(dt, dt+N); - for (int i=0; ilive_smbh_count; i++) dt[i] = min_dt; + for (int i=0; ilive_smbh_output) black_hole_physics.write_bh_data(time_cur, m, x, v, pot, a, adot, dt); + if (config.live_smbh_output) black_hole_physics.write_bh_data(time_cur, m, x, v, pot, a, adot, dt); /* Write BH NB data... */ - if (config->live_smbh_neighbor_output) write_bh_nb_data(time_cur); + if (config.live_smbh_neighbor_output) write_bh_nb_data(time_cur); } /* if (myRank == rootRank) */ @@ -558,8 +562,8 @@ int main(int argc, char *argv[]) /* Find the BH(s) indices in the active list */ int i_bh1=0, i_bh2=1; #ifdef ETICS - int n_bh = config->live_smbh_count; - if (config->grapite_active_search && (n_bh>0)) { + int n_bh = config.live_smbh_count; + if (config.grapite_active_search && (n_bh>0)) { int act_def_grapite_bh_count = 0; int i_bh[n_bh]; for (int i=0; ilive_smbh_count == 2) { + if (config.live_smbh_count == 2) { black_hole_physics.set_xv(x_act_new[i_bh1], x_act_new[i_bh2], v_act_new[i_bh1], v_act_new[i_bh2]); - if (config->live_smbh_custom_eps >= 0) black_hole_physics.adjust_softening(pot_act_new[i_bh1], pot_act_new[i_bh2], a_act_new[i_bh1], a_act_new[i_bh2], adot_act_new[i_bh1], adot_act_new[i_bh2]); - if (config->binary_smbh_pn) black_hole_physics.adjust_post_newtonian(dt[i_bh1], a_act_new[i_bh1], a_act_new[i_bh2], adot_act_new[i_bh1], adot_act_new[i_bh2]); + if (config.live_smbh_custom_eps >= 0) black_hole_physics.adjust_softening(pot_act_new[i_bh1], pot_act_new[i_bh2], a_act_new[i_bh1], a_act_new[i_bh2], adot_act_new[i_bh1], adot_act_new[i_bh2]); + if (config.binary_smbh_pn) black_hole_physics.adjust_post_newtonian(dt[i_bh1], a_act_new[i_bh1], a_act_new[i_bh2], adot_act_new[i_bh1], adot_act_new[i_bh2]); } /* Calculate gravity on active particles due to external forces */ @@ -608,7 +612,7 @@ int main(int argc, char *argv[]) //TODO make beautiful double eta_curr; - if ((config->live_smbh_count > 0) && (ind_act[i] < config->live_smbh_count)) eta_curr = eta_bh; + if ((config.live_smbh_count > 0) && (ind_act[i] < config.live_smbh_count)) eta_curr = eta_bh; else eta_curr = eta; double dt_new = aarseth_step(eta_curr, dt_tmp, a_act_new[i], adot_act_new[i], a2, a3); @@ -624,7 +628,7 @@ int main(int argc, char *argv[]) dt_tmp *= 2; } - if (config->dt_min_warning && (myRank == 0)) { + if (config.dt_min_warning && (myRank == 0)) { if (dt_tmp == dt_min) { printf("!!! Warning1: dt_act = dt_min = %.6E \t ind_act = %07d \n", dt_tmp, ind_act[i]); fflush(stdout); @@ -643,12 +647,12 @@ int main(int argc, char *argv[]) } /* i */ /* define the min. dt over all the act. part. and set it also for the BH... */ - if (config->live_smbh_count > 0) { - if (config->live_smbh_count>=1) dt[0] = min_dt; - if (config->live_smbh_count==2) dt[1] = min_dt; + if (config.live_smbh_count > 0) { + if (config.live_smbh_count>=1) dt[0] = min_dt; + if (config.live_smbh_count==2) dt[1] = min_dt; } - if (config->binary_smbh_influence_sphere_output && (myRank == rootRank)) { + if (config.binary_smbh_influence_sphere_output && (myRank == rootRank)) { //TODO clean up this mass. We don't want to have all these _act arrays; they are only needed for this lame function. binary_smbh_influence_sphere_output(ind_act, n_act, timesteps, time_cur); } @@ -675,10 +679,10 @@ int main(int argc, char *argv[]) if (time_cur >= t_bh) { if (myRank == rootRank) { /* Write BH data... */ - if (config->live_smbh_output) black_hole_physics.write_bh_data(time_cur, m, x, v, pot, a, adot, dt); + if (config.live_smbh_output) black_hole_physics.write_bh_data(time_cur, m, x, v, pot, a, adot, dt); /* Write BH NB data... */ - if (config->live_smbh_neighbor_output) write_bh_nb_data(time_cur); + if (config.live_smbh_neighbor_output) write_bh_nb_data(time_cur); } /* if (myRank == rootRank) */ @@ -689,7 +693,7 @@ int main(int argc, char *argv[]) if (myRank == rootRank) { energy_contr(time_cur, timesteps, n_act_sum, calc_self_grav.g6_calls, N, m, x, v, pot, pot_ext); /* write cont data */ - if (config->output_hdf5) h5_write("data.con", diskstep, N, time_cur, m, x, v, pot, a, adot, 0, true); + if (config.output_hdf5) h5_write("data.con", diskstep, N, time_cur, m, x, v, pot, a, adot, 0, true); else ascii_write("data.con", diskstep, N, time_cur, m, x, v, 16); } /* if (myRank == rootRank) */ @@ -717,12 +721,12 @@ int main(int argc, char *argv[]) diskstep++; if (myRank == rootRank) { sprintf(out_fname, "%06d", diskstep); - if (config->output_hdf5) h5_write(std::string(out_fname) + ".h5", diskstep, N, time_cur, m, x, v, pot, a, adot, config->output_extra_mode, config->output_hdf5_double_precision); - else ascii_write(std::string(out_fname) + ".dat", diskstep, N, time_cur, m, x, v, config->output_ascii_precision); + if (config.output_hdf5) h5_write(std::string(out_fname) + ".h5", diskstep, N, time_cur, m, x, v, pot, a, adot, config.output_extra_mode, config.output_hdf5_double_precision); + else ascii_write(std::string(out_fname) + ".dat", diskstep, N, time_cur, m, x, v, config.output_ascii_precision); } /* if (myRank == rootRank) */ #ifdef ETICS - if (config->etics_dump_coeffs) { + if (config.etics_dump_coeffs) { sprintf(out_fname, "coeffs.%06d.%02d.dat", diskstep, myRank); grapite_dump(out_fname, 2); } @@ -746,8 +750,7 @@ int main(int argc, char *argv[]) fflush(stdout); } /* if (myRank == rootRank) */ - delete config; - delete[] m; delete[] x; delete[] v; delete[] a; delete[] adot; delete[] pot_ext; delete[] t; delete[] dt; delete[] x_act_new; delete[] v_act_new; delete[] a_act_new; delete[] adot_act_new; delete[] pot_act_ext; + delete[] a; delete[] adot; delete[] pot_ext; delete[] t; delete[] dt; delete[] a_act_new; delete[] adot_act_new; delete[] pot_act_ext; /* Finalize the MPI work */ MPI_Finalize(); From aef0f26878fd48d1f41e60e245f479e5457290c3 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Wed, 28 Oct 2020 16:31:45 -0400 Subject: [PATCH 50/65] Improved external gravity calls style --- TODO.md | 12 ---------- phigrape.cpp | 63 +++++++++++++++++++++++++++++----------------------- 2 files changed, 35 insertions(+), 40 deletions(-) diff --git a/TODO.md b/TODO.md index 2cceccc..bf3f426 100644 --- a/TODO.md +++ b/TODO.md @@ -5,16 +5,4 @@ TODO * Memory bug when reading HDF5? x and v not allocated. -* Get rid of all global variables. Including config. - * Break main() into smaller chunks; operations that are timed should become independent functions. - -* Dynamically allocate the big arrays. - -* Create a key-value config file reader to replace the external parameter files. - -* Remove all ifdef blocks, options should be selected in the config file. - -* Optional HDF5 output. - -* In the config file let choose number of digits for ASCII output and 32 or 64-bit floats for HDF5. diff --git a/phigrape.cpp b/phigrape.cpp index 0d5b4dd..e889174 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -83,15 +83,28 @@ private: std::vector acc_loc, jrk_loc; }; -void calc_ext_grav(std::vector &external_gravity_components, int n, const std::vector &x, const std::vector &v, double *pot, double3 *acc, double3* jrk) -// TODO should just be a class that has this pointer array as a member -{ - std::fill(pot, pot+n, 0.); - for (auto component : external_gravity_components) { - if (component->is_active) - component->apply(n, x, v, pot, acc, jrk); +class Calc_ext_grav { +public: + void add_component(External_gravity &component) + { + components.push_back(&component); } -} + bool any_active() + { + for (auto component : components) + if (component->is_active) return true; + return false; + } + void operator()(int n, const std::vector &x, const std::vector &v, double *pot, double3 *acc, double3* jrk) + { + for (auto component : components) { + if (component->is_active) + component->apply(n, x, v, pot, acc, jrk); + } + } +private: + std::vector components; +}; void energy_contr(const double time_cur, const double timesteps, const double n_act_sum, const double g6_calls, int N, const std::vector &m, const std::vector &x, const std::vector &v, const std::vector &pot, double pot_ext[]) { @@ -351,25 +364,18 @@ int main(int argc, char *argv[]) normalization_length = 1000/config.unit_length; normalization_velocity = 1.52484071426404437233e+01*sqrt(config.unit_length/config.unit_mass); } + Calc_ext_grav calc_ext_grav; Plummer ext_bulge(config.ext_m_bulge*normalization_mass, config.ext_b_bulge*normalization_length); + calc_ext_grav.add_component(ext_bulge); Miyamoto_Nagai ext_disk(config.ext_m_disk*normalization_mass, config.ext_a_disk*normalization_length, config.ext_b_disk*normalization_length); + calc_ext_grav.add_component(ext_disk); Plummer ext_halo_plummer(config.ext_m_halo_plummer*normalization_mass, config.ext_b_halo_plummer*normalization_length); + calc_ext_grav.add_component(ext_halo_plummer); Logarithmic_halo ext_log_halo(config.ext_log_halo_v*normalization_velocity, config.ext_log_halo_r*normalization_length); + calc_ext_grav.add_component(ext_log_halo); Dehnen ext_dehnen(config.ext_dehnen_m*normalization_mass, config.ext_dehnen_r*normalization_length, config.ext_dehnen_gamma); - - std::vector external_gravity_components; - external_gravity_components.push_back(&ext_bulge); - external_gravity_components.push_back(&ext_disk); - external_gravity_components.push_back(&ext_halo_plummer); - external_gravity_components.push_back(&ext_log_halo); - external_gravity_components.push_back(&ext_dehnen); - bool has_external_gravity = false; - for (auto component : external_gravity_components) { - if (component->is_active) { - has_external_gravity = true; - break; - } - } + calc_ext_grav.add_component(ext_dehnen); + bool has_external_gravity = calc_ext_grav.any_active(); if (has_external_gravity) printf("External Potential: \n\n"); if (ext_bulge.is_active) printf("m_bulge = %.4E b_bulge = %.4E\n", config.ext_m_bulge*normalization_mass, config.ext_b_bulge*normalization_length); @@ -418,11 +424,10 @@ int main(int argc, char *argv[]) g6_set_tunit(51); g6_set_xunit(51); + bool grapite_active_search_flag = false; #ifdef ETICS grapite_set_dev_exec_threshold(config.grapite_dev_exec_threshold); - bool grapite_active_search_flag = config.grapite_active_search; -#else - bool grapite_active_search_flag = false; + grapite_active_search_flag = config.grapite_active_search; #endif int n_loc = N/n_proc; @@ -480,7 +485,8 @@ int main(int argc, char *argv[]) if (config.binary_smbh_pn) black_hole_physics.adjust_post_newtonian(dt[0], a[0], a[1], adot[0], adot[1]); } - calc_ext_grav(external_gravity_components, N, x, v, pot_ext, a, adot); + std::fill(pot_ext, pot_ext+N, 0.); + calc_ext_grav(N, x, v, pot_ext, a, adot); /* Energy control... */ if (myRank == rootRank) energy_contr(time_cur, timesteps, n_act_sum, calc_self_grav.g6_calls, N, m, x, v, pot, pot_ext); @@ -597,7 +603,8 @@ int main(int argc, char *argv[]) } /* Calculate gravity on active particles due to external forces */ - calc_ext_grav(external_gravity_components, n_act, x_act_new, v_act_new, pot_act_ext, a_act_new, adot_act_new); + std::fill(pot_act_ext, pot_act_ext+n_act, 0.); + calc_ext_grav(n_act, x_act_new, v_act_new, pot_act_ext, a_act_new, adot_act_new); /* correct the active particles positions etc... on all the nodes */ double min_dt = dt_max; @@ -706,7 +713,7 @@ int main(int argc, char *argv[]) // point. if (grapite_cep_index >= 0) { double3 xcm, vcm, xdc, vdc; - grapite_calc_center(N, m, (double(*)[3])x, (double(*)[3])v, xcm, vcm, xdc, vdc); + grapite_calc_center(N, m.data(), (double(*)[3])x.data(), (double(*)[3])v.data(), xcm, vcm, xdc, vdc); x[grapite_cep_index] = xdc; v[grapite_cep_index] = vdc; grapite_update_cep(time_cur, xdc, vdc, a[grapite_cep_index], adot[grapite_cep_index]); From d9ed8e5131b1048edffbfd666e31c87b8c335a18 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Wed, 28 Oct 2020 19:18:37 -0400 Subject: [PATCH 51/65] Got rid of remaining manual allocations, moved some variable declarations to where they are needed --- TODO.md | 6 ++- black_holes.cpp | 2 +- black_holes.h | 8 ++- external.cpp | 1 - external.h | 2 +- io.cpp | 8 +-- io.h | 2 +- phigrape.cpp | 128 ++++++++++++++++++++---------------------------- 8 files changed, 67 insertions(+), 90 deletions(-) diff --git a/TODO.md b/TODO.md index bf3f426..2c926f8 100644 --- a/TODO.md +++ b/TODO.md @@ -1,8 +1,10 @@ TODO ==== -* Make the reamining arrays vectors or smart pointers. - * Memory bug when reading HDF5? x and v not allocated. * Break main() into smaller chunks; operations that are timed should become independent functions. + +* Const everything + +* Remove unneeded includes \ No newline at end of file diff --git a/black_holes.cpp b/black_holes.cpp index c14b970..7790a3b 100644 --- a/black_holes.cpp +++ b/black_holes.cpp @@ -99,7 +99,7 @@ void Black_hole_physics::adjust_post_newtonian( jrk2 += jrk2_corr; } -void Black_hole_physics::write_bh_data(double time_cur, const std::vector &m, const std::vector &x, const std::vector &v, const std::vector &pot, double3 a[], double3 adot[], double dt[]) +void Black_hole_physics::write_bh_data(double time_cur, const std::vector &m, const std::vector &x, const std::vector &v, const std::vector &pot, const std::vector &a, const std::vector &adot, const std::vector &dt) { // This function logs data on the black hole(s). It uses both external data // (the arguments to this function) and optionall internal data to this diff --git a/black_holes.h b/black_holes.h index 402a628..121ae7a 100644 --- a/black_holes.h +++ b/black_holes.h @@ -46,7 +46,7 @@ public: const double dt_bh, // pn_usage should be const double3& acc1, double3& acc2, double3& jrk1, double3& jrk2); - void write_bh_data(double time_cur, const std::vector &m, const std::vector &x, const std::vector &v, const std::vector &pot, double3 a[], double3 adot[], double dt[]); + void write_bh_data(double time_cur, const std::vector &m, const std::vector &x, const std::vector &v, const std::vector &pot, const std::vector &a, const std::vector &adot, const std::vector &dt); public: //TODO make private double m1, m2; int count; @@ -83,7 +83,7 @@ private: class Binary_smbh_influence_sphere_output { public: - Binary_smbh_influence_sphere_output(double factor, int N, const std::vector &m, const std::vector &x, const std::vector &v, const std::vector &pot, double *dt) + Binary_smbh_influence_sphere_output(double factor, int N, const std::vector &m, const std::vector &x, const std::vector &v, const std::vector &pot, const std::vector &dt) : factor(factor), m(m), x(x), v(v), pot(pot), dt(dt) { inf_event.assign(N, 0); @@ -97,9 +97,7 @@ public: void operator()(const std::vector& ind_act, int n_act, double timesteps, double time_cur); private: double factor; - const std::vector &pot; - const std::vector &m; - double /**pot,*/ *dt; + const std::vector &pot, &m, &dt; const std::vector &x, &v; std::vector inf_event; FILE *out; diff --git a/external.cpp b/external.cpp index 27c5f71..3e927ad 100644 --- a/external.cpp +++ b/external.cpp @@ -59,7 +59,6 @@ void Logarithmic_halo::calc_gravity() jerk = tmp * (rv_ij * x - r2_r2_halo * v); } - void Dehnen::calc_gravity() { diff --git a/external.h b/external.h index 08d989f..0702d09 100644 --- a/external.h +++ b/external.h @@ -4,7 +4,7 @@ class External_gravity { public: - void apply(const int n_act, const std::vector &x, const std::vector &v, double pot[], double3 a[], double3 adot[]) + void apply(const int n_act, const std::vector &x, const std::vector &v, std::vector &pot, std::vector &a, std::vector &adot) { for (int i=0; iset_coordinates(x[i], v[i]); diff --git a/io.cpp b/io.cpp index 6bc8e5f..d0a187d 100644 --- a/io.cpp +++ b/io.cpp @@ -146,7 +146,7 @@ void h5_read(const std::string file_name, int *step_num, int *N, double *t, doub #endif } -void h5_write(const std::string file_name, const int step_num, const int N, const double t, std::vector &m, std::vector &x, std::vector &v, const std::vector &pot, const double3 *acc, const double3 *jrk, const int extra_mode=0, const bool use_double_precision=true) +void h5_write(const std::string file_name, const int step_num, const int N, const double t, const std::vector &m, const std::vector &x, const std::vector &v, const std::vector &pot, const std::vector &acc, const std::vector &jrk, const int extra_mode=0, const bool use_double_precision=true) { #ifdef HAS_HDF5 hid_t file_id, group_id, attribute_id, dataspace_id; @@ -174,7 +174,7 @@ void h5_write(const std::string file_name, const int step_num, const int N, cons H5Sclose(dataspace_id); }; - write_dataset("MASS", 1, m.data()); + write_dataset("MASS", 1, (double*)m.data()); // casting away const... write_dataset("X", 2, (double*)x.data()); write_dataset("V", 2, (double*)v.data()); @@ -182,8 +182,8 @@ void h5_write(const std::string file_name, const int step_num, const int N, cons bool write_acc = (extra_mode >> 1) & 1; bool write_jrk = (extra_mode >> 2) & 1; if (write_pot) write_dataset("POT", 1, (double*)pot.data()); - if (write_acc) write_dataset("ACC", 2, (double*)acc); - if (write_jrk) write_dataset("JRK", 2, (double*)jrk); + if (write_acc) write_dataset("ACC", 2, (double*)acc.data()); + if (write_jrk) write_dataset("JRK", 2, (double*)jrk.data()); H5Gclose(group_id); H5Fclose(file_id); diff --git a/io.h b/io.h index 874ca27..7571592 100644 --- a/io.h +++ b/io.h @@ -12,5 +12,5 @@ void ascii_write(const std::string file_name, const int step_num, const int N, c void h5_read(const std::string file_name, int *step_num, int *N, double *t, double m[], double3 x[], double3 v[]); // In case the code is compiled without HDF5 support, the implementation of this function just throws an error -void h5_write(const std::string file_name, const int step_num, const int N, const double t, std::vector &m, std::vector &x, std::vector &v, const std::vector &pot, const double3 *acc, const double3 *jrk, const int extra_mode=0, const bool use_double_precision=true); +void h5_write(const std::string file_name, const int step_num, const int N, const double t, const std::vector &m, const std::vector &x, const std::vector &v, const std::vector &pot, const std::vector &acc, const std::vector &jrk, const int extra_mode=0, const bool use_double_precision=true); // In case the code is compiled without HDF5 support, the implementation of this function just throws an error diff --git a/phigrape.cpp b/phigrape.cpp index e889174..bab4157 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -58,21 +58,20 @@ public: jrk_loc.resize(N); } void operator()(const double t, const int n_act, std::vector &ind_act, std::vector &x_act, std::vector &v_act, - std::vector& pot, double3 acc[], double3 jrk[]) + std::vector& pot, std::vector &acc, std::vector &jrk) { g6_set_ti(clusterid, t); for (int i=0; iis_active) return true; return false; } - void operator()(int n, const std::vector &x, const std::vector &v, double *pot, double3 *acc, double3* jrk) + void operator()(int n, const std::vector &x, const std::vector &v, std::vector &pot, std::vector &acc, std::vector &jrk) { for (auto component : components) { if (component->is_active) @@ -106,7 +105,7 @@ private: std::vector components; }; -void energy_contr(const double time_cur, const double timesteps, const double n_act_sum, const double g6_calls, int N, const std::vector &m, const std::vector &x, const std::vector &v, const std::vector &pot, double pot_ext[]) +void energy_contr(const double time_cur, const double timesteps, const double n_act_sum, const double g6_calls, int N, const std::vector &m, const std::vector &x, const std::vector &v, const std::vector &pot, const std::vector &pot_ext) { double E_pot = 0; for (int i=0; i &t, std::vector &dt) { double min_t_loc, min_t; #ifdef ETICS @@ -197,7 +195,7 @@ public: MPI_Allreduce(&min_t_loc, &min_t, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD); return min_t; } - void get_active_indices(const double min_t, const double t[], const double dt[], int ind_act[], int& n_act) + void get_active_indices(const double min_t, const std::vector &t, const std::vector &dt, std::vector &ind_act, int &n_act) { #ifdef ETICS if (grapite_active_search_flag) { @@ -226,11 +224,11 @@ public: } private: int myRank, n_proc, n_loc, N; - int *ind_act_loc; + std::vector ind_act_loc; bool grapite_active_search_flag; }; -inline void calc_high_derivatives(const double dt_tmp, const double3 a_old, const double3 a_new, const double3 a1_old, const double3 a1_new, double3& a2, double3& a3) +inline void calc_high_derivatives(const double dt_tmp, const double3 &a_old, const double3 &a_new, const double3 &a1_old, const double3 &a1_new, double3 &a2, double3 &a3) { double dtinv = 1/dt_tmp; double dt2inv = dtinv*dtinv; @@ -244,7 +242,7 @@ inline void calc_high_derivatives(const double dt_tmp, const double3 a_old, cons a3 = 12*a0mia1*dt3inv + 6*ad0plad1*dt2inv; } -inline void corrector(const double dt_tmp, const double3 a2, const double3 a3, double3& x, double3& v) +inline void corrector(const double dt_tmp, const double3 &a2, const double3 &a3, double3 &x, double3 &v) { double dt3over6 = dt_tmp*dt_tmp*dt_tmp/6.0; double dt4over24 = dt3over6*dt_tmp/4.0; @@ -254,7 +252,7 @@ inline void corrector(const double dt_tmp, const double3 a2, const double3 a3, d v += dt3over6*a2 + dt4over24*a3; } -inline double aarseth_step(const double eta, const double dt, const double3 a, const double3 a1, const double3 a2, const double3 a3) +inline double aarseth_step(const double eta, const double dt, const double3 &a, const double3 &a1, const double3 &a2, const double3 &a3) { double a1abs = a.norm(); double adot1abs = a1.norm(); @@ -274,8 +272,6 @@ int main(int argc, char *argv[]) double timesteps=0.0, n_act_sum=0.0; - double3 zeros = {0, 0, 0}; // Dummy; can't really be const because of the GRAPE interface. - /* INIT the rand() !!! */ srand(19640916); /* it is just my birthday :-) */ @@ -298,8 +294,6 @@ int main(int argc, char *argv[]) int diskstep, N; double time_cur; - // The memory for m, x, and v is allocated inside h5_read or ascii_read - //double *m; std::vector m; std::vector x, v; if (is_hdf5(config.input_file_name)) { @@ -312,20 +306,6 @@ int main(int argc, char *argv[]) else ascii_read(config.input_file_name, diskstep, N, time_cur, m, x, v); - std::vector ind(N); - std::iota(begin(ind), end(ind), 0); - double3 *a = new double3[N], *adot = new double3[N]; - std::vector pot(N); - double *pot_ext = new double[N], *t = new double[N], *dt = new double[N]; - - /* data for active particles */ - int n_act; - std::vector ind_act(N); - std::vector pot_act_new(N); - std::vector x_act_new(N), v_act_new(N); - double *pot_act_ext = new double[N]; - double3 *a_act_new = new double3[N], *adot_act_new = new double3[N]; - double eps = config.eps; double eta = config.eta; double t_end = config.t_end; @@ -382,8 +362,7 @@ int main(int argc, char *argv[]) if (ext_disk.is_active) printf("m_disk = %.4E a_disk = %.4E b_disk = %.4E\n", config.ext_m_disk*normalization_mass, config.ext_a_disk*normalization_length, config.ext_b_disk*normalization_length); if (ext_halo_plummer.is_active) printf("m_halo = %.4E b_halo = %.4E\n", config.ext_m_halo_plummer*normalization_mass, config.ext_b_halo_plummer*normalization_length); if (ext_log_halo.is_active) printf("v_halo = %.6E r_halo = %.6E \n", config.ext_log_halo_v*normalization_velocity, config.ext_log_halo_r*normalization_length); - if (ext_dehnen.is_active) printf("m_ext = %.6E r_ext = %.6E \t g_ext = %.3E \n", config.ext_dehnen_m*normalization_mass, config.ext_dehnen_r*normalization_length, config.ext_dehnen_gamma); - printf("\n"); + if (ext_dehnen.is_active) printf("m_ext = %.6E r_ext = %.6E \t g_ext = %.3E \n\n", config.ext_dehnen_m*normalization_mass, config.ext_dehnen_r*normalization_length, config.ext_dehnen_gamma); fflush(stdout); double eta_bh = eta/ETA_BH_CORR; @@ -401,9 +380,6 @@ int main(int argc, char *argv[]) fflush(stdout); } /* if (myRank == rootRank) */ - std::fill(t, t+N, time_cur); - std::fill(dt, dt+N, dt_min); - /* some local settings for G6a boards */ int clusterid, numGPU; if (config.devices_per_node==0) { @@ -431,33 +407,19 @@ int main(int argc, char *argv[]) #endif int n_loc = N/n_proc; - Calc_self_grav calc_self_grav(N, n_loc, clusterid, npipe, eps); - Active_search active_search(myRank, n_proc, n_loc, N, grapite_active_search_flag); - Black_hole_physics black_hole_physics; - if (config.live_smbh_count == 1) - black_hole_physics = Black_hole_physics(m[0], 0, myRank, rootRank); - else if (config.live_smbh_count == 2) - black_hole_physics = Black_hole_physics(m[0], m[1], myRank, rootRank); - if (config.binary_smbh_pn) { - black_hole_physics.set_post_newtonian(config.pn_c, config.pn_usage.data()); - if (config.pn_usage[6]) black_hole_physics.set_spins(config.smbh1_spin.data(), config.smbh2_spin.data()); - } - black_hole_physics.set_softening(eps, config.live_smbh_custom_eps); - - Binary_smbh_influence_sphere_output binary_smbh_influence_sphere_output(config.binary_smbh_influence_radius_factor, N, m, x, v, pot, dt); - - Write_bh_nb_data write_bh_nb_data(config.live_smbh_neighbor_number, config.live_smbh_count, N, m, x, v); - #ifdef ETICS grapite_read_particle_tags(N, config.grapite_mask_file_name.c_str(), myRank, n_loc); grapite_set_dt_exp(config.dt_scf); grapite_set_t_exp(time_cur); #endif + std::vector ind(N); + std::iota(begin(ind), end(ind), 0); /* load the nj particles to the G6 */ + double3 zeros = {0, 0, 0}; // Dummy; can't really be const because of the GRAPE interface. for (int k=0; k a(N), adot(N); + std::vector pot(N); + /* define the all particles as a active on all the processors for the first time grav calc. */ + Calc_self_grav calc_self_grav(N, n_loc, clusterid, npipe, eps); calc_self_grav(time_cur, N, ind, x, v, pot, a, adot); - if (config.live_smbh_count == 2) { + Black_hole_physics black_hole_physics; + if (config.live_smbh_count == 1) + black_hole_physics = Black_hole_physics(m[0], 0, myRank, rootRank); + else if (config.live_smbh_count == 2) { + black_hole_physics = Black_hole_physics(m[0], m[1], myRank, rootRank); black_hole_physics.set_xv(x[0], x[1], v[0], v[1]); if (config.live_smbh_custom_eps >= 0) black_hole_physics.adjust_softening(pot[0], pot[1], a[0], a[1], adot[0], adot[1]); - if (config.binary_smbh_pn) black_hole_physics.adjust_post_newtonian(dt[0], a[0], a[1], adot[0], adot[1]); + if (config.binary_smbh_pn) black_hole_physics.adjust_post_newtonian(dt_min, a[0], a[1], adot[0], adot[1]); } + if (config.binary_smbh_pn) { + black_hole_physics.set_post_newtonian(config.pn_c, config.pn_usage.data()); + if (config.pn_usage[6]) black_hole_physics.set_spins(config.smbh1_spin.data(), config.smbh2_spin.data()); + } + black_hole_physics.set_softening(eps, config.live_smbh_custom_eps); - std::fill(pot_ext, pot_ext+N, 0.); + std::vector pot_ext(N, 0.); calc_ext_grav(N, x, v, pot_ext, a, adot); /* Energy control... */ @@ -507,6 +482,7 @@ int main(int argc, char *argv[]) } #endif + std::vector dt(N); /* Define initial timestep for all particles on all nodes */ for (int j=0; j 0) { - double min_dt = *std::min_element(dt, dt+N); + double min_dt = *std::min_element(begin(dt), end(dt)); for (int i=0; i ind_act(N); + std::vector x_act_new(N), v_act_new(N), a_act_new(N), adot_act_new(N); + std::vector t(N, time_cur), pot_act_new(N); + + // Functors for the main integration loop + Active_search active_search(myRank, n_proc, n_loc, N, grapite_active_search_flag); + Binary_smbh_influence_sphere_output binary_smbh_influence_sphere_output(config.binary_smbh_influence_radius_factor, N, m, x, v, pot, dt); + Write_bh_nb_data write_bh_nb_data(config.live_smbh_neighbor_number, config.live_smbh_count, N, m, x, v); + if (myRank == rootRank) { + if (config.live_smbh_output) black_hole_physics.write_bh_data(time_cur, m, x, v, pot, a, adot, dt); + if (config.live_smbh_neighbor_output) write_bh_nb_data(time_cur); + } /* if (myRank == rootRank) */ + /* The main integration loop */ while (time_cur <= t_end) { @@ -563,7 +544,8 @@ int main(int argc, char *argv[]) double min_t = active_search.get_minimum_time(t, dt); /* Get indices of all particles that will be active in this bunch */ - active_search.get_active_indices(min_t, t, dt, ind_act.data(), n_act); + int n_act; + active_search.get_active_indices(min_t, t, dt, ind_act, n_act); /* Find the BH(s) indices in the active list */ int i_bh1=0, i_bh2=1; @@ -603,7 +585,7 @@ int main(int argc, char *argv[]) } /* Calculate gravity on active particles due to external forces */ - std::fill(pot_act_ext, pot_act_ext+n_act, 0.); + std::vector pot_act_ext(N, 0.); calc_ext_grav(n_act, x_act_new, v_act_new, pot_act_ext, a_act_new, adot_act_new); /* correct the active particles positions etc... on all the nodes */ @@ -757,10 +739,6 @@ int main(int argc, char *argv[]) fflush(stdout); } /* if (myRank == rootRank) */ - delete[] a; delete[] adot; delete[] pot_ext; delete[] t; delete[] dt; delete[] a_act_new; delete[] adot_act_new; delete[] pot_act_ext; - /* Finalize the MPI work */ MPI_Finalize(); - - return 0; } From 54231b85370a80e0f21a57e762f56833c7be2cca Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Wed, 28 Oct 2020 21:15:51 -0400 Subject: [PATCH 52/65] Removed remaining macros and unused includes --- TODO.md | 4 +-- config.cpp | 6 +++- config.h | 6 +++- phigrape.conf | 20 ++++++++++- phigrape.cpp | 93 ++++++++++++++++++--------------------------------- 5 files changed, 63 insertions(+), 66 deletions(-) diff --git a/TODO.md b/TODO.md index 2c926f8..7573942 100644 --- a/TODO.md +++ b/TODO.md @@ -5,6 +5,4 @@ TODO * Break main() into smaller chunks; operations that are timed should become independent functions. -* Const everything - -* Remove unneeded includes \ No newline at end of file +* Const everything \ No newline at end of file diff --git a/config.cpp b/config.cpp index 9a7b9ce..62c2cd3 100644 --- a/config.cpp +++ b/config.cpp @@ -190,12 +190,16 @@ Config::Config(std::string file_name) eta = get_parameter(dictionary, "eta"); input_file_name = get_parameter(dictionary, "input_file_name", "data.con"); devices_per_node = get_parameter(dictionary, "devices_per_node", 0); - dt_min_warning = get_parameter(dictionary, "dt_min_warning", false); + dt_max_power = get_parameter(dictionary, "dt_max_power", -3); + dt_min_power = get_parameter(dictionary, "dt_min_power", -36); + eta_s_corr = get_parameter(dictionary, "eta_s_corr", 4); + eta_bh_corr = get_parameter(dictionary, "eta_bh_corr", 4); output_hdf5 = get_parameter(dictionary, "output_hdf5", false); output_hdf5_double_precision = get_parameter(dictionary, "output_hdf5_double_precision", true); output_ascii_precision = get_parameter(dictionary, "output_ascii_precision", 10); output_extra_mode = get_parameter(dictionary, "output_extra_mode", 10); + dt_min_warning = get_parameter(dictionary, "dt_min_warning", false); live_smbh_count = get_parameter(dictionary, "live_smbh_count", 0); live_smbh_custom_eps = get_parameter(dictionary, "live_smbh_custom_eps", -1); diff --git a/config.h b/config.h index 9305e34..b07ffdc 100644 --- a/config.h +++ b/config.h @@ -15,12 +15,16 @@ public: double eta; std::string input_file_name; int devices_per_node; - bool dt_min_warning; + int dt_max_power; + int dt_min_power; + double eta_s_corr; + double eta_bh_corr; bool output_hdf5; bool output_hdf5_double_precision; int output_ascii_precision; int output_extra_mode; + bool dt_min_warning; int live_smbh_count; double live_smbh_custom_eps; diff --git a/phigrape.conf b/phigrape.conf index 13080de..9643b6f 100644 --- a/phigrape.conf +++ b/phigrape.conf @@ -31,7 +31,25 @@ eta = 0.01 # processes on a machine with a single device, set the value to 1 and use the # mpirun utility (or whatever is used in your job scheduler) to launch as many # processes as you like. -#devices_per_node = 1 +devices_per_node = 1 + + +# The power of 2 of the maximum timestep. For example, if dt_max_power=-3 and +# the adaptive timestep algotirhm suggests anything bigger than 0.125, the +# timestep will be 0.125. If the 2^dt_max_power > dt_contr, the maximum timestep +# is dt_contr. [default: -3] +#dt_max_power = -3 + +# The power of 2 of the minimum timestep. [default: -36] +#dt_min_power = -36 + +# Eta correction factor for the first step (the timestep will be calculated with +# eta divided by eta_s_corr) [default: 4] +#eta_s_corr = 4.0 + +# Eta correction factor for the black holes (the timestep for the black holes +# will be calculated with eta divided by eta_bh_corr). [default: 4] +#eta_bh_corr = 4.0 ########## diff --git a/phigrape.cpp b/phigrape.cpp index bab4157..1b2121c 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -1,21 +1,7 @@ -#define ETA_S_CORR 4.0 -#define ETA_BH_CORR 4.0 - -#define DTMAXPOWER -3.0 -#define DTMINPOWER -36.0 - #include #include -#include #include #include -#include -#include -#include -#include -#include -#include -#include #include "black_holes.h" #include "config.h" @@ -28,22 +14,20 @@ #include "grapite.h" #endif -//chrono::steady_clock::time_point walltime_start; - namespace std::chrono { -struct Timer { - void start() - { - t_start = steady_clock::now(); - } - void stop() - { - t_stop = steady_clock::now(); - time = duration_cast(t_stop - t_start).count()*1E-9; - } - double time; // seconds - steady_clock::time_point t_start, t_stop; -}; + struct Timer { + void start() + { + t_start = steady_clock::now(); + } + void stop() + { + t_stop = steady_clock::now(); + time = duration_cast(t_stop - t_start).count()*1E-9; + } + double time; // seconds + steady_clock::time_point t_start, t_stop; + }; } std::chrono::Timer timer; @@ -306,22 +290,15 @@ int main(int argc, char *argv[]) else ascii_read(config.input_file_name, diskstep, N, time_cur, m, x, v); - double eps = config.eps; - double eta = config.eta; - double t_end = config.t_end; - double dt_disk = config.dt_disk; - double dt_contr = config.dt_contr; - double dt_bh = config.dt_bh; - if (myRank == rootRank) { printf("\n"); printf("Begin the calculation of phi-GRAPE program on %03d processors\n", n_proc); printf("\n"); - printf("N = %07d \t eps = %.6E \n", N, eps); - printf("t_beg = %.6E \t t_end = %.6E \n", time_cur, t_end); - printf("dt_disk = %.6E \t dt_contr = %.6E \n", dt_disk, dt_contr); - printf("dt_bh = %.6E \n", dt_bh); - printf("eta = %.6E \n", eta); + printf("N = %07d \t eps = %.6E \n", N, config.eps); + printf("t_beg = %.6E \t t_end = %.6E \n", time_cur, config.t_end); + printf("dt_disk = %.6E \t dt_contr = %.6E \n", config.dt_disk, config.dt_contr); + printf("dt_bh = %.6E \n", config.dt_bh); + printf("eta = %.6E \n", config.eta); printf("\n"); if ((diskstep == 0) && (time_cur == 0)) { @@ -365,18 +342,12 @@ int main(int argc, char *argv[]) if (ext_dehnen.is_active) printf("m_ext = %.6E r_ext = %.6E \t g_ext = %.3E \n\n", config.ext_dehnen_m*normalization_mass, config.ext_dehnen_r*normalization_length, config.ext_dehnen_gamma); fflush(stdout); - double eta_bh = eta/ETA_BH_CORR; - - const double dt_min = pow(2, DTMINPOWER); - const double dt_max = std::min({dt_disk, dt_contr, pow(2, DTMAXPOWER)}); - - double t_disk = dt_disk*(1+floor(time_cur/dt_disk)); - double t_contr = dt_contr*(1+floor(time_cur/dt_contr)); - double t_bh = dt_bh*(1+floor(time_cur/dt_bh)); + double t_disk = config.dt_disk*(1+floor(time_cur/config.dt_disk)); + double t_contr = config.dt_contr*(1+floor(time_cur/config.dt_contr)); + double t_bh = config.dt_bh*(1+floor(time_cur/config.dt_bh)); if (myRank == rootRank) { - printf("t_disk = %.6E t_contr = %.6E t_bh = %.6E \n", t_disk, t_contr, t_bh); - printf("\n"); + printf("t_disk = %.6E t_contr = %.6E t_bh = %.6E \n\n", t_disk, t_contr, t_bh); fflush(stdout); } /* if (myRank == rootRank) */ @@ -413,6 +384,7 @@ int main(int argc, char *argv[]) grapite_set_t_exp(time_cur); #endif + const double dt_min = pow(2, config.dt_min_power); std::vector ind(N); std::iota(begin(ind), end(ind), 0); /* load the nj particles to the G6 */ @@ -442,7 +414,7 @@ int main(int argc, char *argv[]) std::vector pot(N); /* define the all particles as a active on all the processors for the first time grav calc. */ - Calc_self_grav calc_self_grav(N, n_loc, clusterid, npipe, eps); + Calc_self_grav calc_self_grav(N, n_loc, clusterid, npipe, config.eps); calc_self_grav(time_cur, N, ind, x, v, pot, a, adot); Black_hole_physics black_hole_physics; @@ -458,7 +430,7 @@ int main(int argc, char *argv[]) black_hole_physics.set_post_newtonian(config.pn_c, config.pn_usage.data()); if (config.pn_usage[6]) black_hole_physics.set_spins(config.smbh1_spin.data(), config.smbh2_spin.data()); } - black_hole_physics.set_softening(eps, config.live_smbh_custom_eps); + black_hole_physics.set_softening(config.eps, config.live_smbh_custom_eps); std::vector pot_ext(N, 0.); calc_ext_grav(N, x, v, pot_ext, a, adot); @@ -482,13 +454,14 @@ int main(int argc, char *argv[]) } #endif + const double dt_max = std::min({config.dt_disk, config.dt_contr, pow(2, config.dt_max_power)}); std::vector dt(N); /* Define initial timestep for all particles on all nodes */ for (int j=0; j 0) && (ind_act[i] < config.live_smbh_count)) eta_curr = eta_bh; - else eta_curr = eta; + if ((config.live_smbh_count > 0) && (ind_act[i] < config.live_smbh_count)) eta_curr = config.eta/config.eta_bh_corr; + else eta_curr = config.eta; double dt_new = aarseth_step(eta_curr, dt_tmp, a_act_new[i], adot_act_new[i], a2, a3); @@ -675,7 +648,7 @@ int main(int argc, char *argv[]) } /* if (myRank == rootRank) */ - t_bh += dt_bh; + t_bh += config.dt_bh; } /* if (time_cur >= t_bh) */ if (time_cur >= t_contr) { @@ -702,7 +675,7 @@ int main(int argc, char *argv[]) } #endif - t_contr += dt_contr; + t_contr += config.dt_contr; } /* if (time_cur >= t_contr) */ if (time_cur >= t_disk) { @@ -720,7 +693,7 @@ int main(int argc, char *argv[]) grapite_dump(out_fname, 2); } #endif - t_disk += dt_disk; + t_disk += config.dt_disk; } /* if (time_cur >= t_disk) */ } /* while (time_cur < t_end) */ From b6c55a30daa3753b15faf4494018bcb5a1986fff Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Wed, 28 Oct 2020 21:40:46 -0400 Subject: [PATCH 53/65] Made ETICS blocks work with the vector structures --- phigrape.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/phigrape.cpp b/phigrape.cpp index 1b2121c..845557f 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -184,7 +184,7 @@ public: #ifdef ETICS if (grapite_active_search_flag) { int n_act_loc; - grapite_active_search(min_t, ind_act_loc, &n_act_loc); + grapite_active_search(min_t, ind_act_loc.data(), &n_act_loc); if (myRank > 0) for (int i=0; i= 0) { double3 xcm, vcm, xdc, vdc; - grapite_calc_center(N, m, (double(*)[3])x, (double(*)[3])v, xcm, vcm, xdc, vdc); + grapite_calc_center(N, m.data(), (double(*)[3])x.data(), (double(*)[3])v.data(), xcm, vcm, xdc, vdc); x[grapite_cep_index] = xdc; v[grapite_cep_index] = vdc; grapite_update_cep(time_cur, xdc, vdc, zeros, zeros); @@ -447,7 +447,7 @@ int main(int argc, char *argv[]) if (grapite_cep_index >= 0) { double3 xcm, vcm, xdc, vdc; - grapite_calc_center(N, m, (double(*)[3])x, (double(*)[3])v, xcm, vcm, xdc, vdc); + grapite_calc_center(N, m.data(), (double(*)[3])x.data(), (double(*)[3])v.data(), xcm, vcm, xdc, vdc); x[grapite_cep_index] = xdc; v[grapite_cep_index] = vdc; grapite_update_cep(time_cur, xdc, vdc, a[grapite_cep_index], adot[grapite_cep_index]); From 8adb4ac81354be0b5fe8dc736e82f495f07937e6 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Wed, 28 Oct 2020 22:46:27 -0400 Subject: [PATCH 54/65] Fixed memory issue with reading of HDF5 input file and improved style --- Makefile | 1 - TODO.md | 2 -- io.cpp | 76 +++++++++++++++++++++++++++++----------------------- io.h | 12 +++++++-- phigrape.cpp | 16 ++++++----- 5 files changed, 63 insertions(+), 44 deletions(-) diff --git a/Makefile b/Makefile index 06637d0..5b0a0b6 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,6 @@ yebisu: GRAPEHOME = ../yebisu yebisu: GRAPELIB = -L$(GRAPEHOME) -lyebisug6 GRAPEINC = -I$(GRAPEHOME) -CXXFLAGS ?= -mcmodel=medium CXXFLAGS += -O$(OPTIMIZATION) INC = $(GRAPEINC) $(CUDAINC) LIB = $(GRAPELIB) $(CUDALIB) -lm diff --git a/TODO.md b/TODO.md index 7573942..22d82ff 100644 --- a/TODO.md +++ b/TODO.md @@ -1,8 +1,6 @@ TODO ==== -* Memory bug when reading HDF5? x and v not allocated. - * Break main() into smaller chunks; operations that are timed should become independent functions. * Const everything \ No newline at end of file diff --git a/io.cpp b/io.cpp index d0a187d..34c4bbf 100644 --- a/io.cpp +++ b/io.cpp @@ -3,6 +3,7 @@ #endif #include "double3.h" +#include "io.h" #include #include #include @@ -24,8 +25,9 @@ bool is_hdf5(std::string file_name) return result; } -void ascii_read(const std::string file_name, int &step_num, int &N, double& t, std::vector &m, std::vector &x, std::vector &v) +Input_data ascii_read(const std::string &file_name) { + Input_data input_data; char rest[512]; int result; @@ -34,30 +36,31 @@ void ascii_read(const std::string file_name, int &step_num, int &N, double& t, s std::string str; std::getline(file, str); - result = sscanf(str.c_str(), "%d%s", &step_num, rest); + result = sscanf(str.c_str(), "%d%s", &input_data.step_num, rest); if (result!=1) throw std::runtime_error("Error parsing line 1: expected one integer"); std::getline(file, str); - result = sscanf(str.c_str(), "%d%s", &N, rest); + result = sscanf(str.c_str(), "%d%s", &input_data.N, rest); if (result!=1) throw std::runtime_error("Error parsing line 2: expected one integer"); std::getline(file, str); - result = sscanf(str.c_str(), "%lf%s", &t, rest); + result = sscanf(str.c_str(), "%lf%s", &input_data.t, rest); if (result!=1) throw std::runtime_error("Error parsing line 3: expected one real number"); - m.resize(N); - x.resize(N); - v.resize(N); + input_data.m.resize(input_data.N); + input_data.x.resize(input_data.N); + input_data.v.resize(input_data.N); int i = -1; while (std::getline(file, str)) { - if (++i > N) throw std::runtime_error("Error parsing line " + std::to_string(i+4) + ": particle out of range"); - result = sscanf(str.c_str(), "%*s %lf %lf %lf %lf %lf %lf %lf%s", &m[i], &(x[i].x), &(x[i].y), &(x[i].z), &(v[i].x), &(v[i].y), &(v[i].z), rest); + if (++i > input_data.N) throw std::runtime_error("Error parsing line " + std::to_string(i+4) + ": particle out of range"); + result = sscanf(str.c_str(), "%*s %lf %lf %lf %lf %lf %lf %lf%s", &input_data.m[i], &(input_data.x[i].x), &(input_data.x[i].y), &(input_data.x[i].z), &(input_data.v[i].x), &(input_data.v[i].y), &(input_data.v[i].z), rest); } file.close(); + return input_data; } -void ascii_write(const std::string file_name, const int step_num, const int N, const double t, const std::vector &m, const std::vector &x, const std::vector &v, int precision=10) +void ascii_write(const std::string file_name, const int step_num, const int N, const double t, const std::vector &m, const std::vector &x, const std::vector &v, int precision) { auto file = std::ofstream(file_name); if (!file.is_open()) throw std::runtime_error("Cannot open file for output"); @@ -75,9 +78,11 @@ void ascii_write(const std::string file_name, const int step_num, const int N, c file.close(); } -void h5_read(const std::string file_name, int *step_num, int *N, double *t, double m[], double3 x[], double3 v[]) +Input_data h5_read(const std::string &file_name) { #ifdef HAS_HDF5 + Input_data input_data; + // Open file and root group; count number of top level objects hid_t file_id = H5Fopen(file_name.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT); hid_t group_id = H5Gopen2(file_id, "/", H5P_DEFAULT); @@ -92,7 +97,7 @@ void h5_read(const std::string file_name, int *step_num, int *N, double *t, doub if (name.substr(0, 5) == "Step#") step_num_arr.push_back(std::stoi(name.substr(5, std::string::npos))); } // Find the highest step in the file - *step_num = *max_element(step_num_arr.begin(), step_num_arr.end()); + input_data.step_num = *max_element(step_num_arr.begin(), step_num_arr.end()); // Prepare to read the data sets dimensionality data. char path[256]; @@ -100,53 +105,58 @@ void h5_read(const std::string file_name, int *step_num, int *N, double *t, doub int ndims; hsize_t dims[2]; - sprintf(path, "/Step#%d", *step_num); + sprintf(path, "/Step#%d", input_data.step_num); attr_id = H5Aopen_by_name(file_id, path, "Time", H5P_DEFAULT, H5P_DEFAULT); - H5Aread(attr_id, H5T_NATIVE_DOUBLE, t); + H5Aread(attr_id, H5T_NATIVE_DOUBLE, &input_data.t); H5Aclose(attr_id); - sprintf(path, "/Step#%d/MASS", *step_num); + sprintf(path, "/Step#%d/MASS", input_data.step_num); dataset_id = H5Dopen2(file_id, path, H5P_DEFAULT); dataspace_id = H5Dget_space(dataset_id); ndims = H5Sget_simple_extent_ndims(dataspace_id); if (ndims != 1) - throw std::runtime_error("Dataset MASS in Step#" + std::to_string(*step_num) + " of file " + file_name + " is " + std::to_string(ndims) + "-dimensional (expected 1-dimensional)"); + throw std::runtime_error("Dataset MASS in Step#" + std::to_string(input_data.step_num) + " of file " + file_name + " is " + std::to_string(ndims) + "-dimensional (expected 1-dimensional)"); H5Sget_simple_extent_dims(dataspace_id, dims, NULL); - H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, m); - H5Sclose(dataspace_id); - H5Dclose(dataset_id); - *N = dims[0]; + input_data.N = dims[0]; - sprintf(path, "/Step#%d/X", *step_num); - dataset_id = H5Dopen2(file_id, path, H5P_DEFAULT); - dataspace_id = H5Dget_space(dataset_id); - ndims = H5Sget_simple_extent_ndims(dataspace_id); - if (ndims != 2) throw std::runtime_error("Bad dimensionality"); - H5Sget_simple_extent_dims(dataspace_id, dims, NULL); - if ((dims[0] != *N) || (dims[1] != 3)) throw std::runtime_error("Bad dimensionality"); - H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, (double*)x); + input_data.m.resize(input_data.N); + H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, input_data.m.data()); H5Sclose(dataspace_id); H5Dclose(dataset_id); - sprintf(path, "/Step#%d/V", *step_num); + sprintf(path, "/Step#%d/X", input_data.step_num); dataset_id = H5Dopen2(file_id, path, H5P_DEFAULT); dataspace_id = H5Dget_space(dataset_id); ndims = H5Sget_simple_extent_ndims(dataspace_id); - if (ndims != 2) throw std::runtime_error("Bad dimensionality"); + if (ndims != 2) throw std::runtime_error("Bad dimensionality in " + std::string(path)); H5Sget_simple_extent_dims(dataspace_id, dims, NULL); - if ((dims[0] != *N) || (dims[1] != 3)) throw std::runtime_error("Bad dimensionality"); - H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, (double*)v); + if ((dims[0] != input_data.N) || (dims[1] != 3)) throw std::runtime_error("Bad dimensionality"); + input_data.x.resize(input_data.N); + H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, (double*)input_data.x.data()); + H5Sclose(dataspace_id); + H5Dclose(dataset_id); + + sprintf(path, "/Step#%d/V", input_data.step_num); + dataset_id = H5Dopen2(file_id, path, H5P_DEFAULT); + dataspace_id = H5Dget_space(dataset_id); + ndims = H5Sget_simple_extent_ndims(dataspace_id); + if (ndims != 2) throw std::runtime_error("Bad dimensionality in" + std::string(path)); + H5Sget_simple_extent_dims(dataspace_id, dims, NULL); + if ((dims[0] != input_data.N) || (dims[1] != 3)) throw std::runtime_error("Bad dimensionality"); + input_data.v.resize(input_data.N); + H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, (double*)input_data.v.data()); H5Sclose(dataspace_id); H5Dclose(dataset_id); H5Gclose(group_id); H5Fclose(file_id); + return input_data; #else throw std::runtime_error("h5_read was called but compiled without HDF5 support"); #endif } -void h5_write(const std::string file_name, const int step_num, const int N, const double t, const std::vector &m, const std::vector &x, const std::vector &v, const std::vector &pot, const std::vector &acc, const std::vector &jrk, const int extra_mode=0, const bool use_double_precision=true) +void h5_write(const std::string file_name, const int step_num, const int N, const double t, const std::vector &m, const std::vector &x, const std::vector &v, const std::vector &pot, const std::vector &acc, const std::vector &jrk, const int extra_mode, const bool use_double_precision) { #ifdef HAS_HDF5 hid_t file_id, group_id, attribute_id, dataspace_id; diff --git a/io.h b/io.h index 7571592..097ebb9 100644 --- a/io.h +++ b/io.h @@ -1,15 +1,23 @@ #pragma once #include +#include #include "double3.h" +struct Input_data { + int N, step_num; + double t; + std::vector m; + std::vector x, v; +}; + bool is_hdf5(std::string file_name); // This function is implemented independently of the HDF5 library -void ascii_read(const std::string file_name, int &step_num, int &N, double &t, std::vector &m, std::vector &x, std::vector &v); +Input_data ascii_read(const std::string &file_name); void ascii_write(const std::string file_name, const int step_num, const int N, const double t, const std::vector &m, const std::vector &x, const std::vector &v, int precision=10); -void h5_read(const std::string file_name, int *step_num, int *N, double *t, double m[], double3 x[], double3 v[]); +Input_data h5_read(const std::string &file_name); // In case the code is compiled without HDF5 support, the implementation of this function just throws an error void h5_write(const std::string file_name, const int step_num, const int N, const double t, const std::vector &m, const std::vector &x, const std::vector &v, const std::vector &pot, const std::vector &acc, const std::vector &jrk, const int extra_mode=0, const bool use_double_precision=true); diff --git a/phigrape.cpp b/phigrape.cpp index 845557f..1cab74e 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -276,19 +276,23 @@ int main(int argc, char *argv[]) /* Print the Rank and the names of processors */ printf("Rank of the processor %03d on %s \n", myRank, processor_name); - int diskstep, N; - double time_cur; - std::vector m; - std::vector x, v; + Input_data input_data; if (is_hdf5(config.input_file_name)) { #ifndef HAS_HDF5 fprintf(stderr, "ERROR: input file is in HDF5 format, but the code was compiled without HDF5 support\n"); return -1; #endif - h5_read(config.input_file_name, &diskstep, &N, &time_cur, m.data(), x.data(), v.data()); + input_data = h5_read(config.input_file_name); } else - ascii_read(config.input_file_name, diskstep, N, time_cur, m, x, v); + input_data = ascii_read(config.input_file_name); + + int N = input_data.N; + int diskstep = input_data.step_num; + double time_cur = input_data.t; + auto &m = input_data.m; + auto &x = input_data.x; + auto &v = input_data.v; if (myRank == rootRank) { printf("\n"); From dd31b632159a537a1ab45b237e7ff4baa891ff6f Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Sat, 31 Oct 2020 15:08:48 -0400 Subject: [PATCH 55/65] Improved printing of external potential --- TODO.md | 4 +++- external.h | 39 +++++++++++++++++++++++++++++++++------ phigrape.cpp | 49 +++++++++++++++++++++---------------------------- 3 files changed, 57 insertions(+), 35 deletions(-) diff --git a/TODO.md b/TODO.md index 22d82ff..6effc24 100644 --- a/TODO.md +++ b/TODO.md @@ -3,4 +3,6 @@ TODO * Break main() into smaller chunks; operations that are timed should become independent functions. -* Const everything \ No newline at end of file +* Const everything + +* OpenMP \ No newline at end of file diff --git a/external.h b/external.h index 0702d09..ead7920 100644 --- a/external.h +++ b/external.h @@ -1,4 +1,5 @@ #pragma once +#include #include #include "double3.h" @@ -15,11 +16,17 @@ public: } } virtual void calc_gravity() = 0; - bool is_active; + virtual void print_info() {} + void set_name(const std::string &name) + { + this->name = name; + } + bool is_active = false; protected: double potential; double3 acceleration, jerk; double3 x, v; + std::string name = "ext"; void set_coordinates(double3 x, double3 v) { this->x = x; @@ -30,23 +37,38 @@ protected: class Plummer : public External_gravity { public: Plummer(double m, double b) : m(m), b(b) {is_active=(m>0);} - void calc_gravity(); + void calc_gravity() override; + void print_info() override + { + if (!is_active) return; + printf("m_%-5s = %.4E b_%-5s = %.4E\n", name.c_str(), m, name.c_str(), b); + } private: double m, b; }; class Miyamoto_Nagai : public External_gravity { public: - Miyamoto_Nagai(double m, double a, double b) : m(m), a(a), b(b) {is_active=(m>0);} + Miyamoto_Nagai(double m, double a, double b) : m(m), a(a), b(b) {is_active=(m>0); this->set_name("disk");} void calc_gravity(); + void print_info() override + { + if (!is_active) return; + printf("m_%-5s = %.4E a_%-5s = %.4E b_%-5s = %.4E\n", name.c_str(), m, name.c_str(), a, name.c_str(), b); + } private: double m, a, b; }; class Logarithmic_halo : public External_gravity { public: - Logarithmic_halo(double v_halo, double r_halo) : v2_halo(v_halo*v_halo), r2_halo(r_halo*r_halo) {is_active=(r_halo>0);} - void calc_gravity(); + Logarithmic_halo(double v_halo, double r_halo) : v2_halo(v_halo*v_halo), r2_halo(r_halo*r_halo) {is_active=(r_halo>0); this->set_name("halo");} + void calc_gravity() override; + void print_info() override + { + if (!is_active) return; + printf("v_%-4s = %.6E r_%-4s = %.4E\n", name.c_str(), sqrt(v2_halo), name.c_str(), sqrt(r2_halo)); + } private: double v2_halo, r2_halo; }; @@ -54,7 +76,12 @@ private: class Dehnen : public External_gravity { public: Dehnen(double m, double r, double gamma) : m(m), r(r), gamma(gamma) {is_active=(m>0);} - void calc_gravity(); + void calc_gravity() override; + void print_info() override + { + if (!is_active) return; + printf("m_%-5s = %.4E r_%-5s = %.4E g_%-5s = %.4E\n", name.c_str(), m, name.c_str(), r, name.c_str(), gamma); + } private: double m, r, gamma; }; diff --git a/phigrape.cpp b/phigrape.cpp index 1cab74e..b82cb12 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -85,6 +85,13 @@ public: component->apply(n, x, v, pot, acc, jrk); } } + void print_info() + { + for (auto component : components) { + component->print_info(); + } + fflush(stdout); + } private: std::vector components; }; @@ -249,13 +256,8 @@ inline double aarseth_step(const double eta, const double dt, const double3 &a, int main(int argc, char *argv[]) { - /* read the input parameters */ - const Config config("phigrape.conf"); - timer.start(); - double timesteps=0.0, n_act_sum=0.0; - /* INIT the rand() !!! */ srand(19640916); /* it is just my birthday :-) */ @@ -276,6 +278,7 @@ int main(int argc, char *argv[]) /* Print the Rank and the names of processors */ printf("Rank of the processor %03d on %s \n", myRank, processor_name); + const Config config("phigrape.conf"); Input_data input_data; if (is_hdf5(config.input_file_name)) { #ifndef HAS_HDF5 @@ -294,16 +297,20 @@ int main(int argc, char *argv[]) auto &x = input_data.x; auto &v = input_data.v; + double t_disk = config.dt_disk*(1+floor(time_cur/config.dt_disk)); + double t_contr = config.dt_contr*(1+floor(time_cur/config.dt_contr)); + double t_bh = config.dt_bh*(1+floor(time_cur/config.dt_bh)); + if (myRank == rootRank) { printf("\n"); printf("Begin the calculation of phi-GRAPE program on %03d processors\n", n_proc); printf("\n"); - printf("N = %07d \t eps = %.6E \n", N, config.eps); - printf("t_beg = %.6E \t t_end = %.6E \n", time_cur, config.t_end); - printf("dt_disk = %.6E \t dt_contr = %.6E \n", config.dt_disk, config.dt_contr); + printf("N = %07d \t eps = %.6E\n", N, config.eps); + printf("t_beg = %.6E \t t_end = %.6E\n", time_cur, config.t_end); + printf("dt_disk = %.6E \t dt_contr = %.6E\n", config.dt_disk, config.dt_contr); printf("dt_bh = %.6E \n", config.dt_bh); - printf("eta = %.6E \n", config.eta); - printf("\n"); + printf("eta = %.6E\n\n", config.eta); + printf("t_disk = %.6E t_contr = %.6E t_bh = %.6E\n\n", t_disk, t_contr, t_bh); if ((diskstep == 0) && (time_cur == 0)) { FILE *out = fopen("contr.dat", "w"); @@ -327,33 +334,18 @@ int main(int argc, char *argv[]) } Calc_ext_grav calc_ext_grav; Plummer ext_bulge(config.ext_m_bulge*normalization_mass, config.ext_b_bulge*normalization_length); + ext_bulge.set_name("bulge"); calc_ext_grav.add_component(ext_bulge); Miyamoto_Nagai ext_disk(config.ext_m_disk*normalization_mass, config.ext_a_disk*normalization_length, config.ext_b_disk*normalization_length); calc_ext_grav.add_component(ext_disk); Plummer ext_halo_plummer(config.ext_m_halo_plummer*normalization_mass, config.ext_b_halo_plummer*normalization_length); + ext_halo_plummer.set_name("halo"); calc_ext_grav.add_component(ext_halo_plummer); Logarithmic_halo ext_log_halo(config.ext_log_halo_v*normalization_velocity, config.ext_log_halo_r*normalization_length); calc_ext_grav.add_component(ext_log_halo); Dehnen ext_dehnen(config.ext_dehnen_m*normalization_mass, config.ext_dehnen_r*normalization_length, config.ext_dehnen_gamma); calc_ext_grav.add_component(ext_dehnen); - bool has_external_gravity = calc_ext_grav.any_active(); - - if (has_external_gravity) printf("External Potential: \n\n"); - if (ext_bulge.is_active) printf("m_bulge = %.4E b_bulge = %.4E\n", config.ext_m_bulge*normalization_mass, config.ext_b_bulge*normalization_length); - if (ext_disk.is_active) printf("m_disk = %.4E a_disk = %.4E b_disk = %.4E\n", config.ext_m_disk*normalization_mass, config.ext_a_disk*normalization_length, config.ext_b_disk*normalization_length); - if (ext_halo_plummer.is_active) printf("m_halo = %.4E b_halo = %.4E\n", config.ext_m_halo_plummer*normalization_mass, config.ext_b_halo_plummer*normalization_length); - if (ext_log_halo.is_active) printf("v_halo = %.6E r_halo = %.6E \n", config.ext_log_halo_v*normalization_velocity, config.ext_log_halo_r*normalization_length); - if (ext_dehnen.is_active) printf("m_ext = %.6E r_ext = %.6E \t g_ext = %.3E \n\n", config.ext_dehnen_m*normalization_mass, config.ext_dehnen_r*normalization_length, config.ext_dehnen_gamma); - fflush(stdout); - - double t_disk = config.dt_disk*(1+floor(time_cur/config.dt_disk)); - double t_contr = config.dt_contr*(1+floor(time_cur/config.dt_contr)); - double t_bh = config.dt_bh*(1+floor(time_cur/config.dt_bh)); - - if (myRank == rootRank) { - printf("t_disk = %.6E t_contr = %.6E t_bh = %.6E \n\n", t_disk, t_contr, t_bh); - fflush(stdout); - } /* if (myRank == rootRank) */ + if (myRank == rootRank) calc_ext_grav.print_info(); /* some local settings for G6a boards */ int clusterid, numGPU; @@ -439,6 +431,7 @@ int main(int argc, char *argv[]) std::vector pot_ext(N, 0.); calc_ext_grav(N, x, v, pot_ext, a, adot); + double timesteps=0, n_act_sum=0; /* Energy control... */ if (myRank == rootRank) energy_contr(time_cur, timesteps, n_act_sum, calc_self_grav.g6_calls, N, m, x, v, pot, pot_ext); From 11c0db23a3c3680fccffec7e53779a16e603f64c Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Tue, 3 Nov 2020 21:41:21 -0500 Subject: [PATCH 56/65] Compatibility with Sapporo --- Makefile | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 5b0a0b6..49305a7 100644 --- a/Makefile +++ b/Makefile @@ -3,17 +3,19 @@ CPPFLAGS += -DETICS OPTIMIZATION ?= 3 CUDAINC = -I$(CUDAHOME)/include -I$(CUDAHOME)/samples/common/inc/ -CUDALIB = -L$(CUDAHOME)/lib64 -lcudart -lcudadevrt +CUDALIB = -L$(CUDAHOME)/lib64 -lcudart -lcudadevrt -lcuda -GRAPEHOME = ../grapite -GRAPELIB = -L$(GRAPEHOME) -lgrapite -yebisu: GRAPEHOME = ../yebisu -yebisu: GRAPELIB = -L$(GRAPEHOME) -lyebisug6 -GRAPEINC = -I$(GRAPEHOME) +default grapite: GRAPEHOME = ../grapite +default grapite: GRAPELIB = -L$(GRAPEHOME) -lgrapite -fopenmp +yebisu: GRAPEHOME = ../yebisu +yebisu: GRAPELIB = -L$(GRAPEHOME) -lyebisug6 +sapporo: GRAPEHOME = ../sapporo2/lib +sapporo: GRAPELIB = -L$(GRAPEHOME) -lsapporo -fopenmp + GRAPEINC = -I$(GRAPEHOME) CXXFLAGS += -O$(OPTIMIZATION) INC = $(GRAPEINC) $(CUDAINC) -LIB = $(GRAPELIB) $(CUDALIB) -lm +LIB = $(GRAPELIB) $(CUDALIB) -lm -fopenmp MPICXX ?= mpic++ EXECUTABLE ?= phigrape @@ -24,8 +26,8 @@ LIB += -lhdf5 -lz -ldl default: $(MPICXX) $(CPPFLAGS) $(CXXFLAGS) $(INC) black_holes.cpp external.cpp io.cpp config.cpp phigrape.cpp -o $(EXECUTABLE) $(LIB) -yebisu: CPPFLAGS := $(filter-out -DETICS, $(CPPFLAGS)) -yebisu: default +yebisu sapporo: CPPFLAGS := $(filter-out -DETICS, $(CPPFLAGS)) +yebisu sapporo grapite: default clean: - rm -f *.o phigrape + rm -f CUDA *.o phigrape From 0a2344563d4916a0947f4da7f661a5206ace098e Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Wed, 17 Mar 2021 20:37:12 -0400 Subject: [PATCH 57/65] run directory now separate from source directory --- .gitignore | 1 + Makefile | 15 ++++++++------- init.py | 2 ++ 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 737bf91..a83a44e 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,5 @@ grapite-dev-exec-threshold phigrape *.h5 .* +CUDA .gitignore diff --git a/Makefile b/Makefile index 49305a7..f9d07cb 100644 --- a/Makefile +++ b/Makefile @@ -5,23 +5,24 @@ OPTIMIZATION ?= 3 CUDAINC = -I$(CUDAHOME)/include -I$(CUDAHOME)/samples/common/inc/ CUDALIB = -L$(CUDAHOME)/lib64 -lcudart -lcudadevrt -lcuda -default grapite: GRAPEHOME = ../grapite -default grapite: GRAPELIB = -L$(GRAPEHOME) -lgrapite -fopenmp +default: grapite +grapite: GRAPEHOME = ../grapite +grapite: GRAPELIB = -L$(GRAPEHOME) -lgrapite yebisu: GRAPEHOME = ../yebisu yebisu: GRAPELIB = -L$(GRAPEHOME) -lyebisug6 sapporo: GRAPEHOME = ../sapporo2/lib -sapporo: GRAPELIB = -L$(GRAPEHOME) -lsapporo -fopenmp +sapporo: GRAPELIB = -L$(GRAPEHOME) -lsapporo GRAPEINC = -I$(GRAPEHOME) -CXXFLAGS += -O$(OPTIMIZATION) +CXXFLAGS += -std=c++11 -O$(OPTIMIZATION) INC = $(GRAPEINC) $(CUDAINC) -LIB = $(GRAPELIB) $(CUDALIB) -lm -fopenmp +LIB = $(GRAPELIB) $(CUDALIB) -lm MPICXX ?= mpic++ EXECUTABLE ?= phigrape # HDF5 -CPPFLAGS += -DHAS_HDF5 -LIB += -lhdf5 -lz -ldl +#CPPFLAGS += -DHAS_HDF5 +#LIB += -lhdf5 -lz -ldl default: $(MPICXX) $(CPPFLAGS) $(CXXFLAGS) $(INC) black_holes.cpp external.cpp io.cpp config.cpp phigrape.cpp -o $(EXECUTABLE) $(LIB) diff --git a/init.py b/init.py index 649f75f..d6b1f34 100644 --- a/init.py +++ b/init.py @@ -91,6 +91,8 @@ def gen_mask(particle_list, frac): mask = np.ones(N, dtype=int) elif frac==1: mask = np.zeros(N, dtype=int) + elif (frac < 0) or (1 < frac): + raise RuntimeError('Fraction has to be between 0 and 1') else: X = particle_list[:,:3] V = particle_list[:,3:] From 064eb4e3c594b57a2c5a35d4ac119ed79bb6eefd Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Mon, 23 Aug 2021 19:40:55 -0400 Subject: [PATCH 58/65] Removed init. of pot_act_ext from main loop; zero filling of pot_act_ext now only if external potential active; improved warning on minimum timestep; changed CUDAHOME to CUDA_HOME --- Makefile | 20 ++++++++++---------- phigrape.cpp | 17 ++++++++--------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/Makefile b/Makefile index f9d07cb..3ac4642 100644 --- a/Makefile +++ b/Makefile @@ -1,18 +1,18 @@ -CUDAHOME ?= /usr/local/cuda +CUDA_HOME ?= /usr/local/cuda CPPFLAGS += -DETICS OPTIMIZATION ?= 3 -CUDAINC = -I$(CUDAHOME)/include -I$(CUDAHOME)/samples/common/inc/ -CUDALIB = -L$(CUDAHOME)/lib64 -lcudart -lcudadevrt -lcuda +CUDAINC = -I$(CUDA_HOME)/include -I$(CUDA_HOME)/samples/common/inc/ +CUDALIB = -L$(CUDA_HOME)/lib64 -lcudart -lcudadevrt -lcuda default: grapite -grapite: GRAPEHOME = ../grapite -grapite: GRAPELIB = -L$(GRAPEHOME) -lgrapite -yebisu: GRAPEHOME = ../yebisu -yebisu: GRAPELIB = -L$(GRAPEHOME) -lyebisug6 -sapporo: GRAPEHOME = ../sapporo2/lib -sapporo: GRAPELIB = -L$(GRAPEHOME) -lsapporo - GRAPEINC = -I$(GRAPEHOME) +grapite: GRAPE_HOME = ../grapite +grapite: GRAPELIB = -L$(GRAPE_HOME) -lgrapite +yebisu: GRAPE_HOME = ../yebisu +yebisu: GRAPELIB = -L$(GRAPE_HOME) -lyebisug6 +sapporo: GRAPE_HOME = ../sapporo2/lib +sapporo: GRAPELIB = -L$(GRAPE_HOME) -lsapporo + GRAPEINC = -I$(GRAPE_HOME) CXXFLAGS += -std=c++11 -O$(OPTIMIZATION) INC = $(GRAPEINC) $(CUDAINC) diff --git a/phigrape.cpp b/phigrape.cpp index b82cb12..c484045 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -71,12 +71,7 @@ public: void add_component(External_gravity &component) { components.push_back(&component); - } - bool any_active() - { - for (auto component : components) - if (component->is_active) return true; - return false; + if (component.is_active) any_active = true; } void operator()(int n, const std::vector &x, const std::vector &v, std::vector &pot, std::vector &acc, std::vector &jrk) { @@ -92,6 +87,7 @@ public: } fflush(stdout); } + bool any_active = false; private: std::vector components; }; @@ -497,6 +493,7 @@ int main(int argc, char *argv[]) std::vector ind_act(N); std::vector x_act_new(N), v_act_new(N), a_act_new(N), adot_act_new(N); std::vector t(N, time_cur), pot_act_new(N); + std::vector pot_act_ext(N, 0.); // Functors for the main integration loop Active_search active_search(myRank, n_proc, n_loc, N, grapite_active_search_flag); @@ -555,8 +552,10 @@ int main(int argc, char *argv[]) } /* Calculate gravity on active particles due to external forces */ - std::vector pot_act_ext(N, 0.); - calc_ext_grav(n_act, x_act_new, v_act_new, pot_act_ext, a_act_new, adot_act_new); + if (calc_ext_grav.any_active) { + std::fill_n(begin(pot_act_ext), n_act, 0); + calc_ext_grav(n_act, x_act_new, v_act_new, pot_act_ext, a_act_new, adot_act_new); + } /* correct the active particles positions etc... on all the nodes */ double min_dt = dt_max; @@ -589,7 +588,7 @@ int main(int argc, char *argv[]) if (config.dt_min_warning && (myRank == 0)) { if (dt_tmp == dt_min) { - printf("!!! Warning1: dt_act = dt_min = %.6E \t ind_act = %07d \n", dt_tmp, ind_act[i]); + printf("!!! Warning1: dt_act = dt_min = %.6E \t ind_act = %07d time_cur=%.16E\n", dt_tmp, ind_act[i], time_cur); fflush(stdout); } } From 6048c7748e429395de9595fe23e6737af2e70e45 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Fri, 27 Aug 2021 19:08:57 -0400 Subject: [PATCH 59/65] special softening set before first acc adjustment --- phigrape.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/phigrape.cpp b/phigrape.cpp index c484045..aae2390 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -415,14 +415,16 @@ int main(int argc, char *argv[]) else if (config.live_smbh_count == 2) { black_hole_physics = Black_hole_physics(m[0], m[1], myRank, rootRank); black_hole_physics.set_xv(x[0], x[1], v[0], v[1]); - if (config.live_smbh_custom_eps >= 0) black_hole_physics.adjust_softening(pot[0], pot[1], a[0], a[1], adot[0], adot[1]); + if (config.live_smbh_custom_eps >= 0) { + black_hole_physics.set_softening(config.eps, config.live_smbh_custom_eps); + black_hole_physics.adjust_softening(pot[0], pot[1], a[0], a[1], adot[0], adot[1]); + } if (config.binary_smbh_pn) black_hole_physics.adjust_post_newtonian(dt_min, a[0], a[1], adot[0], adot[1]); } if (config.binary_smbh_pn) { black_hole_physics.set_post_newtonian(config.pn_c, config.pn_usage.data()); if (config.pn_usage[6]) black_hole_physics.set_spins(config.smbh1_spin.data(), config.smbh2_spin.data()); } - black_hole_physics.set_softening(config.eps, config.live_smbh_custom_eps); std::vector pot_ext(N, 0.); calc_ext_grav(N, x, v, pot_ext, a, adot); From 15227a9eee0fe63980e0e13849ed6bdf8e3a33f4 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Mon, 30 Aug 2021 09:31:53 -0400 Subject: [PATCH 60/65] exposed grapite_set_eps_bh in conf --- config.cpp | 1 + config.h | 1 + phigrape.conf | 9 +++++++++ phigrape.cpp | 2 ++ 4 files changed, 13 insertions(+) diff --git a/config.cpp b/config.cpp index 62c2cd3..db40311 100644 --- a/config.cpp +++ b/config.cpp @@ -237,6 +237,7 @@ Config::Config(std::string file_name) grapite_mask_file_name = get_parameter(dictionary, "grapite_mask_file_name", "grapite.mask"); etics_dump_coeffs = get_parameter(dictionary, "etics_dump_coeffs", false); grapite_active_search = get_parameter(dictionary, "grapite_active_search", false); + grapite_smbh_star_eps = get_parameter(dictionary, "grapite_smbh_star_eps", -1); grapite_dev_exec_threshold = get_parameter(dictionary, "grapite_dev_exec_threshold", 32); #endif diff --git a/config.h b/config.h index b07ffdc..93c0fa6 100644 --- a/config.h +++ b/config.h @@ -61,6 +61,7 @@ public: std::string grapite_mask_file_name; bool etics_dump_coeffs; bool grapite_active_search; + double grapite_smbh_star_eps; int grapite_dev_exec_threshold; #endif diff --git a/phigrape.conf b/phigrape.conf index 9643b6f..a7f3252 100644 --- a/phigrape.conf +++ b/phigrape.conf @@ -217,6 +217,15 @@ dt_scf = 0.015625 # accelerate the calculation in some circumstances [default: false] #grapite_active_search = true +# Custom softening length for SMBH-star interactions in the hybrid scheme only. +# This value (can also be zero) is used in the direct gravity calculation +# between SMBHs (tag=3) and both core (tag=0) and halo (tag=1) stars. If +# negative, the Plummer softening parameter (`eps`) is used in these +# interactions. Do not confuse with `live_smbh_custom_eps`, which is the +# softening length for SMBH-SMBH interactions, and works both in the normal and +# hybrid schemes. [default: -1] +#grapite_smbh_star_eps = 1E-6 + # If the number of active particles in a particular bunch is bigger than this # threshold, then the execution is on the GPU, otherwise on the CPU. When the # active bunch is small, the overhead of calculating the SCF gravity on the GPU diff --git a/phigrape.cpp b/phigrape.cpp index aae2390..1d18693 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -400,6 +400,8 @@ int main(int argc, char *argv[]) v[grapite_cep_index] = vdc; grapite_update_cep(time_cur, xdc, vdc, zeros, zeros); } + + if (config.grapite_smbh_star_eps >= 0) grapite_set_eps_bh(config.grapite_smbh_star_eps); #endif std::vector a(N), adot(N); From 8b71f4fe9249a2e46c2abbc3d8cd8bb9dee8c883 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Sun, 26 Dec 2021 17:20:20 -0500 Subject: [PATCH 61/65] Cleaned up corrector loop --- phigrape.cpp | 70 ++++++++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/phigrape.cpp b/phigrape.cpp index 1d18693..2976c59 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -163,7 +163,7 @@ public: { ind_act_loc.resize(n_loc); } - double get_minimum_time(const std::vector &t, std::vector &dt) + double get_minimum_time(const std::vector &t, const std::vector &dt) { double min_t_loc, min_t; #ifdef ETICS @@ -249,6 +249,29 @@ inline double aarseth_step(const double eta, const double dt, const double3 &a, return sqrt(eta*(a1abs*a2dot1abs+adot1abs*adot1abs)/(adot1abs*a3dot1abs+a2dot1abs*a2dot1abs)); } +inline double blockize_step(double dt, double dt_prev, double min_t, double dt_min, double dt_max) +{ + double dt_new = dt_prev; + if (dt < dt_min) dt_prev = dt_min; + if ((dt < dt_prev) && (dt > dt_min)) { + int power = log(dt)/M_LN2 - 1; + dt_new = pow(2.0, power); + } + if ((dt > 2*dt_new) && (fmod(min_t, 2*dt_new) == 0) && (2*dt_new <= dt_max)) dt_new *= 2; + return dt_new; +} + +inline void predictor(double min_t, const int n_act, const std::vector &ind_act, const std::vector &t, const std::vector &x, const std::vector &v, const std::vector &a, const std::vector &adot, std::vector &x_act_new, std::vector &v_act_new) +{ + for (int i=0; i0)) { int act_def_grapite_bh_count = 0; @@ -537,14 +562,7 @@ int main(int argc, char *argv[]) #endif /* predict the active particles positions etc... on all the nodes */ - for (int i=0; i 0) && (ind_act[i] < config.live_smbh_count)) eta_curr = config.eta/config.eta_bh_corr; else eta_curr = config.eta; - double dt_new = aarseth_step(eta_curr, dt_tmp, a_act_new[i], adot_act_new[i], a2, a3); + double dt_new = aarseth_step(eta_curr, dt_cur, a_act_new[i], adot_act_new[i], a2, a3); - //TODO the below should be moved to a function - if (dt_new < dt_min) dt_tmp = dt_min; - if ((dt_new < dt_tmp) && (dt_new > dt_min)) { - int power = log(dt_new)/log(2.0) - 1; - dt_tmp = pow(2.0, (double)power); // TODO why is this casting needed here? - } - - if ((dt_new > 2*dt_tmp) && (fmod(min_t, 2*dt_tmp) == 0) && (2*dt_tmp <= dt_max)) { - dt_tmp *= 2; - } + dt_new = blockize_step(dt_new, dt_cur, min_t, dt_min, dt_max); if (config.dt_min_warning && (myRank == 0)) { - if (dt_tmp == dt_min) { - printf("!!! Warning1: dt_act = dt_min = %.6E \t ind_act = %07d time_cur=%.16E\n", dt_tmp, ind_act[i], time_cur); + if (dt_new == dt_min) { + printf("!!! Warning1: dt_act = dt_min = %.6E \t ind_act = %07d time_cur=%.16E\n", dt_cur, ind_act[i], time_cur); fflush(stdout); } } - if (dt_tmp < min_dt) min_dt = dt_tmp; + if (dt_new < min_dt) min_dt = dt_new; x[j_act] = x_act_new[i]; v[j_act] = v_act_new[i]; t[j_act] = min_t; - dt[j_act] = dt_tmp; + dt[j_act] = dt_new; pot[j_act] = pot_act_new[i]; pot_ext[j_act] = pot_act_ext[i]; a[j_act] = a_act_new[i]; @@ -614,10 +623,8 @@ int main(int argc, char *argv[]) if (config.live_smbh_count==2) dt[1] = min_dt; } - if (config.binary_smbh_influence_sphere_output && (myRank == rootRank)) { - //TODO clean up this mass. We don't want to have all these _act arrays; they are only needed for this lame function. + if (config.binary_smbh_influence_sphere_output && (myRank == rootRank)) binary_smbh_influence_sphere_output(ind_act, n_act, timesteps, time_cur); - } /* load the new values for active particles to the local GRAPE's */ for (int i=0; i Date: Sun, 26 Dec 2021 21:40:50 -0500 Subject: [PATCH 62/65] Fixed BH softening correction when grapite_smbh_star_eps is defined --- phigrape.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/phigrape.cpp b/phigrape.cpp index 2976c59..d3a734e 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -441,7 +441,12 @@ int main(int argc, char *argv[]) black_hole_physics = Black_hole_physics(m[0], m[1], myRank, rootRank); black_hole_physics.set_xv(x[0], x[1], v[0], v[1]); if (config.live_smbh_custom_eps >= 0) { - black_hole_physics.set_softening(config.eps, config.live_smbh_custom_eps); +#ifdef ETICS + double eps = (config.grapite_smbh_star_eps >= 0)?config.grapite_smbh_star_eps:config.eps; +#else + double eps = config.eps; +#endif + black_hole_physics.set_softening(eps, config.live_smbh_custom_eps); black_hole_physics.adjust_softening(pot[0], pot[1], a[0], a[1], adot[0], adot[1]); } if (config.binary_smbh_pn) black_hole_physics.adjust_post_newtonian(dt_min, a[0], a[1], adot[0], adot[1]); From fcdafd94a6f044fdff3610ea0443ab2c1b38a35a Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Fri, 14 Jan 2022 17:54:38 -0500 Subject: [PATCH 63/65] Fixed PN force adjustment before PN parameters set --- phigrape.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phigrape.cpp b/phigrape.cpp index d3a734e..4dd4865 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -449,11 +449,11 @@ int main(int argc, char *argv[]) black_hole_physics.set_softening(eps, config.live_smbh_custom_eps); black_hole_physics.adjust_softening(pot[0], pot[1], a[0], a[1], adot[0], adot[1]); } - if (config.binary_smbh_pn) black_hole_physics.adjust_post_newtonian(dt_min, a[0], a[1], adot[0], adot[1]); } if (config.binary_smbh_pn) { black_hole_physics.set_post_newtonian(config.pn_c, config.pn_usage.data()); if (config.pn_usage[6]) black_hole_physics.set_spins(config.smbh1_spin.data(), config.smbh2_spin.data()); + black_hole_physics.adjust_post_newtonian(dt_min, a[0], a[1], adot[0], adot[1]); } std::vector pot_ext(N, 0.); From 633c82b917e706e9242af92a93ed458fb80d448d Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Thu, 19 May 2022 20:35:24 -0400 Subject: [PATCH 64/65] Enabled triple (plus) SMBHs --- black_holes.cpp | 141 ++++++++++++------------------------------------ black_holes.h | 34 ++++++------ config.cpp | 4 +- phigrape.cpp | 44 +++++++-------- 4 files changed, 75 insertions(+), 148 deletions(-) diff --git a/black_holes.cpp b/black_holes.cpp index 7790a3b..2e6f5f7 100644 --- a/black_holes.cpp +++ b/black_holes.cpp @@ -10,64 +10,39 @@ double L[3]; // needed in pn_bh_spin.c #undef SQR /* END legacy inclusion */ -void two_body_gravity( - const double m1, const double3 x1, const double3 v1, - const double m2, const double3 x2, const double3 v2, - const double eps, - double& pot1, double3& acc1, double3& jrk1, - double& pot2, double3& acc2, double3& jrk2) +void two_body_gravity(const Particle_ref& j, const Particle_ref& i, const double eps, double& pot, double3& acc, double3& jrk) { - double3 dx = x1 - x2; - double3 dv = v1 - v2; + double3 dx = i.x - j.x; + double3 dv = i.v - j.v; double r2 = dx.norm2() + eps*eps; double r = sqrt(r2); double r3 = r2*r; double r4 = r2*r2; double RP = 3*(dx*dv)/r; - pot1 = -m2/r; - pot2 = -m1/r; - acc1 = -m2*dx/r3; - acc2 = m1*dx/r3; - jrk1 = -m2*(dv/r3 - RP*dx/r4); - jrk2 = m1*(dv/r3 - RP*dx/r4); + pot = -j.m/r; + acc = -j.m*dx/r3; + jrk = -j.m*(dv/r3 - RP*dx/r4); } -void Black_hole_physics::adjust_softening( - double& pot1, double& pot2, - double3& acc1, double3& acc2, - double3& jrk1, double3& jrk2) +void Black_hole_physics::adjust_softening(const std::vector& particles) { if (eps_new < 0) return; - // calculate and "minus" the BH <-> BH softened pot, acc & jerk - two_body_gravity( - m1, x1, v1, - m2, x2, v2, - eps_old, - bbh_grav.pot1, bbh_grav.a1, bbh_grav.adot1, - bbh_grav.pot2, bbh_grav.a2, bbh_grav.adot2); - pot1 -= bbh_grav.pot1; - pot2 -= bbh_grav.pot2; - acc1 -= bbh_grav.a1; - acc2 -= bbh_grav.a2; - jrk1 -= bbh_grav.adot1; - jrk2 -= bbh_grav.adot2; - - // calculate and "plus" the new BH <-> BH unsoftened pot, acc, jerk - two_body_gravity( - m1, x1, v1, - m2, x2, v2, - eps_new, - bbh_grav.pot1, bbh_grav.a1, bbh_grav.adot1, - bbh_grav.pot2, bbh_grav.a2, bbh_grav.adot2); - pot1 += bbh_grav.pot1; - pot2 += bbh_grav.pot2; - acc1 += bbh_grav.a1; - acc2 += bbh_grav.a2; - jrk1 += bbh_grav.adot1; - jrk2 += bbh_grav.adot2; + double pot_old, pot_new; + double3 acc_old, acc_new, jrk_old, jrk_new; + for (int j = 0; j < particles.size(); j++) { + for (int i = 0; i < particles.size(); i++) { + if (i == j) continue; + two_body_gravity(particles[j], particles[i], eps_old, pot_old, acc_old, jrk_old); + two_body_gravity(particles[j], particles[i], eps_new, pot_new, acc_new, jrk_new); + particles[i].pot += pot_new - pot_old; + particles[i].acc += acc_new - acc_old; + particles[i].jrk += jrk_new - jrk_old; + } + } } +#if 0 void Black_hole_physics::adjust_post_newtonian( const double dt_bh, // pn_usage should be const double3& acc1, double3& acc2, @@ -76,8 +51,8 @@ void Black_hole_physics::adjust_post_newtonian( // calculate and "plus" the new BH <-> BH : PN1, PN2, PN2.5, PN3, PN3.5 : acc, jerk // TODO maybe have the PN terms as local variables here? int tmp; - tmp = calc_force_pn_BH(m1, x1, v1, bbh_grav.spin1, - m2, x2, v2, bbh_grav.spin2, + tmp = calc_force_pn_BH(masses[0], x1, v1, bbh_grav.spin1, + masses[1], x2, v2, bbh_grav.spin2, c, dt_bh, pn_usage, (double(*)[3])bbh_grav.a_pn1, (double(*)[3])bbh_grav.adot_pn1, (double(*)[3])bbh_grav.a_pn2, (double(*)[3])bbh_grav.adot_pn2, myRank, rootRank); @@ -98,72 +73,22 @@ void Black_hole_physics::adjust_post_newtonian( jrk1 += jrk1_corr; jrk2 += jrk2_corr; } +#endif -void Black_hole_physics::write_bh_data(double time_cur, const std::vector &m, const std::vector &x, const std::vector &v, const std::vector &pot, const std::vector &a, const std::vector &adot, const std::vector &dt) +void Black_hole_physics::write_bh_data(const double time_cur, const int count, const std::vector &m, const std::vector &x, const std::vector &v, const std::vector &pot, const std::vector &a, const std::vector &adot, const std::vector &dt) { - // This function logs data on the black hole(s). It uses both external data - // (the arguments to this function) and optionall internal data to this - // object (the most recently calculated force and post-Newtonian terms). auto out = fopen("bh.dat", "a"); - if (count == 2) { - for (int i=0; i < 2; i++) { - double3 *a_pn, *adot_pn, a_bh, adot_bh; - double pot_bh; - if (i==0) { - a_pn = bbh_grav.a_pn1; - adot_pn = bbh_grav.adot_pn1; - pot_bh = bbh_grav.pot1; - a_bh = bbh_grav.a1; - adot_bh = bbh_grav.adot1; - } else { - a_pn = bbh_grav.a_pn2; - adot_pn = bbh_grav.adot_pn2; - pot_bh = bbh_grav.pot2; - a_bh = bbh_grav.a2; - adot_bh = bbh_grav.adot2; - } - if (eps_new >= 0) { - fprintf(out, "%.16E \t %.8E \t % .16E % .16E % .16E \t %.16E \t % .16E % .16E % .16E \t %.16E \t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t %.8E \t\t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E ", - time_cur, m[i], - x[i][0], x[i][1], x[i][2], x[i].norm(), - v[i][0], v[i][1], v[i][2], v[i].norm(), - pot[i], - a[i][0], a[i][1], a[i][2], a[i].norm(), - adot[i][0], adot[i][1], adot[i][2], adot[i].norm(), - dt[i], - pot_bh, - a_bh[0], a_bh[1], a_bh[2], a_bh.norm(), - adot_bh[0], adot_bh[1], adot_bh[2], adot_bh.norm()); - if (c > 0) { - fprintf(out, "\t"); - for (int pn_idx=0; pn_idx < 7; pn_idx++) { - fprintf(out, "\t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E ", a_pn[pn_idx][0], a_pn[pn_idx][1], a_pn[pn_idx][2], a_pn[pn_idx].norm(), adot_pn[pn_idx][0], adot_pn[pn_idx][1], adot_pn[pn_idx][2], adot_pn[pn_idx].norm()); - } - } - fprintf(out, "\n"); - } else { - fprintf(out,"%.16E \t %.8E \t % .16E % .16E % .16E \t %.16E \t % .16E % .16E % .16E \t %.16E \t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t %.8E \n", - time_cur, m[i], - x[i][0], x[i][1], x[i][2], x[i].norm(), - v[i][0], v[i][1], v[i][2], v[i].norm(), - pot[i], - a[i][0], a[i][1], a[i][2], a[i].norm(), - adot[i][0], adot[i][1], adot[i][2], adot[i].norm(), - dt[i]); - } - } - fprintf(out, "\n"); - } else if (count == 1) { + for (int i = 0; i < count; i++) { fprintf(out,"%.16E \t %.8E \t % .16E % .16E % .16E \t %.16E \t % .16E % .16E % .16E \t %.16E \t % .8E \t % .8E % .8E % .8E \t %.8E \t % .8E % .8E % .8E \t %.8E \t %.8E \n", - time_cur, m[0], - x[0][0], x[0][1], x[0][2], x[0].norm(), - v[0][0], v[0][1], v[0][2], v[0].norm(), - pot[0], - a[0][0], a[0][1], a[0][2], a[0].norm(), - adot[0][0], adot[0][1], adot[0][2], adot[0].norm(), - dt[0]); - fprintf(out,"\n"); + time_cur, m[i], + x[i][0], x[i][1], x[i][2], x[i].norm(), + v[i][0], v[i][1], v[i][2], v[i].norm(), + pot[i], + a[i][0], a[i][1], a[i][2], a[i].norm(), + adot[i][0], adot[i][1], adot[i][2], adot[i].norm(), + dt[i]); } + fprintf(out, "\n"); fclose(out); } diff --git a/black_holes.h b/black_holes.h index 121ae7a..3d79184 100644 --- a/black_holes.h +++ b/black_holes.h @@ -3,6 +3,17 @@ #include #include "double3.h" +struct Particle_ref { + Particle_ref(double& m, double3& x, double3& v, double& pot, double3& acc, double3& jrk) : + m(m), x(x), v(v), pot(pot), acc(acc), jrk(jrk) {} + const double& m; + const double3& x; + const double3& v; + double& pot; + double3& acc; + double3& jrk; +}; + struct Bbh_gravity { double pot1, pot2; double3 a1, a2, adot1, adot2, a_pn1[7], a_pn2[7], adot_pn1[7], adot_pn2[7]; @@ -13,8 +24,8 @@ class Black_hole_physics { public: Black_hole_physics() : count(0), c(0) {} - Black_hole_physics(const double m1, const double m2, const int myRank, const int rootRank) - : m1(m1), m2(m2), count(2), c(0), myRank(myRank), rootRank(rootRank) {} + Black_hole_physics(const int count, const int myRank, const int rootRank) + : count(count), c(0), myRank(myRank), rootRank(rootRank) {} void set_post_newtonian(const double c, const int pn_usage[7]) { this->c = c; @@ -25,34 +36,23 @@ public: std::copy(spin1, spin1+3, this->bbh_grav.spin1); std::copy(spin2, spin2+3, this->bbh_grav.spin2); } - void set_xv(const double3& x1, const double3& x2, const double3& v1, const double3& v2) - { - this->x1 = x1; - this->x2 = x2; - this->v1 = v1; - this->v2 = v2; - } void set_softening(const double eps_old, const double eps_new) { this->eps_old = eps_old; this->eps_new = eps_new; } - void adjust_softening( - double& pot1, double& pot2, - double3& acc1, double3& acc2, - double3& jrk1, double3& jrk2); + void adjust_softening(const std::vector& particles); void adjust_post_newtonian( const double dt_bh, // pn_usage should be const double3& acc1, double3& acc2, double3& jrk1, double3& jrk2); - void write_bh_data(double time_cur, const std::vector &m, const std::vector &x, const std::vector &v, const std::vector &pot, const std::vector &a, const std::vector &adot, const std::vector &dt); + void write_bh_data(const double time_cur, const int count, const std::vector &m, const std::vector &x, const std::vector &v, const std::vector &pot, const std::vector &a, const std::vector &adot, const std::vector &dt); public: //TODO make private - double m1, m2; + /////////////std::vector masses; int count; int myRank, rootRank; double eps_old, eps_new; - double3 x1, v1, x2, v2; double c; int pn_usage[7]; Bbh_gravity bbh_grav; @@ -101,4 +101,4 @@ private: const std::vector &x, &v; std::vector inf_event; FILE *out; -}; \ No newline at end of file +}; diff --git a/config.cpp b/config.cpp index db40311..86e704e 100644 --- a/config.cpp +++ b/config.cpp @@ -133,8 +133,8 @@ void Config::error_checking() if (output_hdf5) throw std::runtime_error("HDF5 output format (output_hdf5=true) requires the code to be compiled with HAS_HDF5"); #endif - if ((live_smbh_count < 0) || (live_smbh_count > 2)) - throw std::runtime_error("The number of live black holes (live_smbh_count) can be 0, 1, or 2"); + if (live_smbh_count < 0) + throw std::runtime_error("The number of live black holes (live_smbh_count) has to be greater than or equals to zero"); if (binary_smbh_pn && (live_smbh_count!=2)) throw std::runtime_error("Post-Newtonian gravity (binary_smbh_pn=true) requires live_smbh_count=2"); if (binary_smbh_pn && (pn_c <= 0)) diff --git a/phigrape.cpp b/phigrape.cpp index 4dd4865..f3d8546 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -435,11 +435,10 @@ int main(int argc, char *argv[]) calc_self_grav(time_cur, N, ind, x, v, pot, a, adot); Black_hole_physics black_hole_physics; - if (config.live_smbh_count == 1) - black_hole_physics = Black_hole_physics(m[0], 0, myRank, rootRank); - else if (config.live_smbh_count == 2) { - black_hole_physics = Black_hole_physics(m[0], m[1], myRank, rootRank); - black_hole_physics.set_xv(x[0], x[1], v[0], v[1]); + std::vector smbh_list; + if (config.live_smbh_count >= 1) + black_hole_physics = Black_hole_physics(config.live_smbh_count, myRank, rootRank); + else if (config.live_smbh_count >= 2) { if (config.live_smbh_custom_eps >= 0) { #ifdef ETICS double eps = (config.grapite_smbh_star_eps >= 0)?config.grapite_smbh_star_eps:config.eps; @@ -447,13 +446,18 @@ int main(int argc, char *argv[]) double eps = config.eps; #endif black_hole_physics.set_softening(eps, config.live_smbh_custom_eps); - black_hole_physics.adjust_softening(pot[0], pot[1], a[0], a[1], adot[0], adot[1]); + for (int i = 0; i < config.live_smbh_count; i++) + smbh_list.emplace_back(m[i], x[i], v[i], pot[i], a[i], adot[i]); + black_hole_physics.adjust_softening(smbh_list); } } if (config.binary_smbh_pn) { + throw std::runtime_error("This is the triple+ SMBH version, it cannot do PN yet!"); + #if 0 black_hole_physics.set_post_newtonian(config.pn_c, config.pn_usage.data()); if (config.pn_usage[6]) black_hole_physics.set_spins(config.smbh1_spin.data(), config.smbh2_spin.data()); black_hole_physics.adjust_post_newtonian(dt_min, a[0], a[1], adot[0], adot[1]); + #endif } std::vector pot_ext(N, 0.); @@ -532,7 +536,7 @@ int main(int argc, char *argv[]) Binary_smbh_influence_sphere_output binary_smbh_influence_sphere_output(config.binary_smbh_influence_radius_factor, N, m, x, v, pot, dt); Write_bh_nb_data write_bh_nb_data(config.live_smbh_neighbor_number, config.live_smbh_count, N, m, x, v); if (myRank == rootRank) { - if (config.live_smbh_output) black_hole_physics.write_bh_data(time_cur, m, x, v, pot, a, adot, dt); + if (config.live_smbh_output) black_hole_physics.write_bh_data(time_cur, config.live_smbh_count, m, x, v, pot, a, adot, dt); if (config.live_smbh_neighbor_output) write_bh_nb_data(time_cur); } /* if (myRank == rootRank) */ @@ -547,23 +551,23 @@ int main(int argc, char *argv[]) active_search.get_active_indices(min_t, t, dt, ind_act, n_act); /* Find the BH(s) indices in the active list */ - int i_bh1=0, i_bh2=1; + smbh_list.clear(); #ifdef ETICS /* Unlike with the simple active search, with GPU accelerated GRAPite active search, the list of active indices is not sorted. */ int n_bh = config.live_smbh_count; if (config.grapite_active_search && (n_bh>0)) { int act_def_grapite_bh_count = 0; - int i_bh[n_bh]; for (int i=0; i= 0) black_hole_physics.adjust_softening(pot_act_new[i_bh1], pot_act_new[i_bh2], a_act_new[i_bh1], a_act_new[i_bh2], adot_act_new[i_bh1], adot_act_new[i_bh2]); + if (config.live_smbh_count >= 2) { + if (config.live_smbh_custom_eps >= 0) black_hole_physics.adjust_softening(smbh_list); + #if 0 if (config.binary_smbh_pn) black_hole_physics.adjust_post_newtonian(dt[i_bh1], a_act_new[i_bh1], a_act_new[i_bh2], adot_act_new[i_bh1], adot_act_new[i_bh2]); + #endif } /* Calculate gravity on active particles due to external forces */ @@ -623,10 +628,7 @@ int main(int argc, char *argv[]) } /* i */ /* define the min. dt over all the act. part. and set it also for the BH... */ - if (config.live_smbh_count > 0) { - if (config.live_smbh_count>=1) dt[0] = min_dt; - if (config.live_smbh_count==2) dt[1] = min_dt; - } + for (int i=0; i < config.live_smbh_count; i++) dt[i] = min_dt; if (config.binary_smbh_influence_sphere_output && (myRank == rootRank)) binary_smbh_influence_sphere_output(ind_act, n_act, timesteps, time_cur); @@ -652,7 +654,7 @@ int main(int argc, char *argv[]) if (time_cur >= t_bh) { if (myRank == rootRank) { /* Write BH data... */ - if (config.live_smbh_output) black_hole_physics.write_bh_data(time_cur, m, x, v, pot, a, adot, dt); + if (config.live_smbh_output) black_hole_physics.write_bh_data(time_cur, config.live_smbh_count, m, x, v, pot, a, adot, dt); /* Write BH NB data... */ if (config.live_smbh_neighbor_output) write_bh_nb_data(time_cur); From 6351f8075bed497d07d8a1c9202e65288af48443 Mon Sep 17 00:00:00 2001 From: Yohai Meiron Date: Mon, 30 May 2022 10:28:12 -0400 Subject: [PATCH 65/65] Added #include --- phigrape.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/phigrape.cpp b/phigrape.cpp index f3d8546..52ec687 100644 --- a/phigrape.cpp +++ b/phigrape.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include "black_holes.h" #include "config.h"