void do_the_kick(int i, int tstart, int tend, int tcurrent) { int j; double dv[3]; double dt_entr, dt_gravkick, dt_hydrokick; if(All.ComovingIntegrationOn) { dt_entr = (tend - tstart) * All.Timebase_interval; dt_gravkick = get_gravkick_factor(tstart, tend); dt_hydrokick = get_hydrokick_factor(tstart, tend); } else { dt_entr = dt_gravkick = dt_hydrokick = (tend - tstart) * All.Timebase_interval; } /* do the kick */ for(j = 0; j < 3; j++) { dv[j] = P[i].g.GravAccel[j] * dt_gravkick; #ifdef RELAXOBJECT dv[j] -= P[i].Vel[j] * All.RelaxFac * dt_gravkick; #endif P[i].Vel[j] += dv[j]; P[i].dp[j] += P[i].Mass * dv[j]; } #ifdef DISTORTIONTENSORPS do_distortion_tensor_kick(i, dt_gravkick); #endif if(P[i].Type == 0) /* kick for SPH quantities */ { for(j = 0; j < 3; j++) { dv[j] = SphP[i].a.HydroAccel[j] * dt_hydrokick; P[i].Vel[j] += dv[j]; P[i].dp[j] += P[i].Mass * dv[j]; } double dEntr = SphP[i].e.DtEntropy * dt_entr; #if defined(EOS_DEGENERATE) dEntr *= All.UnitTime_in_s; #endif SphP[i].Entropy = DMAX(SphP[i].Entropy + dEntr, 0.5 * SphP[i].Entropy); check_particle_for_temperature_minimum(i); do_sph_kick_for_extra_physics(i, tstart, tend, dt_entr); } }
/*! This function fills the write buffer with particle data. New output blocks * can in principle be added here. */ void fill_write_buffer(enum iofields blocknr, int *startindex, int pc, int type) { int n, k, pindex; float *fp; #ifdef LONGIDS long long *ip; #else int *ip; #endif #ifdef PERIODIC FLOAT boxSize; #endif #ifdef PMGRID double dt_gravkick_pm = 0; #endif double dt_gravkick, dt_hydrokick, a3inv = 1, fac1, fac2; if(All.ComovingIntegrationOn) { a3inv = 1 / (All.Time * All.Time * All.Time); fac1 = 1 / (All.Time * All.Time); fac2 = 1 / pow(All.Time, 3 * GAMMA - 2); } else a3inv = fac1 = fac2 = 1; #ifdef PMGRID if(All.ComovingIntegrationOn) dt_gravkick_pm = get_gravkick_factor(All.PM_Ti_begstep, All.Ti_Current) - get_gravkick_factor(All.PM_Ti_begstep, (All.PM_Ti_begstep + All.PM_Ti_endstep) / 2); else dt_gravkick_pm = (All.Ti_Current - (All.PM_Ti_begstep + All.PM_Ti_endstep) / 2) * All.Timebase_interval; #endif fp = CommBuffer; ip = CommBuffer; pindex = *startindex; switch (blocknr) { case IO_POS: /* positions */ for(n = 0; n < pc; pindex++) if(P[pindex].Type == type) { for(k = 0; k < 3; k++) { fp[k] = P[pindex].Pos[k]; #ifdef PERIODIC boxSize = All.BoxSize; #ifdef LONG_X if(k == 0) boxSize = All.BoxSize * LONG_X; #endif #ifdef LONG_Y if(k == 1) boxSize = All.BoxSize * LONG_Y; #endif #ifdef LONG_Z if(k == 2) boxSize = All.BoxSize * LONG_Z; #endif while(fp[k] < 0) fp[k] += boxSize; while(fp[k] >= boxSize) fp[k] -= boxSize; #endif } n++; fp += 3; } break; case IO_VEL: /* velocities */ for(n = 0; n < pc; pindex++) if(P[pindex].Type == type) { if(All.ComovingIntegrationOn) { dt_gravkick = get_gravkick_factor(P[pindex].Ti_begstep, All.Ti_Current) - get_gravkick_factor(P[pindex].Ti_begstep, (P[pindex].Ti_begstep + P[pindex].Ti_endstep) / 2); dt_hydrokick = get_hydrokick_factor(P[pindex].Ti_begstep, All.Ti_Current) - get_hydrokick_factor(P[pindex].Ti_begstep, (P[pindex].Ti_begstep + P[pindex].Ti_endstep) / 2); } else dt_gravkick = dt_hydrokick = (All.Ti_Current - (P[pindex].Ti_begstep + P[pindex].Ti_endstep) / 2) * All.Timebase_interval; for(k = 0; k < 3; k++) { fp[k] = P[pindex].Vel[k] + P[pindex].GravAccel[k] * dt_gravkick; if(P[pindex].Type == 0) fp[k] += SphP[pindex].HydroAccel[k] * dt_hydrokick; } #ifdef PMGRID for(k = 0; k < 3; k++) fp[k] += P[pindex].GravPM[k] * dt_gravkick_pm; #endif for(k = 0; k < 3; k++) fp[k] *= sqrt(a3inv); n++; fp += 3; } break; case IO_ID: /* particle ID */ for(n = 0; n < pc; pindex++) if(P[pindex].Type == type) { *ip++ = P[pindex].ID; n++; } break; case IO_MASS: /* particle mass */ for(n = 0; n < pc; pindex++) if(P[pindex].Type == type) { *fp++ = P[pindex].Mass; n++; } break; case IO_U: /* internal energy */ for(n = 0; n < pc; pindex++) if(P[pindex].Type == type) { #ifdef ISOTHERM_EQS *fp++ = SphP[pindex].Entropy; #else *fp++ = dmax(All.MinEgySpec, SphP[pindex].Entropy / GAMMA_MINUS1 * pow(SphP[pindex].Density * a3inv, GAMMA_MINUS1)); #endif n++; } break; case IO_RHO: /* density */ for(n = 0; n < pc; pindex++) if(P[pindex].Type == type) { *fp++ = SphP[pindex].Density; n++; } break; case IO_HSML: /* SPH smoothing length */ for(n = 0; n < pc; pindex++) if(P[pindex].Type == type) { *fp++ = SphP[pindex].Hsml; n++; } break; case IO_POT: /* gravitational potential */ #ifdef OUTPUTPOTENTIAL for(n = 0; n < pc; pindex++) if(P[pindex].Type == type) { *fp++ = P[pindex].Potential; n++; } #endif break; case IO_ACCEL: /* acceleration */ #ifdef OUTPUTACCELERATION for(n = 0; n < pc; pindex++) if(P[pindex].Type == type) { for(k = 0; k < 3; k++) fp[k] = fac1 * P[pindex].GravAccel[k]; #ifdef PMGRID for(k = 0; k < 3; k++) fp[k] += fac1 * P[pindex].GravPM[k]; #endif if(P[pindex].Type == 0) for(k = 0; k < 3; k++) fp[k] += fac2 * SphP[pindex].HydroAccel[k]; fp += 3; n++; } #endif break; case IO_DTENTR: /* rate of change of entropy */ #ifdef OUTPUTCHANGEOFENTROPY for(n = 0; n < pc; pindex++) if(P[pindex].Type == type) { *fp++ = SphP[pindex].DtEntropy; n++; } #endif break; case IO_TSTP: /* timestep */ #ifdef OUTPUTTIMESTEP for(n = 0; n < pc; pindex++) if(P[pindex].Type == type) { *fp++ = (P[pindex].Ti_endstep - P[pindex].Ti_begstep) * All.Timebase_interval; n++; } #endif break; } *startindex = pindex; }
/* This routine computes various global properties of the particle * distribution and stores the result in the struct `SysState'. * Currently, not all the information that's computed here is * actually used (e.g. momentum is not really used anywhere), * just the energies are written to a log-file every once in a while. */ void compute_global_quantities_of_system(void) { int i, j, n, dt_step; struct state_of_system sys; double a1, a2, a3; double entr = 0, egyspec, vel[3]; double dt_entr, dt_gravkick, dt_hydrokick; if(All.ComovingIntegrationOn) { a1 = All.Time; a2 = All.Time * All.Time; a3 = All.Time * All.Time * All.Time; } else { a1 = a2 = a3 = 1; } for(n = 0; n < 6; n++) { sys.MassComp[n] = sys.EnergyKinComp[n] = sys.EnergyPotComp[n] = sys.EnergyIntComp[n] = 0; for(j = 0; j < 4; j++) sys.CenterOfMassComp[n][j] = sys.MomentumComp[n][j] = sys.AngMomentumComp[n][j] = 0; } for(i = 0; i < NumPart; i++) { sys.MassComp[P[i].Type] += P[i].Mass; #if defined(EVALPOTENTIAL) || defined(COMPUTE_POTENTIAL_ENERGY) sys.EnergyPotComp[P[i].Type] += 0.5 * P[i].Mass * P[i].p.Potential / a1; #endif #ifndef WAKEUP dt_step = P[i].TimeBin ? (1 << P[i].TimeBin) : 0; #else dt_step = P[i].dt_step; #endif if(All.ComovingIntegrationOn) { dt_entr = (All.Ti_Current - (P[i].Ti_begstep + dt_step / 2)) * All.Timebase_interval; dt_gravkick = get_gravkick_factor(P[i].Ti_begstep, All.Ti_Current) - get_gravkick_factor(P[i].Ti_begstep, P[i].Ti_begstep + dt_step / 2); dt_hydrokick = get_hydrokick_factor(P[i].Ti_begstep, All.Ti_Current) - get_hydrokick_factor(P[i].Ti_begstep, P[i].Ti_begstep + dt_step / 2); } else dt_entr = dt_gravkick = dt_hydrokick = (All.Ti_Current - (P[i].Ti_begstep + dt_step / 2)) * All.Timebase_interval; for(j = 0; j < 3; j++) { vel[j] = P[i].Vel[j] + P[i].g.GravAccel[j] * dt_gravkick; if(P[i].Type == 0) vel[j] += SphP[i].a.HydroAccel[j] * dt_hydrokick; } if(P[i].Type == 0) entr = SphP[i].Entropy + SphP[i].e.DtEntropy * dt_entr; #ifdef PMGRID if(All.ComovingIntegrationOn) dt_gravkick = get_gravkick_factor(All.PM_Ti_begstep, All.Ti_Current) - get_gravkick_factor(All.PM_Ti_begstep, (All.PM_Ti_begstep + All.PM_Ti_endstep) / 2); else dt_gravkick = (All.Ti_Current - (All.PM_Ti_begstep + All.PM_Ti_endstep) / 2) * All.Timebase_interval; for(j = 0; j < 3; j++) vel[j] += P[i].GravPM[j] * dt_gravkick; #endif sys.EnergyKinComp[P[i].Type] += 0.5 * P[i].Mass * (vel[0] * vel[0] + vel[1] * vel[1] + vel[2] * vel[2]) / a2; if(P[i].Type == 0) { #ifndef EOS_DEGENERATE #if defined(TRADITIONAL_SPH_FORMULATION) egyspec = entr; #else egyspec = entr / (GAMMA_MINUS1) * pow(SphP[i].d.Density / a3, GAMMA_MINUS1); #endif #else egyspec = SphP[i].u; #endif sys.EnergyIntComp[0] += P[i].Mass * egyspec; } for(j = 0; j < 3; j++) { sys.MomentumComp[P[i].Type][j] += P[i].Mass * vel[j]; sys.CenterOfMassComp[P[i].Type][j] += P[i].Mass * P[i].Pos[j]; } sys.AngMomentumComp[P[i].Type][0] += P[i].Mass * (P[i].Pos[1] * vel[2] - P[i].Pos[2] * vel[1]); sys.AngMomentumComp[P[i].Type][1] += P[i].Mass * (P[i].Pos[2] * vel[0] - P[i].Pos[0] * vel[2]); sys.AngMomentumComp[P[i].Type][2] += P[i].Mass * (P[i].Pos[0] * vel[1] - P[i].Pos[1] * vel[0]); } /* some the stuff over all processors */ MPI_Reduce(&sys.MassComp[0], &SysState.MassComp[0], 6, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); MPI_Reduce(&sys.EnergyPotComp[0], &SysState.EnergyPotComp[0], 6, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); MPI_Reduce(&sys.EnergyIntComp[0], &SysState.EnergyIntComp[0], 6, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); MPI_Reduce(&sys.EnergyKinComp[0], &SysState.EnergyKinComp[0], 6, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); MPI_Reduce(&sys.MomentumComp[0][0], &SysState.MomentumComp[0][0], 6 * 4, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); MPI_Reduce(&sys.AngMomentumComp[0][0], &SysState.AngMomentumComp[0][0], 6 * 4, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); MPI_Reduce(&sys.CenterOfMassComp[0][0], &SysState.CenterOfMassComp[0][0], 6 * 4, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); if(ThisTask == 0) { for(i = 0; i < 6; i++) SysState.EnergyTotComp[i] = SysState.EnergyKinComp[i] + SysState.EnergyPotComp[i] + SysState.EnergyIntComp[i]; SysState.Mass = SysState.EnergyKin = SysState.EnergyPot = SysState.EnergyInt = SysState.EnergyTot = 0; for(j = 0; j < 3; j++) SysState.Momentum[j] = SysState.AngMomentum[j] = SysState.CenterOfMass[j] = 0; for(i = 0; i < 6; i++) { SysState.Mass += SysState.MassComp[i]; SysState.EnergyKin += SysState.EnergyKinComp[i]; SysState.EnergyPot += SysState.EnergyPotComp[i]; SysState.EnergyInt += SysState.EnergyIntComp[i]; SysState.EnergyTot += SysState.EnergyTotComp[i]; for(j = 0; j < 3; j++) { SysState.Momentum[j] += SysState.MomentumComp[i][j]; SysState.AngMomentum[j] += SysState.AngMomentumComp[i][j]; SysState.CenterOfMass[j] += SysState.CenterOfMassComp[i][j]; } } for(i = 0; i < 6; i++) for(j = 0; j < 3; j++) if(SysState.MassComp[i] > 0) SysState.CenterOfMassComp[i][j] /= SysState.MassComp[i]; for(j = 0; j < 3; j++) if(SysState.Mass > 0) SysState.CenterOfMass[j] /= SysState.Mass; for(i = 0; i < 6; i++) { SysState.CenterOfMassComp[i][3] = SysState.MomentumComp[i][3] = SysState.AngMomentumComp[i][3] = 0; for(j = 0; j < 3; j++) { SysState.CenterOfMassComp[i][3] += SysState.CenterOfMassComp[i][j] * SysState.CenterOfMassComp[i][j]; SysState.MomentumComp[i][3] += SysState.MomentumComp[i][j] * SysState.MomentumComp[i][j]; SysState.AngMomentumComp[i][3] += SysState.AngMomentumComp[i][j] * SysState.AngMomentumComp[i][j]; } SysState.CenterOfMassComp[i][3] = sqrt(SysState.CenterOfMassComp[i][3]); SysState.MomentumComp[i][3] = sqrt(SysState.MomentumComp[i][3]); SysState.AngMomentumComp[i][3] = sqrt(SysState.AngMomentumComp[i][3]); } SysState.CenterOfMass[3] = SysState.Momentum[3] = SysState.AngMomentum[3] = 0; for(j = 0; j < 3; j++) { SysState.CenterOfMass[3] += SysState.CenterOfMass[j] * SysState.CenterOfMass[j]; SysState.Momentum[3] += SysState.Momentum[j] * SysState.Momentum[j]; SysState.AngMomentum[3] += SysState.AngMomentum[j] * SysState.AngMomentum[j]; } SysState.CenterOfMass[3] = sqrt(SysState.CenterOfMass[3]); SysState.Momentum[3] = sqrt(SysState.Momentum[3]); SysState.AngMomentum[3] = sqrt(SysState.AngMomentum[3]); } /* give everyone the result, maybe the want to do something with it */ MPI_Bcast(&SysState, sizeof(struct state_of_system), MPI_BYTE, 0, MPI_COMM_WORLD); }
/*! This function drifts all particles from the current time to the future: * time0 - > time1 * * If there is no explicit tree construction in the following timestep, the * tree nodes are also drifted and updated accordingly. Note: For periodic * boundary conditions, the mapping of coordinates onto the interval * [0,All.BoxSize] is only done before the domain decomposition, or for * outputs to snapshot files. This simplifies dynamic tree updates, and * allows the domain decomposition to be carried out only every once in a * while. */ void move_particles(int time0, int time1) { int i, j; double dt_drift, dt_gravkick, dt_hydrokick, dt_entr; double t0, t1; t0 = second(); if(All.ComovingIntegrationOn) { dt_drift = get_drift_factor(time0, time1); dt_gravkick = get_gravkick_factor(time0, time1); dt_hydrokick = get_hydrokick_factor(time0, time1); } else { dt_drift = dt_gravkick = dt_hydrokick = (time1 - time0) * All.Timebase_interval; } for(i = 0; i < NumPart; i++) { for(j = 0; j < 3; j++) P[i].Pos[j] += P[i].Vel[j] * dt_drift; if(P[i].Type == 0) { #ifdef PMGRID for(j = 0; j < 3; j++) SphP[i].VelPred[j] += (P[i].GravAccel[j] + P[i].GravPM[j]) * dt_gravkick + SphP[i].HydroAccel[j] * dt_hydrokick; #else for(j = 0; j < 3; j++) SphP[i].VelPred[j] += P[i].GravAccel[j] * dt_gravkick + SphP[i].HydroAccel[j] * dt_hydrokick; #endif SphP[i].Density *= exp(-SphP[i].DivVel * dt_drift); SphP[i].Hsml *= exp(0.333333333333 * SphP[i].DivVel * dt_drift); if(SphP[i].Hsml < All.MinGasHsml) SphP[i].Hsml = All.MinGasHsml; dt_entr = (time1 - (P[i].Ti_begstep + P[i].Ti_endstep) / 2) * All.Timebase_interval; SphP[i].Pressure = (SphP[i].Entropy + SphP[i].DtEntropy * dt_entr) * pow(SphP[i].Density, GAMMA); #ifdef MORRIS97VISC SphP[i].Alpha += SphP[i].DAlphaDt * dt_drift; #endif } } /* if domain-decomp and tree are not going to be reconstructed, update dynamically. */ if(All.NumForcesSinceLastDomainDecomp < All.TotNumPart * All.TreeDomainUpdateFrequency) { for(i = 0; i < Numnodestree; i++) for(j = 0; j < 3; j++) Nodes[All.MaxPart + i].u.d.s[j] += Extnodes[All.MaxPart + i].vs[j] * dt_drift; force_update_len(); force_update_pseudoparticles(); } t1 = second(); All.CPU_Predict += timediff(t0, t1); }