The FARGO_THORIN code developer's guide
 All Data Structures Files Functions Variables Typedefs Macros
Psys.c
Go to the documentation of this file.
1 /** \file Psys.c
2 
3 Contains the functions that set up the planetary system configuration.
4 In addition, the last two functions allow to track the first planet
5 (number 0) of the planetary system, in order to perform a calculation
6 in the frame corotating either with this planet or with its
7 guiding-center.
8 
9 @author THORIN modifications by
10 Ondřej Chrenko <chrenko@sirrah.troja.mff.cuni.cz>, Copyright (C) 2017;
11 original code by Frédéric Masset
12 
13 */
14 
15 #include "fargo.h"
16 
18 
19 extern boolean GuidingCenter;
20 
21 int FindNumberOfPlanets (filename)
22 char *filename;
23 {
24  FILE *input;
25  char s[512];
26  int Counter=0;
27  input = fopen (filename, "r");
28  if (input == NULL) {
29  fprintf (stderr, "Error : can't find '%s'.\n", filename);
30  prs_exit (1);
31  }
32  while (fgets(s, 510, input) != NULL) {
33  if (isalpha(s[0]))
34  Counter++;
35  }
36  fclose (input);
37  return Counter;
38 }
39 
40 PlanetarySystem *AllocPlanetSystem (nb) /* #THORIN: 3rd dimension added, acceleration from the disk added */
41  int nb;
42 {
43  real *mass, *x, *y, *z, *vx, *vy, *vz, *acc, *ax, *ay, *az;
44  boolean *feeldisk, *feelothers;
45  int i;
46  PlanetarySystem *sys;
47  sys = (PlanetarySystem *)malloc (sizeof(PlanetarySystem));
48  if (sys == NULL) {
49  fprintf (stderr, "Not enough memory.\n");
50  prs_exit (1);
51  }
52  x = (real *)malloc (sizeof(real)*(nb+1));
53  y = (real *)malloc (sizeof(real)*(nb+1));
54  z = (real *)malloc (sizeof(real)*(nb+1));
55  vx = (real *)malloc (sizeof(real)*(nb+1));
56  vy = (real *)malloc (sizeof(real)*(nb+1));
57  vz = (real *)malloc (sizeof(real)*(nb+1));
58  mass = (real *)malloc (sizeof(real)*(nb+1));
59  acc = (real *)malloc (sizeof(real)*(nb+1));
60  if ((x == NULL) || (y == NULL) || (z == NULL) || (vx == NULL) || (vy == NULL) || (vz == NULL) || (acc == NULL) || (mass == NULL)) {
61  fprintf (stderr, "Not enough memory.\n");
62  prs_exit (1);
63  }
64  ax = (real *)malloc (sizeof(real)*(nb+1));
65  ay = (real *)malloc (sizeof(real)*(nb+1));
66  az = (real *)malloc (sizeof(real)*(nb+1));
67  if ((ax == NULL) || (ay == NULL) || (az == NULL)) {
68  fprintf (stderr, "Not enough memory.\n");
69  prs_exit (1);
70  }
71  feeldisk = (boolean *)malloc (sizeof(real)*(nb+1));
72  feelothers = (boolean *)malloc (sizeof(real)*(nb+1));
73  if ((feeldisk == NULL) || (feelothers == NULL)) {
74  fprintf (stderr, "Not enough memory.\n");
75  prs_exit (1);
76  }
77  sys->x = x;
78  sys->y = y;
79  sys->z = z;
80  sys->vx= vx;
81  sys->vy= vy;
82  sys->vz= vz;
83  sys->ax= ax;
84  sys->ay= ay;
85  sys->az= az;
86  sys->acc=acc;
87  sys->mass = mass;
88  sys->FeelDisk = feeldisk;
89  sys->FeelOthers = feelothers;
90  for (i = 0; i < nb; i++) {
91  x[i] = y[i] = z[i] = vx[i] = vy[i] = vz[i] = mass[i] = acc[i] = 0.0;
92  ax[i] = ay[i] = az[i] = 0.0;
93  feeldisk[i] = feelothers[i] = YES;
94  }
95  return sys;
96 }
97 
98 void FreePlanetary (sys) /* #THORIN: free also z,vz,ax,ay,az */
99 PlanetarySystem *sys;
100 {
101  free (sys->x);
102  free (sys->vx);
103  free (sys->y);
104  free (sys->vy);
105  free (sys->z);
106  free (sys->vz);
107  free (sys->ax);
108  free (sys->ay);
109  free (sys->az);
110  free (sys->mass);
111  free (sys->acc);
112  free (sys->FeelOthers);
113  free (sys->FeelDisk);
114  free (sys);
115 }
116 
118 char *filename;
119 {
120  FILE *input;
121  char s[512], nm[512], test1[512], test2[512], *s1;
122  PlanetarySystem *sys;
123  int i=0, nb;
124  float mass, dist, accret;
125  boolean feeldis, feelothers;
126  nb = FindNumberOfPlanets (filename);
127  if (CPU_Master)
128  printf ("%d planet(s) found.\n", nb);
129  sys = AllocPlanetSystem (nb);
130  input = fopen (filename, "r");
131  sys->nb = nb;
132  while (fgets(s, 510, input) != NULL) {
133  sscanf(s, "%s ", nm);
134  if (isalpha(s[0])) {
135  s1 = s + strlen(nm);
136  sscanf(s1 + strspn(s1, "\t :=>_"), "%f %f %f %s %s", &dist, &mass, &accret, test1, test2);
137  sys->mass[i] = (real)mass;
138  feeldis = feelothers = YES;
139  if (tolower(*test1) == 'n') feeldis = NO;
140  if (tolower(*test2) == 'n') feelothers = NO;
141  sys->x[i] = (real)dist*(1.0+ECCENTRICITY);
142  sys->y[i] = 0.0;
143  sys->vy[i] = (real)sqrt((1.0+mass)/dist)*\
144  sqrt(1.0-ECCENTRICITY*ECCENTRICITY)/(1.0+ECCENTRICITY);
145  sys->vx[i] = -0.0000000001*sys->vy[i];
146  sys->acc[i] = accret;
147  sys->FeelDisk[i] = feeldis;
148  sys->FeelOthers[i] = feelothers;
149  i++;
150  }
151  }
152  return sys;
153 }
154 
155 void ListPlanets (sys) /* #THORIN: 3rd dimension added */
156 PlanetarySystem *sys;
157 {
158  int nb;
159  int i;
160  nb = sys->nb;
161  if (!CPU_Master) return;
162  for (i = 0; i < nb; i++) {
163  printf ("Planet number %d\n", i);
164  printf ("---------------\n");
165  printf ("x = %.10f\ty = %.10f\tz = %.10f\n", sys->x[i],sys->y[i],sys->z[i]);
166  printf ("vx = %.10f\tvy = %.10f\tvz = %.10f\n", sys->vx[i],sys->vy[i],sys->vz[i]);
167  if (sys->acc[i] == 0.0)
168  printf ("Non-accreting.\n");
169  else
170  printf ("accretion time = %.10f\n", 1.0/(sys->acc[i]));
171  if (sys->FeelDisk[i] == YES) {
172  printf ("Feels the disk potential\n");
173  } else {
174  printf ("Doesn't feel the disk potential\n");
175  }
176  if (sys->FeelOthers[i] == YES) {
177  printf ("Feels the other planets potential\n");
178  } else {
179  printf ("Doesn't feel the other planets potential\n");
180  }
181  printf ("\n");
182  }
183 }
184 
185 /** The original function was modified to
186  * handle 3D inclined orbits. It is similar
187  * to the one used in fargo3D but employs tools
188  * from the REBOUND package. */
189 real GetPsysInfo (sys, action) /* #THORIN */
190 PlanetarySystem *sys;
191 boolean action;
192 {
193  real d1,d2,cross;
194  real x,y,z, vx, vy, vz, m, a3;
195  real hx,hy,hz,d,Ax,Ay,PerihelionPA;
196  real xc, yc;
197  struct reb_orbit orbit;
198  struct reb_particle p={0};
199  static struct reb_particle primary={0};
200  /* ----- */
201  if (primary.m != 1.0) {
202  primary.m = 1.0;
203  }
204  p.x = xc = x = sys->x[0];
205  p.y = yc = y = sys->y[0];
206  p.z = z = sys->z[0];
207  p.vx = vx = sys->vx[0];
208  p.vy = vy = sys->vy[0];
209  p.vz = vz = sys->vz[0];
210  p.m = sys->mass[0];
211  m = sys->mass[0]+1.;
212  orbit = reb_tools_particle_to_orbit (G, p, primary);
213  if (GuidingCenter == YES) {
214  if (orbit.e > 1e-8 && orbit.inc > 1e-8) {
215  // if (orbit.e > 1.e-12) {
216  hx = y*vz - z*vy; /* spec. orbital momentum */
217  hy = z*vx - x*vz;
218  hz = x*vy - y*vx;
219  d = sqrt(x*x+y*y+z*z);
220  Ax = vy*hz-vz*hy - G*m*x/d; /* the eccentric vector components */
221  Ay = vz*hx-vx*hz - G*m*y/d;
222  if (Ax*Ax+Ay*Ay > 0.0) {
223  PerihelionPA = atan2(Ay,Ax); /* angle of peric. w.r.t. the reference direction */
224  } else {
225  PerihelionPA = atan2(y,x);
226  }
227  xc = orbit.a*cos(orbit.M+PerihelionPA)*cos(orbit.inc);
228  yc = orbit.a*sin(orbit.M+PerihelionPA)*cos(orbit.inc);
229  }
230  }
231  switch (action) {
232  case MARK:
233  Xplanet = xc;
234  Yplanet = yc;
235  return 0.;
236  break;
237  case GET:
238  x = xc;
239  y = yc;
240  d2 = sqrt(x*x+y*y);
241  d1 = sqrt(Xplanet*Xplanet+Yplanet*Yplanet);
242  cross = Xplanet*y-x*Yplanet;
243  Xplanet = x;
244  Yplanet = y;
245  return asin(cross/(d1*d2));
246  break;
247  case FREQUENCY:
248  if (GuidingCenter == YES) {
249  a3 = (orbit.a)*(orbit.a)*(orbit.a);
250  return sqrt(m/a3);
251  } else {
252  return (x*vy-y*vx)/(x*x+y*y);
253  }
254  break;
255  }
256  return 0.0;
257 }
258 
259 /** An analogue of the GetPsysInfo() function;
260  * here a rebound simulation structure is used as
261  * a call argument. */
262 real GetPsysInfoFromRsim (rsim, action) /* #THORIN */
263 struct reb_simulation *rsim;
264 boolean action;
265 {
266  struct reb_particle* const particles = rsim->particles;
267  real d1,d2,cross;
268  real x,y,z, vx, vy, vz, m, a3;
269  real hx,hy,hz,d,Ax,Ay,PerihelionPA;
270  real xc, yc;
271  struct reb_orbit orbit;
272  /* ----- */
273  xc = x = particles[1].x; /* first planet has index 1 in REBOUND (but index 0 in FARGO) */
274  yc = y = particles[1].y;
275  z = particles[1].z;
276  vx = particles[1].vx;
277  vy = particles[1].vy;
278  vz = particles[1].vz;
279  m = particles[1].m + particles[0].m; /* the primary has index 0 in REBOUND (does not exist in FARGO) */
280  orbit = reb_tools_particle_to_orbit (G, particles[1], particles[0]);
281  if (GuidingCenter == YES) {
282  if (orbit.e > 1e-8 && orbit.inc > 1e-8) {
283 // if (orbit.e > 1.e-8) {
284  hx = y*vz - z*vy; /* spec. orbital momentum */
285  hy = z*vx - x*vz;
286  hz = x*vy - y*vx;
287  d = sqrt(x*x+y*y+z*z);
288  Ax = vy*hz-vz*hy - G*m*x/d; /* the eccentric vector components */
289  Ay = vz*hx-vx*hz - G*m*y/d;
290  if (Ax*Ax+Ay*Ay > 0.0) {
291  PerihelionPA = atan2(Ay,Ax); /* angle of peric. w.r.t. the reference direction */
292  } else {
293  PerihelionPA = atan2(y,x);
294  }
295  xc = orbit.a*cos(orbit.M+PerihelionPA)*cos(orbit.inc);
296  yc = orbit.a*sin(orbit.M+PerihelionPA)*cos(orbit.inc);
297  }
298  }
299  switch (action) {
300  case MARK:
301  Xplanet = xc;
302  Yplanet = yc;
303  return 0.;
304  break;
305  case GET:
306  x = xc;
307  y = yc;
308  d2 = sqrt(x*x+y*y);
309  d1 = sqrt(Xplanet*Xplanet+Yplanet*Yplanet);
310  cross = Xplanet*y-x*Yplanet;
311  Xplanet = x;
312  Yplanet = y;
313  return asin(cross/(d1*d2));
314  break;
315  case FREQUENCY:
316  if (GuidingCenter == YES) {
317  a3 = (orbit.a)*(orbit.a)*(orbit.a);
318  return sqrt(m/a3);
319  } else {
320  return (x*vy-y*vx)/(x*x+y*y);
321  }
322  break;
323  }
324  return 0.0;
325 }
326 
327 /** Synchronises the planetary system with the frame.
328  * Affects the rebound simulation structure only,
329  * 'sys' and 'rsim' are synchronised later on. */
330 void RotatePsys (rsim, angle) /* #THORIN */
331 struct reb_simulation *rsim;
332 real angle;
333 {
334  int i;
335  real sint, cost, xt, yt;
336  struct reb_particle* const particles = rsim->particles;
337  sint = sin(angle);
338  cost = cos(angle);
339  for (i=1; i<rsim->N; i++) {
340  xt = particles[i].x;
341  yt = particles[i].y;
342  particles[i].x = xt*cost+yt*sint;
343  particles[i].y = -xt*sint+yt*cost;
344  xt = particles[i].vx;
345  yt = particles[i].vy;
346  particles[i].vx = xt*cost+yt*sint;
347  particles[i].vy = -xt*sint+yt*cost;
348  }
349 }
double real
Definition of the type 'real' used throughout the code.
Definition: types.h:20
boolean * FeelOthers
For each planet tells if it feels the other planet's gravity.
Definition: types.h:111
#define YES
Definition: types.h:46
boolean * FeelDisk
For each planet tells if it feels the disk (ie migrates)
Definition: types.h:110
real * z
z-coordinate of the planets
Definition: types.h:101
#define MARK
Definition: types.h:59
#define GET
Definition: types.h:58
real * vz
z-coordinate of the planets'velocities
Definition: types.h:104
real * x
x-coordinate of the planets
Definition: types.h:99
real * y
y-coordinate of the planets
Definition: types.h:100
real * vx
x-coordinate of the planets'velocities
Definition: types.h:102
real * mass
Masses of the planets.
Definition: types.h:98
Contains all the information about a planetary system at a given instant in time. ...
Definition: types.h:96
int nb
Number of planets.
Definition: types.h:97
PlanetarySystem * InitPlanetarySystem(char *filename)
Definition: Psys.c:117
static real Xplanet
Definition: Psys.c:17
#define FREQUENCY
Definition: types.h:60
#define G
Definition: fondam.h:11
int FindNumberOfPlanets(char *filename)
Definition: Psys.c:21
real * acc
The planets' accretion times^-1.
Definition: types.h:108
real ECCENTRICITY
Definition: param_noex.h:40
real * ay
ay-coordinate of the planets' acceleration from the disk
Definition: types.h:106
real * vy
y-coordinate of the planets'velocities
Definition: types.h:103
real GetPsysInfoFromRsim(struct reb_simulation *rsim, boolean action)
An analogue of the GetPsysInfo() function; here a rebound simulation structure is used as a call argu...
Definition: Psys.c:262
boolean GuidingCenter
Definition: Interpret.c:29
#define NO
Definition: types.h:47
void FreePlanetary(PlanetarySystem *sys)
Definition: Psys.c:98
Contains all the include directives requested by the code.
real * ax
ax-coordinate of the planets' acceleration from the disk
Definition: types.h:105
real * az
az-coordinate of the planets' acceleration from the disk
Definition: types.h:107
real GetPsysInfo(PlanetarySystem *sys, boolean action)
The original function was modified to handle 3D inclined orbits.
Definition: Psys.c:189
void RotatePsys(struct reb_simulation *rsim, real angle)
Synchronises the planetary system with the frame.
Definition: Psys.c:330
boolean CPU_Master
Definition: global.h:3
static real Yplanet
Definition: Psys.c:17
PlanetarySystem * AllocPlanetSystem(int nb)
Definition: Psys.c:40
void ListPlanets(PlanetarySystem *sys)
Definition: Psys.c:155
void prs_exit(int numb)
Definition: LowTasks.c:33