gks2d-str/code/gks_basic.cpp

521 lines
14 KiB
C++
Raw Normal View History

2022-12-02 16:15:01 +08:00
//this libarary includes some basic functions for gks
#include"gks_basic.h"
#define S 110.4
//artifical viscosity for euler problem
double c1_euler = -1.0; //initialization
double c2_euler = -1.0; //initialization
bool is_Prandtl_fix = false; //initialization
double Pr = 1.0; //initialization
// to prepare the basic element for moment calculation
MMDF1d::MMDF1d() { u = 1.0; lambda = 1.0; };
MMDF1d::MMDF1d(double u_in, double lambda_in)
{
u = u_in;
lambda = lambda_in;
calcualte_MMDF1d();
}
void MMDF1d::calcualte_MMDF1d()
{
uwhole[0] = 1;
uwhole[1] = u;
uplus[0] = 0.5 * Alpha(lambda, -u);
uminus[0] = 0.5 * Alpha(lambda, u);
uplus[1] = u * uplus[0] + 0.5 * Beta(lambda, u);
uminus[1] = u * uminus[0] - 0.5 * Beta(lambda, u);
for (int i = 2; i <= 9; i++)
{
uwhole[i] = u * uwhole[i - 1] + 0.5 * (i - 1) / lambda * uwhole[i - 2];
}
for (int i = 2; i <= 9; i++)
{
uplus[i] = u * uplus[i - 1] + 0.5 * (i - 1) / lambda * uplus[i - 2];
uminus[i] = u * uminus[i - 1] + 0.5 * (i - 1) / lambda * uminus[i - 2];
}
xi2 = 0.5 * K / lambda;
xi4 = 0.25 * (K * K + 2 * K) / (lambda * lambda);
//xi6?? how to calculate
xi6 = 0.5 * (K + 4) / lambda * xi4;
for (int i = 0; i < 10; i++)
{
for (int k = 0; k < 4; k++)
{
if ((i + 2 * k) <= 9)
{
if (k == 0)
{
upxi[i][k] = uplus[i];
unxi[i][k] = uminus[i];
}
if (k == 1)
{
upxi[i][k] = uplus[i] * xi2;
unxi[i][k] = uminus[i] * xi2;
}
if (k == 2)
{
upxi[i][k] = uplus[i] * xi4;
unxi[i][k] = uminus[i] * xi4;
}
if (k == 3)
{
upxi[i][k] = uplus[i] * xi6;
unxi[i][k] = uminus[i] * xi6;
}
}
}
}
for (int i = 0; i < 10; i++)
{
for (int k = 0; k < 4; k++)
{
if ((i + 2 * k) <= 9)
{
if (k == 0)
{
uxi[i][k] = uwhole[i];
}
if (k == 1)
{
uxi[i][k] = uwhole[i] * xi2;
}
if (k == 2)
{
uxi[i][k] = uwhole[i] * xi4;
}
if (k == 3)
{
uxi[i][k] = uwhole[i] * xi6;
}
}
}
}
}
//a general G function
void G(int no_u, int no_xi, double* psi, double a[3], MMDF1d m)
{
psi[0] = a[0] * m.uxi[no_u][no_xi] + a[1] * m.uxi[no_u + 1][no_xi] + a[2] * 0.5 * (m.uxi[no_u + 2][no_xi] + m.uxi[no_u][no_xi + 1]);
psi[1] = a[0] * m.uxi[no_u + 1][no_xi] + a[1] * m.uxi[no_u + 2][no_xi] + a[2] * 0.5 * (m.uxi[no_u + 3][no_xi] + m.uxi[no_u + 1][no_xi + 1]);
psi[2] = 0.5 * (a[0] * (m.uxi[no_u + 2][no_xi] + m.uxi[no_u][no_xi + 1]) +
a[1] * (m.uxi[no_u + 3][no_xi] + m.uxi[no_u + 1][no_xi + 1]) +
a[2] * 0.5 * (m.uxi[no_u + 4][no_xi] + m.uxi[no_u][no_xi + 2] + 2 * m.uxi[no_u + 2][no_xi + 1]));
}
void GL(int no_u, int no_xi, double* psi, double a[3], MMDF1d m)
{
psi[0] = a[0] * m.upxi[no_u][no_xi] + a[1] * m.upxi[no_u + 1][no_xi] + a[2] * 0.5 * (m.upxi[no_u + 2][no_xi] + m.upxi[no_u][no_xi + 1]);
psi[1] = a[0] * m.upxi[no_u + 1][no_xi] + a[1] * m.upxi[no_u + 2][no_xi] + a[2] * 0.5 * (m.upxi[no_u + 3][no_xi] + m.upxi[no_u + 1][no_xi + 1]);
psi[2] = 0.5 * (a[0] * (m.upxi[no_u + 2][no_xi] + m.upxi[no_u][no_xi + 1]) +
a[1] * (m.upxi[no_u + 3][no_xi] + m.upxi[no_u + 1][no_xi + 1]) +
a[2] * 0.5 * (m.upxi[no_u + 4][no_xi] + m.upxi[no_u][no_xi + 2] + 2 * m.upxi[no_u + 2][no_xi + 1]));
}
void GR(int no_u, int no_xi, double* psi, double a[3], MMDF1d m)
{
psi[0] = a[0] * m.unxi[no_u][no_xi] + a[1] * m.unxi[no_u + 1][no_xi] + a[2] * 0.5 * (m.unxi[no_u + 2][no_xi] + m.unxi[no_u][no_xi + 1]);
psi[1] = a[0] * m.unxi[no_u + 1][no_xi] + a[1] * m.unxi[no_u + 2][no_xi] + a[2] * 0.5 * (m.unxi[no_u + 3][no_xi] + m.unxi[no_u + 1][no_xi + 1]);
psi[2] = 0.5 * (a[0] * (m.unxi[no_u + 2][no_xi] + m.unxi[no_u][no_xi + 1]) +
a[1] * (m.unxi[no_u + 3][no_xi] + m.unxi[no_u + 1][no_xi + 1]) +
a[2] * 0.5 * (m.unxi[no_u + 4][no_xi] + m.unxi[no_u][no_xi + 2] + 2 * m.unxi[no_u + 2][no_xi + 1]));
}
//moments of the maxwellian distribution function
MMDF::MMDF() { u = 1.0; v = 1.0; lambda = 1.0; };
MMDF::MMDF(double u_in, double v_in, double lambda_in)
{
u = u_in;
v = v_in;
lambda = lambda_in;
calcualte_MMDF();
}
void MMDF::calcualte_MMDF()
{
//the moment of u in whole domain
uwhole[0] = 1;
uwhole[1] = u;
//the moment of u in half domain (>0 && <0)
uplus[0] = 0.5 * Alpha(lambda, -u);
uminus[0] = 1.0 - uplus[0];
uplus[1] = u * uplus[0] + 0.5 * Beta(lambda, u);
uminus[1] = u - uplus[1];
double overlambda = 1.0 / lambda;
for (int i = 2; i <= 6; i++)
{
uwhole[i] = u * uwhole[i - 1] + 0.5 * (i - 1) * overlambda * uwhole[i - 2];
}
for (int i = 2; i <= 6; i++)
{
uplus[i] = u * uplus[i - 1] + 0.5 * (i - 1) * overlambda * uplus[i - 2];
uminus[i] = uwhole[i] - uplus[i];
}
//the moment of v in whole domain
//the moment of v in half domain is useless
vwhole[0] = 1;
vwhole[1] = v;
for (int i = 2; i <= 6; i++)
{
vwhole[i] = v * vwhole[i - 1] + 0.5 * (i - 1) * overlambda * vwhole[i - 2];
}
//the moment of xi (kesi)
xi2 = 0.5 * K * overlambda;
xi4 = 0.25 * (K * K + 2 * K) * overlambda * overlambda;
//xi6?? how to calculate
//xi6 = 0.5*(K + 4) / lambda*xi4; // no use
//get other variables by the above mement variables
//i, j, k, means i power of u, j power of v, and 2k power of xi
for (int i = 0; i < 7; i++)
{
for (int j = 0; j < 7; j++)
{
for (int k = 0; k < 3; k++)
{
if ((i + j + 2 * k) <= 6)
{
if (k == 0)
{
// u, half domain > 0; v, whole domain; xi, equals 0
upvxi[i][j][k] = uplus[i] * vwhole[j];
// u, half domain < 0; v, whole domain; xi, equals 0
unvxi[i][j][k] = uminus[i] * vwhole[j];
// u, whole domain ; v, whole domain; xi, equals 0
uvxi[i][j][k] = upvxi[i][j][k] + unvxi[i][j][k];
// = (uplus[i] + uminus[i]) * vwhole[j] = uwhole[i] * vwhole[j]
}
if (k == 1)
{
// u, half domain > 0; v, whole domain; xi, equals 2
upvxi[i][j][k] = uplus[i] * vwhole[j] * xi2;
// u, half domain < 0; v, whole domain; xi, equals 2
unvxi[i][j][k] = uminus[i] * vwhole[j] * xi2;
// u, whole domain ; v, whole domain; xi, equals 2
uvxi[i][j][k] = upvxi[i][j][k] + unvxi[i][j][k];
}
if (k == 2)
{
// u, half domain > 0; v, whole domain; xi, equals 4
upvxi[i][j][k] = uplus[i] * vwhole[j] * xi4;
// u, half domain < 0; v, whole domain; xi, equals 4
unvxi[i][j][k] = uminus[i] * vwhole[j] * xi4;
// u, whole domain ; v, whole domain; xi, equals 4
uvxi[i][j][k] = upvxi[i][j][k] + unvxi[i][j][k];
}
}
}
}
}
}
MMDF1st::MMDF1st() { u = 1.0; v = 1.0; lambda = 1.0; };
MMDF1st::MMDF1st(double u_in, double v_in, double lambda_in)
{
u = u_in;
v = v_in;
lambda = lambda_in;
calcualte_MMDF1st();
}
void MMDF1st::calcualte_MMDF1st()
{
uwhole[0] = 1.0;
uwhole[1] = u;
//return erfc(sqrt(lambda)*u);
//return exp(-lambda*u*u) / sqrt(pi*lambda);
uminus[0] = 0.5 * Alpha(lambda, u);
uplus[0] = 1.0 - uminus[0];
double beta = Beta(lambda, u);
//uplus[1] = u*uplus[0] + 0.5*Beta(lambda, u);
//uminus[1] = u*uminus[0] - 0.5*Beta(lambda, u);
uplus[1] = u * uplus[0] + 0.5 * beta;
uminus[1] = u * uminus[0] - 0.5 * beta;
double overlambda = 1.0 / lambda;
for (int i = 2; i <= 3; i++)
{
uwhole[i] = u * uwhole[i - 1] + 0.5 * (i - 1) * overlambda * uwhole[i - 2];
}
for (int i = 2; i <= 3; i++)
{
uplus[i] = u * uplus[i - 1] + 0.5 * (i - 1) * overlambda * uplus[i - 2];
uminus[i] = uwhole[i] - uplus[i];
}
vwhole[0] = 1;
vwhole[1] = v;
for (int i = 2; i <= 2; i++)
{
vwhole[i] = v * vwhole[i - 1] + 0.5 * (i - 1) * overlambda * vwhole[i - 2];
}
xi2 = 0.5 * K * overlambda;
}
void Collision(double* w0, double left, double right, MMDF& m2, MMDF& m3)
{
// get the equilibrium variables by collision
w0[0] = left * m2.uplus[0] + right * m3.uminus[0];
w0[1] = left * m2.uplus[1] + right * m3.uminus[1];
w0[2] = left * m2.vwhole[1] * m2.uplus[0] + right * m3.vwhole[1] * m3.uminus[0];
w0[3] = 0.5 * left * (m2.uplus[2] + m2.uplus[0] * m2.vwhole[2] + m2.uplus[0] * m2.xi2) +
0.5 * right * (m3.uminus[2] + m3.uminus[0] * m3.vwhole[2] + m3.uminus[0] * m3.xi2);
}
void Collision(double* w0, double left, double right, MMDF1st& m2, MMDF1st& m3)
{
w0[0] = left * m2.uplus[0] + right * m3.uminus[0];
w0[1] = left * m2.uplus[1] + right * m3.uminus[1];
w0[2] = left * m2.vwhole[1] * m2.uplus[0] + right * m3.vwhole[1] * m3.uminus[0];
w0[3] = 0.5 * left * (m2.uplus[2] + m2.uplus[0] * m2.vwhole[2] + m2.uplus[0] * m2.xi2) +
0.5 * right * (m3.uminus[2] + m3.uminus[0] * m3.vwhole[2] + m3.uminus[0] * m3.xi2);
}
void A(double* a, double der[4], double prim[4])
{
//Note: solve the a coefficient (slope information), equivalent to solving the matrix to get a
//input: der[4], the gradient of conservative variables, density, momentumX, momentumY, energy, partialW/patialX
//input: prim[4], the primary variables (density, u, v, lambda) at one point or one interface
//output: a, solve the results
double R4, R3, R2;
double overden = 1.0 / prim[0];
//double overlambda = 1.0 / prim[3];
R4 = der[3] * overden - 0.5 * (prim[1] * prim[1] + prim[2] * prim[2] + 0.5 * (K + 2) / prim[3]) * der[0] * overden;
R3 = (der[2] - prim[2] * der[0]) * overden;
R2 = (der[1] - prim[1] * der[0]) * overden;
a[3] = (4.0 / (K + 2)) * prim[3] * prim[3] * (2 * R4 - 2 * prim[1] * R2 - 2 * prim[2] * R3);
a[2] = 2 * prim[3] * R3 - prim[2] * a[3];
a[1] = 2 * prim[3] * R2 - prim[1] * a[3];
a[0] = der[0] * overden - prim[1] * a[1] - prim[2] * a[2] - 0.5 * a[3] * (prim[1] * prim[1] + prim[2] * prim[2] + 0.5 * (K + 2) / prim[3]);
//R4 = der[3] / prim[0] - 0.5*(prim[1] * prim[1] + prim[2] * prim[2] + 0.5*(K + 2) / prim[3])*der[0] / prim[0];
//R3 = (der[2] - prim[2]*der[0]) / prim[0];
//R2 = (der[1] - prim[1]*der[0]) / prim[0];
//a[3] = 4.0 * prim[3]*prim[3] / (K + 2)*(2.0 * R4 - 2.0 * prim[1]*R2 - 2.0 * prim[2]*R3);
//a[2] = 2.0 * prim[3]*R3 - prim[2]*a[3];
//a[1] = 2.0 * prim[3]*R2 - prim[1]*a[3];
//a[0] = der[0] / prim[0] - prim[1]*a[1] - prim[2]*a[2] - 0.5*a[3] * (prim[1]*prim[1] + prim[2]*prim[2] + 0.5*(K + 2) / prim[3]);
}
double Get_Tau_NS(double density0, double lambda0)
{
if (tau_type == Euler)
{
return 0.0;
}
else if (tau_type == NS)
{
if (Mu > 0.0)
{
//cout << "here" << endl;
return 2.0 * Mu * lambda0 / density0;
}
else if (Nu > 0.0)
{
return 2 * Nu * lambda0;
}
else
{
return 0.0;
}
}
else if (tau_type == Sutherland)
{
return TauNS_Sutherland(density0, lambda0);
}
else
{
return TauNS_power_law(density0, lambda0);
}
}
double Get_Tau(double density_left, double density_right, double density0, double lambda_left, double lambda_right, double lambda0, double dt)
{
if (tau_type == Euler)
{
if (c1_euler <= 0 && c2_euler <= 0)
{
return 0.0;
}
else
{
double C = c2_euler * abs(density_left / lambda_left - density_right / lambda_right) / abs(density_left / lambda_left + density_right / lambda_right);
//C+= c2_euler * abs(density_left - density_right) / abs(density_left + density_right);
//if (C < 10)
//{
return c1_euler * dt + dt * C;
//}
//else
//{
// return c1_euler*dt + 10*dt;
// //return c1_euler*dt + dt*C;
//}
}
}
else if (tau_type == NS)
{
double tau_n = c2_euler * abs(density_left / lambda_left - density_right / lambda_right) / abs(density_left / lambda_left + density_right / lambda_right) * dt;
if (tau_n != tau_n)
{
tau_n = 0.0;
}
if ((Mu > 0.0 && Nu > 0.0) || (Mu < 0.0 && Nu < 0.0))
{
return 0.0;
}
else
{
if (Mu > 0.0)
{
return tau_n + 2.0 * Mu * lambda0 / density0;
}
else if (Nu > 0.0)
{
return tau_n + 2 * Nu * lambda0;
}
else
{
return 0.0;
}
}
}
else if (tau_type == Sutherland)
{
double tau_n = c2_euler * abs(density_left / lambda_left - density_right / lambda_right) / abs(density_left / lambda_left + density_right / lambda_right) * dt;
if (tau_n != tau_n)
{
tau_n = 0.0;
}
if ((Mu > 0.0 && Nu > 0.0) || (Mu < 0.0 && Nu < 0.0))
{
return 0.0;
}
else
{
if (Mu > 0.0)
{
return tau_n + TauNS_Sutherland(density0, lambda0);
}
else if (Nu > 0.0)
{
return tau_n + 2 * Nu * lambda0;
}
else
{
return 0.0;
}
}
}
else if (tau_type == Power_law)
{
double tau_n = c2_euler * abs(density_left / lambda_left - density_right / lambda_right) / abs(density_left / lambda_left + density_right / lambda_right) * dt;
if (tau_n != tau_n)
{
tau_n = 0.0;
}
if ((Mu > 0.0 && Nu > 0.0) || (Mu < 0.0 && Nu < 0.0))
{
return 0.0;
}
else
{
if (Mu > 0.0)
{
return tau_n + TauNS_power_law(density0, lambda0);
}
else if (Nu > 0.0)
{
return tau_n + 2 * Nu * lambda0;
}
else
{
return 0.0;
}
}
}
else
{
return 0.0;
}
}
double TauNS_Sutherland(double density0, double lambda0)
{
double T0 = 1.0 / 2.0 / (lambda0 * R_gas);
double mu = Mu * pow(T0 / T_inf, 1.5) * (T_inf + S) / (T0 + S);
return 2.0 * mu * lambda0 / density0;
}
double TauNS_power_law(double density0, double lambda0)
{
double T0 = 1.0 / 2.0 / (lambda0 * R_gas);
double mu = Mu * pow(T0 / T_inf, 0.76);
return 2.0 * mu * lambda0 / density0;
}
//计算λ
double Lambda(double density, double u, double densityE)
{
return (K + 1.0) * 0.25 * (density / (densityE - 0.5 * density * (u * u)));
}
double Lambda(double density, double u, double v, double densityE)
{
return (K + 2.0) * 0.25 * (density / (densityE - 0.5 * density * (u * u + v * v)));
}
void Convar_to_ULambda_1d(double* primvar, double convar[3])
{
primvar[0] = convar[0];
primvar[1] = U(convar[0], convar[1]);
primvar[2] = Lambda(convar[0], primvar[1], convar[2]);
}
//计算α,α=erfc±√λ*U
double Alpha(double lambda, double u)
{
return erfc(sqrt(lambda) * u);
//return erfcmy(sqrt(lambda)*u);
}
//计算β,β=e^(-λ*U^2)/(√πλ)
double Beta(double lambda, double u)
{
double pi = 3.14159265358979323846;
return exp(-lambda * u * u) / sqrt(pi * lambda);
}
//solution of matrix equation b=Ma 1D
void Microslope(double* a, double der[3], double prim[3])
{
double R4, R2;
R4 = der[2] / prim[0] - 0.5 * (prim[1] * prim[1] + 0.5 * (K + 1) / prim[2]) * der[0] / prim[0];
R2 = (der[1] - prim[1] * der[0]) / prim[0];
a[2] = 4 * prim[2] * prim[2] / (K + 1) * (2 * R4 - 2 * prim[1] * R2);
a[1] = 2 * prim[2] * R2 - prim[1] * a[2];
a[0] = der[0] / prim[0] - prim[1] * a[1] - 0.5 * a[2] * (prim[1] * prim[1] + 0.5 * (K + 1) / prim[2]);
}
void Convar_to_ULambda_2d(double* primvar, double convar[4]) //density, U, V, lambda
{
primvar[0] = convar[0];
primvar[1] = U(convar[0], convar[1]);
primvar[2] = V(convar[0], convar[2]);
//here primvar[3] refers lambda
primvar[3] = Lambda(convar[0], primvar[1], primvar[2], convar[3]);
}