PLUTO
tc_flux.c
Go to the documentation of this file.
1 /* ///////////////////////////////////////////////////////////////////// */
2 /*!
3  \file
4  \brief Compute the thermal conduction flux.
5 
6  Compute the thermal conduction flux along one row of computational
7  zones for the HD and MHD modules according to Spitzer (1962):
8  \f[
9  \vec{F}_c = \frac{q}{|\vec{F}_{\rm class}| + q}\vec{F}_{\rm class}
10  \f]
11  where \f$ \vec{F}_{\rm class} = \kappa_\parallel \nabla T\f$ is the
12  classical (hydrodynamic) thermal conduction flux,
13  \f$ q = F_{\rm sat} = 5\phi \rho c_{\rm iso}^3\f$ is the saturated flux.
14  Temperature is, at present, simply computed as \f$p/\rho\f$.
15 
16  The classical flux is purely parabolic, and it is discretized using
17  standard finite differences.
18  The saturated flux is included only when the macro ::TC_SATURATED_FLUX
19  is enabled and it is treated in an upwind manner following the guidelines
20  given in the appendix of Mignone et al. 2012 (see also Balsara (2008)
21  for alternative discretization methods).
22 
23  In MHD, the classical flux further splits into 2 components, along
24  and across the magnetic field lines (see Eq. [7] of Mignone et al.).
25 
26  This function also computes the inverse of the time
27  step and return its maximum over the current sweep.
28 
29  \b References
30  - "Simulating anisotropic thermal conduction in supernova remnants
31  - I. Numerical methods",
32  Balsara, Tilley, Howk, MNRAS (2008) 386, 627
33  - "The PLUTO Code for Adaptive Mesh Computations in Astrophysical
34  Fluid Dynamics" \n
35  Mignone et al, ApJS (2012) 198, 7M
36 
37  \authors A. Mignone (mignone@ph.unito.it)\n
38  T. Matsakos
39  \date Aug 24, 2015
40 */
41 /* ///////////////////////////////////////////////////////////////////// */
42 #include "pluto.h"
43 
44 #ifndef TC_SATURATED_FLUX
45 /*! When set to YES (default), include saturation effects when
46  computing the conduction flux. */
47  #define TC_SATURATED_FLUX YES
48 #endif
49 
50 /*! When set to YES, saturated flux is computed using an upwind
51  selection rule.
52  When set to NO, staurated flux is treated in the same manner as
53  the conduction flux. */
54 #define HYPERBOLIC_SAT_FLUX YES
55 
56 /* ********************************************************************* */
57 void TC_Flux (double ***T, const State_1D *state,
58  double **dcoeff, int beg, int end, Grid *grid)
59 /*!
60  * Compute the thermal conduction flux, state->par_flx.
61  *
62  * \param [in] T 3D array containing the dimensionless
63  * temperature
64  * \param [in,out] state pointer to a State_1D structure
65  * \param [out] dcoeff the diffusion coefficient needed for computing
66  * the time step.
67  * \param [in] beg initial index of computation
68  * \param [in] end final index of computation
69  * \param [in] grid pointer to an array of Grid structures
70  *
71  * \return This function has no return value.
72  *********************************************************************** */
73 {
74  int i, j, k, nv;
75  double bgradT, Bmag, dTmag;
76  double Fc, Fcmag, Fsat, g1 = g_gamma - 1.0;
77  double x1, x2, x3;
78  double alpha, uL, uR, suL, suR, bn;
79  double vi[NVAR], kpar=0.0, knor=0.0, phi;
80  double bck_fld[3];
81  static double **gradT;
82 
83 /* -----------------------------------------------------------
84  1. Allocate memory, compute temperature gradient in the
85  required direction and set 2 out of the 3 coordinates.
86  ----------------------------------------------------------- */
87 
88  if (gradT == NULL) {
89  gradT = ARRAY_2D(NMAX_POINT, 3, double);
90  }
91 
92  GetGradient (T, gradT, beg, end, grid);
93  if (g_dir == JDIR || g_dir == KDIR) x1 = grid[IDIR].x[g_i];
94  if (g_dir == IDIR || g_dir == KDIR) x2 = grid[JDIR].x[g_j];
95  if (g_dir == IDIR || g_dir == JDIR) x3 = grid[KDIR].x[g_k];
96 
97 /* -----------------------------------------------
98  2. Compute Thermal Conduction Flux (tcflx).
99  ----------------------------------------------- */
100 
101  for (i = beg; i <= end; i++){
102 
103  for (nv = 0; nv < NVAR; nv++) {
104  vi[nv] = 0.5*(state->vh[i][nv] + state->vh[i+1][nv]);
105  }
106 
107  /* ------------------------------------------------
108  2a. Obtain the thermal conduction coefficients
109  along (kpar) and across (knor) the field
110  lines. This is done at the cell interface.
111  ------------------------------------------------ */
112 
113  if (g_dir == IDIR) x1 = grid[IDIR].xr[i];
114  if (g_dir == JDIR) x2 = grid[JDIR].xr[i];
115  if (g_dir == KDIR) x3 = grid[KDIR].xr[i];
116 
117 #if PHYSICS == MHD && BACKGROUND_FIELD == YES
118  BackgroundField(x1,x2,x3, bck_fld);
119  EXPAND(vi[BX1] += bck_fld[0]; ,
120  vi[BX2] += bck_fld[1]; ,
121  vi[BX3] += bck_fld[2];)
122 #endif
123 
124  TC_kappa(vi, x1, x2, x3, &kpar, &knor, &phi);
125  dTmag = D_EXPAND( gradT[i][0]*gradT[i][0],
126  + gradT[i][1]*gradT[i][1],
127  + gradT[i][2]*gradT[i][2]);
128  dTmag = sqrt(dTmag) + 1.e-12;
129 
130  /* ---------------------------------------------------
131  2b. Compute magnitude of saturated flux using
132  a Roe-like average
133  --------------------------------------------------- */
134 
135 #if TC_SATURATED_FLUX == YES
136  #if HYPERBOLIC_SAT_FLUX == YES
137 /*
138  uL = state->vL[i][PRS]/g1; suL = sqrt(uL);
139  uR = state->vR[i][PRS]/g1; suR = sqrt(uR);
140  scrh = 5.0*phi*g1*sqrt(g1/vi[RHO]);
141  csat[i] = scrh*(uR + uL + suR*suL)/(suL + suR);
142  Fsat = 0.5*scrh*(uL*suL + uR*suR);
143  if (gradT[i][g_dir] > 0.0) Fsat += 0.5*csat[i]*(uR - uL);
144  else if (gradT[i][g_dir] < 0.0) Fsat -= 0.5*csat[i]*(uR - uL);
145 
146 */
147  uL = state->vL[i][PRS];
148  uR = state->vR[i][PRS];
149  if (gradT[i][g_dir] > 0.0) Fsat = 5.0*phi/sqrt(vi[RHO])*uR*sqrt(uR);
150  else if (gradT[i][g_dir] < 0.0) Fsat = 5.0*phi/sqrt(vi[RHO])*uL*sqrt(uL);
151  else Fsat = 5.0*phi*vi[PRS]*sqrt(vi[PRS]/vi[RHO]);
152  #else
153  Fsat = 5.0*phi*vi[PRS]*sqrt(vi[PRS]/vi[RHO]);
154  #endif
155 #endif
156 
157  /* ------------------------------------------------------
158  2c. Compute the classical MHD thermal conduction
159  flux Fc and the diffusion coefficient dcoeff.
160  ------------------------------------------------------ */
161 
162 #if PHYSICS == HD
163 
164  Fc = kpar*gradT[i][g_dir]; /* -- classical thermal conduction flux -- */
165 /*
166 {
167  double x = kpar*dTmag/Fsat;
168  double flx_lim = exp(-x*x);
169  state->par_flx[i][ENG] = flx_lim*Fc
170  + (1.0 - flx_lim)*Fsat*gradT[i][g_dir]/dTmag;
171  dcoeff[i][ENG] = flx_lim*kpar/vi[RHO]*(g_gamma - 1.0);
172 }
173 */
174  #if TC_SATURATED_FLUX == YES
175  alpha = Fsat/(Fsat + kpar*dTmag);
176  #else
177  alpha = 1.0;
178  #endif
179  state->tc_flux[i][ENG] = alpha*Fc;
180  dcoeff[i][ENG] = fabs(alpha*kpar/vi[RHO])*g1;
181 
182 #elif PHYSICS == MHD
183 
184  Bmag = EXPAND(vi[BX1]*vi[BX1], + vi[BX2]*vi[BX2], + vi[BX3]*vi[BX3]);
185  Bmag = sqrt(Bmag) + 1.e-12;
186 
187  bgradT = D_EXPAND( vi[BX1]*gradT[i][0],
188  + vi[BX2]*gradT[i][1],
189  + vi[BX3]*gradT[i][2]);
190  bgradT /= Bmag;
191 
192  bn = vi[BX1 + g_dir]/Bmag; /* -- unit vector component -- */
193  Fc = kpar*bgradT*bn + knor*(gradT[i][g_dir] - bn*bgradT);
194  Fcmag = sqrt((kpar*kpar - knor*knor)*bgradT*bgradT +
195  knor*knor*dTmag*dTmag);
196 
197  #if TC_SATURATED_FLUX == YES
198  alpha = Fsat/(Fsat + Fcmag);
199  #else
200  alpha = 1.0;
201  #endif
202  state->tc_flux[i][ENG] = alpha*Fc;
203  dcoeff[i][ENG] = fabs(Fcmag/dTmag*bn*alpha/vi[RHO])*g1;
204 #endif
205  }
206 }
207 #undef HYPERBOLIC_SAT_FLUX
208 
static double alpha
Definition: init.c:3
tuple T
Definition: Sph_disk.py:33
double g_gamma
Definition: globals.h:112
double ** vh
Primitive state at n+1/2 (only for one step method)
Definition: structs.h:162
double * xr
Definition: structs.h:81
void BackgroundField(double x1, double x2, double x3, double *B0)
Definition: init.c:79
#define RHO
Definition: mod_defs.h:19
double ** vR
Primitive variables to the right of the interface, .
Definition: structs.h:139
void TC_Flux(double ***T, const State_1D *state, double **dcoeff, int beg, int end, Grid *grid)
Definition: tc_flux.c:57
#define KDIR
Definition: pluto.h:195
void TC_kappa(double *, double, double, double, double *, double *, double *)
Definition: tc_kappa.c:20
int g_i
x1 grid index when sweeping along the x2 or x3 direction.
Definition: globals.h:82
#define IDIR
Definition: pluto.h:193
int g_dir
Specifies the current sweep or direction of integration.
Definition: globals.h:86
int g_j
x2 grid index when sweeping along the x1 or x3 direction.
Definition: globals.h:83
Definition: structs.h:78
int j
Definition: analysis.c:2
int k
Definition: analysis.c:2
double * x
Definition: structs.h:80
double ** tc_flux
Thermal conduction flux.
Definition: structs.h:152
int g_k
x3 grid index when sweeping along the x1 or x2 direction.
Definition: globals.h:84
void GetGradient(double ***, double **, int, int, Grid *)
Definition: tc_functions.c:4
#define BX3
Definition: mod_defs.h:27
PLUTO main header file.
D_EXPAND(tot/[n]=(double) grid[IDIR].np_int_glob;, tot/[n]=(double) grid[JDIR].np_int_glob;, tot/[n]=(double) grid[KDIR].np_int_glob;)
Definition: analysis.c:27
long int NMAX_POINT
Maximum number of points among the three directions, boundaries excluded.
Definition: globals.h:62
int i
Definition: analysis.c:2
#define BX1
Definition: mod_defs.h:25
double ** vL
Primitive variables to the left of the interface, .
Definition: structs.h:136
#define ARRAY_2D(nx, ny, type)
Definition: prototypes.h:171
#define BX2
Definition: mod_defs.h:26
#define JDIR
Definition: pluto.h:194
#define NVAR
Definition: pluto.h:609