The FARGO_THORIN code developer's guide
 All Data Structures Files Functions Variables Typedefs Macros
Pframeforce.c
Go to the documentation of this file.
1 /**
2  * @file Pframeforce.c
3  *
4  * @brief Calculates the gravitational interactions
5  * between the disk and massive bodies in terms of a
6  * vertically averaged potential.
7  *
8  * @author Ondřej Chrenko <chrenko@sirrah.troja.mff.cuni.cz>
9  *
10  * @details The function FillForcesArrays() computes the
11  * gravitational acceleration due to planet-disk and star-disk
12  * interactions adopting the outline of Muller & Kley (2012).
13  * Works both for the gas and pebbles.
14  * The indirect terms are included as well as a
15  * deep cubic potential with thickness smoothing (see Eq. (37)
16  * in Chrenko et al. 2017). There is also a function which
17  * provides the inclination damping for 3D planetary orbits.
18  *
19  * @section LICENSE
20  * Copyright (c) 2017 Ondřej Chrenko. See the LICENSE file of the
21  * distribution.
22  *
23  */
24 
25 #include "fargo.h"
26 
27 extern boolean AllowAccretion, Corotating, Indirect_Term;
30 
31 extern boolean DumpTorqueNow, DumpTorqueDensNow; /* #THORIN: new output control */
32 
33  /* Below : work in non-rotating frame */
34  /* centered on the primary */
35 /** Using the vertical averaging procedure of Muller &
36  * Kley (2012), calculates the acceleration in planet-disk
37  * and star-disk interactions for both gas and pebbles. */
38 void FillForcesArrays (Rho, sys) /* #THORIN: redesigned using accelerations instead of the potential */
39 PolarGrid *Rho;
40 PlanetarySystem *sys;
41 {
42  int i,j,l,nr,ns,k,npl;
43  real x, y;
44  real xpl, ypl, zpl, mpl, dpl, invdpl3, smoothing;
45  int m, Nvert;
46  real d2, d, H, H2, zmax, deltaz;
47  real rsm[MAXPLANETS], rsm2[MAXPLANETS], sigma, znode, znode2, denom, ax, ay, ar, at, axindir, ayindir;
48  real rst, rst2[MAXPLANETS], rst3[MAXPLANETS], rst4[MAXPLANETS], taper, omegainv, r2, r2chk_1, r2chk_2;
49  real integstar, sum, tmp, tmpbuf;
50  real cs_avr, integstar_avr, sigma_avr, H_avr;
51  real tau_avr=0.0, p_H_avr=0.0, p_integstar_avr=0.0, p_integstar=0.0, pax=0.0, pay=0.0, pH=0.0, Hcorr=0.0;
52  Pair IndirectTermFromPlanets;
53  boolean IntegrateWithPlanet[MAXPLANETS], IntegrateLocally;
54  real axstar, aystar, hillcut[MAXPLANETS]={1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0}, mcell;
55  real rhill[MAXPLANETS], smoothing2[MAXPLANETS], Hpl[MAXPLANETS], s2[MAXPLANETS], integpl[MAXPLANETS], p_integpl[MAXPLANETS], rmorevert2[MAXPLANETS];
56  real tmparray[MAXPLANETS]={0.,0.,0.,0.,0.,0.,0.,0.,0.,0.}, axpl[MAXPLANETS]={0.,0.,0.,0.,0.,0.,0.,0.,0.,0.}, aypl[MAXPLANETS]={0.,0.,0.,0.,0.,0.,0.,0.,0.,0.};
57  real *agr, *agt, *pagr, *pagt, *rho, *tau, *cs, *abs, *ord, *tqwk;
58  agr = GravAccelRad->Field;
59  agt = GravAccelTheta->Field;
60  rho = Rho->Field;
61  cs = SoundSpeed->Field;
62  abs = CellAbscissa->Field;
63  ord = CellOrdinate->Field;
64  nr = Rho->Nrad;
65  ns = Rho->Nsec;
66  if (Pebbles) {
67  pagr = PebbleGravAccelRad->Field;
69  tau = StokesNumber->Field;
70  }
71  if (TorqueDensity) tqwk = Torque->Field;
72  npl = sys->nb;
73 #pragma omp parallel for
74  for (i = 0; i < (nr+1)*ns; i++) {
75  agr[i] = 0.0;
76  agt[i] = 0.0;
77  if (Pebbles) {
78  pagr[i] = 0.0;
79  pagt[i] = 0.0;
80  }
81  }
82  // pre-calculate planet distances, FULL hill spheres (with no mass tapering) and indirect term caused by planets accelerating the star
83  axstar = 0.0;
84  aystar = 0.0;
85  for (k = 0; k < npl; k++) {
86  axpl[k] = 0.0;
87  aypl[k] = 0.0;
88  xpl = sys->x[k];
89  ypl = sys->y[k];
90  zpl = sys->z[k];
91  mpl = sys->mass[k];
92  dpl = sqrt(xpl*xpl+ypl*ypl+zpl*zpl);
93  rhill[k] = dpl*pow((1.0/3.0*mpl),1.0/3.0);
94  smoothing = ThicknessSmoothing (xpl,ypl); // see Force.c
95  Hpl[k] = smoothing/THICKNESSSMOOTHING; // get the thickness along planet's orbit from the smoothing value
96  smoothing2[k] = smoothing*smoothing;
97  rst = 0.5*rhill[k]; // specif. lengths for the potential tapered by cubic spline
98  rst2[k] = rst*rst;
99  rst3[k] = rst2[k]*rst;
100  rst4[k] = rst3[k]*rst;
101  rsm[k] = 0.05*rhill[k]; // small smoothing length to avoid diverging denom. near planets
102  rsm2[k] = rsm[k]*rsm[k];
103  rmorevert2[k] = 2.0*rhill[k];
104  rmorevert2[k] *= rmorevert2[k];
105  if (Indirect_Term == YES) {
106  invdpl3 = 1.0/(dpl*dpl*dpl); // finally, we look for the indirect term if needed
107  mpl *= MassTaper;
108  axstar += mpl*invdpl3*xpl;
109  aystar += mpl*invdpl3*ypl;
110  }
111  }
112  IndirectTermFromPlanets.x = - axstar;
113  IndirectTermFromPlanets.y = - aystar;
114  axstar = 0.0; // reset the protostar's acceleration - in the following, its accel. from the disk will be computed
115  aystar = 0.0;
116 #pragma omp parallel for \
117  firstprivate (tau_avr,p_H_avr,p_integstar_avr,p_integstar,pax,pay,pH,Hcorr) \
118  private (omegainv, r2, Nvert, cs_avr, H_avr, \
119 H2, zmax, deltaz, sigma_avr, integstar_avr, znode, znode2, sum, \
120 d2, d, denom, IntegrateLocally, ax, ay, x, y, mcell, H, \
121 xpl, ypl, zpl, s2, r2chk_1, r2chk_2, IntegrateWithPlanet, integpl, p_integpl, hillcut, \
122 sigma, integstar, taper, tmp, ar, mpl, at, \
123 i,j,k,l,m) \
124  reduction (+ : axstar,aystar)
125  // 2DO axpl[MAXPLANETS], aypl[MAXPLANETS] should also be included in reduction (this should be possible in OpenMP 4.5)
126  // 2DO and atomic clauses should be removed
127  for (i = 0; i<nr; i++) {
128  omegainv = OmegaInv[i];
129  r2 = Rmed2[i];
130  Nvert = 10;
131  // 1|---> in each ring, estimate the acceleration from the star using the Gaussian profile with azim. average H
132  cs_avr = 0.0;
133  if (Pebbles) tau_avr = 0.0;
134  for (j = 0; j<ns; j++) {
135  l = j + i*ns;
136  cs_avr += cs[l];
137  if (Pebbles) tau_avr += tau[l];
138  }
139  cs_avr /= (real)ns;
140  H_avr = cs_avr*omegainv*SQRT_ADIABIND_INV;
141  if (Pebbles) {
142  tau_avr /= (real)ns;
143  p_H_avr = H_avr*sqrt(PEBBLEALPHA/tau_avr);
144  p_integstar_avr = 0.0;
145  }
146  H2 = H_avr*H_avr;
147  zmax = 3.0*H_avr;
148  deltaz = zmax/(real)Nvert;
149  sigma_avr = 0.0;
150  integstar_avr = 0.0;
151  for (m=1; m<=Nvert; m++) { // note for pebbles: H_peb = H*sqrt(alpha/tau), thus also znode_peb = znode*sqrt(alpha/tau), thus sum is the same (alpha/tau cancels out)
152  znode = ((real)m-0.5)*deltaz;
153  znode2 = znode*znode;
154  sum = exp(-(0.5*znode2/H2));
155  sigma_avr += sum;
156  d2 = r2 + znode2; // only d2 must be recomputed for pebbles as znode_peb != z_node
157  d = sqrt(d2);
158  denom = d*d2;
159  integstar_avr += sum/denom;
160  if (Pebbles) {
161  znode2 *= PEBBLEALPHA/tau_avr;
162  d2 = r2 + znode2;
163  d = sqrt(d2);
164  denom = d*d2;
165  p_integstar_avr += sum/denom;
166  }
167  }
168  // 1|<---
169  // now go through individual cells and decide whether to do the integration using
170  // the local H. The criteria for this: a) if H is too different compared to H_avr
171  // b) if the cell is expected to be strongly influenced by one of the planets
172  for (j = 0; j<ns; j++) {
173  IntegrateLocally = NO;
174  Nvert = 10;
175  ax = 0.0;
176  ay = 0.0;
177  if (Pebbles) {
178  pax = 0.0;
179  pay = 0.0;
180  }
181  l = j + i*ns;
182  x = abs[l];
183  y = ord[l];
184  mcell = rho[l]*Surf[i];
185  H = cs[l]*omegainv*SQRT_ADIABIND_INV;
186  H2 = H*H;
187  // 2|---> check for H vs H_avrg
188  if (fabs(H-H_avr)/H_avr > 0.05) IntegrateLocally = YES;
189  if (Pebbles) {
190  Hcorr = sqrt(PEBBLEALPHA/tau[l]);
191  pH = H*Hcorr;
192  if (fabs(pH-p_H_avr)/p_H_avr > 0.05) IntegrateLocally = YES;
193  }
194  // 2|<---
195  // 3|---> check for the distance w.r.t. planet and thickness related to
196  // standard smoothing- Calculate and save cell-planet distances and (if needed) taper
197  // to exclude the hill sphere from the torque evaluation
198  for (k = 0; k < npl; k++) {
199  xpl = sys->x[k];
200  ypl = sys->y[k];
201  zpl = sys->z[k];
202  s2[k] = (x-xpl)*(x-xpl) + (y-ypl)*(y-ypl);
203  r2chk_1 = 10.0*Hpl[k]; // 2DO will be moved to parameters
204  r2chk_1 *= r2chk_1;
205  r2chk_2 = 5.0*rhill[k]; // 2DO will be moved to parameters
206  r2chk_2 *= r2chk_2;
207  if (MassTaper == 1.0 && (s2[k] < r2chk_1 || s2[k] < r2chk_2)) {
208  IntegrateLocally = YES;
209  IntegrateWithPlanet[k] = YES;
210  integpl[k] = 0.0;
211  if (Pebbles) p_integpl[k] = 0.0;
212  d2 = s2[k] + zpl*zpl;
213  if (ExcludeHill) {
214  hillcut[k] = 1.0/(exp(-(sqrt(d2)/rhill[k]-HILLCUT)/HILLCUT*10.0)+1.0);
215  }
216  } else {
217  IntegrateWithPlanet[k] = NO;
218  }
219  if (s2[k] < rmorevert2[k]) Nvert = 30;
220  }
221  // 3|<---
222  // 4|---> Perform the local integration if needed
223  if (IntegrateLocally) {
224  zmax = 3.0*H;
225  deltaz = zmax/(real)Nvert;
226  sigma = 0.0;
227  integstar = 0.0;
228  if (Pebbles) p_integstar = 0.0;
229  for (m=1; m<=Nvert; m++) {
230  znode = ((real)m-0.5)*deltaz;
231  znode2 = znode*znode;
232  sum = exp(-(0.5*znode2/H2));
233  sigma += sum;
234  d2 = r2 + znode2; // part for the star
235  d = sqrt(d2);
236  denom = d*d2;
237  integstar += sum/denom;
238  if (Pebbles) {
239  d2 = r2 + znode2*Hcorr*Hcorr;
240  d = sqrt(d2);
241  denom = d*d2;
242  p_integstar += sum/denom;
243  }
244  for (k = 0; k < npl; k++) { // part for the planets
245  if (IntegrateWithPlanet[k]==YES) {
246  zpl = sys->z[k];
247  d2 = s2[k] + (znode-zpl)*(znode-zpl);
248  if (d2 < rst2[k]) {
249  d = sqrt(d2);
250  taper = -3.0*d2*d2/rst4[k] + 4.0*d*d2/rst3[k];
251  } else {
252  taper = 1.0;
253  }
254  d2 += rsm2[k];
255  d = sqrt(d2);
256  denom = d*d2;
257  integpl[k] += sum/denom*taper; // 2DO condition below should again be parametric
258  if (zpl < - 0.05*H || zpl > 0.05*H) { // For inclined planets, one cannot expect the integral to be symmetric w.r.t. the midplane.
259  d2 = s2[k] + (-znode-zpl)*(-znode-zpl); // thus integrate also the "mirror" nodes (with -znode vertical coordinate)
260  if (d2 < rst2[k]) {
261  d = sqrt(d2);
262  taper = -3.0*d2*d2/rst4[k] + 4.0*d*d2/rst3[k];
263  } else {
264  taper = 1.0;
265  }
266  d2 += rsm2[k];
267  d = sqrt(d2);
268  denom = d*d2;
269  integpl[k] += sum/denom*taper;
270  }
271  if (Pebbles) {
272  d2 = s2[k] + (znode*Hcorr-zpl)*(znode*Hcorr-zpl);
273  if (d2 < rst2[k]) {
274  d = sqrt(d2);
275  taper = -3.0*d2*d2/rst4[k] + 4.0*d*d2/rst3[k];
276  } else {
277  taper = 1.0;
278  }
279  d2 += rsm2[k];
280  d = sqrt(d2);
281  denom = d*d2;
282  p_integpl[k] += sum/denom*taper;
283  if (zpl < - 0.05*pH || zpl > 0.05*pH) { // 2DO condition again should be parametric
284  d2 = s2[k] + (-znode*Hcorr-zpl)*(-znode*Hcorr-zpl); // integrate also the "mirror" nodes (with -znode vertical coordinate)
285  if (d2 < rst2[k]) {
286  d = sqrt(d2);
287  taper = -3.0*d2*d2/rst4[k] + 4.0*d*d2/rst3[k];
288  } else {
289  taper = 1.0;
290  }
291  d2 += rsm2[k];
292  d = sqrt(d2);
293  denom = d*d2;
294  p_integpl[k] += sum/denom*taper;
295  }
296  }
297  }
298  }
299  } // 4|<---
300  } else { // 5|---> If local integration is not necessary, use the orbital average
301  sigma = sigma_avr;
302  integstar = integstar_avr;
303  if (Pebbles) p_integstar = p_integstar_avr;
304  } // 5|<---
305  // 6|---> cell-star interaction update
306  tmp = integstar/sigma;
307  ar = - Rmed[i]*tmp; // acceleration from the star is always radial -> can be updated directly
308  agr[l] += ar;
309  if (i>=Zero_or_active && i<Max_or_active) {
310  axstar += mcell*tmp*x;
311  aystar += mcell*tmp*y;
312  }
313  if (Pebbles) {
314  tmp = p_integstar/sigma;
315  ar = - Rmed[i]*tmp;
316  pagr[l] += ar;
317  }
318  // 6|<---
319  // 7|---> cell-planet interaction update
320  for (k = 0; k < npl; k++) {
321  xpl = sys->x[k];
322  ypl = sys->y[k];
323  zpl = sys->z[k];
324  mpl = sys->mass[k];
325  if (IntegrateWithPlanet[k]==YES) { // case when local integration was done
326  if (zpl < - 0.05*H || zpl > 0.05*H) {
327  tmp = (x-xpl)*integpl[k]/(2.0*sigma); // here integpl is taken from -zmax to zmax, whereas sigma only from 0 to zmax -> must multiply by 2
328  } else {
329  tmp = (x-xpl)*integpl[k]/sigma;
330  }
331  ax += - mpl*tmp;
332  if (i>=Zero_or_active && i<Max_or_active) {
333  if (ExcludeHill) tmp *= hillcut[k];
334 #pragma omp atomic
335  axpl[k] += mcell*tmp;
336  if (TorqueDensity && GETTORQUEFORPLANET==k) tqwk[l] = -ypl*mcell*tmp;
337  }
338  if (zpl < - 0.05*H || zpl > 0.05*H) {
339  tmp = (y-ypl)*integpl[k]/(2.0*sigma);
340  } else {
341  tmp = (y-ypl)*integpl[k]/sigma;
342  }
343  ay += - mpl*tmp;
344  if (i>=Zero_or_active && i<Max_or_active) {
345  if (ExcludeHill) tmp *= hillcut[k];
346 #pragma omp atomic
347  aypl[k] += mcell*tmp;
348  if (TorqueDensity && GETTORQUEFORPLANET==k) tqwk[l] += xpl*mcell*tmp;
349  }
350  if (Pebbles) {
351  if (zpl < - 0.05*pH || zpl > 0.05*pH) {
352  tmp = (x-xpl)*p_integpl[k]/(2.0*sigma);
353  } else {
354  tmp = (x-xpl)*p_integpl[k]/sigma;
355  }
356  pax += -mpl*tmp;
357  if (zpl < - 0.05*pH || zpl > 0.05*pH) {
358  tmp = (y-ypl)*p_integpl[k]/(2.0*sigma);
359  } else {
360  tmp = (y-ypl)*p_integpl[k]/sigma;
361  }
362  pay += -mpl*tmp;
363  }
364  } else { // simple point-mass acceleration otherwise
365  mpl *= MassTaper;
366  d2 = s2[k] + zpl*zpl + smoothing2[k];
367  d = sqrt(d2);
368  denom = d*d2;
369  tmp = (x-xpl)/denom;
370  ax += - mpl*tmp;
371  if (i>=Zero_or_active && i<Max_or_active) {
372  if (ExcludeHill) tmp *= hillcut[k];
373 #pragma omp atomic
374  axpl[k] += mcell*tmp;
375  if (TorqueDensity && GETTORQUEFORPLANET==k) tqwk[l] = -ypl*mcell*tmp;
376  }
377  tmp = (y-ypl)/denom;
378  ay += - mpl*tmp;
379  if (i>=Zero_or_active && i<Max_or_active) {
380  if (ExcludeHill) tmp *= hillcut[k];
381 #pragma omp atomic
382  aypl[k] += mcell*tmp;
383  if (TorqueDensity && GETTORQUEFORPLANET==k) tqwk[l] += xpl*mcell*tmp;
384  }
385  if (Pebbles) {
386  d2 += - smoothing2[k] + smoothing2[k]*Hcorr*Hcorr;
387  d = sqrt(d2);
388  denom = d*d2;
389  tmp = (x-xpl)/denom;
390  pax += -mpl*tmp;
391  tmp = (y-ypl)/denom;
392  pay += -mpl*tmp;
393  }
394  }
395  }
396  // 7|<---
397  ar = (x*ax + y*ay)*InvRmed[i]; // transform ax,ay to ar,at and do the update
398  at = (x*ay - y*ax)*InvRmed[i];
399  agr[l] += ar;
400  agt[l] += at;
401  if (Pebbles) {
402  ar = (x*pax + y*pay)*InvRmed[i];
403  at = (x*pay - y*pax)*InvRmed[i];
404  pagr[l] += ar;
405  pagt[l] += at;
406  }
407  }
408  }
409  // MPI reductions
410  MPI_Allreduce (&axstar, &tmpbuf, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
411  IndirectTerm.x = -tmpbuf;
412  MPI_Allreduce (&aystar, &tmpbuf, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
413  IndirectTerm.y = -tmpbuf;
414  MPI_Allreduce (&axpl, &tmparray, 10, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
415  for (k=0; k<npl; k++) {
416  sys->ax[k] = tmparray[k];
417  }
418  MPI_Allreduce (&aypl, &tmparray, 10, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
419  for (k=0; k<npl; k++) {
420  sys->ay[k] = tmparray[k];
421  }
422  // correct the disk acceleration using the indirect terms
423  axindir = IndirectTerm.x;
424  ayindir = IndirectTerm.y;
425  if (Indirect_Term == YES) {
426  axindir += IndirectTermFromPlanets.x;
427  ayindir += IndirectTermFromPlanets.y;
428  }
429  for (i=0; i<nr; i++) {
430  for (j=0; j<ns; j++) {
431  l = j + i*ns;
432  x = abs[l];
433  y = ord[l];
434  ar = (x*axindir + y*ayindir)*InvRmed[i];
435  at = (x*ayindir - y*axindir)*InvRmed[i];
436  agr[l] += ar;
437  agt[l] += at;
438  if (Pebbles) {
439  pagr[l] += ar;
440  pagt[l] += at;
441  }
442  }
443  }
444 }
445 
446 /** Updates the planet velocities due to disk forces.
447  * Also applies the inclination damping. */
448 void AdvanceSystemFromDisk (Rho, sys, dt) /* #THORIN uses directly the accelerations calculated above */
449 PlanetarySystem *sys;
450 PolarGrid *Rho;
451 real dt;
452 {
453  int npl, k, i;
454  real x,y,z,m,vz,damp;
455  char command[1024];
456  npl = sys->nb;
457  if (DumpTorqueNow) {
459  UpdateLog (Rho, sys);
460  }
461  if (DumpTorqueDensNow) {
465  if (Merge && (CPU_Number > 1) && CPU_Master) {
466  for (i=1; i<CPU_Number; i++) {
467  sprintf (command, "cd %s; cat gastorque%d.dat.%05d >> gastorque%d.dat",\
469  system (command);
470  }
471  sprintf (command, "cd %s; rm -f gastorque%d.dat.0*", OUTPUTDIR, TimeStep);
472  system (command);
473  }
474  }
475  for (k = 0; k < npl; k++) {
476  if (sys->FeelDisk[k] == YES) {
477  m=sys->mass[k];
478  x=sys->x[k];
479  y=sys->y[k];
480  z=sys->z[k];
481  vz = sys->vz[k];
482  damp = DampingTW04 (Rho, m, x, y, z, vz);
483  sys->vx[k] += dt * sys->ax[k];
484  sys->vy[k] += dt * sys->ay[k];
485  sys->vz[k] += dt * (sys->az[k] + damp);
486  sys->vx[k] += dt * IndirectTerm.x;
487  sys->vy[k] += dt * IndirectTerm.y;
488  }
489  }
490 }
491 
492 /** Artificial vertical force to damp the orbital
493  * inclinations using the Tanaka & Ward (2004)
494  * prescription (see also Morbidelli et al. 2007, Pierens & Nelson 2008) */
495 real DampingTW04 (Rho, m, x, y, z, vz) /* #THORIN */
496 PolarGrid *Rho;
497 real m,x,y,z,vz;
498 {
499  real r, ang, Omega, cs4inv, damp=0.0, rhoavr=0.0, csavr=0.0, tmp;
500  real *rho, *cs;
501  int i, j, l, ns;
502  rho = Rho->Field;
503  ns = Rho->Nsec;
504  cs = SoundSpeed->Field;
505  r = sqrt(x*x + y*y); /* find position in the midplane */
506  if ( (VERTICALDAMPING > 0.0) && (z>0.0) && (r >= Rinf[Zero_or_active] && r <= Rsup[Max_or_active-1]) ) {
507  /* condition satisfied only for a CPU which contains the planet within its active zone */
508  ang = atan2(y,x); /* get the damping value on this cpu */
509  if (ang < 0.0) ang += 2.0*PI;
510  i = Zero_or_active;
511  while (Rsup[i] < r) i++;
512  for (j=0; j<ns; j++) {
513  l = j + i*ns;
514  rhoavr += rho[l];
515  csavr += cs[l];
516  }
517  csavr /= (real)ns;
518  rhoavr /= (real)ns;
519  cs4inv = pow(csavr, -4.0); /* 2DO isothermal case ? */
520  Omega = pow(r, -1.5); /* Keplerian angular velocity at planets' position */
521  damp = VERTICALDAMPING*m*rhoavr*Omega*cs4inv*(-2.176*vz - 0.871*z*Omega); /* Tanaka&Ward 04 formula */
522  }
523  if (CPU_Number==1) return damp; /* we are done in case of a serial build */
524  MPI_Allreduce (&damp, &tmp, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); /* other CPUs have damp=0.0, the sum reduction distributes the result among them */
525  damp = tmp;
526  return tmp;
527 }
528 
530  real *u, *v;
531  int n;
532 {
533  int i;
534  real lapl=0.0;
535  for (i = 1; i < n; i++)
536  u[i] = 2.0*v[i]-u[i-1];
537  for (i = 1; i < n-1; i++) {
538  lapl += fabs(u[i+1]+u[i-1]-2.0*u[i]);
539  }
540  return lapl;
541 }
542 
543 /** Part of the initialisation */
544 void InitGasDensityEnergy (Rho, Energy) /* #THORIN */
545 PolarGrid *Rho, *Energy;
546 {
547  int i, j, l, nr, ns;
548  real *rho, *energy;
549  /* ----- */
550  nr = Rho->Nrad;
551  ns = Rho->Nsec;
552  rho = Rho->Field;
553  for (i=0; i<nr; i++) {
554  for (j=0; j<ns; j++) {
555  l = j + i*ns;
556  rho[l] = SigmaMed[i]; /* SigmaMed[] was initialized through FillSigma()*/
557  }
558  }
559  energy = Energy->Field;
560  for (i=0; i<nr; i++) {
561  for (j=0; j<ns; j++) {
562  l = j + i*ns;
563  energy[l] = EnergyMed[i]; /* EnergyMed[] initialized in FillEnergy(); Theo.c*/
564  }
565  }
566 }
567 
568 void InitGasVelocity (Vr, Vt) /* #THORIN */
569 PolarGrid *Vr, *Vt;
570 {
571  int i, j, l, nr, ns;
572  real *vr, *vt, *pres, *cs;
573  real r, rg, omega, ri;
574  real viscosity, t1, t2, r1, r2;
575  /* ----- */
576  vr = Vr->Field;
577  vt = Vt->Field;
578  nr = Vr->Nrad;
579  ns = Vr->Nsec;
580  cs = SoundSpeed->Field;
581  pres= Pressure->Field;
582  /* loading a file with prescribed soundspeed profile was possible here,
583  * now it is redundant (and thus discarded) */
584  mpi_make1Dprofile (pres, globpressvec);/* extract the HD quantity (from all CPUs
585  if necessary) and arrange it into a
586  single 1D array (globpressvec) describing
587  all radial rings by quantities averaged
588  over each ring. */
589  /* This part is always calculated, but it is stored in vtheta only if CentrifugalBalance==YES.
590  ---->
591  !!! 2DO This option has not been tested yet. */
592  for (i = 1; i < GLOBALNRAD; i++) {
593  /* The equation below is the same as in the original FARGO besides the first
594  * term, which is now more general (the pressure difference between two
595  * neighbouring rings). */
596  vt_int[i]=(globpressvec[i] - globpressvec[i-1])/ \
597  (.5*(Sigma(GlobalRmed[i])+Sigma(GlobalRmed[i-1])))/(GlobalRmed[i]-GlobalRmed[i-1])+ \
598  G*(1.0/GlobalRmed[i-1]-1.0/GlobalRmed[i])/(GlobalRmed[i]-GlobalRmed[i-1]);
599  /* The rest of the routine is unchanged, only the density initialization
600  * was discarded (it is already done before this routine) */
601  vt_int[i] = sqrt(vt_int[i]*Radii[i])-Radii[i]*OmegaFrame;
602  }
603  t1 = vt_cent[0] = vt_int[1]+.75*(vt_int[1]-vt_int[2]);
604  r1 = ConstructSequence (vt_cent, vt_int, GLOBALNRAD);
605  vt_cent[0] += .25*(vt_int[1]-vt_int[2]);
606  t2 = vt_cent[0];
607  r2 = ConstructSequence (vt_cent, vt_int, GLOBALNRAD);
608  t1 = t1-r1/(r2-r1)*(t2-t1);
609  vt_cent[0] = t1;
610  ConstructSequence (vt_cent, vt_int, GLOBALNRAD);
611  vt_cent[GLOBALNRAD]=vt_cent[GLOBALNRAD-1];
612  /* <----- */
613  if (ParametricCooling) {
614  FillCoolingTime (); /* for both functions see Theo.c */
615  FillQplus (); /* ! This function calls FViscosity() which might need the azimuth-averaged values of sound speed
616  which are stored in 'globcsvec[]'. It is required that ComputeSoundSpeed() is called before InitGasVelocity(). */
617  }
618  /* "Usual" velocity initialization */
619  for (i = 0; i <= nr; i++) {
620  if (i == nr) {
621  r = Rmed[nr-1];
622  ri= Rinf[nr-1];
623  }
624  else {
625  r = Rmed[i];
626  ri= Rinf[i];
627  }
628  viscosity = FViscosity (r);
629  for (j = 0; j < ns; j++) {
630  l = j+i*ns;
631  rg = r;
632  omega = sqrt(G*1.0/rg/rg/rg);
633  /* this one is original:
634  vt[l] = omega*r*\
635  sqrt(1.0-pow(ASPECTRATIO,2.0)*\
636  pow(r,2.0*FLARINGINDEX)*\
637  (1.+SIGMASLOPE-2.0*FLARINGINDEX)); */
638  /* the initial azimuthal velocity profile is refined using a simple relationship, see e.g. Masset 2002 */
639  vt[l] = omega*r*sqrt(1.0-cs[l]*cs[l]*r/ADIABIND);
640  /* vt[l] = omega*r*sqrt(1.0-pow(ASPECTRATIO,2.0)*pow(r,2.0*FLARINGINDEX)); */
641  vt[l] -= OmegaFrame*r;
642  if (CentrifugalBalance)
643  vt[l] = vt_cent[i+IMIN];
644  if (i == nr)
645  vr[l] = 0.0;
646  else {
647  vr[l] = IMPOSEDDISKDRIFT*SIGMA0/SigmaInf[i]/ri;
648  if (ViscosityAlpha) {
649  vr[l] -= 3.0*viscosity/r*(-SIGMASLOPE+2.0*FLARINGINDEX+1.0);
650  } else {
651  vr[l] -= 3.0*viscosity/r*(-SIGMASLOPE+.5);
652  }
653  }
654  }
655  }
656  for (j = 0; j < ns; j++)
657  vr[j] = vr[j+ns*nr] = 0.0;
658 }
659 /* <---- */
double real
Definition of the type 'real' used throughout the code.
Definition: types.h:20
real SIGMASLOPE
Definition: param_noex.h:27
real Rsup[MAX1D]
Definition: global.h:11
int CPU_Number
Definition: global.h:2
#define YES
Definition: types.h:46
boolean AllowAccretion
static real vt_cent[MAX1D]
Definition: Pframeforce.c:29
real * z
z-coordinate of the planets
Definition: types.h:101
real EnergyMed[MAX1D]
Definition: global.h:16
#define MPI_DOUBLE
Definition: mpi_dummy.h:11
PolarGrid * PebbleGravAccelTheta
Definition: global.h:39
char OUTPUTDIR[512]
Definition: param_noex.h:11
boolean Indirect_Term
Definition: Interpret.c:31
real * x
x-coordinate of the planets
Definition: types.h:99
PolarGrid * SoundSpeed
Definition: global.h:35
void FillCoolingTime()
Definition: Theo.c:110
real ThicknessSmoothing(real x, real y)
Computes the local thickness from the sound speed and applies the thickness smoothing parameter...
Definition: Force.c:75
real globpressvec[MAX1D]
Definition: global.h:16
real * y
y-coordinate of the planets
Definition: types.h:100
int Zero_or_active
Definition: global.h:6
real OmegaInv[MAX1D]
Definition: global.h:15
A structure used to store any scalar fied on the computational domain.
Definition: types.h:37
real GlobalRmed[MAX1D]
Definition: global.h:13
void MPI_Barrier()
Definition: mpi_dummy.c:64
real Rmed2[MAX1D]
Definition: global.h:15
real * Field
Definition: types.h:40
real * mass
Masses of the planets.
Definition: types.h:98
real Rmed[MAX1D]
Definition: global.h:11
Contains all the information about a planetary system at a given instant in time. ...
Definition: types.h:96
void InitGasVelocity(PolarGrid *Vr, PolarGrid *Vt)
Definition: Pframeforce.c:568
real Radii[MAX1D]
Definition: global.h:13
real DampingTW04(PolarGrid *Rho, real m, real x, real y, real z, real vz)
Artificial vertical force to damp the orbital inclinations using the Tanaka & Ward (2004) prescriptio...
Definition: Pframeforce.c:495
PolarGrid * CellOrdinate
Definition: global.h:33
real SQRT_ADIABIND_INV
Definition: global.h:19
int nb
Number of planets.
Definition: types.h:97
static real vt_int[MAX1D]
Definition: Pframeforce.c:29
real THICKNESSSMOOTHING
Definition: param_noex.h:22
int IMIN
Definition: global.h:4
real x
Definition: types.h:27
boolean DumpTorqueDensNow
Definition: main.c:21
boolean DumpTorqueNow
Definition: main.c:21
int GLOBALNRAD
Definition: global.h:10
PolarGrid * GravAccelRad
Definition: global.h:39
real FLARINGINDEX
Definition: param_noex.h:39
#define G
Definition: fondam.h:11
boolean CentrifugalBalance
Definition: global.h:31
int TimeStep
Definition: global.h:23
boolean TorqueDensity
Definition: global.h:28
real SigmaInf[MAX1D]
Definition: global.h:14
real FViscosity()
PolarGrid * PebbleGravAccelRad
Definition: global.h:39
real VERTICALDAMPING
Definition: param_noex.h:79
real OmegaFrame
Definition: global.h:20
void MPI_Allreduce(void *ptr, void *ptr2, int count, int type, int foo3, int foo4)
Definition: mpi_dummy.c:72
#define MPI_SUM
Definition: mpi_dummy.h:17
void FillForcesArrays(PolarGrid *Rho, PlanetarySystem *sys)
Using the vertical averaging procedure of Muller & Kley (2012), calculates the acceleration in planet...
Definition: Pframeforce.c:38
real ConstructSequence(real *u, real *v, int n)
Definition: Pframeforce.c:529
void InitGasDensityEnergy(PolarGrid *Rho, PolarGrid *Energy)
Part of the initialisation.
Definition: Pframeforce.c:544
real * ay
ay-coordinate of the planets' acceleration from the disk
Definition: types.h:106
int Max_or_active
Definition: global.h:7
PolarGrid * StokesNumber
Definition: global.h:38
PolarGrid * CellAbscissa
Definition: global.h:33
static Pair IndirectTerm
Definition: Pframeforce.c:28
PolarGrid * Pressure
Definition: global.h:35
real Surf[MAX1D]
Definition: global.h:11
real y
Definition: types.h:28
#define NO
Definition: types.h:47
int GETTORQUEFORPLANET
Definition: param_noex.h:95
real ADIABIND
Definition: param_noex.h:54
PolarGrid * GravAccelTheta
Definition: global.h:39
#define MAXPLANETS
Definition: types.h:67
Contains all the include directives requested by the code.
real Rinf[MAX1D]
Definition: global.h:11
real IMPOSEDDISKDRIFT
Definition: param_noex.h:38
real SigmaMed[MAX1D]
Definition: global.h:14
boolean Merge
Definition: global.h:29
real SIGMA0
Definition: param_noex.h:8
Set of two reals.
Definition: types.h:26
real * ax
ax-coordinate of the planets' acceleration from the disk
Definition: types.h:105
boolean ViscosityAlpha
Definition: global.h:30
void AdvanceSystemFromDisk(PolarGrid *Rho, PlanetarySystem *sys, real dt)
Updates the planet velocities due to disk forces.
Definition: Pframeforce.c:448
void UpdateLog(PolarGrid *Rho, PlanetarySystem *psys)
Calculates and writes the disk torques (both specific and normalized) acting on the planets...
Definition: Force.c:27
real Energy()
boolean ParametricCooling
Definition: global.h:24
real InvRmed[MAX1D]
Definition: global.h:12
real Sigma()
boolean ExcludeHill
Definition: global.h:31
PolarGrid * Torque
Definition: global.h:40
void WriteDiskPolar(PolarGrid *array, int number)
Definition: Output.c:153
void FillQplus()
Definition: Theo.c:125
real HILLCUT
Definition: param_noex.h:78
void mpi_make1Dprofile(real *gridfield, real *axifield)
Definition: mpiTasks.c:12
boolean CPU_Master
Definition: global.h:3
#define PI
Definition: fondam.h:12
boolean Corotating
Definition: Interpret.c:30
#define MPI_COMM_WORLD
Definition: mpi_dummy.h:10
#define MAX1D
Definition: types.h:65
real MassTaper
Definition: global.h:14
boolean Pebbles
Definition: global.h:27
real PEBBLEALPHA
Definition: param_noex.h:87