void calc_potentials(void) { int64_t i,j=0,count=0,last_id=-1; for (i=0; i<num_p; i++) { if (p[i].hid != last_id) { if (last_id >= 0) h[last_id].num_p = i-h[last_id].p_start; last_id = p[i].hid; h[last_id].p_start = i; } } if (last_id >= 0) h[last_id].num_p = i-h[last_id].p_start; for (i=0; i<num_h; i++) { struct halo *the_h = h+i; if (the_h->id < 0) continue; if (max_num_po < the_h->num_p) { max_num_po = the_h->num_p; po = check_realloc(po, sizeof(struct potential)*max_num_po, "Allocating potentials"); } for (j=0; j<the_h->num_p; j++) { po[j].id = p[the_h->p_start+j].id; memcpy(po[j].pos, p[the_h->p_start+j].pos, sizeof(float)*6); po[j].pe = po[j].ke = 0; } compute_kinetic_energy(po, the_h->num_p, the_h->pos+3, the_h->pos); compute_potential(po, the_h->num_p); count=0; for (j=0; j<the_h->num_p; j++) if (po[j].pe >= po[j].ke) count++; printf("%"PRId64" %"PRId64"\n", the_h->id, count); for (j=0; j<the_h->num_p; j++) if (po[j].pe >= po[j].ke) printf("%"PRId64"\n", po[j].id); } }
int main(int argc, char **argv) { char buffer[1024]; float f[6]; //float cen[6] = {0}; float cen[6] = //{26.203939, 14.303870, 6.479383, -240.270966, 103.091614, 384.215027}; {26.203751, 14.304119, 6.480038, -225.746475, 103.026428, 409.277405}; int64_t i; //PARTICLE_MASS = 1.36e8*20; SCALE_NOW = 1.0; PARTICLE_MASS = 1.36e8; while (fgets(buffer, 1024, stdin)) { sscanf(buffer, "%f %f %f %f %f %f", f, f+1, f+2, f+3, f+4, f+5); //for (i=0; i<6; i++) cen[i]+=f[i]; memcpy(pot[num_pot].pos, f, sizeof(float)*6); pot[num_pot].flags = 0; num_pot++; if (num_pot == NUM_POT) break; } //for (i=0; i<6; i++) cen[i]/=(float)num_pot; //for (i=0; i<100; i++) compute_kinetic_energy(pot, num_pot, cen); compute_potential(pot, num_pot); calc_circ_potential(pot, num_pot, cen); qsort(pot, num_pot, sizeof(struct potential), compare_x); for (i=0; i<num_pot; i++) { printf("%f %f %f %g %g %g\n", pot[i].pos[0], pot[i].pos[1], pot[i].pos[2], pot[i].pe, pot[i].pe2, pot[i].pe-pot[i].ke); //, pot[i].ke, //(pot[i].pe > pot[i].ke) ? 1 : 0); } }
int main(){ iniciar(); float a[3] = {2.4, 2.9, 4.1}; float b[3] = {2.4, 2.9, 4.1}; init_nbody(3, a, b); compute_potential(); char line[256]; char header[256]; fr = fopen("32Mpc_050.0256.fvol", "rt"); while(fgets(line, 256, fr) != NULL){ sscanf(line, "%s", header); } fclose(fr); printf("%s\n", header); return 0; }
/*! This function finds the next synchronization point of the system (i.e. the * earliest point of time any of the particles needs a force computation), * and drifts the system to this point of time. If the system drifts over * the desired time of a snapshot file, the function will drift to this * moment, generate an output, and then resume the drift. */ void find_next_sync_point_and_drift(void) { int n, flag, *temp, i, nskip=20; long long int min_glob, min; double timeold; double t0, t1; int task_max, loc_max, tot_loc_max, list_loc_max[NTask], n_check; double hubble_a, dt_raytrace=0, nh_local, nh_max, tot_nh_max, mass_max, tot_mass_max, ray_dist2, list_nh_max[NTask], list_mass_max[NTask]; #ifdef RAYTRACE_TG double nu_min_H = 3.3e15; double nu_min_He = 1.32e16; double c_s = 16.5967; //soundspeed of 20,000K gas in km/s #endif if (All.ComovingIntegrationOn) { /* comoving variables */ hubble_a = All.Omega0 / (All.Time * All.Time * All.Time) + (1 - All.Omega0 - All.OmegaLambda) / (All.Time * All.Time) + All.OmegaLambda; hubble_a = All.Hubble * All.HubbleParam * sqrt(hubble_a); } else hubble_a = 1.0; t0 = second(); timeold = All.Time; /*SINK - must skip any accreted particles at the beginning of the SPH particle list*/ for(i = 0; i < NumPart; i++) { if(P[i].Type == 5 || P[i].ID >= 0) break; } if(i == NumPart) min = INT_MAX; else { for(n = i+1, min = P[i].Ti_endstep; n < NumPart; n++) { if(P[n].Type == 0 && P[n].ID < 0) /*SINK*/ continue; if(min > P[n].Ti_endstep) min = P[n].Ti_endstep; } } MPI_Allreduce(&min, &min_glob, 1, MPI_LONG, MPI_MIN, MPI_COMM_WORLD); /* We check whether this is a full step where all particles are synchronized */ flag = 1; for(n = 0; n < NumPart; n++) { if(P[n].Type == 0 && P[n].ID < 0) /*SINK*/ continue; if(P[n].Ti_endstep > min_glob) flag = 0; } MPI_Allreduce(&flag, &Flag_FullStep, 1, MPI_INT, MPI_MIN, MPI_COMM_WORLD); #ifdef PMGRID if(min_glob >= All.PM_Ti_endstep) { min_glob = All.PM_Ti_endstep; Flag_FullStep = 1; } #endif /* Determine 'NumForceUpdate', i.e. the number of particles on this processor that are going to be active */ for(n = 0, NumForceUpdate = 0; n < NumPart; n++) { if(P[n].Type == 0 && P[n].ID < 0) /*SINK*/ continue; if(P[n].Ti_endstep == min_glob) #ifdef SELECTIVE_NO_GRAVITY if(!((1 << P[n].Type) & (SELECTIVE_NO_GRAVITY))) #endif NumForceUpdate++; } /* note: NumForcesSinceLastDomainDecomp has type "long long" */ temp = malloc(NTask * sizeof(int)); MPI_Allgather(&NumForceUpdate, 1, MPI_INT, temp, 1, MPI_INT, MPI_COMM_WORLD); for(n = 0; n < NTask; n++) All.NumForcesSinceLastDomainDecomp += temp[n]; free(temp); t1 = second(); All.CPU_Predict += timediff(t0, t1); tot_nh_max = nh_max = nh_local = tot_mass_max = mass_max = tot_loc_max = loc_max = task_max = 0; for(n = 0; n < NTask; n++) list_nh_max[n] = list_mass_max[n] = list_loc_max[n] = 0; for(i = 0; i < N_gas; i++) if(P[i].ID > 0 /*&& P[i].Mass / All.HubbleParam * 1.0e10 < All.RefinementMass*/) { nh_local = SphP[i].Density*All.UnitDensity_in_cgs*All.HubbleParam*All.HubbleParam/All.Time/All.Time/All.Time*HYDROGEN_MASSFRAC/PROTONMASS; //if(nh_local > nh_max) if(P[i].ID == 2931027) { nh_max = nh_local; mass_max = P[i].Mass; loc_max = i; } } MPI_Allgather(&nh_max, 1, MPI_DOUBLE, &list_nh_max, 1, MPI_DOUBLE, MPI_COMM_WORLD); MPI_Allgather(&mass_max, 1, MPI_DOUBLE, &list_mass_max, 1, MPI_DOUBLE, MPI_COMM_WORLD); MPI_Allgather(&loc_max, 1, MPI_INT, &list_loc_max, 1, MPI_INT, MPI_COMM_WORLD); for(n = 0; n < NTask; n++) if(list_nh_max[n] > tot_nh_max) { tot_nh_max = list_nh_max[n]; tot_mass_max = list_mass_max[n]; tot_loc_max = list_loc_max[n]; task_max = n; } dt_raytrace = fmax(fmax((min_glob - All.Time_last) * All.Timebase_interval, All.MinSizeTimestep), All.Timebase_interval) / hubble_a * All.UnitTime_in_s; All.t_s = All.t_s + dt_raytrace; //time in seconds All.r_s = All.x_s * c_s * All.t_s / 3.08568025e16 / All.Time * All.HubbleParam; //shock radius in km (converted to comoving kpc) All.n_s = All.alpha0/(4.0*3.14159*6.67e-8*pow(All.t_s,2))*HYDROGEN_MASSFRAC/PROTONMASS; All.n_sink = All.alpha0/(4.0*3.14159*6.67e-8*pow((All.tacc - 300.*3.e7),2))*HYDROGEN_MASSFRAC/PROTONMASS; //All.n_sink = 1.e-1; All.Time_last = min_glob; #ifdef RAYTRACE_TG if(ThisTask == task_max) ray_dist2 = (P[tot_loc_max].Pos[0] - All.BoxSize / 2.0) * (P[tot_loc_max].Pos[0] - All.BoxSize / 2.0) + (P[tot_loc_max].Pos[1] - All.BoxSize / 2.0) * (P[tot_loc_max].Pos[1] - All.BoxSize / 2.0) + (P[tot_loc_max].Pos[2] - All.BoxSize / 2.0) * (P[tot_loc_max].Pos[2] - All.BoxSize / 2.0); MPI_Bcast(&ray_dist2, 1, MPI_DOUBLE, task_max, MPI_COMM_WORLD); if(ThisTask == task_max) { if(All.NumCurrentTiStep % 100 == 0) printf("Densest particle (ID %d) with nh = %g at x = %g, y = %g, z = %g and mass %g\n", P[tot_loc_max].ID, tot_nh_max, P[tot_loc_max].Pos[0], P[tot_loc_max].Pos[1], P[tot_loc_max].Pos[2], P[tot_loc_max].Mass / All.HubbleParam * 1.0e10); for(n = 0; n < N_gas; n++) if(P[n].ID == P[tot_loc_max].ID) //center ray at most dense particle { All.star_mass = P[n].Mass/All.HubbleParam/1.e-10; //sink mass in solar masses printf("star_mass =%lg\n", All.star_mass); //All.star_mass = 1.e-5; //All.star_mass = 0; //All.star_mass = 2.e1; } n_check = 140740; if(All.NumCurrentTiStep == 0) { //All.mdot= 0.095*pow(All.star_mass, -0.814); All.numtot = 155639; All.alpha = alpha_calc(n_check); All.mdot = mdot_calc(All.numtot); //All.mdot = 1.e-7; //All.mdot = 1.e6; } All.flag_sink = 0; if(All.NumCurrentTiStep == 10 || All.NumCurrentTiStep == 1000 || All.t_s - All.t_s0 > 3.e7) { All.alpha = alpha_calc(n_check); All.mdot = mdot_calc(All.numtot); //All.mdot= 1.e-7; //All.mdot= 1.e6; All.numtot = All.numtot + All.sink_number_global; All.t_s0 = All.t_s; All.flag_sink = 1; printf("All.numtot = %d, All.t_s0_sink = %lg, All.t_s0 = %lg\n", All.numtot, All.t_s0_sink, All.t_s0); } if(All.NumCurrentTiStep < 1) All.lum_tot = lum_calc(1, All.star_mass, All.mdot, nu_min_H, 1.e-5); if(All.NumCurrentTiStep % 100 == 0) printf("run lum_tot = %lg, Teff = %lg, mdot = %lg\n", All.lum_tot, All.Teff, All.mdot); if(All.ray_flag_sun == 3) { for(i=0; i<=6; i++) { All.heat_ion[i] = heat_ion_rates(i, All.lum_tot, All.Teff); COOLR.heat_ion[i] = All.heat_ion[i]; if(All.NumCurrentTiStep % 10000 == 0) printf("heat_ion %d = %lg\n", i, COOLR.heat_ion[i]); } } } MPI_Bcast(&All.star_mass, 1, MPI_DOUBLE, task_max, MPI_COMM_WORLD); MPI_Bcast(&All.star_rad, 1, MPI_DOUBLE, task_max, MPI_COMM_WORLD); MPI_Bcast(&All.alpha, 1, MPI_DOUBLE, task_max, MPI_COMM_WORLD); MPI_Bcast(&All.numtot, 1, MPI_INT, task_max, MPI_COMM_WORLD); MPI_Bcast(&All.mdot, 1, MPI_DOUBLE, task_max, MPI_COMM_WORLD); MPI_Bcast(&All.t_s0, 1, MPI_DOUBLE, task_max, MPI_COMM_WORLD); MPI_Bcast(&All.flag_sink, 1, MPI_INT, task_max, MPI_COMM_WORLD); MPI_Bcast(&All.tacc, 1, MPI_DOUBLE, task_max, MPI_COMM_WORLD); MPI_Bcast(&COOLR.heat_ion, 7, MPI_DOUBLE, task_max, MPI_COMM_WORLD); //make sure ray doesn't go outside of box (?) //ARS adding condition that the LW radiation actually needs to be significant before computation time will be spent on the ray-tracing) if(tot_nh_max >= 0.99*All.ray_crit_dens && ray.flag_continue == 0 && ray_dist2 < All.ray_r_max_sink * All.ray_r_max_sink) { ray.flag_start = 1; if(ThisTask == task_max) All.ray_center_ID = P[tot_loc_max].ID; MPI_Bcast(&All.ray_center_ID, 1, MPI_INT, task_max, MPI_COMM_WORLD); if(ThisTask == task_max && All.NumCurrentTiStep % 1000 == 0) printf("Found starp (ID %d) at x = %g, y = %g, z = %g with mass %g\n", P[tot_loc_max].ID, P[tot_loc_max].Pos[0], P[tot_loc_max].Pos[1], P[tot_loc_max].Pos[2], P[tot_loc_max].Mass / All.HubbleParam * 1.0e10); } // ARS asks why we cannot have a SINK be a star particle (starp)? if(tot_nh_max > 0.99*All.SinkCriticalDens && ray_dist2 < All.ray_r_max_sink * All.ray_r_max_sink) { if(ThisTask == task_max && All.NumCurrentTiStep % 100 == 0) printf("Problem! A sink instead of a starp will form (ID %d) at x = %g, y = %g, z = %g with mass %g! Aborting...\n", P[tot_loc_max].ID, P[tot_loc_max].Pos[0], P[tot_loc_max].Pos[1], P[tot_loc_max].Pos[2], P[tot_loc_max].Mass / All.HubbleParam * 1.0e10); //exit(0); } if(All.lum_tot < 1.e36 || All.star_mass < 1.0) { nskip = 100; if(ThisTask == 0 && All.NumCurrentTiStep % 100 == 0) printf("Let's not ray trace quite so often\n"); } if(ray.flag_start == 1 && ray.flag_continue == 0 || (ray.flag_start == 1 && All.NumCurrentTiStep % nskip == 0) || (ray.flag_start == 1 && All.t_s - All.t_s0_acc > 3.e5) || All.NumCurrentTiStep < 2) //ARS asks: Where should the parentheses go? { All.t_s0_acc = All.t_s; if(ThisTask == 0) printf("Imma gonna ray trace so there.\n"); if(ray.flag_start == 1 && ray.flag_continue == 0) { All.Time_last_raytrace = All.Time; dt_raytrace = fmax(All.Timebase_interval, All.MinSizeTimestep) / hubble_a * All.UnitTime_in_s; } else dt_raytrace = fmax(fmax((min_glob - All.Time_last_raytrace) * All.Timebase_interval, All.MinSizeTimestep), All.Timebase_interval) / hubble_a * All.UnitTime_in_s; if(ThisTask == task_max) { ray.Q_H_ion = lum_calc(0, All.star_mass, All.mdot, nu_min_H, dt_raytrace); ray.Q_He_ion = lum_calc(0, All.star_mass, All.mdot, nu_min_He, dt_raytrace); All.Q_LW = lum_calc(4, All.star_mass, All.mdot, nu_min_H, dt_raytrace); All.lum_tot = lum_calc(1, All.star_mass, All.mdot, nu_min_H, dt_raytrace); } MPI_Bcast(&ray.Q_H_ion, 1, MPI_DOUBLE, task_max, MPI_COMM_WORLD); MPI_Bcast(&ray.Q_He_ion, 1, MPI_DOUBLE, task_max, MPI_COMM_WORLD); MPI_Bcast(&All.lum_tot, 1, MPI_DOUBLE, task_max, MPI_COMM_WORLD); MPI_Bcast(&All.Teff, 1, MPI_DOUBLE, task_max, MPI_COMM_WORLD); All.r_s = All.x_s * c_s * All.t_s / 3.08568025e16 / All.Time * All.HubbleParam; //shock radius in km (converted to comoving kpc) All.n_s = All.alpha0/(4.0*3.14159*6.67e-8*pow(All.t_s,2))*HYDROGEN_MASSFRAC/PROTONMASS; All.n_sink = All.alpha0/(4.0*3.14159*6.67e-8*pow((All.tacc - 300.*3.e7),2))*HYDROGEN_MASSFRAC/PROTONMASS; All.n_hii = All.alpha0/(4.0*3.14159*6.67e-8*pow((All.tacc - 1600.*3.e7),2))*HYDROGEN_MASSFRAC/PROTONMASS; if(All.n_hii < 2.35e6) All.n_hii = 2.35e6; //All.n_hii = 1.e3; if(ThisTask == 0) printf("t_s = %lg, tacc = %lg, r_s = %lg, n_s = %lg n_sink = %lg, n_hii = %lg\n", All.t_s, All.tacc, All.r_s, All.n_s, All.n_sink, All.n_hii); //if(All.lum_tot > 0.0) raytrace_TG(dt_raytrace); All.Time_last_raytrace = min_glob; } #endif while(min_glob >= All.Ti_nextoutput && All.Ti_nextoutput >= 0) { #ifdef CHEMCOOL All.NeedAbundancesForOutput = 1; #endif move_particles(All.Ti_Current, All.Ti_nextoutput); All.Ti_Current = All.Ti_nextoutput; if(All.ComovingIntegrationOn) All.Time = All.TimeBegin * exp(All.Ti_Current * All.Timebase_interval); else All.Time = All.TimeBegin + All.Ti_Current * All.Timebase_interval; #ifdef OUTPUTPOTENTIAL All.NumForcesSinceLastDomainDecomp = 1 + All.TotNumPart * All.TreeDomainUpdateFrequency; domain_Decomposition(); compute_potential(); #endif if(All.NumCurrentTiStep > 20) savepositions(All.SnapshotFileCount++); /* write snapshot file */ #ifdef CHEMCOOL All.NeedAbundancesForOutput = 0; #endif All.Ti_nextoutput = find_next_outputtime(All.Ti_nextoutput + 1); #ifdef CHEMCOOL All.Ti_nextnextoutput = find_next_outputtime(All.Ti_nextoutput + 1); #endif } move_particles(All.Ti_Current, min_glob); All.Ti_Current = min_glob; if(All.ComovingIntegrationOn) All.Time = All.TimeBegin * exp(All.Ti_Current * All.Timebase_interval); else All.Time = All.TimeBegin + All.Ti_Current * All.Timebase_interval; All.TimeStep = All.Time - timeold; }
/*! This routine contains the main simulation loop that iterates over single * timesteps. The loop terminates when the cpu-time limit is reached, when a * `stop' file is found in the output directory, or when the simulation ends * because we arrived at TimeMax. */ void run(void) { FILE *fd; int stopflag = 0; char stopfname[200], contfname[200]; double t0, t1, tstart, tend, nh_local, nh_max, tot_dens_max, nh_max_nosink, tot_nh_max_nosink; int nsinks, i, j, k; /*SINKS*/ double a3, a3inv, hubble_param, hubble_param2, Temp, SinkCriticalDensity; sprintf(stopfname, "%sstop", All.OutputDir); sprintf(contfname, "%scont", All.OutputDir); unlink(contfname); do /* main loop */ { t0 = second(); if(All.ComovingIntegrationOn) { a3=All.Time*All.Time*All.Time; a3inv=1.e0/a3; hubble_param = All.HubbleParam; hubble_param2 = hubble_param*hubble_param; } else a3 = a3inv = hubble_param = hubble_param2 =1.0; //MPI_Barrier(MPI_COMM_WORLD); particle_check(a3, a3inv, hubble_param, hubble_param2); find_next_sync_point_and_drift(); /* find next synchronization point and drift particles to this time. * If needed, this function will also write an output file * at the desired time. */ every_timestep_stuff(); /* write some info to log-files */ domain_Decomposition(); /* do domain decomposition if needed */ N_sinks = 0; for(i = 0; i < NumPart; i++) { if(P[i].Type == 5) N_sinks++; } compute_accelerations(0); /* compute accelerations for * the particles that are to be advanced */ /* check whether we want a full energy statistics */ if((All.Time - All.TimeLastStatistics) >= All.TimeBetStatistics) { #ifdef COMPUTE_POTENTIAL_ENERGY compute_potential(); #endif energy_statistics(); /* compute and output energy statistics */ All.TimeLastStatistics += All.TimeBetStatistics; } /*SINKS*/ MPI_Barrier(MPI_COMM_WORLD); //MPI_Allreduce(&prad_avg, &prad_tot, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); //MPI_Allreduce(&pres_avg, &pres_tot, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); if(All.NumCurrentTiStep % 1000 == 0) printf("myrank = %d, Ngas = %d, NumPart = %d, TNgas = %lu, TNumPart = %lu, All.t_s = %lg, All.t_s0 = %lg, All.t_s0_sink = %lg, All.t_s0_acc = %lg\n", ThisTask, N_gas, NumPart, All.TotN_gas, All.TotNumPart, All.t_s, All.t_s0, All.t_s0_sink, All.t_s0_acc); MPI_Barrier(MPI_COMM_WORLD); tstart = second(); if(ThisTask == 0 && All.NumCurrentTiStep % 10000 == 0) printf("line 144 of run.c - before sink()\n"); if(/*All.t_s - All.t_s0_sink > 1.e5 || ray.r_min < 1.01*2.0e0*All.SofteningGas ||*/ All.flag_sink == 1 || (All.NumCurrentTiStep % 20 == 0 && All.NumCurrentTiStep > 0) || All.NumCurrentTiStep == 2) { sink(); } for(i = 0; i < N_gas; i++) if(SphP[i].sink > 0.5 && All.NumCurrentTiStep % 10000 == 0) printf("sinkval = %g \n", SphP[i].sink); if(ThisTask == 0 && All.NumCurrentTiStep % 10000 == 0) printf("line 144 of run.c - after sink()\n"); if(/*All.t_s - All.t_s0_sink > 1.e5 || ray.r_min < 1.01*2.0e0*All.SofteningGas ||*/ All.flag_sink == 1 || (All.NumCurrentTiStep % 20 == 0 && All.NumCurrentTiStep > 0) || All.NumCurrentTiStep == 2) { All.t_s0_sink = All.t_s; accrete(); } for(i = 0; i < N_gas; i++) if(SphP[i].sink > 0.5 && All.NumCurrentTiStep % 10000 == 0) printf("new new sinkval = %g \n", SphP[i].sink); tend = second(); All.CPU_Sinks += timediff(tstart,tend); MPI_Barrier(MPI_COMM_WORLD); // if(nsinks) // { All.NumForcesSinceLastDomainDecomp = All.TotNumPart * All.TreeDomainUpdateFrequency + 1; // } /*SINKS*/ advance_and_find_timesteps(); /* 'kick' active particles in * momentum space and compute new * timesteps for them */ #ifdef TURBULENCE if(N_gas>0) { tstart = second(); rsk_turbdriving(); tend = second(); All.CPU_Turbulence+= timediff(tstart,tend); } #endif All.NumCurrentTiStep++; /* Check whether we need to interrupt the run */ if(ThisTask == 0) { /* Is the stop-file present? If yes, interrupt the run. */ if((fd = fopen(stopfname, "r"))) { fclose(fd); stopflag = 1; unlink(stopfname); } /* are we running out of CPU-time ? If yes, interrupt run. */ if(CPUThisRun > 0.85 * All.TimeLimitCPU) { printf("reaching time-limit. stopping.\n"); stopflag = 2; } } MPI_Bcast(&stopflag, 1, MPI_INT, 0, MPI_COMM_WORLD); if(stopflag) { restart(0); /* write restart file */ MPI_Barrier(MPI_COMM_WORLD); if(stopflag == 2 && ThisTask == 0) { if((fd = fopen(contfname, "w"))) fclose(fd); } if(stopflag == 2 && All.ResubmitOn && ThisTask == 0) { close_outputfiles(); system(All.ResubmitCommand); } return; } /* is it time to write a regular restart-file? (for security) */ if(ThisTask == 0) { if((CPUThisRun - All.TimeLastRestartFile) >= All.CpuTimeBetRestartFile) { All.TimeLastRestartFile = CPUThisRun; stopflag = 3; } else stopflag = 0; } MPI_Bcast(&stopflag, 1, MPI_INT, 0, MPI_COMM_WORLD); if(stopflag == 3) { restart(0); /* write an occasional restart file */ stopflag = 0; if(ThisTask == 0) printf("writing restart files!\n"); } t1 = second(); All.CPU_Total += timediff(t0, t1); CPUThisRun += timediff(t0, t1); } while(All.Ti_Current < TIMEBASE && All.Time <= All.TimeMax); restart(0); /* savepositions(All.SnapshotFileCount++);*/ /* write a last snapshot * file at final time (will * be overwritten if * All.TimeMax is increased * and the run is continued) */ }
/*! This routine contains the main simulation loop that iterates over single * timesteps. The loop terminates when the cpu-time limit is reached, when a * `stop' file is found in the output directory, or when the simulation ends * because we arrived at TimeMax. */ void run(void) { FILE *fd; int stopflag = 0; char stopfname[200], contfname[200]; double t0, t1; sprintf(stopfname, "%sstop", All.OutputDir); sprintf(contfname, "%scont", All.OutputDir); unlink(contfname); do /* main loop */ { t0 = second(); find_next_sync_point_and_drift(); /* find next synchronization point and drift particles to this time. * If needed, this function will also write an output file * at the desired time. */ every_timestep_stuff(); /* write some info to log-files */ domain_Decomposition(); /* do domain decomposition if needed */ compute_accelerations(0); /* compute accelerations for * the particles that are to be advanced */ /* check whether we want a full energy statistics */ if((All.Time - All.TimeLastStatistics) >= All.TimeBetStatistics) { #ifdef COMPUTE_POTENTIAL_ENERGY compute_potential(); #endif energy_statistics(); /* compute and output energy statistics */ All.TimeLastStatistics += All.TimeBetStatistics; } advance_and_find_timesteps(); /* 'kick' active particles in * momentum space and compute new * timesteps for them */ All.NumCurrentTiStep++; /* Check whether we need to interrupt the run */ if(ThisTask == 0) { /* Is the stop-file present? If yes, interrupt the run. */ if((fd = fopen(stopfname, "r"))) { fclose(fd); stopflag = 1; unlink(stopfname); } /* are we running out of CPU-time ? If yes, interrupt run. */ if(CPUThisRun > 0.85 * All.TimeLimitCPU) { printf("reaching time-limit. stopping.\n"); stopflag = 2; } } MPI_Bcast(&stopflag, 1, MPI_INT, 0, MPI_COMM_WORLD); if(stopflag) { restart(0); /* write restart file */ MPI_Barrier(MPI_COMM_WORLD); if(stopflag == 2 && ThisTask == 0) { if((fd = fopen(contfname, "w"))) fclose(fd); } if(stopflag == 2 && All.ResubmitOn && ThisTask == 0) { close_outputfiles(); system(All.ResubmitCommand); } return; } /* is it time to write a regular restart-file? (for security) */ if(ThisTask == 0) { if((CPUThisRun - All.TimeLastRestartFile) >= All.CpuTimeBetRestartFile) { All.TimeLastRestartFile = CPUThisRun; stopflag = 3; } else stopflag = 0; } MPI_Bcast(&stopflag, 1, MPI_INT, 0, MPI_COMM_WORLD); if(stopflag == 3) { restart(0); /* write an occasional restart file */ stopflag = 0; } t1 = second(); All.CPU_Total += timediff(t0, t1); CPUThisRun += timediff(t0, t1); } while(All.Ti_Current < TIMEBASE && All.Time <= All.TimeMax); restart(0); savepositions(All.SnapshotFileCount++); /* write a last snapshot * file at final time (will * be overwritten if * All.TimeMax is increased * and the run is continued) */ }
/*! This function finds the next synchronization point of the system (i.e. the * earliest point of time any of the particles needs a force computation), * and drifts the system to this point of time. If the system drifts over * the desired time of a snapshot file, the function will drift to this * moment, generate an output, and then resume the drift. */ void find_next_sync_point_and_drift(void) { int n, min, min_glob, flag, *temp; double timeold; double t0, t1; t0 = second(); timeold = All.Time; for(n = 1, min = P[0].Ti_endstep; n < NumPart; n++) if(min > P[n].Ti_endstep) min = P[n].Ti_endstep; MPI_Allreduce(&min, &min_glob, 1, MPI_INT, MPI_MIN, MPI_COMM_WORLD); /* We check whether this is a full step where all particles are synchronized */ flag = 1; for(n = 0; n < NumPart; n++) if(P[n].Ti_endstep > min_glob) flag = 0; MPI_Allreduce(&flag, &Flag_FullStep, 1, MPI_INT, MPI_MIN, MPI_COMM_WORLD); #ifdef PMGRID if(min_glob >= All.PM_Ti_endstep) { min_glob = All.PM_Ti_endstep; Flag_FullStep = 1; } #endif /* Determine 'NumForceUpdate', i.e. the number of particles on this processor that are going to be active */ for(n = 0, NumForceUpdate = 0; n < NumPart; n++) { if(P[n].Ti_endstep == min_glob) #ifdef SELECTIVE_NO_GRAVITY if(!((1 << P[n].Type) & (SELECTIVE_NO_GRAVITY))) #endif NumForceUpdate++; } /* note: NumForcesSinceLastDomainDecomp has type "long long" */ temp = malloc(NTask * sizeof(int)); MPI_Allgather(&NumForceUpdate, 1, MPI_INT, temp, 1, MPI_INT, MPI_COMM_WORLD); for(n = 0; n < NTask; n++) All.NumForcesSinceLastDomainDecomp += temp[n]; free(temp); t1 = second(); All.CPU_Predict += timediff(t0, t1); while(min_glob >= All.Ti_nextoutput && All.Ti_nextoutput >= 0) { move_particles(All.Ti_Current, All.Ti_nextoutput); All.Ti_Current = All.Ti_nextoutput; if(All.ComovingIntegrationOn) All.Time = All.TimeBegin * exp(All.Ti_Current * All.Timebase_interval); else All.Time = All.TimeBegin + All.Ti_Current * All.Timebase_interval; #ifdef OUTPUTPOTENTIAL All.NumForcesSinceLastDomainDecomp = 1 + All.TotNumPart * All.TreeDomainUpdateFrequency; domain_Decomposition(); compute_potential(); #endif savepositions(All.SnapshotFileCount++); /* write snapshot file */ All.Ti_nextoutput = find_next_outputtime(All.Ti_nextoutput + 1); } move_particles(All.Ti_Current, min_glob); All.Ti_Current = min_glob; if(All.ComovingIntegrationOn) All.Time = All.TimeBegin * exp(All.Ti_Current * All.Timebase_interval); else All.Time = All.TimeBegin + All.Ti_Current * All.Timebase_interval; All.TimeStep = All.Time - timeold; }
void algorithms::Planner<IROBOT>::initialize(algorithms::KDDecomposer<IROBOT>& decomposer, const CONFIG& goal, const IROBOT& robot) { compute_potential(robot, goal); }