354 lines
15 KiB
C++
354 lines
15 KiB
C++
/*
|
|
Copyright (C) 2014-2020, Johannes Pekkila, Miikka Vaisala.
|
|
|
|
This file is part of Astaroth.
|
|
|
|
Astaroth is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Astaroth is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Astaroth. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/**
|
|
* @file
|
|
* \brief Brief info.
|
|
*
|
|
* Detailed info.
|
|
*
|
|
*/
|
|
#pragma once
|
|
#include "errchk.h"
|
|
|
|
typedef long double MODEL_REAL;
|
|
|
|
typedef enum { AXIS_X, AXIS_Y, AXIS_Z, NUM_AXIS_TYPES } AxisType;
|
|
|
|
template <AxisType axis>
|
|
static inline MODEL_REAL
|
|
der_scal(const int& i, const int& j, const int& k, const AcMeshInfo& mesh_info,
|
|
const MODEL_REAL* scal)
|
|
{
|
|
MODEL_REAL f0, f1, f2, f4, f5, f6;
|
|
MODEL_REAL ds;
|
|
|
|
switch (axis) {
|
|
case AXIS_X:
|
|
f0 = scal[acVertexBufferIdx(i - 3, j, k, mesh_info)];
|
|
f1 = scal[acVertexBufferIdx(i - 2, j, k, mesh_info)];
|
|
f2 = scal[acVertexBufferIdx(i - 1, j, k, mesh_info)];
|
|
f4 = scal[acVertexBufferIdx(i + 1, j, k, mesh_info)];
|
|
f5 = scal[acVertexBufferIdx(i + 2, j, k, mesh_info)];
|
|
f6 = scal[acVertexBufferIdx(i + 3, j, k, mesh_info)];
|
|
ds = mesh_info.real_params[AC_dsx];
|
|
break;
|
|
case AXIS_Y:
|
|
f0 = scal[acVertexBufferIdx(i, j - 3, k, mesh_info)];
|
|
f1 = scal[acVertexBufferIdx(i, j - 2, k, mesh_info)];
|
|
f2 = scal[acVertexBufferIdx(i, j - 1, k, mesh_info)];
|
|
f4 = scal[acVertexBufferIdx(i, j + 1, k, mesh_info)];
|
|
f5 = scal[acVertexBufferIdx(i, j + 2, k, mesh_info)];
|
|
f6 = scal[acVertexBufferIdx(i, j + 3, k, mesh_info)];
|
|
ds = mesh_info.real_params[AC_dsy];
|
|
break;
|
|
case AXIS_Z:
|
|
f0 = scal[acVertexBufferIdx(i, j, k - 3, mesh_info)];
|
|
f1 = scal[acVertexBufferIdx(i, j, k - 2, mesh_info)];
|
|
f2 = scal[acVertexBufferIdx(i, j, k - 1, mesh_info)];
|
|
f4 = scal[acVertexBufferIdx(i, j, k + 1, mesh_info)];
|
|
f5 = scal[acVertexBufferIdx(i, j, k + 2, mesh_info)];
|
|
f6 = scal[acVertexBufferIdx(i, j, k + 3, mesh_info)];
|
|
ds = mesh_info.real_params[AC_dsz];
|
|
break;
|
|
default:
|
|
ERROR("Unknown axis type");
|
|
}
|
|
return ((f6 - f0) + MODEL_REAL(-9.) * (f5 - f1) + MODEL_REAL(45.) * (f4 - f2)) /
|
|
(MODEL_REAL(60.) * ds);
|
|
}
|
|
|
|
template <AxisType axis>
|
|
static inline MODEL_REAL
|
|
der2_scal(const int& i, const int& j, const int& k, const AcMeshInfo& mesh_info,
|
|
const MODEL_REAL* scal)
|
|
{
|
|
MODEL_REAL f0, f1, f2, f3, f4, f5, f6;
|
|
MODEL_REAL ds;
|
|
|
|
f3 = scal[acVertexBufferIdx(i, j, k, mesh_info)];
|
|
|
|
switch (axis) {
|
|
case AXIS_X:
|
|
f0 = scal[acVertexBufferIdx(i - 3, j, k, mesh_info)];
|
|
f1 = scal[acVertexBufferIdx(i - 2, j, k, mesh_info)];
|
|
f2 = scal[acVertexBufferIdx(i - 1, j, k, mesh_info)];
|
|
f4 = scal[acVertexBufferIdx(i + 1, j, k, mesh_info)];
|
|
f5 = scal[acVertexBufferIdx(i + 2, j, k, mesh_info)];
|
|
f6 = scal[acVertexBufferIdx(i + 3, j, k, mesh_info)];
|
|
ds = mesh_info.real_params[AC_dsx];
|
|
break;
|
|
case AXIS_Y:
|
|
f0 = scal[acVertexBufferIdx(i, j - 3, k, mesh_info)];
|
|
f1 = scal[acVertexBufferIdx(i, j - 2, k, mesh_info)];
|
|
f2 = scal[acVertexBufferIdx(i, j - 1, k, mesh_info)];
|
|
f4 = scal[acVertexBufferIdx(i, j + 1, k, mesh_info)];
|
|
f5 = scal[acVertexBufferIdx(i, j + 2, k, mesh_info)];
|
|
f6 = scal[acVertexBufferIdx(i, j + 3, k, mesh_info)];
|
|
ds = mesh_info.real_params[AC_dsy];
|
|
break;
|
|
case AXIS_Z:
|
|
f0 = scal[acVertexBufferIdx(i, j, k - 3, mesh_info)];
|
|
f1 = scal[acVertexBufferIdx(i, j, k - 2, mesh_info)];
|
|
f2 = scal[acVertexBufferIdx(i, j, k - 1, mesh_info)];
|
|
f4 = scal[acVertexBufferIdx(i, j, k + 1, mesh_info)];
|
|
f5 = scal[acVertexBufferIdx(i, j, k + 2, mesh_info)];
|
|
f6 = scal[acVertexBufferIdx(i, j, k + 3, mesh_info)];
|
|
ds = mesh_info.real_params[AC_dsz];
|
|
break;
|
|
default:
|
|
ERROR("Unknown axis type");
|
|
}
|
|
return (MODEL_REAL(2.) * (f0 + f6) + MODEL_REAL(-27.) * (f1 + f5) +
|
|
MODEL_REAL(270.) * (f2 + f4) + MODEL_REAL(-490.) * f3) /
|
|
(MODEL_REAL(180.) * ds * ds);
|
|
}
|
|
|
|
static MODEL_REAL
|
|
laplace_scal(const int& i, const int& j, const int& k,
|
|
const AcMeshInfo& mesh_info, const MODEL_REAL* scal)
|
|
{
|
|
return der2_scal<AXIS_X>(i, j, k, mesh_info, scal) +
|
|
der2_scal<AXIS_Y>(i, j, k, mesh_info, scal) +
|
|
der2_scal<AXIS_Z>(i, j, k, mesh_info, scal);
|
|
}
|
|
|
|
static void
|
|
laplace_vec(const int& i, const int& j, const int& k,
|
|
const AcMeshInfo& mesh_info, const MODEL_REAL* vec_x,
|
|
const MODEL_REAL* vec_y, const MODEL_REAL* vec_z, MODEL_REAL* laplace_x,
|
|
MODEL_REAL* laplace_y, MODEL_REAL* laplace_z)
|
|
{
|
|
*laplace_x = laplace_scal(i, j, k, mesh_info, vec_x);
|
|
*laplace_y = laplace_scal(i, j, k, mesh_info, vec_y);
|
|
*laplace_z = laplace_scal(i, j, k, mesh_info, vec_z);
|
|
}
|
|
|
|
static MODEL_REAL
|
|
div_vec(const int& i, const int& j, const int& k, const AcMeshInfo& mesh_info,
|
|
const MODEL_REAL* vec_x, const MODEL_REAL* vec_y, const MODEL_REAL* vec_z)
|
|
{
|
|
return der_scal<AXIS_X>(i, j, k, mesh_info, vec_x) +
|
|
der_scal<AXIS_Y>(i, j, k, mesh_info, vec_y) +
|
|
der_scal<AXIS_Z>(i, j, k, mesh_info, vec_z);
|
|
}
|
|
|
|
static void
|
|
grad(const int& i, const int& j, const int& k, const AcMeshInfo& mesh_info,
|
|
const MODEL_REAL* scal, MODEL_REAL* res_x, MODEL_REAL* res_y, MODEL_REAL* res_z)
|
|
{
|
|
*res_x = der_scal<AXIS_X>(i, j, k, mesh_info, scal);
|
|
*res_y = der_scal<AXIS_Y>(i, j, k, mesh_info, scal);
|
|
*res_z = der_scal<AXIS_Z>(i, j, k, mesh_info, scal);
|
|
}
|
|
|
|
static MODEL_REAL
|
|
vec_dot_nabla_scal(const int& i, const int& j, const int& k,
|
|
const AcMeshInfo& mesh_info, const MODEL_REAL* vec_x,
|
|
const MODEL_REAL* vec_y, const MODEL_REAL* vec_z, const MODEL_REAL* scal)
|
|
{
|
|
const int idx = acVertexBufferIdx(i, j, k, mesh_info);
|
|
MODEL_REAL ddx_scal, ddy_scal, ddz_scal;
|
|
grad(i, j, k, mesh_info, scal, &ddx_scal, &ddy_scal, &ddz_scal);
|
|
return vec_x[idx] * ddx_scal + vec_y[idx] * ddy_scal +
|
|
vec_z[idx] * ddz_scal;
|
|
}
|
|
|
|
/*
|
|
* =============================================================================
|
|
* Viscosity
|
|
* =============================================================================
|
|
*/
|
|
typedef enum { DERNM_XY, DERNM_YZ, DERNM_XZ } DernmType;
|
|
|
|
template <DernmType dernm>
|
|
static MODEL_REAL
|
|
dernm_scal(const int& i, const int& j, const int& k,
|
|
const AcMeshInfo& mesh_info, const MODEL_REAL* scal)
|
|
{
|
|
|
|
MODEL_REAL fac;
|
|
|
|
const MODEL_REAL dsx = mesh_info.real_params[AC_dsx];
|
|
const MODEL_REAL dsy = mesh_info.real_params[AC_dsy];
|
|
const MODEL_REAL dsz = mesh_info.real_params[AC_dsz];
|
|
|
|
MODEL_REAL f_p1_p1, f_m1_p1, f_m1_m1, f_p1_m1;
|
|
MODEL_REAL f_p2_p2, f_m2_p2, f_m2_m2, f_p2_m2;
|
|
MODEL_REAL f_p3_p3, f_m3_p3, f_m3_m3, f_p3_m3;
|
|
|
|
switch (dernm) {
|
|
case DERNM_XY:
|
|
fac = MODEL_REAL(1. / 720.) * (MODEL_REAL(1.) / dsx) * (MODEL_REAL(1.) / dsy);
|
|
f_p1_p1 = scal[acVertexBufferIdx(i + 1, j + 1, k, mesh_info)];
|
|
f_m1_p1 = scal[acVertexBufferIdx(i - 1, j + 1, k, mesh_info)];
|
|
f_m1_m1 = scal[acVertexBufferIdx(i - 1, j - 1, k, mesh_info)];
|
|
f_p1_m1 = scal[acVertexBufferIdx(i + 1, j - 1, k, mesh_info)];
|
|
|
|
f_p2_p2 = scal[acVertexBufferIdx(i + 2, j + 2, k, mesh_info)];
|
|
f_m2_p2 = scal[acVertexBufferIdx(i - 2, j + 2, k, mesh_info)];
|
|
f_m2_m2 = scal[acVertexBufferIdx(i - 2, j - 2, k, mesh_info)];
|
|
f_p2_m2 = scal[acVertexBufferIdx(i + 2, j - 2, k, mesh_info)];
|
|
|
|
f_p3_p3 = scal[acVertexBufferIdx(i + 3, j + 3, k, mesh_info)];
|
|
f_m3_p3 = scal[acVertexBufferIdx(i - 3, j + 3, k, mesh_info)];
|
|
f_m3_m3 = scal[acVertexBufferIdx(i - 3, j - 3, k, mesh_info)];
|
|
f_p3_m3 = scal[acVertexBufferIdx(i + 3, j - 3, k, mesh_info)];
|
|
break;
|
|
case DERNM_YZ:
|
|
// NOTE this is a bit different from the old one, second is j+1k-1
|
|
// instead of j-1,k+1
|
|
fac = MODEL_REAL(1. / 720.) * (MODEL_REAL(1.) / dsy) * (MODEL_REAL(1.) / dsz);
|
|
f_p1_p1 = scal[acVertexBufferIdx(i, j + 1, k + 1, mesh_info)];
|
|
f_m1_p1 = scal[acVertexBufferIdx(i, j - 1, k + 1, mesh_info)];
|
|
f_m1_m1 = scal[acVertexBufferIdx(i, j - 1, k - 1, mesh_info)];
|
|
f_p1_m1 = scal[acVertexBufferIdx(i, j + 1, k - 1, mesh_info)];
|
|
|
|
f_p2_p2 = scal[acVertexBufferIdx(i, j + 2, k + 2, mesh_info)];
|
|
f_m2_p2 = scal[acVertexBufferIdx(i, j - 2, k + 2, mesh_info)];
|
|
f_m2_m2 = scal[acVertexBufferIdx(i, j - 2, k - 2, mesh_info)];
|
|
f_p2_m2 = scal[acVertexBufferIdx(i, j + 2, k - 2, mesh_info)];
|
|
|
|
f_p3_p3 = scal[acVertexBufferIdx(i, j + 3, k + 3, mesh_info)];
|
|
f_m3_p3 = scal[acVertexBufferIdx(i, j - 3, k + 3, mesh_info)];
|
|
f_m3_m3 = scal[acVertexBufferIdx(i, j - 3, k - 3, mesh_info)];
|
|
f_p3_m3 = scal[acVertexBufferIdx(i, j + 3, k - 3, mesh_info)];
|
|
break;
|
|
case DERNM_XZ:
|
|
fac = MODEL_REAL(1. / 720.) * (MODEL_REAL(1.) / dsx) * (MODEL_REAL(1.) / dsz);
|
|
f_p1_p1 = scal[acVertexBufferIdx(i + 1, j, k + 1, mesh_info)];
|
|
f_m1_p1 = scal[acVertexBufferIdx(i - 1, j, k + 1, mesh_info)];
|
|
f_m1_m1 = scal[acVertexBufferIdx(i - 1, j, k - 1, mesh_info)];
|
|
f_p1_m1 = scal[acVertexBufferIdx(i + 1, j, k - 1, mesh_info)];
|
|
|
|
f_p2_p2 = scal[acVertexBufferIdx(i + 2, j, k + 2, mesh_info)];
|
|
f_m2_p2 = scal[acVertexBufferIdx(i - 2, j, k + 2, mesh_info)];
|
|
f_m2_m2 = scal[acVertexBufferIdx(i - 2, j, k - 2, mesh_info)];
|
|
f_p2_m2 = scal[acVertexBufferIdx(i + 2, j, k - 2, mesh_info)];
|
|
|
|
f_p3_p3 = scal[acVertexBufferIdx(i + 3, j, k + 3, mesh_info)];
|
|
f_m3_p3 = scal[acVertexBufferIdx(i - 3, j, k + 3, mesh_info)];
|
|
f_m3_m3 = scal[acVertexBufferIdx(i - 3, j, k - 3, mesh_info)];
|
|
f_p3_m3 = scal[acVertexBufferIdx(i + 3, j, k - 3, mesh_info)];
|
|
break;
|
|
default:
|
|
ERROR("Invalid dernm type");
|
|
}
|
|
return fac * (MODEL_REAL(270.) * (f_p1_p1 - f_m1_p1 + f_m1_m1 - f_p1_m1) -
|
|
MODEL_REAL(27.) * (f_p2_p2 - f_m2_p2 + f_m2_m2 - f_p2_m2) +
|
|
MODEL_REAL(2.) * (f_p3_p3 - f_m3_p3 + f_m3_m3 - f_p3_m3));
|
|
}
|
|
|
|
static void
|
|
grad_div_vec(const int& i, const int& j, const int& k,
|
|
const AcMeshInfo& mesh_info, const MODEL_REAL* vec_x,
|
|
const MODEL_REAL* vec_y, const MODEL_REAL* vec_z, MODEL_REAL* gdvx,
|
|
MODEL_REAL* gdvy, MODEL_REAL* gdvz)
|
|
{
|
|
*gdvx = der2_scal<AXIS_X>(i, j, k, mesh_info, vec_x) +
|
|
dernm_scal<DERNM_XY>(i, j, k, mesh_info, vec_y) +
|
|
dernm_scal<DERNM_XZ>(i, j, k, mesh_info, vec_z);
|
|
|
|
*gdvy = dernm_scal<DERNM_XY>(i, j, k, mesh_info, vec_x) +
|
|
der2_scal<AXIS_Y>(i, j, k, mesh_info, vec_y) +
|
|
dernm_scal<DERNM_YZ>(i, j, k, mesh_info, vec_z);
|
|
|
|
*gdvz = dernm_scal<DERNM_XZ>(i, j, k, mesh_info, vec_x) +
|
|
dernm_scal<DERNM_YZ>(i, j, k, mesh_info, vec_y) +
|
|
der2_scal<AXIS_Z>(i, j, k, mesh_info, vec_z);
|
|
}
|
|
|
|
static void
|
|
S_grad_lnrho(const int& i, const int& j, const int& k,
|
|
const AcMeshInfo& mesh_info, const MODEL_REAL* vec_x,
|
|
const MODEL_REAL* vec_y, const MODEL_REAL* vec_z, const MODEL_REAL* lnrho,
|
|
MODEL_REAL* sgrhox, MODEL_REAL* sgrhoy, MODEL_REAL* sgrhoz)
|
|
{
|
|
const MODEL_REAL c23 = MODEL_REAL(2. / 3.);
|
|
const MODEL_REAL c13 = MODEL_REAL(1. / 3.);
|
|
|
|
const MODEL_REAL Sxx = c23 * der_scal<AXIS_X>(i, j, k, mesh_info, vec_x) -
|
|
c13 * (der_scal<AXIS_Y>(i, j, k, mesh_info, vec_y) +
|
|
der_scal<AXIS_Z>(i, j, k, mesh_info, vec_z));
|
|
const MODEL_REAL Sxy = MODEL_REAL(.5) *
|
|
(der_scal<AXIS_Y>(i, j, k, mesh_info, vec_x) +
|
|
der_scal<AXIS_X>(i, j, k, mesh_info, vec_y));
|
|
const MODEL_REAL Sxz = MODEL_REAL(.5) *
|
|
(der_scal<AXIS_Z>(i, j, k, mesh_info, vec_x) +
|
|
der_scal<AXIS_X>(i, j, k, mesh_info, vec_z));
|
|
|
|
const MODEL_REAL Syx = Sxy;
|
|
const MODEL_REAL Syy = c23 * der_scal<AXIS_Y>(i, j, k, mesh_info, vec_y) -
|
|
c13 * (der_scal<AXIS_X>(i, j, k, mesh_info, vec_x) +
|
|
der_scal<AXIS_Z>(i, j, k, mesh_info, vec_z));
|
|
const MODEL_REAL Syz = MODEL_REAL(.5) *
|
|
(der_scal<AXIS_Z>(i, j, k, mesh_info, vec_y) +
|
|
der_scal<AXIS_Y>(i, j, k, mesh_info, vec_z));
|
|
|
|
const MODEL_REAL Szx = Sxz;
|
|
const MODEL_REAL Szy = Syz;
|
|
const MODEL_REAL Szz = c23 *
|
|
der_scal<AXIS_Z>(
|
|
i, j, k, mesh_info,
|
|
vec_z) // replaced from "c23*der_scal<AXIS_Z>(i,
|
|
// j, k, mesh_info, vec_x)"! TODO recheck
|
|
// that ddz_uu_z is the correct one
|
|
- c13 * (der_scal<AXIS_X>(i, j, k, mesh_info, vec_x) +
|
|
der_scal<AXIS_Y>(i, j, k, mesh_info, vec_y));
|
|
|
|
// Grad lnrho
|
|
|
|
MODEL_REAL glnx, glny, glnz;
|
|
|
|
grad(i, j, k, mesh_info, lnrho, &glnx, &glny, &glnz);
|
|
|
|
*sgrhox = Sxx * glnx + Sxy * glny + Sxz * glnz;
|
|
*sgrhoy = Syx * glnx + Syy * glny + Syz * glnz;
|
|
*sgrhoz = Szx * glnx + Szy * glny + Szz * glnz;
|
|
}
|
|
|
|
static void
|
|
nu_const(const int& i, const int& j, const int& k, const AcMeshInfo& mesh_info,
|
|
const MODEL_REAL* vec_x, const MODEL_REAL* vec_y, const MODEL_REAL* vec_z,
|
|
const MODEL_REAL* scal, MODEL_REAL* visc_x, MODEL_REAL* visc_y, MODEL_REAL* visc_z)
|
|
{
|
|
MODEL_REAL lx, ly, lz;
|
|
laplace_vec(i, j, k, mesh_info, vec_x, vec_y, vec_z, &lx, &ly, &lz);
|
|
// lx = ly = lz = .0f;
|
|
|
|
MODEL_REAL gx, gy, gz;
|
|
grad_div_vec(i, j, k, mesh_info, vec_x, vec_y, vec_z, &gx, &gy, &gz);
|
|
// gx = gy =gz = .0f;
|
|
|
|
MODEL_REAL sgrhox, sgrhoy, sgrhoz;
|
|
S_grad_lnrho(i, j, k, mesh_info, vec_x, vec_y, vec_z, scal, &sgrhox,
|
|
&sgrhoy, &sgrhoz);
|
|
// sgrhox = sgrhoy = sgrhoz = .0f;
|
|
|
|
*visc_x = mesh_info.real_params[AC_nu_visc] *
|
|
(lx + MODEL_REAL(1. / 3.) * gx + MODEL_REAL(2.) * sgrhox)
|
|
+ mesh_info.real_params[AC_zeta] * gx;
|
|
*visc_y = mesh_info.real_params[AC_nu_visc] *
|
|
(ly + MODEL_REAL(1. / 3.) * gy + MODEL_REAL(2.) * sgrhoy)
|
|
+ mesh_info.real_params[AC_zeta] * gy;
|
|
*visc_z = mesh_info.real_params[AC_nu_visc] *
|
|
(lz + MODEL_REAL(1. / 3.) * gz + MODEL_REAL(2.) * sgrhoz)
|
|
+ mesh_info.real_params[AC_zeta] * gz;
|
|
}
|