16 #define CFLSECURITY 0.5
46 #pragma omp parallel for private(j,l) shared(bool)
47 for (i = 0; i < nr; i++) {
48 for (j = 0; j < ns; j++) {
63 char InputName[256], OutputName[256];
65 sprintf (InputName,
"%s%s",
OUTPUTDIR,
"radii.dat");
66 sprintf (OutputName,
"%s%s",
OUTPUTDIR,
"used_rad.dat");
67 input = fopen (InputName,
"r");
69 mastererr (
"Warning : no `radii.dat' file found. Using default.\n");
80 mastererr (
"Reading 'radii.dat' file.\n");
82 fscanf (input,
"%f", &temporary);
90 for (i = 0; i <
NRAD; i++) {
105 for (i = 1; i <
NRAD; i++) {
109 output = fopen (OutputName,
"w");
110 if (output == NULL) {
111 mastererr (
"Can't write %s.\nProgram stopped.\n", OutputName);
115 fprintf (output,
"%.18g\n",
Radii[i]);
119 if (input != NULL) fclose (input);
189 new= newarray->Field;
190 #pragma omp parallel for private(j,l)
191 for (i = 0; i <= nr; i++) {
192 for (j = 0; j < ns; j++) {
202 struct reb_simulation *rsim;
221 while (dtemp < 0.999999999*
DT) {
254 OmegaFrame = OmegaNew;
263 if (Crashed ==
YES) {
266 fprintf (stdout,
"\nCrash! at time %.12g\n",
timeCRASH);
294 Transport (Rho, Vrad, Vtheta, Energy, Label, dt);
308 int i, j, l, lim, ljm, ljp, nr, ns;
309 real *vrad, *vtheta, *rho;
310 real *vradint, *vthetaint;
311 real *accr, *acct, *dragr, *dragt;
312 real gradp, vt2, dxtheta, tmp;
314 real supp_torque=0.0;
322 vtheta = Vtheta->Field;
323 vradint = VradInt->
Field;
324 vthetaint = VthetaInt->
Field;
339 #pragma omp parallel private(j,l,lim,ljm,ljp,dxtheta,vt2,gradp,invdxtheta,supp_torque,tmp)
341 #pragma omp for nowait
342 for (i = 1; i < nr; i++) {
343 for (j = 0; j < ns; j++) {
347 if (j == 0) ljm = i*ns+ns-1;
349 if (j == ns-1) ljp = i*ns;
350 gradp = (press[l]-press[lim])*2.0/(rho[l]+rho[lim])*
InvDiffRmed[i];
351 vt2 = vtheta[l]+vtheta[ljp]+vtheta[lim]+vtheta[ljp-ns];
354 tmp = -gradp+0.5*(agr[l]+agr[lim])+vt2*
InvRinf[i];
355 vradint[l] = vrad[l]+dt*tmp;
359 tmp = dragr[l]*2.0/(rho[l]+rho[lim]);
360 vradint[l] += dt*tmp;
367 for (i = 0; i < nr; i++) {
370 invdxtheta = 1.0/dxtheta;
371 for (j = 0; j < ns; j++) {
375 if (j == 0) ljm = i*ns+ns-1;
377 if (j == ns-1) ljp = i*ns;
378 gradp = (press[l]-press[ljm])*2.0/(rho[l]+rho[ljm])*invdxtheta;
379 tmp = -gradp + 0.5*(agt[l]+agt[ljm]);
380 vthetaint[l] = vtheta[l]+dt*tmp;
381 vthetaint[l] += dt*supp_torque;
383 acct[l] = tmp + supp_torque;
385 tmp = dragt[l]*2.0/(rho[l]+rho[ljm]);
386 vthetaint[l] += dt*tmp;
406 int i, j, l, lim, lip, ljm, ljp, nr, ns;
407 real *vrad, *vtheta, *rho, *energy;
408 real *vradnew, *vthetanew, *qt, *qr, *energyint;
409 real dxtheta, invdxtheta;
414 vrad = VradInt->
Field;
415 vtheta = VthetaInt->
Field;
417 vradnew = VradNew->
Field;
418 vthetanew = VthetaNew->
Field;
419 qt = TemperInt->
Field;
420 energy = Energy->Field;
421 energyint = EnergyInt->
Field;
426 #pragma omp parallel for private(j,dxtheta,l,lim,lip,ljm,ljp,dv)
427 for (i = 0; i < nr; i++) {
428 for (j = 0; j < ns; j++) {
432 if (j == ns-1) ljp = i*ns;
433 dv = vrad[lip]-vrad[l];
438 dv = vtheta[ljp]-vtheta[l];
445 #pragma omp parallel private(l,lim,lip,ljm,ljp,j,dxtheta,invdxtheta)
447 #pragma omp for nowait
449 for (i = 1; i < nr; i++) {
450 for (j = 0; j < ns; j++) {
453 vradnew[l] = vrad[l]-dt*2.0/(rho[l]+rho[lim])*(qr[l]-qr[lim])*
InvDiffRmed[i];
458 for (i = 0; i < nr; i++) {
460 invdxtheta = 1.0/dxtheta;
461 for (j = 0; j < ns; j++) {
464 if (j == 0) ljm = i*ns+ns-1;
465 vthetanew[l] = vtheta[l]-dt*2.0/(rho[l]+rho[ljm])*(qt[l]-qt[ljm])*invdxtheta;
473 #pragma omp for nowait
474 for (i=0; i<nr; i++) {
476 invdxtheta = 1.0/dxtheta;
477 for (j = 0; j < ns; j++) {
481 if (j == ns-1) ljp = i*ns;
482 energyint[l] = energy[l] - \
484 dt*qt[l]*(vtheta[ljp]-vtheta[l])*invdxtheta;
497 real *rho, *energy, *energynew, *qplus, *Trr, *Trp, *Tpp, *divergence;
499 real viscosity, r0, r1, r2, qplus1, qplus2, tmp1, tmp2;
504 energy = EnergyInt->
Field;
506 energynew = EnergyNew->
Field;
516 #pragma omp parallel default(none) \
517 shared (nr,ns,Rmed,rho,Trr,Trp,Tpp,divergence,qplus,r0,r1,r2,EnergyMed,\
518 dt,SigmaMed,CoolingTimeMed,energy,QplusMed,energynew,\
519 ParametricCooling,ADIABIND) \
520 private (i,j,l,viscosity,qplus1,qplus2,tmp1,tmp2)
526 for (i=1; i<nr; i++) {
528 for (j=0; j<ns; j++) {
530 if (viscosity != 0.0) {
531 qplus[l] = 0.5/viscosity/rho[l]*(Trr[l]*Trr[l] + \
532 2.0*Trp[l]*Trp[l] + \
534 qplus[l] += (2.0/9.0)*viscosity*rho[l]*divergence[l]*divergence[l];
543 for (j=0; j<ns; j++) {
544 qplus1 = qplus[j+ns];
545 qplus2 = qplus[j+2*ns];
546 if (viscosity != 0.0) {
548 qplus[j] = qplus1*exp( log(qplus1/qplus2)*log(r0/r1)/log(r1/r2) );
556 for (i=0; i<nr; i++) {
557 for (j=0; j<ns; j++) {
564 energynew[l] = tmp1/tmp2;
579 int i, j, l, ns, nr, lip, ljp;
580 real invdt1, invdt2, invdt3, invdt4, invdt5=1e-30, cs, newdt, dt;
582 real itdbg1=0., itdbg2=0., itdbg3=0., itdbg4=0., itdbg5=0., mdtdbg=0.;
584 real *vt, *vr, dxrad, dxtheta, dvr, dvt, viscr=0., visct=0.;
593 for (i = 0; i < nr; i++) {
597 for (j = 0; j < ns; j++) {
606 for (j = 0; j < ns; j++) {
609 Vresidual[j] = vt[l]-Vmoy[i];
611 Vresidual[j] = vt[l];
613 Vresidual[ns]=Vresidual[0];
614 for (j = 0; j < ns; j++) {
618 if (j == ns-1) ljp = i*ns;
620 invdt1 = cs/(
min2(dxrad,dxtheta));
621 invdt2 = fabs(vr[l])/dxrad;
622 invdt3 = fabs(Vresidual[j])/dxtheta;
625 if (dvr >= 0.0) dvr = 1e-10;
627 if (dvt >= 0.0) dvt = 1e-10;
629 invdt4 =
max2(dvr/dxrad,dvt/dxtheta);
636 dt =
CFLSECURITY/sqrt(invdt1*invdt1+invdt2*invdt2+invdt3*invdt3+\
646 itdbg1 = 1.0/invdt1; itdbg2=1.0/invdt2;
647 itdbg3=1.0/invdt3; itdbg4=1.0/invdt4;
650 viscr = dxrad/dvr/4.0/CVNR/
CVNR;
651 visct = dxtheta/dvt/4.0/CVNR/
CVNR;
658 if (dt < newdt) newdt = dt;
660 if (deltaT < newdt) newdt = deltaT;
662 printf (
"Timestep control information for CPU %d: \n",
CPU_Rank);
663 printf (
"Most restrictive cell at i=%d and j=%d\n", ideb, jdeb);
664 printf (
"located at radius Rmed : %g\n",
Rmed[ideb]);
665 printf (
"Sound speed limit : %g\n", itdbg1);
666 printf (
"Radial motion limit : %g\n", itdbg2);
667 printf (
"Residual circular motion limit : %g\n", itdbg3);
668 printf (
"Artificial viscosity limit : %g\n", itdbg4);
669 printf (
" Arise from r with limit : %g\n", viscr);
670 printf (
" and from theta with limit : %g\n", visct);
671 printf (
"Physical viscosity limit : %g\n", itdbg5);
672 printf (
"Limit time step for this cell : %g\n", mdtdbg);
673 printf (
"Limit time step adopted : %g\n", newdt);
674 if (newdt < mdtdbg) {
675 printf (
"Discrepancy arise either from shear.\n");
676 printf (
"or from the imposed DT interval.\n");
679 return (
int)(ceil(deltaT/newdt));
687 real *rho, *energy, *cs;
692 energy = Energy->Field;
694 for (i=0; i<nr; i++) {
695 for (j=0; j<ns; j++) {
712 real *rho, *energy, *pressure, *cs;
717 energy = Energy->Field;
720 for (i=0; i<nr; i++) {
721 for (j=0; j<ns; j++) {
724 pressure[l] = rho[l]*cs[l]*cs[l];
726 pressure[l] = (
ADIABIND-1.0)*energy[l];
738 real *rho, *energy, *temperature, *pressure;
743 energy = Energy->Field;
746 for (i=0; i<nr; i++) {
747 for (j=0; j<ns; j++) {
752 temperature[l] = tmp1*tmp2;
755 temperature[l] = tmp1*tmp2;
void ImposeKeplerianEdges()
double real
Definition of the type 'real' used throughout the code.
void AlgoGas(PolarGrid *Rho, PolarGrid *Vrad, PolarGrid *Vtheta, PolarGrid *Energy, PolarGrid *Label, PlanetarySystem *sys, struct reb_simulation *rsim)
void ImplicitRadiativeDiffusion(PolarGrid *Rho, PolarGrid *EnergyInt, PolarGrid *EnergyNew, real dt)
The main numerical solver of the energy equation.
int ConditionCFL(PolarGrid *Vrad, PolarGrid *Vtheta, real deltaT)
boolean PrescribedAccretion
real max2(real a, real b)
void SynchronizeFargoRebound()
PolarGrid * PebbleGravAccelTheta
PolarGrid * CreatePolarGrid(int Nr, int Ns, char *name)
void SetWaveKillingZones()
Sets the wave-killing factors within the damping zones; inspired by de Val-Borro et al...
static PolarGrid * VthetaInt
PolarGrid * DragForceTheta
static PolarGrid * VthetaNew
A structure used to store any scalar fied on the computational domain.
real min2(real a, real b)
static PolarGrid * VradNew
int Nrad
Radial size of the grid, in number of zones.
real GetPsysInfoFromRsim()
void SubStep1Pebbles(PolarGrid *Vrad, PolarGrid *Vtheta, real dt)
Applies a semi-implicit method to evolve the pebbles dynamically.
Contains all the information about a planetary system at a given instant in time. ...
static PolarGrid * VradInt
void ComputeSoundSpeed(PolarGrid *Rho, PolarGrid *Energy)
Updates the sound speed over the mesh.
void InitGasVelocity(PolarGrid *Vr, PolarGrid *Vt)
static int GasTimeStepsCFL
real CoolingTimeMed[MAX1D]
void CorrectPebblesVtheta(real domega)
Corrects the azimuthal flow velocity of pebbles to keep up with the frame rotation.
void PebbleStokesNumbers(PolarGrid *Rho)
Calculates the local Stokes number using the dominant pebble size, local gas density and parametric p...
void AccreteOntoPlanets(PolarGrid *Rho, PolarGrid *Vrad, PolarGrid *Vtheta, real dt, PlanetarySystem *sys)
void ComputePressureField(PolarGrid *Rho, PolarGrid *Energy)
Updates the pressure over the mesh.
void UpdateDivVelocAndStressTensor()
void AccretePebblesOntoPlanets(PlanetarySystem *sys, PolarGrid *Rho, PolarGrid *Energy, PolarGrid *Vtheta, real dt)
Finds the amount of pebbles to be transfered from the pebble disk onto the planets.
void InitEuler(PolarGrid *Rho, PolarGrid *Vr, PolarGrid *Vt, PolarGrid *En)
PolarGrid * PebbleGravAccelRad
boolean DetectCrashPebbles()
Safety check for negative pebble densities.
void MPI_Allreduce(void *ptr, void *ptr2, int count, int type, int foo3, int foo4)
void ComputeTemperatureField(PolarGrid *Rho, PolarGrid *Energy)
Updates the temperature over the mesh.
void FillForcesArrays(PolarGrid *Rho, PlanetarySystem *sys)
Using the vertical averaging procedure of Muller & Kley (2012), calculates the acceleration in planet...
void InitGasDensityEnergy(PolarGrid *Rho, PolarGrid *Energy)
Part of the initialisation.
void ParametricAccretion(PlanetarySystem *sys, real dt)
Writes filtering factors if needed.
void SubStep3(PolarGrid *Rho, real dt)
Numerical step reponsible for the energy update.
void SubStep2(PolarGrid *Rho, PolarGrid *Energy, real dt)
void SubStep1(PolarGrid *Vrad, PolarGrid *Vtheta, PolarGrid *Rho, real dt)
void UpdateVelocityWithViscousTerms()
static PolarGrid * TemperInt
void mastererr(const char *template,...)
PolarGrid * GravAccelTheta
PolarGrid * DivergenceVelocity
void InitRadiatDiffusionFields()
Initialises the polar arrays associated with the heating/cooling processes.
void ParticleDiffusion(PolarGrid *Rho)
Applies the particle diffusion term acting on pebbles.
boolean DetectCrash(PolarGrid *array)
Contains all the include directives requested by the code.
int Nsec
Azimuthal size of the grid, in number of zones.
void CriticalCharTime(PolarGrid *Vrad, PolarGrid *Vtheta)
Restricts the time step using the CFL condition for the pebble fluid.
void AdvanceSystemFromDisk(PolarGrid *Rho, PlanetarySystem *sys, real dt)
Updates the planet velocities due to disk forces.
static PolarGrid * EnergyNew
static PolarGrid * EnergyInt
void EvolvePebbleDisk(real dt)
Calls the transport routines and applies the boundary conditions for pebbles.
void ActualiseGas(PolarGrid *array, PolarGrid *newarray)
boolean ParametricCooling
void AdvanceSystemRebound()
void CommunicateBoundaries(PolarGrid *Density, PolarGrid *Vrad, PolarGrid *Vtheta, PolarGrid *Energy, PolarGrid *Label)
static int AlreadyCrashed
PolarGrid * GasAcceltheta
void WriteDiskPolar(PolarGrid *array, int number)
void SourceTermsPebbles(PolarGrid *Vrad, PolarGrid *Vtheta, real dt)
Calculates the source terms acting on pebbles.
void InitPebbleArrays()
Initialise polar arrays associated with the pebble disk.
void ApplyBoundaryCondition()
void mpi_make1Dprofile(real *gridfield, real *axifield)
void SynchronizePebbleDisc()
Synchronises pebble fluid hydrodynamic quantities among the overlapping grid zones.
void masterprint(const char *template,...)
boolean DiffusiveParticles