SPINS Science Files: Difference between revisions
(Update with more functions) |
|||
(20 intermediate revisions by 3 users not shown) | |||
Line 3: | Line 3: | ||
Unless otherwise mentioned, the functions below work for both unmapped and mapped domains where the mapping is along the bottom of the domain (where the bottom is at the 0-index in the z-dimension, as opposed to at the <math> N_z-1 </math> index). Another way to say this is that z increases with the index. | Unless otherwise mentioned, the functions below work for both unmapped and mapped domains where the mapping is along the bottom of the domain (where the bottom is at the 0-index in the z-dimension, as opposed to at the <math> N_z-1 </math> index). Another way to say this is that z increases with the index. | ||
== bottom_slope.cpp == | == Details and Notes == | ||
=== Notation === | |||
<span style="color:red">Warning!</span> Multiple different notations are used below. Subscripts of <math> u </math>, <math> v </math>, and <math> w </math> are always derivatives with respect to the subscript variable. However, subscripts of <math> \omega </math> and <math> t </math> are components. That is, <math> u_x </math> and <math> \omega_x </math> are the x-derivative of <math> u </math> and the x-component of vorticity. | |||
=== Units === | |||
The units of each of the functions have been built under the assumption that physical units are being used in the simulation. These computations will work for nondimensional simulations, but more care must be taken to ensure the scalings are appropriate. Physical units are typically: | |||
{| class="wikitable" | |||
|- | |||
|Length | |||
|m | |||
|- | |||
|Time | |||
|s | |||
|- | |||
|Density | |||
|kg/m^3 | |||
|} | |||
The reference density should be 1000 kg/m^3 for the stress and dissipation calculations to be physically correct. The density field can be (and often is) non-dimensionalized to <math> \rho'= \rho/\rho_0 - 1 </math>. If nondimensionalized, [[#compute_Background_PE.cpp|compute_Background_PE.cpp]] and [[#compute_BPE_from_internal.cpp|compute_BPE_from_internal.cpp]] assume this form of scaling. These two functions also need to know if the density field is dimensional or not. | |||
== Boundary Stresses == | |||
These functions compute the surface stresses on the top and bottom boundaries. It is assumed that <math> z=z_\text{max}</math> is the top and <math> z=z_\text{min}</math> is the bottom. | |||
Further calculations and saving to disk of various quantities of the stresses are made in the src/BaseCase directory. | |||
=== bottom_slope.cpp === | |||
Compute the vector of the bottom slope at each x-grid point. This is used for calculating the stresses along the bottom boundary (cf. [[#bottom_stress_x.cpp|bottom_stress_x.cpp]] and [[#bottom_stress_y.cpp|bottom_stress_y.cpp]]). | |||
<div id="bottom_stress_x.cpp"></div> | <div id="bottom_stress_x.cpp"></div> | ||
== bottom_stress_x.cpp == | === bottom_stress_x.cpp === | ||
Compute the 2D vector of the x-component of stress on the bottom boundary. The z boundary condition must be no slip. | |||
If the case is unmapped: | If the case is unmapped: | ||
Line 14: | Line 44: | ||
<math> t_x = \mu u_z </math> | <math> t_x = \mu u_z </math> | ||
where <math> \mu </math> is the dynamic viscosity. | where <math> \mu = \nu \rho_0 </math> is the dynamic viscosity. | ||
If the case is mapped: | If the case is mapped: | ||
Line 25: | Line 55: | ||
<div id="bottom_stress_y.cpp"></div> | <div id="bottom_stress_y.cpp"></div> | ||
== bottom_stress_y.cpp == | === bottom_stress_y.cpp === | ||
Compute the 2D vector of the y-component of stress on the bottom boundary. The z boundary condition must be no slip. | |||
If the case is unmapped: | If the case is unmapped: | ||
Line 32: | Line 62: | ||
<math> t_y = \mu v_z </math> | <math> t_y = \mu v_z </math> | ||
where <math> \mu </math> is the dynamic viscosity. | where <math> \mu = \nu \rho_0 </math> is the dynamic viscosity. | ||
If the case is mapped: | If the case is mapped: | ||
Line 40: | Line 70: | ||
where <math> \alpha(x) = \sqrt{1 + h'^2(x)} </math> and where <math> h'(x) </math> is the bottom slope. | where <math> \alpha(x) = \sqrt{1 + h'^2(x)} </math> and where <math> h'(x) </math> is the bottom slope. | ||
== compute_Background_PE == | === top_stress_x.cpp === | ||
Compute the 2D vector of the x-component of stress on the top boundary. The z boundary condition must be no slip and have no mapping along the top boundary. Implementation for mapping is missing as of 2020 (it would entail copying what is done for the bottom boundary). | |||
<math> t_x = -\mu u_z </math> | |||
where <math> \mu = \nu \rho_0 </math> is the dynamic viscosity. | |||
=== top_stress_y.cpp === | |||
Compute the 2D vector of the y-component of stress on the top boundary. The z boundary condition must be no slip and have no mapping along the top boundary. Implementation for mapping is missing as of 2020 (it's would entail copying what is done for the bottom boundary). | |||
<math> t_y = -\mu v_z </math> | |||
where <math> \mu = \nu \rho_0 </math> is the dynamic viscosity. | |||
== Energy Budget == | |||
See [[Energy Budget]] for more details. | |||
<div id="compute_Background_PE.cpp"></div> | |||
=== compute_Background_PE.cpp === | |||
Compute the value of the background potential energy, | |||
<math> E_b = g \int_V \rho_* z_* dV </math> | <math> E_b = g \int_V \rho_* z_* dV </math> | ||
where <math> z_* </math> is the depth of an element of the sorted density field which minimized the potential energy (ie. <math> \rho_*</math>). For more information see Winters et al. (1995). | where <math> z_* </math> is the depth of an element of the sorted density field which minimized the potential energy (ie. <math> \rho_*</math>). For more information see Winters et al. (1995). It is assumed that gravity points in the negative z direction. | ||
== compute_BPE_from_internal.cpp == | |||
<div id="compute_BPE_from_internal.cpp"></div> | |||
=== compute_BPE_from_internal.cpp === | |||
Compute the rate of energy transfer from internal energy into background potential energy. | |||
<math> \phi_i = -g\kappa \int_A \rho(z=z_u) - \rho(z=z_l) dA </math> | <math> \phi_i = -g\kappa \int_A \rho(z=z_u) - \rho(z=z_l) dA </math> | ||
where <math> z_u </math> and <math> z_l </math> are the depths of the upper and lower boundaries, respectively. The integral is taken over the horizontal extent. | where <math> z_u </math> and <math> z_l </math> are the depths of the upper and lower boundaries, respectively. The integral is taken over the horizontal extent. | ||
For more information see Winters et al. (1995). | For more information see Winters et al. (1995). It is assumed that gravity points in the negative z direction. | ||
=== dissipation.cpp === | |||
Compute the viscous dissipation <math> \epsilon = 2 \mu e_{ij} e_{ij} </math> | |||
where summation is implied over duplicate indices and <math> e_{ij} = \frac{1}{2} (\frac{\partial u_i}{\partial x_j} + \frac{\partial u_j}{\partial x_i})</math> | |||
is the strain rate tensor. | |||
== Vorticity and Vorticity Equation == | |||
See the [[Vorticity equation]] | |||
=== compute_vorticity.cpp === | |||
Compute all vorticity components. | |||
=== compute_vort_x.cpp === | |||
Compute the x-component of vorticity: <math> \omega_x = w_y - v_z </math> | |||
=== compute_vort_y.cpp === | |||
Compute the y-component of vorticity: <math> \omega_y = u_z - w_x </math> | |||
=== compute_vort_z.cpp === | |||
Compute the z-component of vorticity: <math> \omega_z = v_x - u_y </math> | |||
=== vortex_stretch_x.cpp === | |||
Compute the x-component of the vorticity production due to stretching/tilting | |||
<math> \omega_x u_x + \omega_y u_y + \omega_z u_z </math> | |||
=== vortex_stretch_y.cpp === | |||
Compute the y-component of the vorticity production due to stretching/tilting | |||
<math> \omega_x v_x + \omega_y v_y + \omega_z v_z </math> | |||
=== vortex_stretch_z.cpp === | |||
Compute the z-component of the vorticity production due to stretching/tilting | |||
<math> \omega_x w_x + \omega_y w_y + \omega_z w_z </math> | |||
== Enstrophy equation == | |||
See the [[Enstrophy equation]]. | |||
=== enstrophy_density.cpp === | |||
Compute the enstrophy density | |||
<math> \Omega = \frac{1}{2} \omega_i\omega_i = \frac{1}{2} (\omega_x^2 + \omega_y^2 + \omega_z^2) </math> | |||
=== enstrophy_stretch_production.cpp === | |||
Compute the enstrophy production due to vortex tilting/stretching | |||
<math> \omega_i \omega_j e_{ij} = \omega_i \omega_j \frac{\partial u_i}{\partial x_j} </math> | |||
where summation is implied over duplicate indices and <math> e_{ij} = \frac{1}{2} (\frac{\partial u_i}{\partial x_j} + \frac{\partial u_j}{\partial x_i})</math> | |||
is the strain rate tensor. | |||
== Coherent Vortex Identification for 3D Flows== | |||
The characteristic polynomial of <math>u_{i,j}</math> can be written as | |||
<math>\lambda^3 - P\lambda^2 + Q\lambda - R = 0,</math> | |||
assuming that the flow is 3D. These coefficients are invariants—i.e., scalars—of the flow, and can be used to identify coherent structures that exist in all reference frames. They are given by | |||
<math> P = \lambda_1+\lambda_2+\lambda_3=u_{i,i} , </math> | |||
== compute_quadweights.cpp == | <math> Q = \frac{1}{2}(\lambda_1^2+\lambda_2^2+\lambda_3^2)=\frac{1}{2}(P^2-u_{i,j}u_{j,i})=\frac{1}{2}(P^2+\Omega_{ij}\Omega_{ij}-S_{ij}S_{ij}), </math> | ||
<math> R = \frac{1}{3}\lambda_1\lambda_2\lambda_3 = det(u_{i,j}). </math> | |||
SPINS assumes the flow is incompressible, so P=0. The more useful variables are Q and R. As can be seen from the definition of Q, large positive values of Q imply that rotation dominates while large negative values of Q imply that strain dominates; this property therefore clarifies whether a region of high vorticity is due to a vortex, or due to a shear stress, respectively. While not immediately obvious, regions of large and positive R correspond to axial stretching in the flow while large and negative R correspond to planar stretching. As a consequence, intersecting iso-surfaces of large Q and large R likely contain coherent vortices. | |||
This discussion of Q and R is adapted from [http://hdl.handle.net/10012/10138 Anton Baglaenko’s PhD thesis]. | |||
=== Q_invt.cpp === | |||
This calculates Q using | |||
<math>Q=-\frac{1}{2}u_{i,j}u_{j,i}</math> | |||
=== R_invt.cpp === | |||
This calculates R using | |||
<math> R = det(u_{i,j}) = \frac{1}{3}u_{i,j}u_{j,k}u_{k,i} </math> | |||
== Other == | |||
=== compute_quadweights.cpp === | |||
Compute the quadrature weights for each dimension. | |||
If the boundary condition is no-slip, use the Clenshaw-Curtis quadrature weights: | If the boundary condition is no-slip, use the Clenshaw-Curtis quadrature weights: | ||
Line 66: | Line 206: | ||
<math> w = L_x/N_x = \Delta x </math> | <math> w = L_x/N_x = \Delta x </math> | ||
== | === find_expansion.cpp === | ||
Returns the expansion types for each field. | |||
{| class="wikitable" | |||
!colspan="1"|Boundary Condition | |||
!colspan="4"|Flow Variable | |||
|- | |||
|- | |||
| | |||
|style="text-align:center;"|u | |||
|style="text-align:center;"|v | |||
|style="text-align:center;"|w | |||
|style="text-align:center;"|otherwise | |||
|- | |||
|Fourier | |||
|Periodic | |||
|Periodic | |||
|Periodic | |||
|Periodic | |||
|- | |||
|No slip | |||
|Chebyshev | |||
|Chebyshev | |||
|Chebyshev | |||
|Chebyshev | |||
|- | |||
|Free slip in x | |||
|sine | |||
|cosine | |||
|cosine | |||
|cosine | |||
|- | |||
|Free slip in y | |||
|cosine | |||
|sine | |||
|cosine | |||
|cosine | |||
|- | |||
|Free slip in z | |||
|cosine | |||
|cosine | |||
|sine | |||
|cosine | |||
|} | |||
Spins assumes that a variable ending in <code>_x</code>, <code>_y</code>, or <code>_z</code> is the x, y, or z derivative of that particular variable. This is needed to get the proper expansion type for the derivative of the given variable. | |||
=== get_quad.cpp === | |||
Fairly certain that this is a deprecated function | |||
=== overturning_2d.cpp === | |||
Details to be added. It's an old function and probably deprecated. | |||
=== read_2d_restart.cpp === | |||
For reading 2D spins files and (likely) extending to 3D. | |||
Unsure why this is in /Science. IO should also be cleaned up since there's a bunch of overlapping functions. | |||
=== read_2d_slice.cpp === | |||
For reading 2D matlab files or 2D slices. | |||
Unsure why this is in /Science. IO should also be cleaned up since there's a bunch of overlapping functions. | |||
=== swap_trig.cpp === | |||
Change cosine expansion to sine expansion and vice versa. To be used in find_expansion for variables of derivatives. | |||
== Nonlinear Equations of State == | |||
Several equations of state are included as inline functions in Science.hpp. They will take temperature, salinity, or both as arguments and there are 3 available to choose from. The first is the full nonlinear equation of state from MacDougall et. al (2003) (JAOT) which is valid for <math>0-45 PSU</math> and <math>0-40^\circ C</math>. Note that the current implementation assumes that the temperature is taken to be at surface pressure (the temperature is in situ). This is not a bad simplification for SPINS, as the model is incompressible. | |||
<div id="nleos.cpp"></div> | |||
=== nleos.cpp === | |||
nleos.cpp calls a full nonlinear equation of state from MacDougall et. al (2003) (JAOT) which is valid for <math>0-45 PSU</math> and <math>0-40^\circ C</math>. The user is required to supply temperature and salinity. | |||
<math>\rho = \rho(T,S)</math> | |||
<div id="quadeos.cpp"></div> | |||
=== quadeos.cpp === | |||
quadeos.cpp calls an approximation of the EOS from MacDougall et. al. (2003) (JAOT) for use with temperature only. This EOS is intended for use between <math> 0-10^\circ C</math>. It takes the form | |||
<math>\rho(T) = \rho(T_{md}) + C(T - T_{md})^2</math> | |||
where | |||
<math>T_{md} = 3.98^\circ C</math> | |||
<div id="lineos.cpp"></div> | |||
=== lineos.cpp === | |||
lineos.cpp calls a linear, two-constituent (heat/salt) equation of state. The user selects the reference temperature and salinity within the case file, and using this information, the reference density and expansion coefficients are calculated numerically from MacDougall et. al. (2003). The EOS takes the form | |||
<math>\rho(T) = \rho(T_0,S_0)[(1 +\alpha(T - T_0) + \beta(S - S_0)]</math> | |||
where | |||
<math>\alpha = \frac{1}{\rho(T_0,S_0)}\frac{\partial \rho}{\partial T}</math> | |||
and | |||
<math>\beta = \frac{1}{\rho(T_0,S_0)}\frac{\partial \rho}{\partial S}</math> | |||
Latest revision as of 09:41, 15 October 2021
SPINS comes with a variety of Science files which help with simulation data analysis. Below is a list of currently available functions with a brief description of their purpose and the assumptions behind their implementation. These Science files are in spins/src/Science.
Unless otherwise mentioned, the functions below work for both unmapped and mapped domains where the mapping is along the bottom of the domain (where the bottom is at the 0-index in the z-dimension, as opposed to at the index). Another way to say this is that z increases with the index.
Details and Notes
Notation
Warning! Multiple different notations are used below. Subscripts of , , and are always derivatives with respect to the subscript variable. However, subscripts of and are components. That is, and are the x-derivative of and the x-component of vorticity.
Units
The units of each of the functions have been built under the assumption that physical units are being used in the simulation. These computations will work for nondimensional simulations, but more care must be taken to ensure the scalings are appropriate. Physical units are typically:
Length | m |
Time | s |
Density | kg/m^3 |
The reference density should be 1000 kg/m^3 for the stress and dissipation calculations to be physically correct. The density field can be (and often is) non-dimensionalized to . If nondimensionalized, compute_Background_PE.cpp and compute_BPE_from_internal.cpp assume this form of scaling. These two functions also need to know if the density field is dimensional or not.
Boundary Stresses
These functions compute the surface stresses on the top and bottom boundaries. It is assumed that is the top and is the bottom.
Further calculations and saving to disk of various quantities of the stresses are made in the src/BaseCase directory.
bottom_slope.cpp
Compute the vector of the bottom slope at each x-grid point. This is used for calculating the stresses along the bottom boundary (cf. bottom_stress_x.cpp and bottom_stress_y.cpp).
bottom_stress_x.cpp
Compute the 2D vector of the x-component of stress on the bottom boundary. The z boundary condition must be no slip.
If the case is unmapped:
where is the dynamic viscosity.
If the case is mapped:
where and where is the bottom slope.
bottom_stress_y.cpp
Compute the 2D vector of the y-component of stress on the bottom boundary. The z boundary condition must be no slip.
If the case is unmapped:
where is the dynamic viscosity.
If the case is mapped:
where and where is the bottom slope.
top_stress_x.cpp
Compute the 2D vector of the x-component of stress on the top boundary. The z boundary condition must be no slip and have no mapping along the top boundary. Implementation for mapping is missing as of 2020 (it would entail copying what is done for the bottom boundary).
where is the dynamic viscosity.
top_stress_y.cpp
Compute the 2D vector of the y-component of stress on the top boundary. The z boundary condition must be no slip and have no mapping along the top boundary. Implementation for mapping is missing as of 2020 (it's would entail copying what is done for the bottom boundary).
where is the dynamic viscosity.
Energy Budget
See Energy Budget for more details.
compute_Background_PE.cpp
Compute the value of the background potential energy,
where is the depth of an element of the sorted density field which minimized the potential energy (ie. ). For more information see Winters et al. (1995). It is assumed that gravity points in the negative z direction.
compute_BPE_from_internal.cpp
Compute the rate of energy transfer from internal energy into background potential energy.
where and are the depths of the upper and lower boundaries, respectively. The integral is taken over the horizontal extent. For more information see Winters et al. (1995). It is assumed that gravity points in the negative z direction.
dissipation.cpp
Compute the viscous dissipation
where summation is implied over duplicate indices and is the strain rate tensor.
Vorticity and Vorticity Equation
See the Vorticity equation
compute_vorticity.cpp
Compute all vorticity components.
compute_vort_x.cpp
Compute the x-component of vorticity:
compute_vort_y.cpp
Compute the y-component of vorticity:
compute_vort_z.cpp
Compute the z-component of vorticity:
vortex_stretch_x.cpp
Compute the x-component of the vorticity production due to stretching/tilting
vortex_stretch_y.cpp
Compute the y-component of the vorticity production due to stretching/tilting
vortex_stretch_z.cpp
Compute the z-component of the vorticity production due to stretching/tilting
Enstrophy equation
See the Enstrophy equation.
enstrophy_density.cpp
Compute the enstrophy density
enstrophy_stretch_production.cpp
Compute the enstrophy production due to vortex tilting/stretching
where summation is implied over duplicate indices and is the strain rate tensor.
Coherent Vortex Identification for 3D Flows
The characteristic polynomial of can be written as
assuming that the flow is 3D. These coefficients are invariants—i.e., scalars—of the flow, and can be used to identify coherent structures that exist in all reference frames. They are given by
SPINS assumes the flow is incompressible, so P=0. The more useful variables are Q and R. As can be seen from the definition of Q, large positive values of Q imply that rotation dominates while large negative values of Q imply that strain dominates; this property therefore clarifies whether a region of high vorticity is due to a vortex, or due to a shear stress, respectively. While not immediately obvious, regions of large and positive R correspond to axial stretching in the flow while large and negative R correspond to planar stretching. As a consequence, intersecting iso-surfaces of large Q and large R likely contain coherent vortices.
This discussion of Q and R is adapted from Anton Baglaenko’s PhD thesis.
Q_invt.cpp
This calculates Q using
R_invt.cpp
This calculates R using
Other
compute_quadweights.cpp
Compute the quadrature weights for each dimension.
If the boundary condition is no-slip, use the Clenshaw-Curtis quadrature weights:
If the boundary condition is free-slip, use the trapezoid rule:
find_expansion.cpp
Returns the expansion types for each field.
Boundary Condition | Flow Variable | |||
---|---|---|---|---|
u | v | w | otherwise | |
Fourier | Periodic | Periodic | Periodic | Periodic |
No slip | Chebyshev | Chebyshev | Chebyshev | Chebyshev |
Free slip in x | sine | cosine | cosine | cosine |
Free slip in y | cosine | sine | cosine | cosine |
Free slip in z | cosine | cosine | sine | cosine |
Spins assumes that a variable ending in _x
, _y
, or _z
is the x, y, or z derivative of that particular variable. This is needed to get the proper expansion type for the derivative of the given variable.
get_quad.cpp
Fairly certain that this is a deprecated function
overturning_2d.cpp
Details to be added. It's an old function and probably deprecated.
read_2d_restart.cpp
For reading 2D spins files and (likely) extending to 3D.
Unsure why this is in /Science. IO should also be cleaned up since there's a bunch of overlapping functions.
read_2d_slice.cpp
For reading 2D matlab files or 2D slices.
Unsure why this is in /Science. IO should also be cleaned up since there's a bunch of overlapping functions.
swap_trig.cpp
Change cosine expansion to sine expansion and vice versa. To be used in find_expansion for variables of derivatives.
Nonlinear Equations of State
Several equations of state are included as inline functions in Science.hpp. They will take temperature, salinity, or both as arguments and there are 3 available to choose from. The first is the full nonlinear equation of state from MacDougall et. al (2003) (JAOT) which is valid for and . Note that the current implementation assumes that the temperature is taken to be at surface pressure (the temperature is in situ). This is not a bad simplification for SPINS, as the model is incompressible.
nleos.cpp
nleos.cpp calls a full nonlinear equation of state from MacDougall et. al (2003) (JAOT) which is valid for and . The user is required to supply temperature and salinity.
quadeos.cpp
quadeos.cpp calls an approximation of the EOS from MacDougall et. al. (2003) (JAOT) for use with temperature only. This EOS is intended for use between . It takes the form
where
lineos.cpp
lineos.cpp calls a linear, two-constituent (heat/salt) equation of state. The user selects the reference temperature and salinity within the case file, and using this information, the reference density and expansion coefficients are calculated numerically from MacDougall et. al. (2003). The EOS takes the form
where
and