22 #define TRAPEZEPS 1.0e-7
83 static real pebbleflux=0.0;
85 real *rho, *vr, *etafc, *etacc, *psize, *tau, *pdens, *pvr, *pvt;
86 real rho1, vr1, etafc1, etacc1;
87 real pdens1, psize1, tau1, pvr1, pvt1;
88 real vtcorr, vkepl, fac, etaterm, pvrtemp;
93 psize = PebbleSize->
Field;
98 etafc = EtaFaceCentered->
Field;
99 etacc = EtaCellCentered->
Field;
102 for (i=0; i<nr; i++) {
108 for (j=0; j<ns; j++) {
121 tau1 = sqrt(tau1)/(
Rmed[i]*etacc1);
124 vkepl = pow (
Rmed[i], -0.5);
125 fac = 1.0/(tau1*tau1 + 1.0);
126 etaterm = etafc1*vkepl;
127 pvr1 = -2.0*tau1*fac*(etaterm - 0.5/tau1*vr1);
128 etaterm = etacc1*vkepl;
129 pvrtemp = -2.0*tau1*fac*(etaterm - 0.5/tau1*vr1);
130 pvt1 = -fac*(etaterm - 0.5*tau1*vr1);
131 pvt1 += (vkepl - vtcorr);
132 pdens1 = pebbleflux/(2.0*
PI*
Rmed[i]*fabs(pvrtemp));
134 for (j=0; j<ns; j++) {
152 sprintf (command,
"cd %s; cat gaspebblestokes0.dat.%05d >> gaspebblestokes0.dat",\
155 sprintf (command,
"cd %s; cat gaspebblesize0.dat.%05d >> gaspebblesize0.dat",\
159 sprintf (command,
"cd %s; rm -f gaspebblestokes0.dat.0*",
OUTPUTDIR);
161 sprintf (command,
"cd %s; rm -f gaspebblesize0.dat.0*",
OUTPUTDIR);
170 real *pdens, *pvr, *pvt;
177 for (i=0; i<nr; i++) {
181 for (j=0; j<ns; j++) {
198 int i, j, l, lim, ljp, nr, ns;
199 real vtcorr, vkinv, vtcc;
200 real *vt, *etafc, *etacc;
205 etafc = EtaFaceCentered->
Field;
206 etacc = EtaCellCentered->
Field;
207 #pragma omp parallel default(none) \
208 shared (nr,ns,Rmed,OmegaFrame,vt,etacc,etafc) \
209 private (i,j,l,vtcorr,vkinv,ljp,lim,vtcc)
212 for (i=0; i<nr; i++) {
214 vkinv = sqrt(
Rmed[i]);
215 for (j=0; j<ns; j++) {
218 if (j == ns-1) ljp = i*ns;
219 vtcc = 0.5*(vt[l]+vt[ljp]);
220 etacc[l] = 1.0 - (vtcc + vtcorr)*vkinv;
224 for (i=1; i<nr; i++) {
225 for (j=0; j<ns; j++) {
228 etafc[l] = 0.5*(etacc[l]+etacc[lim]);
232 for (j=0; j<ns; j++) {
233 etafc[j] = etafc[j+ns];
244 real *rho, *tau, *psize;
250 psize = PebbleSize->
Field;
251 #pragma omp parallel for default(none) \
252 shared (nr,ns,tau,pebbulkdens,psize,rho,SQRT_ADIABIND_INV) \
254 for (i=0; i<nr; i++) {
255 for (j=0; j<ns; j++) {
269 static real integral;
270 real iter, spacing, x, sum;
273 integral = 0.5*(b-
a)*(exp(-0.5*a*a/H2) + exp(-0.5*b*b/H2));
276 iter = pow(2.0,(
real)(n-2));
277 spacing = (b-
a)/iter;
280 for (j=1; j<=(int)iter; j++) {
281 sum += exp(-0.5*x*x/H2);
284 integral = 0.5*(integral + (b-
a)*sum/iter);
296 real integral, iold, H2;
299 integral =
Trapzd (n,a,b,H2);
301 if (fabs(integral-iold) <
TRAPEZEPS*fabs(iold) || (integral == 0.0 && iold == 0.0))
return integral;
305 masterprint (
"Warning! Integration of the column mass did not converge. Terminating now...\n");
317 real *pdens, *abs, *ord;
318 real *pvr, *pvt, *tau, *cs, *vt, *macc;
319 int nr,ns,k,i,j,l,imin,imax,ncell,tempint;
320 real dMplanet, dPXplanet, dPYplanet;
321 real Xplanet,
Yplanet, Zplanet,
VXplanet,
VYplanet, VZplanet, Mplanet, PXplanet, PYplanet, Rplanet, Rplanet3D, Omegaplanet;
322 real vtcorr, xcell, ycell, vrcell, vtcell, vxcell, vycell, flow, flowx, flowy, vrel;
323 real ifrac, frac, Mt, Rbondi, tbondi, fac, Reff=0.0, Reff2, Rhill;
324 real R2, H, Hpeb, zmin, zmax, dM, mcell, voldenspeb, temp;
325 real ang, plradius, plrho, dE, L, tdelay, taper;
326 real tau_mean, dM_upper, Hpeb_mean, pdens_mean, veloc, dM_model, limiter;
337 macc = AccretedMass->
Field;
341 for (k=0; k<sys->nb; k++) {
342 dMplanet = dPXplanet = dPYplanet = 0.0;
346 VXplanet = sys->vx[k];
347 VYplanet = sys->vy[k];
348 VZplanet = sys->vz[k];
349 Mplanet = sys->mass[k];
350 PXplanet = VXplanet*Mplanet;
351 PYplanet = VYplanet*Mplanet;
352 Rplanet = Xplanet*Xplanet + Yplanet*
Yplanet;
353 Rplanet3D = sqrt(Rplanet + Zplanet*Zplanet);
354 Rplanet = sqrt(Rplanet);
355 Rhill = Rplanet3D*pow(1.0/3.0*Mplanet, 1.0/3.0);
356 Omegaplanet = pow(Rplanet, -1.5);
358 frac = ifrac-floor(ifrac);
361 flowx = -flow*Yplanet/Rplanet;
362 flowy = flow*Xplanet/Rplanet;
363 vrel = sqrt((VXplanet-flowx)*(VXplanet-flowx) + (VYplanet-flowy)*(VYplanet-flowy) + VZplanet*VZplanet);
364 Mt = sqrt(1.0/3.0)*pow(vrel,3.0)/Omegaplanet;
367 while (
Rinf[imax] > (Rplanet+Rhill) && imax >= imin) imax--;
368 while (
Rsup[imin] < (Rplanet-Rhill) && imin <= imax) imin++;
372 for (i=imin; i<=imax; i++) {
373 for (j=0; j<ns; j++) {
383 tau_mean /= (
real)ncell;
386 Rbondi = Mplanet/vrel/vrel;
387 tbondi = Rbondi/vrel;
388 fac = sqrt(tau_mean*pow(Rplanet, 1.5)/tbondi);
391 fac = pow(tau_mean/0.1, 1.0/3.0);
394 if (Reff > Rhill) Reff = Rhill;
401 for (i=imin; i<=imax; i++) {
403 for (j=0; j<ns; j++) {
407 R2 = (xcell-
Xplanet)*(xcell-Xplanet) + (ycell-
Yplanet)*(ycell-Yplanet);
411 zmin = Zplanet - sqrt(Reff2 - R2);
412 zmax = Zplanet + sqrt(Reff2 - R2);
413 mcell =
Surf[i]*pdens[l];
416 if (dM > mcell) dM = 0.99999999*mcell;
420 pdens_mean += pdens[l];
433 Hpeb_mean /= (
real)ncell;
434 pdens_mean /= (
real)ncell;
440 veloc = Reff*Omegaplanet;
442 if (Hpeb_mean < Reff) {
443 dM_model = 2.0*Reff*veloc*pdens_mean;
445 dM_model =
PI*Reff*Reff*veloc*pdens_mean/Hpeb_mean*
SQRT2PI_INV;
448 if (dM_upper > dM_model) {
449 limiter = dM_model/dM_upper;
454 for (i=imin; i<=imax; i++) {
456 for (j=0; j<ns; j++) {
462 vtcell = pvt[l] + vtcorr;
463 vxcell = (vrcell*xcell - vtcell*ycell)*
InvRmed[i];
464 vycell = (vrcell*ycell + vtcell*xcell)*
InvRmed[i];
465 dM = macc[l]*limiter;
467 mcell =
Surf[i]*pdens[l];
468 pdens[l] = (mcell - dM)/
Surf[i];
469 if (pdens[l] < 0.0) pdens[l] = 1.e-20;
471 dPXplanet += dM*vxcell;
472 dPYplanet += dM*vycell;
485 if (Rplanet >=
Rinf[0] && Rplanet <=
Rsup[nr-1]) {
488 if (taper > 1.0) taper = 1.0;
490 plradius = pow (3.0*Mplanet/(4.0*
PI*plrho), 1.0/3.0);
491 L = Mplanet*dMplanet/dt/plradius;
492 ang = atan2(Yplanet,Xplanet);
493 if (ang < 0.0) ang += 2.0*
PI;
495 while (
Rsup[i] < Rplanet) i++;
496 j = floor((
real)ns/2.0/
PI*ang + 0.5);
500 dE = L*taper/
Surf[i];
505 PXplanet += dPXplanet;
506 PYplanet += dPYplanet;
508 sys->mass[k] = Mplanet;
509 sys->vx[k] = PXplanet/Mplanet;
510 sys->vy[k] = PYplanet/Mplanet;
527 real *pvr, *pvt, *tau, *paccr, *pacct, *vr, *vt, *pdens, *dragr, *dragt;
529 real Omega, vt2, drag;
530 int nr, ns, i, j, l, lim, ljm, ljp;
535 paccr = PebbleAccelrad->
Field;
536 pacct = PebbleAcceltheta->
Field;
546 #pragma omp parallel private(i,j,l,lim,ljm,ljp,vt2,Omega,drag)
549 for (i = 1; i < nr; i++) {
551 for (j = 0; j < ns; j++) {
555 if (j == 0) ljm = i*ns+ns-1;
557 if (j == ns-1) ljp = i*ns;
558 vt2 = pvt[l]+pvt[ljp]+pvt[lim]+pvt[ljp-ns];
561 paccr[l] = vt2*
InvRinf[i]+0.5*(pagr[l]+pagr[lim]);
563 drag = Omega*(pvr[l] - vr[l])/tau[l];
564 dragr[l] = 0.5*(pdens[l]+pdens[lim])*drag;
569 for (i = 0; i < nr; i++) {
571 for (j = 0; j < ns; j++) {
575 if (j == 0) ljm = i*ns+ns-1;
577 if (j == ns-1) ljp = i*ns;
578 pacct[l] = 0.5*(pagt[l]+pagt[ljm]);
580 drag = Omega*(pvt[l] - vt[l])/tau[l];
581 dragt[l] = 0.5*(pdens[l]+pdens[ljm])*drag;
594 real *pvr, *pvt, *tau, *paccr, *pacct, *accr, *acct, *vr, *vt;
600 paccr = PebbleAccelrad->
Field;
601 pacct = PebbleAcceltheta->
Field;
608 #pragma omp parallel private(j,l,Omega,efac)
611 for (i = 0; i < nr; i++) {
613 for (j = 0; j < ns; j++) {
615 efac = exp(-dt*Omega/tau[l]);
617 pvr[l] = pvr[l]*efac + accr[l]*dt + \
618 (vr[l] + (paccr[l] - accr[l])*tau[l]/Omega)*(1.0 - efac);
620 pvt[l] = pvt[l]*efac + acct[l]*dt + \
621 (vt[l] + (pacct[l] - acct[l])*tau[l]/Omega)*(1.0 - efac);
632 int i,j,l,lim,ljm,nr,ns;
633 real corr, dxtheta, invdxtheta;
634 real *rho, *pdens, *pvr, *pvt;
641 #pragma omp parallel default(none) \
642 shared (nr,ns,Rinf,SCHMIDTNUMBER,rho,pdens,InvDiffRmed,pvr,Rmed,pvt) \
643 private (i,j,l,lim,ljm,corr,dxtheta,invdxtheta)
646 for (i=1; i<nr; i++) {
647 for (j=0; j<ns; j++) {
651 corr *= (rho[l] + rho[lim])/(pdens[l] + pdens[lim]);
652 corr *= (pdens[l]/rho[l] - pdens[lim]/rho[lim])*
InvDiffRmed[i];
657 for (i=0; i<nr; i++) {
659 invdxtheta = 1.0/dxtheta;
660 for (j=0; j<ns; j++) {
663 if (j == 0) ljm = i*ns+ns-1;
665 corr *= (rho[l] + rho[ljm])/(pdens[l] + pdens[ljm]);
666 corr *= (pdens[l]/rho[l] - pdens[ljm]/rho[ljm])*invdxtheta;
688 real *pdens, *pvr, *pvt;
705 real dxrad, dxtheta, pvtmed=0.0, invdt1, invdt2, invdt3, invdt4, Vresidual, temp;
706 real *pvr, *pvt, *vr, *vt;
719 for (j=0; j<ns; j++) {
725 for (j=0; j<ns; j++) {
727 invdt1 = fabs(pvr[l])/dxrad;
729 Vresidual = pvt[l] - pvtmed;
733 invdt2 = fabs(Vresidual)/dxtheta;
734 invdt3 = fabs(pvr[l] - vr[l])/dxrad;
735 invdt4 = fabs(pvt[l] - vt[l])/dxtheta;
736 temp = invdt1*invdt1 + invdt2*invdt2 + invdt3*invdt3 + invdt4*invdt4;
783 int k, i, j, l, nr, ns;
785 real plrho, plradius, L, ang, dE;
786 static real doubling=0.0;
791 for (k=0; k<sys->nb; k++) {
792 Mplanet = sys->mass[k];
795 dMplanet = Mplanet*dt/doubling;
796 Rplanet = sqrt(Xplanet*Xplanet + Yplanet*Yplanet);
799 if (Rplanet >=
Rinf[0] && Rplanet <=
Rsup[nr-1]) {
802 if (taper > 1.0) taper = 1.0;
804 plradius = pow (3.0*Mplanet/(4.0*
PI*plrho), 1.0/3.0);
805 L = Mplanet*Mplanet/doubling/plradius;
806 ang = atan2(Yplanet,Xplanet);
807 if (ang < 0.0) ang += 2.0*
PI;
809 while (
Rsup[i] < Rplanet) i++;
810 j = floor((
real)ns/2.0/
PI*ang + 0.5);
814 dE = L*taper/
Surf[i];
819 sys->mass[k] = Mplanet;
double real
Definition of the type 'real' used throughout the code.
void EtaPressureSupport(PolarGrid *Vtheta)
Calculates tha gas rotation parameter eta.
PolarGrid * PebbleGravAccelTheta
void EquilPebbleDisk(PolarGrid *Rho, PolarGrid *Vrad, PolarGrid *Vtheta)
Sets up a pebble disk in a coagulation-drift equilibrium.
real Trapzd(int n, real a, real b, real H2)
Trapezoidal rule to integrate the column mass of pebbles located within the accretion radius...
PolarGrid * CreatePolarGrid(int Nr, int Ns, char *name)
real IntegrateColumnMass(real a, real b, real Hpeb)
Primitive algorithm to find the mass in a vertical column of pebbles overlapping the accretion radius...
PolarGrid * DragForceTheta
void RestartPebbleDisk(PolarGrid *Rho, int index)
Reads arrays necessary to restart the pebble disk.
A structure used to store any scalar fied on the computational domain.
int Nrad
Radial size of the grid, in number of zones.
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 * PebbleAcceltheta
real PebVthetaInit[MAX1D]
void SynchronizeOverlapFields(real *field, int nr, int nsync)
For a MPI-split grid, synchronizes the values in a requested number 'nsync' of the overlapping radial...
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 WritePebbles(int index)
Outputs the pebble fluid arrays.
boolean heatsrc_index[MAXPLANETS]
static PolarGrid * EtaCellCentered
static PolarGrid * PebbleDensTemp
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.
static PolarGrid * AccretedMass
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 ParametricAccretion(PlanetarySystem *sys, real dt)
Writes filtering factors if needed.
void InitPebblesViaFlux(PolarGrid *Rho, PolarGrid *Vrad)
Imposing the radial mass flux of pebbles in a coagulation-drift equilibrium, initialises their surfac...
void BckpFieldsForBC()
Backs up the initial state of the pebble disk to impose damping boundary conditions later...
static PolarGrid * PebbleAccelrad
void ParticleDiffusion(PolarGrid *Rho)
Applies the particle diffusion term acting on pebbles.
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.
real GetGlobalIFrac(real r)
void ReadfromFile(PolarGrid *array, char *fileprefix, int filenumber)
void EvolvePebbleDisk(real dt)
Calls the transport routines and applies the boundary conditions for pebbles.
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 mpi_make1Dprofile(real *gridfield, real *axifield)
void SynchronizePebbleDisc()
Synchronises pebble fluid hydrodynamic quantities among the overlapping grid zones.
static PolarGrid * EtaFaceCentered
static PolarGrid * PebbleSize
void masterprint(const char *template,...)