Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

timestep.c

Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <string.h>
00004 #include <math.h>
00005 #include <mpi.h>
00006 #include "allvars.h"
00007 #include "proto.h"
00008 
00013 static double fac1, fac2, fac3, hubble_a, atime, a3inv;
00014 static double dt_displacement = 0;
00015 
00016 
00024 void advance_and_find_timesteps(void)
00025 {
00026   int i, j, no, ti_step, ti_min, tend, tstart;
00027   double dt_entr, dt_entr2, dt_gravkick, dt_hydrokick, dt_gravkick2, dt_hydrokick2, t0, t1;
00028   double minentropy, aphys;
00029   FLOAT dv[3];
00030 
00031 #ifdef FLEXSTEPS
00032   int ti_grp;
00033 #endif
00034 #if defined(PSEUDOSYMMETRIC) && !defined(FLEXSTEPS)
00035   double apred, prob;
00036   int ti_step2;
00037 #endif
00038 #ifdef PMGRID
00039   double dt_gravkickA, dt_gravkickB;
00040 #endif
00041 #ifdef MAKEGLASS
00042   double disp, dispmax, globmax, dmean, fac, disp2sum, globdisp2sum;
00043 #endif
00044 
00045   t0 = second();
00046 
00047   if(All.ComovingIntegrationOn)
00048     {
00049       fac1 = 1 / (All.Time * All.Time);
00050       fac2 = 1 / pow(All.Time, 3 * GAMMA - 2);
00051       fac3 = pow(All.Time, 3 * (1 - GAMMA) / 2.0);
00052       hubble_a = All.Omega0 / (All.Time * All.Time * All.Time)
00053         + (1 - All.Omega0 - All.OmegaLambda) / (All.Time * All.Time) + All.OmegaLambda;
00054 
00055       hubble_a = All.Hubble * sqrt(hubble_a);
00056       a3inv = 1 / (All.Time * All.Time * All.Time);
00057       atime = All.Time;
00058     }
00059   else
00060     fac1 = fac2 = fac3 = hubble_a = a3inv = atime = 1;
00061 
00062 #ifdef NOPMSTEPADJUSTMENT
00063   dt_displacement = All.MaxSizeTimestep;
00064 #else
00065   if(Flag_FullStep || dt_displacement == 0)
00066     find_dt_displacement_constraint(hubble_a * atime * atime);
00067 #endif
00068 
00069 #ifdef PMGRID
00070   if(All.ComovingIntegrationOn)
00071     dt_gravkickB = get_gravkick_factor(All.PM_Ti_begstep, All.Ti_Current) -
00072       get_gravkick_factor(All.PM_Ti_begstep, (All.PM_Ti_begstep + All.PM_Ti_endstep) / 2);
00073   else
00074     dt_gravkickB = (All.Ti_Current - (All.PM_Ti_begstep + All.PM_Ti_endstep) / 2) * All.Timebase_interval;
00075 
00076   if(All.PM_Ti_endstep == All.Ti_Current)       /* need to do long-range kick */
00077     {
00078       /* make sure that we reconstruct the domain/tree next time because we don't kick the tree nodes in this case */
00079       All.NumForcesSinceLastDomainDecomp = 1 + All.TotNumPart * All.TreeDomainUpdateFrequency;
00080     }
00081 #endif
00082 
00083 
00084 #ifdef MAKEGLASS
00085   for(i = 0, dispmax = 0, disp2sum = 0; i < NumPart; i++)
00086     {
00087       for(j = 0; j < 3; j++)
00088         {
00089           P[i].GravPM[j] *= -1;
00090           P[i].GravAccel[j] *= -1;
00091           P[i].GravAccel[j] += P[i].GravPM[j];
00092           P[i].GravPM[j] = 0;
00093         }
00094 
00095       disp = sqrt(P[i].GravAccel[0] * P[i].GravAccel[0] +
00096                   P[i].GravAccel[1] * P[i].GravAccel[1] + P[i].GravAccel[2] * P[i].GravAccel[2]);
00097 
00098       disp *= 2.0 / (3 * All.Hubble * All.Hubble);
00099 
00100       disp2sum += disp * disp;
00101 
00102       if(disp > dispmax)
00103         dispmax = disp;
00104     }
00105 
00106   MPI_Allreduce(&dispmax, &globmax, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
00107   MPI_Allreduce(&disp2sum, &globdisp2sum, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
00108 
00109   dmean = pow(P[0].Mass / (All.Omega0 * 3 * All.Hubble * All.Hubble / (8 * M_PI * All.G)), 1.0 / 3);
00110 
00111   if(globmax > dmean)
00112     fac = dmean / globmax;
00113   else
00114     fac = 1.0;
00115 
00116   if(ThisTask == 0)
00117     {
00118       printf("\nglass-making:  dmean= %g  global disp-maximum= %g  rms= %g\n\n",
00119              dmean, globmax, sqrt(globdisp2sum / All.TotNumPart));
00120       fflush(stdout);
00121     }
00122 
00123   for(i = 0, dispmax = 0; i < NumPart; i++)
00124     {
00125       for(j = 0; j < 3; j++)
00126         {
00127           P[i].Vel[j] = 0;
00128           P[i].Pos[j] += fac * P[i].GravAccel[j] * 2.0 / (3 * All.Hubble * All.Hubble);
00129           P[i].GravAccel[j] = 0;
00130         }
00131     }
00132 #endif
00133 
00134 
00135 
00136 
00137   /* Now assign new timesteps and kick */
00138 
00139 #ifdef FLEXSTEPS
00140   if((All.Ti_Current % (4 * All.PresentMinStep)) == 0)
00141     if(All.PresentMinStep < TIMEBASE)
00142       All.PresentMinStep *= 2;
00143 
00144   for(i = 0; i < NumPart; i++)
00145     {
00146       if(P[i].Ti_endstep == All.Ti_Current)
00147         {
00148           ti_step = get_timestep(i, &aphys, 0);
00149 
00150           /* make it a power 2 subdivision */
00151           ti_min = TIMEBASE;
00152           while(ti_min > ti_step)
00153             ti_min >>= 1;
00154           ti_step = ti_min;
00155 
00156           if(ti_step < All.PresentMinStep)
00157             All.PresentMinStep = ti_step;
00158         }
00159     }
00160 
00161   ti_step = All.PresentMinStep;
00162   MPI_Allreduce(&ti_step, &All.PresentMinStep, 1, MPI_INT, MPI_MIN, MPI_COMM_WORLD);
00163 
00164   if(dt_displacement < All.MaxSizeTimestep)
00165     ti_step = (int) (dt_displacement / All.Timebase_interval);
00166   else
00167     ti_step = (int) (All.MaxSizeTimestep / All.Timebase_interval);
00168 
00169   /* make it a power 2 subdivision */
00170   ti_min = TIMEBASE;
00171   while(ti_min > ti_step)
00172     ti_min >>= 1;
00173   All.PresentMaxStep = ti_min;
00174 
00175 
00176   if(ThisTask == 0)
00177     printf("Syn Range = %g  PresentMinStep = %d  PresentMaxStep = %d \n",
00178            (double) All.PresentMaxStep / All.PresentMinStep, All.PresentMinStep, All.PresentMaxStep);
00179 
00180 #endif
00181 
00182 
00183   for(i = 0; i < NumPart; i++)
00184     {
00185       if(P[i].Ti_endstep == All.Ti_Current)
00186         {
00187           ti_step = get_timestep(i, &aphys, 0);
00188 
00189           /* make it a power 2 subdivision */
00190           ti_min = TIMEBASE;
00191           while(ti_min > ti_step)
00192             ti_min >>= 1;
00193           ti_step = ti_min;
00194 
00195 #ifdef FLEXSTEPS
00196           ti_grp = P[i].FlexStepGrp % All.PresentMaxStep;
00197           ti_grp = (ti_grp / All.PresentMinStep) * All.PresentMinStep;
00198           ti_step = ((P[i].Ti_endstep + ti_grp + ti_step) / ti_step) * ti_step - (P[i].Ti_endstep + ti_grp);
00199 #else
00200 
00201 #ifdef PSEUDOSYMMETRIC
00202           if(P[i].Type != 0)
00203             {
00204               if(P[i].Ti_endstep > P[i].Ti_begstep)
00205                 {
00206                   apred = aphys + ((aphys - P[i].AphysOld) / (P[i].Ti_endstep - P[i].Ti_begstep)) * ti_step;
00207                   if(fabs(apred - aphys) < 0.5 * aphys)
00208                     {
00209                       ti_step2 = get_timestep(i, &apred, -1);
00210                       ti_min = TIMEBASE;
00211                       while(ti_min > ti_step2)
00212                         ti_min >>= 1;
00213                       ti_step2 = ti_min;
00214 
00215                       if(ti_step2 < ti_step)
00216                         {
00217                           get_timestep(i, &apred, ti_step);
00218                           prob =
00219                             ((apred - aphys) / (aphys - P[i].AphysOld) * (P[i].Ti_endstep -
00220                                                                           P[i].Ti_begstep)) / ti_step;
00221                           if(prob < get_random_number(P[i].ID))
00222                             ti_step /= 2;
00223                         }
00224                       else if(ti_step2 > ti_step)
00225                         {
00226                           get_timestep(i, &apred, 2 * ti_step);
00227                           prob =
00228                             ((apred - aphys) / (aphys - P[i].AphysOld) * (P[i].Ti_endstep -
00229                                                                           P[i].Ti_begstep)) / ti_step;
00230                           if(prob < get_random_number(P[i].ID + 1))
00231                             ti_step *= 2;
00232                         }
00233                     }
00234                 }
00235               P[i].AphysOld = aphys;
00236             }
00237 #endif
00238 
00239 #ifdef SYNCHRONIZATION
00240           if(ti_step > (P[i].Ti_endstep - P[i].Ti_begstep))     /* timestep wants to increase */
00241             {
00242               if(((TIMEBASE - P[i].Ti_endstep) % ti_step) > 0)
00243                 ti_step = P[i].Ti_endstep - P[i].Ti_begstep;    /* leave at old step */
00244             }
00245 #endif
00246 #endif /* end of FLEXSTEPS */
00247 
00248           if(All.Ti_Current == TIMEBASE)        /* we here finish the last timestep. */
00249             ti_step = 0;
00250 
00251           if((TIMEBASE - All.Ti_Current) < ti_step)     /* check that we don't run beyond the end */
00252             ti_step = TIMEBASE - All.Ti_Current;
00253 
00254           tstart = (P[i].Ti_begstep + P[i].Ti_endstep) / 2;     /* midpoint of old step */
00255           tend = P[i].Ti_endstep + ti_step / 2; /* midpoint of new step */
00256 
00257           if(All.ComovingIntegrationOn)
00258             {
00259               dt_entr = (tend - tstart) * All.Timebase_interval;
00260               dt_entr2 = (tend - P[i].Ti_endstep) * All.Timebase_interval;
00261               dt_gravkick = get_gravkick_factor(tstart, tend);
00262               dt_hydrokick = get_hydrokick_factor(tstart, tend);
00263               dt_gravkick2 = get_gravkick_factor(P[i].Ti_endstep, tend);
00264               dt_hydrokick2 = get_hydrokick_factor(P[i].Ti_endstep, tend);
00265             }
00266           else
00267             {
00268               dt_entr = dt_gravkick = dt_hydrokick = (tend - tstart) * All.Timebase_interval;
00269               dt_gravkick2 = dt_hydrokick2 = dt_entr2 = (tend - P[i].Ti_endstep) * All.Timebase_interval;
00270             }
00271 
00272           P[i].Ti_begstep = P[i].Ti_endstep;
00273           P[i].Ti_endstep = P[i].Ti_begstep + ti_step;
00274 
00275 
00276           /* do the kick */
00277 
00278           for(j = 0; j < 3; j++)
00279             {
00280               dv[j] = P[i].GravAccel[j] * dt_gravkick;
00281               P[i].Vel[j] += dv[j];
00282             }
00283 
00284           if(P[i].Type == 0)    /* SPH stuff */
00285             {
00286               for(j = 0; j < 3; j++)
00287                 {
00288                   dv[j] += SphP[i].HydroAccel[j] * dt_hydrokick;
00289                   P[i].Vel[j] += SphP[i].HydroAccel[j] * dt_hydrokick;
00290 
00291                   SphP[i].VelPred[j] =
00292                     P[i].Vel[j] - dt_gravkick2 * P[i].GravAccel[j] - dt_hydrokick2 * SphP[i].HydroAccel[j];
00293 #ifdef PMGRID
00294                   SphP[i].VelPred[j] += P[i].GravPM[j] * dt_gravkickB;
00295 #endif
00296                 }
00297 
00298               /* In case of cooling, we prevent that the entropy (and
00299                  hence temperature decreases by more than a factor 0.5 */
00300 
00301               if(SphP[i].DtEntropy * dt_entr > -0.5 * SphP[i].Entropy)
00302                 SphP[i].Entropy += SphP[i].DtEntropy * dt_entr;
00303               else
00304                 SphP[i].Entropy *= 0.5;
00305 
00306               if(All.MinEgySpec)
00307                 {
00308                   minentropy = All.MinEgySpec * GAMMA_MINUS1 / pow(SphP[i].Density * a3inv, GAMMA_MINUS1);
00309                   if(SphP[i].Entropy < minentropy)
00310                     {
00311                       SphP[i].Entropy = minentropy;
00312                       SphP[i].DtEntropy = 0;
00313                     }
00314                 }
00315 
00316               /* In case the timestep increases in the new step, we
00317                  make sure that we do not 'overcool' when deriving
00318                  predicted temperatures. The maximum timespan over
00319                  which prediction can occur is ti_step/2, i.e. from
00320                  the middle to the end of the current step */
00321 
00322               dt_entr = ti_step / 2 * All.Timebase_interval;
00323               if(SphP[i].Entropy + SphP[i].DtEntropy * dt_entr < 0.5 * SphP[i].Entropy)
00324                 SphP[i].DtEntropy = -0.5 * SphP[i].Entropy / dt_entr;
00325             }
00326 
00327 
00328           /* if tree is not going to be reconstructed, kick parent nodes dynamically.
00329            */
00330           if(All.NumForcesSinceLastDomainDecomp < All.TotNumPart * All.TreeDomainUpdateFrequency)
00331             {
00332               no = Father[i];
00333               while(no >= 0)
00334                 {
00335                   for(j = 0; j < 3; j++)
00336                     Extnodes[no].vs[j] += dv[j] * P[i].Mass / Nodes[no].u.d.mass;
00337 
00338                   no = Nodes[no].u.d.father;
00339                 }
00340             }
00341         }
00342     }
00343 
00344 
00345 
00346 #ifdef PMGRID
00347   if(All.PM_Ti_endstep == All.Ti_Current)       /* need to do long-range kick */
00348     {
00349       ti_step = TIMEBASE;
00350       while(ti_step > (dt_displacement / All.Timebase_interval))
00351         ti_step >>= 1;
00352 
00353       if(ti_step > (All.PM_Ti_endstep - All.PM_Ti_begstep))     /* PM-timestep wants to increase */
00354         {
00355           /* we only increase if an integer number of steps will bring us to the end */
00356           if(((TIMEBASE - All.PM_Ti_endstep) % ti_step) > 0)
00357             ti_step = All.PM_Ti_endstep - All.PM_Ti_begstep;    /* leave at old step */
00358         }
00359 
00360       if(All.Ti_Current == TIMEBASE)    /* we here finish the last timestep. */
00361         ti_step = 0;
00362 
00363       tstart = (All.PM_Ti_begstep + All.PM_Ti_endstep) / 2;
00364       tend = All.PM_Ti_endstep + ti_step / 2;
00365 
00366       if(All.ComovingIntegrationOn)
00367         dt_gravkick = get_gravkick_factor(tstart, tend);
00368       else
00369         dt_gravkick = (tend - tstart) * All.Timebase_interval;
00370 
00371       All.PM_Ti_begstep = All.PM_Ti_endstep;
00372       All.PM_Ti_endstep = All.PM_Ti_begstep + ti_step;
00373 
00374       if(All.ComovingIntegrationOn)
00375         dt_gravkickB = -get_gravkick_factor(All.PM_Ti_begstep, (All.PM_Ti_begstep + All.PM_Ti_endstep) / 2);
00376       else
00377         dt_gravkickB =
00378           -((All.PM_Ti_begstep + All.PM_Ti_endstep) / 2 - All.PM_Ti_begstep) * All.Timebase_interval;
00379 
00380       for(i = 0; i < NumPart; i++)
00381         {
00382           for(j = 0; j < 3; j++)        /* do the kick */
00383             P[i].Vel[j] += P[i].GravPM[j] * dt_gravkick;
00384 
00385           if(P[i].Type == 0)
00386             {
00387               if(All.ComovingIntegrationOn)
00388                 {
00389                   dt_gravkickA = get_gravkick_factor(P[i].Ti_begstep, All.Ti_Current) -
00390                     get_gravkick_factor(P[i].Ti_begstep, (P[i].Ti_begstep + P[i].Ti_endstep) / 2);
00391                   dt_hydrokick = get_hydrokick_factor(P[i].Ti_begstep, All.Ti_Current) -
00392                     get_hydrokick_factor(P[i].Ti_begstep, (P[i].Ti_begstep + P[i].Ti_endstep) / 2);
00393                 }
00394               else
00395                 dt_gravkickA = dt_hydrokick =
00396                   (All.Ti_Current - (P[i].Ti_begstep + P[i].Ti_endstep) / 2) * All.Timebase_interval;
00397 
00398               for(j = 0; j < 3; j++)
00399                 SphP[i].VelPred[j] = P[i].Vel[j]
00400                   + P[i].GravAccel[j] * dt_gravkickA
00401                   + SphP[i].HydroAccel[j] * dt_hydrokick + P[i].GravPM[j] * dt_gravkickB;
00402             }
00403         }
00404     }
00405 #endif
00406 
00407   t1 = second();
00408   All.CPU_TimeLine += timediff(t0, t1);
00409 }
00410 
00411 
00412 
00413 
00423 int get_timestep(int p,         
00424                  double *aphys, 
00425                  int flag        )
00427 {
00428   double ax, ay, az, ac, csnd;
00429   double dt = 0, dt_courant = 0, dt_accel;
00430   int ti_step;
00431 
00432 #ifdef CONDUCTION
00433   double dt_cond;
00434 #endif
00435 
00436   if(flag == 0)
00437     {
00438       ax = fac1 * P[p].GravAccel[0];
00439       ay = fac1 * P[p].GravAccel[1];
00440       az = fac1 * P[p].GravAccel[2];
00441 
00442 #ifdef PMGRID
00443       ax += fac1 * P[p].GravPM[0];
00444       ay += fac1 * P[p].GravPM[1];
00445       az += fac1 * P[p].GravPM[2];
00446 #endif
00447 
00448       if(P[p].Type == 0)
00449         {
00450           ax += fac2 * SphP[p].HydroAccel[0];
00451           ay += fac2 * SphP[p].HydroAccel[1];
00452           az += fac2 * SphP[p].HydroAccel[2];
00453         }
00454 
00455       ac = sqrt(ax * ax + ay * ay + az * az);   /* this is now the physical acceleration */
00456       *aphys = ac;
00457     }
00458   else
00459     ac = *aphys;
00460 
00461   if(ac == 0)
00462     ac = 1.0e-30;
00463 
00464   switch (All.TypeOfTimestepCriterion)
00465     {
00466     case 0:
00467       if(flag > 0)
00468         {
00469           dt = flag * All.Timebase_interval;
00470           dt /= hubble_a;       /* convert dloga to physical timestep  */
00471           ac = 2 * All.ErrTolIntAccuracy * atime * All.SofteningTable[P[p].Type] / (dt * dt);
00472           *aphys = ac;
00473           return flag;
00474         }
00475       dt = dt_accel = sqrt(2 * All.ErrTolIntAccuracy * atime * All.SofteningTable[P[p].Type] / ac);
00476 #ifdef ADAPTIVE_GRAVSOFT_FORGAS
00477       if(P[p].Type == 0)
00478         dt = dt_accel = sqrt(2 * All.ErrTolIntAccuracy * atime * SphP[p].Hsml / 2.8 / ac);
00479 #endif
00480       break;
00481     default:
00482       endrun(888);
00483       break;
00484     }
00485 
00486   if(P[p].Type == 0)
00487     {
00488       csnd = sqrt(GAMMA * SphP[p].Pressure / SphP[p].Density);
00489 
00490       if(All.ComovingIntegrationOn)
00491         dt_courant = 2 * All.CourantFac * All.Time * SphP[p].Hsml / (fac3 * SphP[p].MaxSignalVel);
00492       else
00493         dt_courant = 2 * All.CourantFac * SphP[p].Hsml / SphP[p].MaxSignalVel;
00494 
00495       if(dt_courant < dt)
00496         dt = dt_courant;
00497     }
00498 
00499   /* convert the physical timestep to dloga if needed. Note: If comoving integration has not been selected,
00500      hubble_a=1.
00501    */
00502   dt *= hubble_a;
00503 
00504   if(dt >= All.MaxSizeTimestep)
00505     dt = All.MaxSizeTimestep;
00506 
00507   if(dt >= dt_displacement)
00508     dt = dt_displacement;
00509 
00510   if(dt < All.MinSizeTimestep)
00511     {
00512 #ifndef NOSTOP_WHEN_BELOW_MINTIMESTEP
00513       printf("warning: Timestep wants to be below the limit `MinSizeTimestep'\n");
00514 
00515       if(P[p].Type == 0)
00516         {
00517           printf
00518             ("Part-ID=%d  dt=%g dtc=%g ac=%g xyz=(%g|%g|%g)  hsml=%g  maxsignalvel=%g dt0=%g eps=%g\n",
00519              (int) P[p].ID, dt, dt_courant * hubble_a, ac, P[p].Pos[0], P[p].Pos[1], P[p].Pos[2],
00520              SphP[p].Hsml, SphP[p].MaxSignalVel,
00521              sqrt(2 * All.ErrTolIntAccuracy * atime * All.SofteningTable[P[p].Type] / ac) * hubble_a,
00522              All.SofteningTable[P[p].Type]);
00523         }
00524       else
00525         {
00526           printf("Part-ID=%d  dt=%g ac=%g xyz=(%g|%g|%g)\n", (int) P[p].ID, dt, ac, P[p].Pos[0], P[p].Pos[1],
00527                  P[p].Pos[2]);
00528         }
00529       fflush(stdout);
00530       endrun(888);
00531 #endif
00532       dt = All.MinSizeTimestep;
00533     }
00534 
00535   ti_step = dt / All.Timebase_interval;
00536 
00537   if(!(ti_step > 0 && ti_step < TIMEBASE))
00538     {
00539       printf("\nError: A timestep of size zero was assigned on the integer timeline!\n"
00540              "We better stop.\n"
00541              "Task=%d Part-ID=%d dt=%g tibase=%g ti_step=%d ac=%g xyz=(%g|%g|%g) tree=(%g|%g%g)\n\n",
00542              ThisTask, (int) P[p].ID, dt, All.Timebase_interval, ti_step, ac,
00543              P[p].Pos[0], P[p].Pos[1], P[p].Pos[2], P[p].GravAccel[0], P[p].GravAccel[1], P[p].GravAccel[2]);
00544 #ifdef PMGRID
00545       printf("pm_force=(%g|%g|%g)\n", P[p].GravPM[0], P[p].GravPM[1], P[p].GravPM[2]);
00546 #endif
00547       if(P[p].Type == 0)
00548         printf("hydro-frc=(%g|%g|%g)\n", SphP[p].HydroAccel[0], SphP[p].HydroAccel[1], SphP[p].HydroAccel[2]);
00549 
00550       fflush(stdout);
00551       endrun(818);
00552     }
00553 
00554   return ti_step;
00555 }
00556 
00557 
00566 void find_dt_displacement_constraint(double hfac  )
00567 {
00568   int i, j, type, *temp;
00569   int count[6];
00570   long long count_sum[6];
00571   double v[6], v_sum[6], mim[6], min_mass[6];
00572   double dt, dmean, asmth = 0;
00573 
00574   dt_displacement = All.MaxSizeTimestep;
00575 
00576   if(All.ComovingIntegrationOn)
00577     {
00578       for(type = 0; type < 6; type++)
00579         {
00580           count[type] = 0;
00581           v[type] = 0;
00582           mim[type] = 1.0e30;
00583         }
00584 
00585       for(i = 0; i < NumPart; i++)
00586         {
00587           v[P[i].Type] += P[i].Vel[0] * P[i].Vel[0] + P[i].Vel[1] * P[i].Vel[1] + P[i].Vel[2] * P[i].Vel[2];
00588           if(mim[P[i].Type] > P[i].Mass)
00589             mim[P[i].Type] = P[i].Mass;
00590           count[P[i].Type]++;
00591         }
00592 
00593       MPI_Allreduce(v, v_sum, 6, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
00594       MPI_Allreduce(mim, min_mass, 6, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD);
00595 
00596       temp = malloc(NTask * 6 * sizeof(int));
00597       MPI_Allgather(count, 6, MPI_INT, temp, 6, MPI_INT, MPI_COMM_WORLD);
00598       for(i = 0; i < 6; i++)
00599         {
00600           count_sum[i] = 0;
00601           for(j = 0; j < NTask; j++)
00602             count_sum[i] += temp[j * 6 + i];
00603         }
00604       free(temp);
00605 
00606       for(type = 0; type < 6; type++)
00607         {
00608           if(count_sum[type] > 0)
00609             {
00610               if(type == 0)
00611                 dmean =
00612                   pow(min_mass[type] / (All.OmegaBaryon * 3 * All.Hubble * All.Hubble / (8 * M_PI * All.G)),
00613                       1.0 / 3);
00614               else
00615                 dmean =
00616                   pow(min_mass[type] /
00617                       ((All.Omega0 - All.OmegaBaryon) * 3 * All.Hubble * All.Hubble / (8 * M_PI * All.G)),
00618                       1.0 / 3);
00619 
00620               dt = All.MaxRMSDisplacementFac * hfac * dmean / sqrt(v_sum[type] / count_sum[type]);
00621 
00622 #ifdef PMGRID
00623               asmth = All.Asmth[0];
00624 #ifdef PLACEHIGHRESREGION
00625               if(((1 << type) & (PLACEHIGHRESREGION)))
00626                 asmth = All.Asmth[1];
00627 #endif
00628               if(asmth < dmean)
00629                 dt = All.MaxRMSDisplacementFac * hfac * asmth / sqrt(v_sum[type] / count_sum[type]);
00630 #endif
00631 
00632               if(ThisTask == 0)
00633                 printf("type=%d  dmean=%g asmth=%g minmass=%g a=%g  sqrt(<p^2>)=%g  dlogmax=%g\n",
00634                        type, dmean, asmth, min_mass[type], All.Time, sqrt(v_sum[type] / count_sum[type]), dt);
00635 
00636               if(dt < dt_displacement)
00637                 dt_displacement = dt;
00638             }
00639         }
00640 
00641       if(ThisTask == 0)
00642         printf("displacement time constraint: %g  (%g)\n", dt_displacement, All.MaxSizeTimestep);
00643     }
00644 }

Generated on Sat Apr 22 15:29:41 2006 for GADGET-2 by  doxygen 1.3.9.1