PLUTO
init.c
Go to the documentation of this file.
1 /* ///////////////////////////////////////////////////////////////////// */
2 /*!
3  \file
4  \brief Axisymmetric jet propagation.
5 
6  \b Description.\n
7  The jet problem is set up in axisymmetric cylindrical coordinates
8  \f$ (R,z) \f$.
9  We label ambient and jet values with the suffix "a" and "j", respectively.
10  The ambient medium is at rest and is characterized by uniform density
11  and pressure, \f$ \rho_a \f$ and \f$ p_a \f$.
12  The beam enters from the lower-z boundary from a circular nozzle of
13  radius \f$ R_j \f$ and carries a constant poloidal field \f$ B_z \f$
14  and a (radially-varying) toroidal component \f$ B_\phi(R) \f$.
15  Flow variables are prescribed as
16  \f[ \left\{\begin{array}{lcl}
17  \rho(R) &=& \rho_j \\ \noalign{\medskip}
18  v_z(R) &=& v_j \\ \noalign{\medskip}
19  B_\phi(R) &=& \DS \left\{\begin{array}{ll}
20  -B_m R/a & \quad{\rm for}\quad R<a \\ \noalign{\medskip}
21  -B_m a/R & \quad{\rm for}\quad R>a
22  \end{array}\right. \\ \noalign{\medskip}
23  B_z(R) &=& B_{z0}\quad\mathrm{(const)}
24  \end{array}\right. \f]
25  Here \c a is the magnetization radius while \f$ v_R = B_R = 0 \f$.
26  These profiles are similar to the ones used by Tesileanu et al. (2008).
27  The pressure distribution is found by solving the radial momentum
28  balance between thermal, centrifugal and magnetic forces:
29  \f[
30  \frac{dp}{dR} = \frac{\rho v_\phi^2}{R} -
31  \frac{1}{2}\left[\frac{1}{R^2}\frac{d(R^2B^2_\phi)}{dR}
32  +\frac{dB_z^2}{dR}\right]
33  \f]
34  Neglecting rotation and assuming \c Bz to be constant the solution of
35  radial momentum balance becomes
36  \f[
37  p(R) = p_a + B_m^2\left[1-\min\left(\frac{R^2}{a^2},1\right)\right]
38  \f]
39  and the jet on-axis pressure increases for increasing toroidal field:
40  \f[
41  p(R=0) \equiv p_j = p_a + B_m^2
42  \f]
43  where \f$p_a\f$ is the ambient pressure.
44 
45  \b Normalization.\n
46  Since the MHD equations are scale-invariant we have the freedom to
47  specify a reference length, density and velocity. Here we choose
48  - Length: jet radius \f$R_j=1\f$;
49  - Density: ambient density \f$\rho_a=1\f$;
50  - Velocity:
51  - adiabtic setup (no cooling):
52  ambient sound speed: \f$c_a = \Gamma p_a/\rho_a = 1\f$
53  (from which it follows \f$p_a = 1/\Gamma\f$).
54  - radiative setup (with cooling): 1 Km/s (set by \c UNIT_VELOCITY).
55  In this case, the ambient pressure is computed from the ambient
56  temperature <tt> Ta = 2500 K </tt>.
57 
58  In this way the number of parameters is reduced to 4:
59  -# <tt>g_inputParam[ETA]</tt>: density contrast
60  \f$ \eta = \rho_j/\rho_a
61  \qquad\Longrightarrow\qquad \rho_j = \eta
62  \f$
63  -# <tt>g_inputParam[JET_VEL]</tt>: Jet velocity \f$ v_j \f$.
64  This is also the Mach number of the beam with respect to the ambient
65  in the adiabatic setup;
66  -# <tt>g_inpurParam[SIGMA_Z]</tt>: poloidal magnetization;
67  -# <tt>g_inpurParam[SIGMA_PHI]</tt>: toroidal magnetization;
68  Magnetization are defined as follows:
69  \f[ \left\{\begin{array}{ll}
70  \sigma_z &= \DS \frac{B_z^2}{2p_a} \\ \noalign{\medskip}
71  \sigma_\phi &= \DS \frac{<B_\phi^2>}{2p_a}
72  \end{array}\right.
73  \qquad\Longrightarrow\qquad
74  \left\{\begin{array}{ll}
75  B_z^2 &= \DS 2\sigma_zp_a \\ \noalign{\medskip}
76  B_m^2 &= \DS \frac{2\sigma_\phi}{a^2(1/2-2\log a)}p_a
77  \end{array}\right.
78  \f]
79  Here the average value of \f$B^2_\phi\f$ is simply found as
80  \f[
81  <B^2_\phi> = \frac{\int_0^1 B^2_\phi R\,dR}{\int_0^1 R\,dR}
82  = B_m^2a^2\left(\frac{1}{2} - 2\log a\right)
83  \f]
84 
85  The following MAPLE code can be used to verify the solution:
86  \code
87  restart; # Solve radial equilibrium balance equation
88  assume (a < 1, a > 0);
89  B[phi] := -B[m]*R/a;
90  ode := diff(p(R),R) = -1/(2*R^2)*diff(R^2*B[phi]^2,R);
91  dsolve({ode,p(a)=pa}); # only for R < a
92  \endcode
93 
94  When cooling is enabled, two additional parameters controlling the
95  amplitude and frequency of perturbation can be used:
96  -# <tt>g_inputParam[PERT_AMPLITUDE]</tt>: perturbation amplitude (in
97  units of jet velocity);
98  -# <tt>g_inputParam[PERT_PERIOD]</tt>: perturbation period (in years).
99 
100  The jet problem has been tested using a variety of configurations, namely:
101  <CENTER>
102  Conf.| GEOMETRY |DIM| T. STEPPING|RECONSTRUCTION|divB| EOS | COOLING
103  -----|-----------|---|----------- |--------------| ---|--------|--------
104  #01 |CYLINDRICAL| 2 | RK2 | LINEAR | CT | IDEAL | NO
105  #02 |CYLINDRICAL| 2 | HANCOCK | LINEAR | CT | IDEAL | NO
106  #03 |CYLINDRICAL| 2 | ChTr | PARABOLIC | CT | IDEAL | NO
107  #04 |CYLINDRICAL|2.5| RK2 | LINEAR |NONE| IDEAL | NO
108  #05 |CYLINDRICAL|2.5| RK2 | LINEAR | CT | IDEAL | NO
109  #06 |CYLINDRICAL|2.5| RK2 | LINEAR | CT |PVTE_LAW| NO
110  #07 |CYLINDRICAL|2.5| ChTr | PARABOLIC |NONE| IDEAL | SNEq
111  #08 |CYLINDRICAL|2.5| ChTr | PARABOLIC |NONE| IDEAL | MINEq
112  #09 |CYLINDRICAL|2.5| ChTr | PARABOLIC |NONE| IDEAL | H2_COOL
113  </CENTER>
114  Here 2.5 is a short-cut for to 2 dimensions and 3 components.
115 
116  The following image show the (log) density map at the end of
117  simulation for setup #01.
118 
119  \image html mhd_jet.01.jpg "Density map at the end of the computation for configuration #01"
120 
121  \author A. Mignone (mignone@ph.unito.it)
122  \date Sept 12, 2014
123 
124  \b References
125  - "Simulating radiative astrophysical flows with the PLUTO code:
126  a non-equilibrium, multi-species cooling function"
127  Tesileanu, Mignone and Massaglia, A&A (2008) 488,429.
128 */
129 /* ///////////////////////////////////////////////////////////////////// */
130 #include "pluto.h"
131 
132 void GetJetValues (double, double *);
133 static double Profile (double, double);
134 
135 static double a = 0.8; /* -- Magnetization radius -- */
136 static double Ta, pa,mua; /* -- Ambient pressure -- */
137 
138 /* ********************************************************************* */
139 void Init (double *v, double x1, double x2, double x3)
140 /*
141  * Define ambient values and units.
142  *********************************************************************** */
143 {
144  int nv;
145  static int first_call = 1;
146  double nH = 200.0;
147  static double veq[NVAR];
148 
149  v[RHO] = 1.0;
150  v[VX1] = v[VX2] = v[VX3] = 0.0;
151 #if COOLING == NO
152  v[PRS] = pa = 0.6;
153  /* v[PRS] = Pressure(v, Ta); */
154 #else
155  #if COOLING == H2_COOL
156  Ta = 100.0; /* Ambient temperature for molecular cooling */
157  #else
158  Ta = 2500.0; /* Ambient temperature for atomic cooling */
159  #endif
160  if (first_call) CompEquil(nH, Ta, veq);
161  for (nv = NFLX; nv < NFLX + NIONS; nv++) v[nv] = veq[nv];
163  v[PRS] = pa = Ta*v[RHO]/(KELVIN*mua);
164 #endif
165 
166  EXPAND(v[BX1] = 0.0; ,
167  v[BX2] = sqrt(2.0*g_inputParam[SIGMA_Z]*pa); ,
168  v[BX3] = 0.0;)
169 
170  v[AX1] = v[AX2] = 0.0;
171  v[AX3] = 0.5*x1*v[BX2];
172 
173  v[TRC] = 0.0;
174 
175 #if COOLING == H2_COOL
176  g_minCoolingTemp = 10.0;
177  g_maxCoolingRate = 0.1;
178 #else
179  g_minCoolingTemp = 2500.0;
180  g_maxCoolingRate = 0.2;
181 #endif
182  g_smallPressure = 1.e-3;
183 
184  first_call = 0;
185 }
186 /* ********************************************************************* */
187 void Analysis (const Data *d, Grid *grid)
188 /*
189  *
190  *
191  *********************************************************************** */
192 {
193 
194 }
195 /* ********************************************************************* */
196 void UserDefBoundary (const Data *d, RBox *box, int side, Grid *grid)
197 /*!
198  * Set the injection boundary condition at the lower z-boundary
199  * (\c X2-beg must be set to \c userdef in \c pluto.ini).
200  * For \f$ R \le 1 \f$ we set constant input values (given by the
201  * ::GetJetValues() function while for $ R > 1 $ the solution has
202  * equatorial symmetry with respect to the \c z=0 plane.
203  * To avoid numerical problems with a "top-hat" discontinuous jump,
204  * we smoothly merge the inlet and reflected value using a profile
205  * function ::Profile().
206  *
207  *********************************************************************** */
208 {
209  int i, j, k, nv;
210  double *x1, *x2, *x3;
211  double r, vjet[256], vout[NVAR], q;
212  double t, omega; /* pulsed jet frequency */
213 
214  x1 = grid[IDIR].xgc;
215  x2 = grid[JDIR].xgc;
216  x3 = grid[KDIR].xgc;
217 
218  if (side == 0) { /* -- check solution inside domain -- */
219  DOM_LOOP(k,j,i){}
220  }
221 
222  if (side == X2_BEG){ /* -- X2_BEG boundary -- */
223  if (box->vpos == CENTER){ /* -- cell-centered boundary conditions -- */
224  BOX_LOOP(box,k,j,i){
225  GetJetValues (x1[i], vjet);
226 
227  /* -- add pulsed perturbation -- */
228 
229  #if COOLING != NO
230  t = g_time*UNIT_LENGTH/UNIT_VELOCITY; /* time in seconds */
231  omega = 2.0*CONST_PI/(86400.*365.*g_inputParam[PERT_PERIOD]);
232  vjet[VX2] *= 1.0 + g_inputParam[PERT_AMPLITUDE]*sin(omega*t);
233  #endif
234 
235  /* -- copy and reflect ambient medium values -- */
236 
237  VAR_LOOP(nv) vout[nv] = d->Vc[nv][k][2*JBEG - j - 1][i];
238  vout[VX2] *= -1.0;
239  EXPAND(vout[BX1] *= -1.0; ,
240  ; ,
241  vout[BX3] *= -1.0;)
242 
243  VAR_LOOP(nv){
244  d->Vc[nv][k][j][i] = vout[nv]-(vout[nv]-vjet[nv])*Profile(x1[i], nv);
245  }
246  }
247 
248  }else if (box->vpos == X1FACE){ /* -- staggered fields -- */
249  #ifdef STAGGERED_MHD
250  x1 = grid[IDIR].A;
251  BOX_LOOP(box,k,j,i){
252  vout[BX1] = -d->Vs[BX1s][k][2*JBEG - j - 1][i];
253  d->Vs[BX1s][k][j][i] = vout[BX1]
254  - (vout[BX1] - vjet[BX1])*Profile(x1[i], BX1);
255  }
256  #endif
257  }else if (box->vpos == X3FACE){
258 
259  }
260  }
261 }
262 
263 /* ********************************************************************* */
264 void GetJetValues (double R, double *vj)
265 /*!
266  * Define jet value as functions of the (cylindrical) radial
267  * coordinate.
268  * For a periodic jet configuration, density and verical velocity
269  * smoothly join the ambient values. This has no effect on equilibrium
270  * as long as rotation profile depends on the chosen density profile.
271  *
272  *********************************************************************** */
273 {
274  int nv;
275  static int first_call = 1;
276  static double veq[NVAR];
277  double Bz, Bm = 0.0, x;
278 
279  if (fabs(R) < 1.e-9) R = 1.e-9;
280  x = R/a;
281 
282  vj[RHO] = 1.0 + (g_inputParam[ETA] - 1.0);
283  Bz = sqrt(2.0*g_inputParam[SIGMA_Z]*pa);
284  Bm = sqrt(2.0*g_inputParam[SIGMA_PHI]*pa/(a*a*(0.5 - 2.0*log(a))));
285 
286  EXPAND( vj[BX1] = 0.0; ,
287  vj[BX2] = Bz; ,
288  vj[BX3] = -Bm*(x < 1.0 ? x:1.0/x);)
289  vj[AX1] = vj[AX2] = 0.0;
290  vj[AX3] = 0.5*R*Bz;
291 
292  EXPAND( vj[VX1] = 0.0; ,
293  vj[VX2] = g_inputParam[JET_VEL]; ,
294  vj[VX3] = 0.0; )
295 
296  vj[PRS] = pa + Bm*Bm*(1.0 - MIN(x*x,1.0));
297  vj[TRC] = 1.0;
298 
299  #if COOLING != NO
300  static double Tj,muj;
301  #if COOLING == H2_COOL
302  Tj = Ta*(1.0 + Bm*Bm/pa)/g_inputParam[ETA]; /* Guess Tj assuming muj = mua */
303  if (first_call){
304  CompEquil(200.0*g_inputParam[ETA], Tj, veq);
305  muj = MeanMolecularWeight(veq);
306  Tj *= muj/mua; /* Improve guess */
307  }
308  #else
309  if (first_call) CompEquil(200.0*g_inputParam[ETA], Ta, veq);
310  #endif
311  for (nv = NFLX; nv < NFLX+NIONS; nv++) vj[nv] = veq[nv];
312  #endif
313  first_call = 0;
314 
315 }
316 
317 /* ********************************************************************* */
318 double Profile (double R, double nv)
319 /*
320  *
321  *
322  *********************************************************************** */
323 {
324  double R4 = R*R*R*R, R8 = R4*R4;
325 
326  #if PHYSICS == MHD && COMPONENTS == 3 /* Start with a smoother profile */
327  if (g_time < 0.1) return 1.0/cosh(R4); /* with toroidal magnetic fields */
328  #endif
329  return 1.0/cosh(R8);
330 }
#define PERT_PERIOD
static double a
Definition: init.c:135
double **** Vs
The main four-index data array used for face-centered staggered magnetic fields.
Definition: structs.h:43
void UserDefBoundary(const Data *d, RBox *box, int side, Grid *grid)
Definition: init.c:98
DOM_LOOP(k, j, i)
Definition: analysis.c:22
#define VX2
Definition: mod_defs.h:29
#define PERT_AMPLITUDE
#define CENTER
Definition: pluto.h:200
int vpos
Location of the variable inside the cell.
Definition: structs.h:359
#define RHO
Definition: mod_defs.h:19
#define X3FACE
Definition: pluto.h:203
void CompEquil(double n, double T, double *v)
Definition: comp_equil.c:44
#define BOX_LOOP(B, k, j, i)
Definition: macros.h:70
double **** Vc
The main four-index data array used for cell-centered primitive variables.
Definition: structs.h:31
#define AX2
Definition: mod_defs.h:86
#define JET_VEL
#define TRC
Definition: pluto.h:581
double g_smallPressure
Small value for pressure fix.
Definition: globals.h:110
#define KELVIN
Definition: pluto.h:401
static double pa
Definition: init.c:136
#define VX1
Definition: mod_defs.h:28
#define KDIR
Definition: pluto.h:195
static double Ta
Definition: init.c:136
#define X1FACE
Definition: pluto.h:201
#define MIN(a, b)
Definition: macros.h:104
#define SIGMA_PHI
#define UNIT_VELOCITY
Unit velocity in cm/sec.
Definition: pluto.h:377
#define VAR_LOOP(n)
Definition: macros.h:226
#define NFLX
Definition: mod_defs.h:32
#define IDIR
Definition: pluto.h:193
#define UNIT_LENGTH
Unit Length in cm.
Definition: pluto.h:373
#define NIONS
Definition: cooling.h:28
Definition: structs.h:78
#define AX3
Definition: mod_defs.h:87
double g_inputParam[32]
Array containing the user-defined parameters.
Definition: globals.h:131
int j
Definition: analysis.c:2
int k
Definition: analysis.c:2
#define BX1s
Definition: ct.h:27
double * xgc
Cell volumetric centroid (!= x when geometry != CARTESIAN).
Definition: structs.h:84
#define BX3
Definition: mod_defs.h:27
double g_minCoolingTemp
The minimum temperature (in K) below which cooling is suppressed.
Definition: globals.h:106
static double Profile(double, double)
Definition: init.c:318
PLUTO main header file.
Definition: structs.h:30
int i
Definition: analysis.c:2
double MeanMolecularWeight(double *V)
void GetJetValues(double, double *)
Definition: init.c:264
double g_time
The current integration time.
Definition: globals.h:117
#define ETA
#define AX1
Definition: mod_defs.h:85
#define BX1
Definition: mod_defs.h:25
static double mua
Definition: init.c:136
#define VX3
Definition: mod_defs.h:30
#define CONST_PI
.
Definition: pluto.h:269
#define X2_BEG
Boundary region at X2 beg.
Definition: pluto.h:148
#define BX2
Definition: mod_defs.h:26
#define JDIR
Definition: pluto.h:194
double g_maxCoolingRate
The maximum fractional variation due to cooling from one step to the next.
Definition: globals.h:104
long int JBEG
Lower grid index of the computational domain in the the X2 direction for the local processor...
Definition: globals.h:39
#define SIGMA_Z
#define NVAR
Definition: pluto.h:609
Definition: structs.h:346
static Runtime q
double * A
Right interface area, A[i] = .
Definition: structs.h:87
void Analysis(const Data *d, Grid *grid)
Definition: init.c:66
void Init(double *v, double x1, double x2, double x3)
Definition: init.c:17