1a515125bSLeila Ghaffari // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at 2a515125bSLeila Ghaffari // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights 3a515125bSLeila Ghaffari // reserved. See files LICENSE and NOTICE for details. 4a515125bSLeila Ghaffari // 5a515125bSLeila Ghaffari // This file is part of CEED, a collection of benchmarks, miniapps, software 6a515125bSLeila Ghaffari // libraries and APIs for efficient high-order finite element and spectral 7a515125bSLeila Ghaffari // element discretizations for exascale applications. For more information and 8a515125bSLeila Ghaffari // source code availability see http://github.com/ceed. 9a515125bSLeila Ghaffari // 10a515125bSLeila Ghaffari // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, 11a515125bSLeila Ghaffari // a collaborative effort of two U.S. Department of Energy organizations (Office 12a515125bSLeila Ghaffari // of Science and the National Nuclear Security Administration) responsible for 13a515125bSLeila Ghaffari // the planning and preparation of a capable exascale ecosystem, including 14a515125bSLeila Ghaffari // software, applications, hardware, advanced system engineering and early 15a515125bSLeila Ghaffari // testbed platforms, in support of the nation's exascale computing imperative. 16a515125bSLeila Ghaffari 17a515125bSLeila Ghaffari /// @file 18a515125bSLeila Ghaffari /// Density current initial condition and operator for Navier-Stokes example using PETSc 19a515125bSLeila Ghaffari 20a515125bSLeila Ghaffari // Model from: 21a515125bSLeila Ghaffari // Semi-Implicit Formulations of the Navier-Stokes Equations: Application to 22a515125bSLeila Ghaffari // Nonhydrostatic Atmospheric Modeling, Giraldo, Restelli, and Lauter (2010). 23a515125bSLeila Ghaffari 24a515125bSLeila Ghaffari #ifndef densitycurrent_h 25a515125bSLeila Ghaffari #define densitycurrent_h 26a515125bSLeila Ghaffari 27a515125bSLeila Ghaffari #include <math.h> 28a515125bSLeila Ghaffari 29a515125bSLeila Ghaffari #ifndef M_PI 30a515125bSLeila Ghaffari #define M_PI 3.14159265358979323846 31a515125bSLeila Ghaffari #endif 32a515125bSLeila Ghaffari 33a515125bSLeila Ghaffari #ifndef setup_context_struct 34a515125bSLeila Ghaffari #define setup_context_struct 35a515125bSLeila Ghaffari typedef struct SetupContext_ *SetupContext; 36a515125bSLeila Ghaffari struct SetupContext_ { 37a515125bSLeila Ghaffari CeedScalar theta0; 38a515125bSLeila Ghaffari CeedScalar thetaC; 39a515125bSLeila Ghaffari CeedScalar P0; 40a515125bSLeila Ghaffari CeedScalar N; 41a515125bSLeila Ghaffari CeedScalar cv; 42a515125bSLeila Ghaffari CeedScalar cp; 43a515125bSLeila Ghaffari CeedScalar g; 44a515125bSLeila Ghaffari CeedScalar rc; 45a515125bSLeila Ghaffari CeedScalar lx; 46a515125bSLeila Ghaffari CeedScalar ly; 47a515125bSLeila Ghaffari CeedScalar lz; 48a515125bSLeila Ghaffari CeedScalar center[3]; 49a515125bSLeila Ghaffari CeedScalar dc_axis[3]; 50a515125bSLeila Ghaffari CeedScalar wind[3]; 51a515125bSLeila Ghaffari CeedScalar time; 52a515125bSLeila Ghaffari int wind_type; // See WindType: 0=ROTATION, 1=TRANSLATION 53a515125bSLeila Ghaffari int bubble_type; // See BubbleType: 0=SPHERE, 1=CYLINDER 54a515125bSLeila Ghaffari int bubble_continuity_type; // See BubbleContinuityType: 0=SMOOTH, 1=BACK_SHARP 2=THICK 55a515125bSLeila Ghaffari }; 56a515125bSLeila Ghaffari #endif 57a515125bSLeila Ghaffari 58a515125bSLeila Ghaffari #ifndef dc_context_struct 59a515125bSLeila Ghaffari #define dc_context_struct 60a515125bSLeila Ghaffari typedef struct DCContext_ *DCContext; 61a515125bSLeila Ghaffari struct DCContext_ { 62a515125bSLeila Ghaffari CeedScalar lambda; 63a515125bSLeila Ghaffari CeedScalar mu; 64a515125bSLeila Ghaffari CeedScalar k; 65a515125bSLeila Ghaffari CeedScalar cv; 66a515125bSLeila Ghaffari CeedScalar cp; 67a515125bSLeila Ghaffari CeedScalar g; 68a515125bSLeila Ghaffari int stabilization; // See StabilizationType: 0=none, 1=SU, 2=SUPG 69a515125bSLeila Ghaffari }; 70a515125bSLeila Ghaffari #endif 71a515125bSLeila Ghaffari 72a515125bSLeila Ghaffari // ***************************************************************************** 73a515125bSLeila Ghaffari // This function sets the initial conditions and the boundary conditions 74a515125bSLeila Ghaffari // 75a515125bSLeila Ghaffari // These initial conditions are given in terms of potential temperature and 76a515125bSLeila Ghaffari // Exner pressure and then converted to density and total energy. 77a515125bSLeila Ghaffari // Initial momentum density is zero. 78a515125bSLeila Ghaffari // 79a515125bSLeila Ghaffari // Initial Conditions: 80a515125bSLeila Ghaffari // Potential Temperature: 81a515125bSLeila Ghaffari // theta = thetabar + delta_theta 82a515125bSLeila Ghaffari // thetabar = theta0 exp( N**2 z / g ) 83a515125bSLeila Ghaffari // delta_theta = r <= rc : thetaC(1 + cos(pi r/rc)) / 2 84a515125bSLeila Ghaffari // r > rc : 0 85a515125bSLeila Ghaffari // r = sqrt( (x - xc)**2 + (y - yc)**2 + (z - zc)**2 ) 86a515125bSLeila Ghaffari // with (xc,yc,zc) center of domain, rc characteristic radius of thermal bubble 87a515125bSLeila Ghaffari // Exner Pressure: 88a515125bSLeila Ghaffari // Pi = Pibar + deltaPi 89a515125bSLeila Ghaffari // Pibar = 1. + g**2 (exp( - N**2 z / g ) - 1) / (cp theta0 N**2) 90a515125bSLeila Ghaffari // deltaPi = 0 (hydrostatic balance) 91a515125bSLeila Ghaffari // Velocity/Momentum Density: 92a515125bSLeila Ghaffari // Ui = ui = 0 93a515125bSLeila Ghaffari // 94a515125bSLeila Ghaffari // Conversion to Conserved Variables: 95a515125bSLeila Ghaffari // rho = P0 Pi**(cv/Rd) / (Rd theta) 96a515125bSLeila Ghaffari // E = rho (cv T + (u u)/2 + g z) 97a515125bSLeila Ghaffari // 98a515125bSLeila Ghaffari // Boundary Conditions: 99a515125bSLeila Ghaffari // Mass Density: 100a515125bSLeila Ghaffari // 0.0 flux 101a515125bSLeila Ghaffari // Momentum Density: 102a515125bSLeila Ghaffari // 0.0 103a515125bSLeila Ghaffari // Energy Density: 104a515125bSLeila Ghaffari // 0.0 flux 105a515125bSLeila Ghaffari // 106a515125bSLeila Ghaffari // Constants: 107a515125bSLeila Ghaffari // theta0 , Potential temperature constant 108a515125bSLeila Ghaffari // thetaC , Potential temperature perturbation 109a515125bSLeila Ghaffari // P0 , Pressure at the surface 110a515125bSLeila Ghaffari // N , Brunt-Vaisala frequency 111a515125bSLeila Ghaffari // cv , Specific heat, constant volume 112a515125bSLeila Ghaffari // cp , Specific heat, constant pressure 113a515125bSLeila Ghaffari // Rd = cp - cv, Specific heat difference 114a515125bSLeila Ghaffari // g , Gravity 115a515125bSLeila Ghaffari // rc , Characteristic radius of thermal bubble 116a515125bSLeila Ghaffari // center , Location of bubble center 117a515125bSLeila Ghaffari // dc_axis , Axis of density current cylindrical anomaly, or {0,0,0} for spherically symmetric 118a515125bSLeila Ghaffari // ***************************************************************************** 119a515125bSLeila Ghaffari 120a515125bSLeila Ghaffari // ***************************************************************************** 121a515125bSLeila Ghaffari // This helper function provides support for the exact, time-dependent solution 122a515125bSLeila Ghaffari // (currently not implemented) and IC formulation for density current 123a515125bSLeila Ghaffari // ***************************************************************************** 124a515125bSLeila Ghaffari CEED_QFUNCTION_HELPER int Exact_DC(CeedInt dim, CeedScalar time, 125a515125bSLeila Ghaffari const CeedScalar X[], CeedInt Nf, CeedScalar q[], 126a515125bSLeila Ghaffari void *ctx) { 127a515125bSLeila Ghaffari // Context 128a515125bSLeila Ghaffari const SetupContext context = (SetupContext)ctx; 129a515125bSLeila Ghaffari const CeedScalar theta0 = context->theta0; 130a515125bSLeila Ghaffari const CeedScalar thetaC = context->thetaC; 131a515125bSLeila Ghaffari const CeedScalar P0 = context->P0; 132a515125bSLeila Ghaffari const CeedScalar N = context->N; 133a515125bSLeila Ghaffari const CeedScalar cv = context->cv; 134a515125bSLeila Ghaffari const CeedScalar cp = context->cp; 135a515125bSLeila Ghaffari const CeedScalar g = context->g; 136a515125bSLeila Ghaffari const CeedScalar rc = context->rc; 137a515125bSLeila Ghaffari const CeedScalar *center = context->center; 138a515125bSLeila Ghaffari const CeedScalar *dc_axis = context->dc_axis; 139*139613f2SLeila Ghaffari const CeedScalar Rd = cp - cv; 140a515125bSLeila Ghaffari 141a515125bSLeila Ghaffari // Setup 142a515125bSLeila Ghaffari // -- Coordinates 143a515125bSLeila Ghaffari const CeedScalar x = X[0]; 144a515125bSLeila Ghaffari const CeedScalar y = X[1]; 145a515125bSLeila Ghaffari const CeedScalar z = X[2]; 146a515125bSLeila Ghaffari 147a515125bSLeila Ghaffari // -- Potential temperature, density current 148a515125bSLeila Ghaffari CeedScalar rr[3] = {x - center[0], y - center[1], z - center[2]}; 149a515125bSLeila Ghaffari // (I - q q^T) r: distance from dc_axis (or from center if dc_axis is the zero vector) 150a515125bSLeila Ghaffari for (CeedInt i=0; i<3; i++) 151a515125bSLeila Ghaffari rr[i] -= dc_axis[i] * 152a515125bSLeila Ghaffari (dc_axis[0]*rr[0] + dc_axis[1]*rr[1] + dc_axis[2]*rr[2]); 153a515125bSLeila Ghaffari const CeedScalar r = sqrt(rr[0]*rr[0] + rr[1]*rr[1] + rr[2]*rr[2]); 154a515125bSLeila Ghaffari const CeedScalar delta_theta = r <= rc ? thetaC*(1. + cos(M_PI*r/rc))/2. : 0.; 155a515125bSLeila Ghaffari const CeedScalar theta = theta0*exp(N*N*z/g) + delta_theta; 156a515125bSLeila Ghaffari 157a515125bSLeila Ghaffari // -- Exner pressure, hydrostatic balance 158a515125bSLeila Ghaffari const CeedScalar Pi = 1. + g*g*(exp(-N*N*z/g) - 1.) / (cp*theta0*N*N); 159a515125bSLeila Ghaffari // -- Density 160a515125bSLeila Ghaffari 161a515125bSLeila Ghaffari const CeedScalar rho = P0 * pow(Pi, cv/Rd) / (Rd*theta); 162a515125bSLeila Ghaffari 163a515125bSLeila Ghaffari // Initial Conditions 164a515125bSLeila Ghaffari q[0] = rho; 165a515125bSLeila Ghaffari q[1] = 0.0; 166a515125bSLeila Ghaffari q[2] = 0.0; 167a515125bSLeila Ghaffari q[3] = 0.0; 168a515125bSLeila Ghaffari q[4] = rho * (cv*theta*Pi + g*z); 169a515125bSLeila Ghaffari 170a515125bSLeila Ghaffari return 0; 171a515125bSLeila Ghaffari } 172a515125bSLeila Ghaffari 173a515125bSLeila Ghaffari // ***************************************************************************** 174*139613f2SLeila Ghaffari // Helper function for computing flux Jacobian 175*139613f2SLeila Ghaffari // ***************************************************************************** 176*139613f2SLeila Ghaffari CEED_QFUNCTION_HELPER void computeFluxJacobian_NS(CeedScalar dF[3][5][5], 177*139613f2SLeila Ghaffari const CeedScalar rho, const CeedScalar u[3], const CeedScalar E, 178*139613f2SLeila Ghaffari const CeedScalar gamma, const CeedScalar g, CeedScalar z) { 179*139613f2SLeila Ghaffari CeedScalar u_sq = u[0]*u[0] + u[1]*u[1] + u[2]*u[2]; // Velocity square 180*139613f2SLeila Ghaffari for (CeedInt i=0; i<3; i++) { // Jacobian matrices for 3 directions 181*139613f2SLeila Ghaffari for (CeedInt j=0; j<3; j++) { // Rows of each Jacobian matrix 182*139613f2SLeila Ghaffari dF[i][j+1][0] = ((i==j) ? ((gamma-1.)*(u_sq/2. - g*z)) : 0.) - u[i]*u[j]; 183*139613f2SLeila Ghaffari for (CeedInt k=0; k<3; k++) { // Columns of each Jacobian matrix 184*139613f2SLeila Ghaffari dF[i][0][k+1] = ((i==k) ? 1. : 0.); 185*139613f2SLeila Ghaffari dF[i][j+1][k+1] = ((j==k) ? u[i] : 0.) + 186*139613f2SLeila Ghaffari ((i==k) ? u[j] : 0.) - 187*139613f2SLeila Ghaffari ((i==j) ? u[k] : 0.) * (gamma-1.); 188*139613f2SLeila Ghaffari dF[i][4][k+1] = ((i==k) ? (E*gamma/rho - (gamma-1.)*u_sq/2.) : 0.) - 189*139613f2SLeila Ghaffari (gamma-1.)*u[i]*u[k]; 190*139613f2SLeila Ghaffari } 191*139613f2SLeila Ghaffari dF[i][j+1][4] = ((i==j) ? (gamma-1.) : 0.); 192*139613f2SLeila Ghaffari } 193*139613f2SLeila Ghaffari dF[i][4][0] = u[i] * ((gamma-1.)*u_sq - E*gamma/rho); 194*139613f2SLeila Ghaffari dF[i][4][4] = u[i] * gamma; 195*139613f2SLeila Ghaffari } 196*139613f2SLeila Ghaffari } 197*139613f2SLeila Ghaffari 198*139613f2SLeila Ghaffari // ***************************************************************************** 199a515125bSLeila Ghaffari // This QFunction sets the initial conditions for density current 200a515125bSLeila Ghaffari // ***************************************************************************** 201a515125bSLeila Ghaffari CEED_QFUNCTION(ICsDC)(void *ctx, CeedInt Q, 202a515125bSLeila Ghaffari const CeedScalar *const *in, CeedScalar *const *out) { 203a515125bSLeila Ghaffari // Inputs 204a515125bSLeila Ghaffari const CeedScalar (*X)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 205a515125bSLeila Ghaffari 206a515125bSLeila Ghaffari // Outputs 207a515125bSLeila Ghaffari CeedScalar (*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 208a515125bSLeila Ghaffari 209a515125bSLeila Ghaffari CeedPragmaSIMD 210a515125bSLeila Ghaffari // Quadrature Point Loop 211a515125bSLeila Ghaffari for (CeedInt i=0; i<Q; i++) { 212a515125bSLeila Ghaffari const CeedScalar x[] = {X[0][i], X[1][i], X[2][i]}; 213*139613f2SLeila Ghaffari CeedScalar q[5] = {0.}; 214a515125bSLeila Ghaffari 215a515125bSLeila Ghaffari Exact_DC(3, 0., x, 5, q, ctx); 216a515125bSLeila Ghaffari 217a515125bSLeila Ghaffari for (CeedInt j=0; j<5; j++) 218a515125bSLeila Ghaffari q0[j][i] = q[j]; 219a515125bSLeila Ghaffari } // End of Quadrature Point Loop 220a515125bSLeila Ghaffari 221a515125bSLeila Ghaffari // Return 222a515125bSLeila Ghaffari return 0; 223a515125bSLeila Ghaffari } 224a515125bSLeila Ghaffari 225a515125bSLeila Ghaffari // ***************************************************************************** 226a515125bSLeila Ghaffari // This QFunction implements the following formulation of Navier-Stokes with 227a515125bSLeila Ghaffari // explicit time stepping method 228a515125bSLeila Ghaffari // 229a515125bSLeila Ghaffari // This is 3D compressible Navier-Stokes in conservation form with state 230a515125bSLeila Ghaffari // variables of density, momentum density, and total energy density. 231a515125bSLeila Ghaffari // 232a515125bSLeila Ghaffari // State Variables: q = ( rho, U1, U2, U3, E ) 233a515125bSLeila Ghaffari // rho - Mass Density 234a515125bSLeila Ghaffari // Ui - Momentum Density, Ui = rho ui 235a515125bSLeila Ghaffari // E - Total Energy Density, E = rho (cv T + (u u)/2 + g z) 236a515125bSLeila Ghaffari // 237a515125bSLeila Ghaffari // Navier-Stokes Equations: 238a515125bSLeila Ghaffari // drho/dt + div( U ) = 0 239a515125bSLeila Ghaffari // dU/dt + div( rho (u x u) + P I3 ) + rho g khat = div( Fu ) 240a515125bSLeila Ghaffari // dE/dt + div( (E + P) u ) = div( Fe ) 241a515125bSLeila Ghaffari // 242a515125bSLeila Ghaffari // Viscous Stress: 243a515125bSLeila Ghaffari // Fu = mu (grad( u ) + grad( u )^T + lambda div ( u ) I3) 244a515125bSLeila Ghaffari // 245a515125bSLeila Ghaffari // Thermal Stress: 246a515125bSLeila Ghaffari // Fe = u Fu + k grad( T ) 247a515125bSLeila Ghaffari // 248a515125bSLeila Ghaffari // Equation of State: 249a515125bSLeila Ghaffari // P = (gamma - 1) (E - rho (u u) / 2 - rho g z) 250a515125bSLeila Ghaffari // 251a515125bSLeila Ghaffari // Stabilization: 252a515125bSLeila Ghaffari // Tau = diag(TauC, TauM, TauM, TauM, TauE) 253a515125bSLeila Ghaffari // f1 = rho sqrt(ui uj gij) 254a515125bSLeila Ghaffari // gij = dXi/dX * dXi/dX 255a515125bSLeila Ghaffari // TauC = Cc f1 / (8 gii) 256a515125bSLeila Ghaffari // TauM = min( 1 , 1 / f1 ) 257a515125bSLeila Ghaffari // TauE = TauM / (Ce cv) 258a515125bSLeila Ghaffari // 259a515125bSLeila Ghaffari // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 260a515125bSLeila Ghaffari // 261a515125bSLeila Ghaffari // Constants: 262a515125bSLeila Ghaffari // lambda = - 2 / 3, From Stokes hypothesis 263a515125bSLeila Ghaffari // mu , Dynamic viscosity 264a515125bSLeila Ghaffari // k , Thermal conductivity 265a515125bSLeila Ghaffari // cv , Specific heat, constant volume 266a515125bSLeila Ghaffari // cp , Specific heat, constant pressure 267a515125bSLeila Ghaffari // g , Gravity 268a515125bSLeila Ghaffari // gamma = cp / cv, Specific heat ratio 269a515125bSLeila Ghaffari // 270a515125bSLeila Ghaffari // We require the product of the inverse of the Jacobian (dXdx_j,k) and 271a515125bSLeila Ghaffari // its transpose (dXdx_k,j) to properly compute integrals of the form: 272a515125bSLeila Ghaffari // int( gradv gradu ) 273a515125bSLeila Ghaffari // 274a515125bSLeila Ghaffari // ***************************************************************************** 275a515125bSLeila Ghaffari CEED_QFUNCTION(DC)(void *ctx, CeedInt Q, 276a515125bSLeila Ghaffari const CeedScalar *const *in, CeedScalar *const *out) { 277a515125bSLeila Ghaffari // *INDENT-OFF* 278a515125bSLeila Ghaffari // Inputs 279a515125bSLeila Ghaffari const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 280a515125bSLeila Ghaffari (*dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 281a515125bSLeila Ghaffari (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 282a515125bSLeila Ghaffari (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 283a515125bSLeila Ghaffari // Outputs 284a515125bSLeila Ghaffari CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 285a515125bSLeila Ghaffari (*dv)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 286a515125bSLeila Ghaffari // *INDENT-ON* 287a515125bSLeila Ghaffari 288a515125bSLeila Ghaffari // Context 289a515125bSLeila Ghaffari DCContext context = (DCContext)ctx; 290a515125bSLeila Ghaffari const CeedScalar lambda = context->lambda; 291a515125bSLeila Ghaffari const CeedScalar mu = context->mu; 292a515125bSLeila Ghaffari const CeedScalar k = context->k; 293a515125bSLeila Ghaffari const CeedScalar cv = context->cv; 294a515125bSLeila Ghaffari const CeedScalar cp = context->cp; 295a515125bSLeila Ghaffari const CeedScalar g = context->g; 296a515125bSLeila Ghaffari const CeedScalar gamma = cp / cv; 297a515125bSLeila Ghaffari 298a515125bSLeila Ghaffari CeedPragmaSIMD 299a515125bSLeila Ghaffari // Quadrature Point Loop 300a515125bSLeila Ghaffari for (CeedInt i=0; i<Q; i++) { 301a515125bSLeila Ghaffari // *INDENT-OFF* 302a515125bSLeila Ghaffari // Setup 303a515125bSLeila Ghaffari // -- Interp in 304a515125bSLeila Ghaffari const CeedScalar rho = q[0][i]; 305a515125bSLeila Ghaffari const CeedScalar u[3] = {q[1][i] / rho, 306a515125bSLeila Ghaffari q[2][i] / rho, 307a515125bSLeila Ghaffari q[3][i] / rho 308a515125bSLeila Ghaffari }; 309a515125bSLeila Ghaffari const CeedScalar E = q[4][i]; 310a515125bSLeila Ghaffari // -- Grad in 311a515125bSLeila Ghaffari const CeedScalar drho[3] = {dq[0][0][i], 312a515125bSLeila Ghaffari dq[1][0][i], 313a515125bSLeila Ghaffari dq[2][0][i] 314a515125bSLeila Ghaffari }; 315a515125bSLeila Ghaffari const CeedScalar dU[3][3] = {{dq[0][1][i], 316a515125bSLeila Ghaffari dq[1][1][i], 317a515125bSLeila Ghaffari dq[2][1][i]}, 318a515125bSLeila Ghaffari {dq[0][2][i], 319a515125bSLeila Ghaffari dq[1][2][i], 320a515125bSLeila Ghaffari dq[2][2][i]}, 321a515125bSLeila Ghaffari {dq[0][3][i], 322a515125bSLeila Ghaffari dq[1][3][i], 323a515125bSLeila Ghaffari dq[2][3][i]} 324a515125bSLeila Ghaffari }; 325a515125bSLeila Ghaffari const CeedScalar dE[3] = {dq[0][4][i], 326a515125bSLeila Ghaffari dq[1][4][i], 327a515125bSLeila Ghaffari dq[2][4][i] 328a515125bSLeila Ghaffari }; 329a515125bSLeila Ghaffari // -- Interp-to-Interp q_data 330a515125bSLeila Ghaffari const CeedScalar wdetJ = q_data[0][i]; 331a515125bSLeila Ghaffari // -- Interp-to-Grad q_data 332a515125bSLeila Ghaffari // ---- Inverse of change of coordinate matrix: X_i,j 333a515125bSLeila Ghaffari // *INDENT-OFF* 334a515125bSLeila Ghaffari const CeedScalar dXdx[3][3] = {{q_data[1][i], 335a515125bSLeila Ghaffari q_data[2][i], 336a515125bSLeila Ghaffari q_data[3][i]}, 337a515125bSLeila Ghaffari {q_data[4][i], 338a515125bSLeila Ghaffari q_data[5][i], 339a515125bSLeila Ghaffari q_data[6][i]}, 340a515125bSLeila Ghaffari {q_data[7][i], 341a515125bSLeila Ghaffari q_data[8][i], 342a515125bSLeila Ghaffari q_data[9][i]} 343a515125bSLeila Ghaffari }; 344a515125bSLeila Ghaffari // *INDENT-ON* 345a515125bSLeila Ghaffari // -- Grad-to-Grad q_data 346a515125bSLeila Ghaffari // dU/dx 347a515125bSLeila Ghaffari CeedScalar du[3][3] = {{0}}; 348a515125bSLeila Ghaffari CeedScalar drhodx[3] = {0}; 349a515125bSLeila Ghaffari CeedScalar dEdx[3] = {0}; 350a515125bSLeila Ghaffari CeedScalar dUdx[3][3] = {{0}}; 351a515125bSLeila Ghaffari CeedScalar dXdxdXdxT[3][3] = {{0}}; 352a515125bSLeila Ghaffari for (int j=0; j<3; j++) { 353a515125bSLeila Ghaffari for (int k=0; k<3; k++) { 354a515125bSLeila Ghaffari du[j][k] = (dU[j][k] - drho[k]*u[j]) / rho; 355a515125bSLeila Ghaffari drhodx[j] += drho[k] * dXdx[k][j]; 356a515125bSLeila Ghaffari dEdx[j] += dE[k] * dXdx[k][j]; 357a515125bSLeila Ghaffari for (int l=0; l<3; l++) { 358a515125bSLeila Ghaffari dUdx[j][k] += dU[j][l] * dXdx[l][k]; 359a515125bSLeila Ghaffari dXdxdXdxT[j][k] += dXdx[j][l]*dXdx[k][l]; //dXdx_j,k * dXdx_k,j 360a515125bSLeila Ghaffari } 361a515125bSLeila Ghaffari } 362a515125bSLeila Ghaffari } 363a515125bSLeila Ghaffari CeedScalar dudx[3][3] = {{0}}; 364a515125bSLeila Ghaffari for (int j=0; j<3; j++) 365a515125bSLeila Ghaffari for (int k=0; k<3; k++) 366a515125bSLeila Ghaffari for (int l=0; l<3; l++) 367a515125bSLeila Ghaffari dudx[j][k] += du[j][l] * dXdx[l][k]; 368a515125bSLeila Ghaffari // -- grad_T 369a515125bSLeila Ghaffari const CeedScalar grad_T[3] = {(dEdx[0]/rho - E*drhodx[0]/(rho*rho) - /* *NOPAD* */ 370a515125bSLeila Ghaffari (u[0]*dudx[0][0] + u[1]*dudx[1][0] + u[2]*dudx[2][0]))/cv, 371a515125bSLeila Ghaffari (dEdx[1]/rho - E*drhodx[1]/(rho*rho) - /* *NOPAD* */ 372a515125bSLeila Ghaffari (u[0]*dudx[0][1] + u[1]*dudx[1][1] + u[2]*dudx[2][1]))/cv, 373a515125bSLeila Ghaffari (dEdx[2]/rho - E*drhodx[2]/(rho*rho) - /* *NOPAD* */ 374a515125bSLeila Ghaffari (u[0]*dudx[0][2] + u[1]*dudx[1][2] + u[2]*dudx[2][2]) - g)/cv 375a515125bSLeila Ghaffari }; 376a515125bSLeila Ghaffari 377a515125bSLeila Ghaffari // -- Fuvisc 378a515125bSLeila Ghaffari // ---- Symmetric 3x3 matrix 379a515125bSLeila Ghaffari const CeedScalar Fu[6] = {mu*(dudx[0][0] * (2 + lambda) + /* *NOPAD* */ 380a515125bSLeila Ghaffari lambda * (dudx[1][1] + dudx[2][2])), 381a515125bSLeila Ghaffari mu*(dudx[0][1] + dudx[1][0]), /* *NOPAD* */ 382a515125bSLeila Ghaffari mu*(dudx[0][2] + dudx[2][0]), /* *NOPAD* */ 383a515125bSLeila Ghaffari mu*(dudx[1][1] * (2 + lambda) + /* *NOPAD* */ 384a515125bSLeila Ghaffari lambda * (dudx[0][0] + dudx[2][2])), 385a515125bSLeila Ghaffari mu*(dudx[1][2] + dudx[2][1]), /* *NOPAD* */ 386a515125bSLeila Ghaffari mu*(dudx[2][2] * (2 + lambda) + /* *NOPAD* */ 387a515125bSLeila Ghaffari lambda * (dudx[0][0] + dudx[1][1])) 388a515125bSLeila Ghaffari }; 389a515125bSLeila Ghaffari // -- Fevisc 390a515125bSLeila Ghaffari const CeedScalar Fe[3] = {u[0]*Fu[0] + u[1]*Fu[1] + u[2]*Fu[2] + /* *NOPAD* */ 391a515125bSLeila Ghaffari k*grad_T[0], /* *NOPAD* */ 392a515125bSLeila Ghaffari u[0]*Fu[1] + u[1]*Fu[3] + u[2]*Fu[4] + /* *NOPAD* */ 393a515125bSLeila Ghaffari k*grad_T[1], /* *NOPAD* */ 394a515125bSLeila Ghaffari u[0]*Fu[2] + u[1]*Fu[4] + u[2]*Fu[5] + /* *NOPAD* */ 395a515125bSLeila Ghaffari k*grad_T[2] /* *NOPAD* */ 396a515125bSLeila Ghaffari }; 397*139613f2SLeila Ghaffari // Pressure 398*139613f2SLeila Ghaffari const CeedScalar 399*139613f2SLeila Ghaffari E_kinetic = 0.5 * rho * (u[0]*u[0] + u[1]*u[1] + u[2]*u[2]), 400*139613f2SLeila Ghaffari E_potential = rho*g*x[2][i], 401*139613f2SLeila Ghaffari E_internal = E - E_kinetic - E_potential, 402*139613f2SLeila Ghaffari P = E_internal * (gamma - 1.); // P = pressure 403*139613f2SLeila Ghaffari 404a515125bSLeila Ghaffari // jacob_F_conv[3][5][5] = dF(convective)/dq at each direction 405*139613f2SLeila Ghaffari CeedScalar jacob_F_conv[3][5][5] = {{{0.}}}; 406*139613f2SLeila Ghaffari computeFluxJacobian_NS(jacob_F_conv, rho, u, E, gamma, g, x[2][i]); 407a515125bSLeila Ghaffari 408a515125bSLeila Ghaffari // jacob_F_conv_T = jacob_F_conv^T 409a515125bSLeila Ghaffari CeedScalar jacob_F_conv_T[3][5][5]; 410a515125bSLeila Ghaffari for (int j=0; j<3; j++) 411a515125bSLeila Ghaffari for (int k=0; k<5; k++) 412a515125bSLeila Ghaffari for (int l=0; l<5; l++) 413a515125bSLeila Ghaffari jacob_F_conv_T[j][k][l] = jacob_F_conv[j][l][k]; 414a515125bSLeila Ghaffari 415a515125bSLeila Ghaffari // dqdx collects drhodx, dUdx and dEdx in one vector 416a515125bSLeila Ghaffari CeedScalar dqdx[5][3]; 417a515125bSLeila Ghaffari for (int j=0; j<3; j++) { 418a515125bSLeila Ghaffari dqdx[0][j] = drhodx[j]; 419a515125bSLeila Ghaffari dqdx[4][j] = dEdx[j]; 420a515125bSLeila Ghaffari for (int k=0; k<3; k++) 421a515125bSLeila Ghaffari dqdx[k+1][j] = dUdx[k][j]; 422a515125bSLeila Ghaffari } 423a515125bSLeila Ghaffari 424a515125bSLeila Ghaffari // strong_conv = dF/dq * dq/dx (Strong convection) 425a515125bSLeila Ghaffari CeedScalar strong_conv[5] = {0}; 426a515125bSLeila Ghaffari for (int j=0; j<3; j++) 427a515125bSLeila Ghaffari for (int k=0; k<5; k++) 428a515125bSLeila Ghaffari for (int l=0; l<5; l++) 429a515125bSLeila Ghaffari strong_conv[k] += jacob_F_conv[j][k][l] * dqdx[l][j]; 430a515125bSLeila Ghaffari 431a515125bSLeila Ghaffari // Body force 432a515125bSLeila Ghaffari const CeedScalar body_force[5] = {0, 0, 0, -rho*g, 0}; 433a515125bSLeila Ghaffari 434a515125bSLeila Ghaffari // The Physics 435a515125bSLeila Ghaffari // Zero dv so all future terms can safely sum into it 436a515125bSLeila Ghaffari for (int j=0; j<5; j++) 437a515125bSLeila Ghaffari for (int k=0; k<3; k++) 438a515125bSLeila Ghaffari dv[k][j][i] = 0; 439a515125bSLeila Ghaffari 440a515125bSLeila Ghaffari // -- Density 441a515125bSLeila Ghaffari // ---- u rho 442a515125bSLeila Ghaffari for (int j=0; j<3; j++) 443a515125bSLeila Ghaffari dv[j][0][i] += wdetJ*(rho*u[0]*dXdx[j][0] + rho*u[1]*dXdx[j][1] + 444a515125bSLeila Ghaffari rho*u[2]*dXdx[j][2]); 445a515125bSLeila Ghaffari // -- Momentum 446a515125bSLeila Ghaffari // ---- rho (u x u) + P I3 447a515125bSLeila Ghaffari for (int j=0; j<3; j++) 448a515125bSLeila Ghaffari for (int k=0; k<3; k++) 449a515125bSLeila Ghaffari dv[k][j+1][i] += wdetJ*((rho*u[j]*u[0] + (j==0?P:0))*dXdx[k][0] + 450a515125bSLeila Ghaffari (rho*u[j]*u[1] + (j==1?P:0))*dXdx[k][1] + 451a515125bSLeila Ghaffari (rho*u[j]*u[2] + (j==2?P:0))*dXdx[k][2]); 452a515125bSLeila Ghaffari // ---- Fuvisc 453a515125bSLeila Ghaffari const CeedInt Fuviscidx[3][3] = {{0, 1, 2}, {1, 3, 4}, {2, 4, 5}}; // symmetric matrix indices 454a515125bSLeila Ghaffari for (int j=0; j<3; j++) 455a515125bSLeila Ghaffari for (int k=0; k<3; k++) 456a515125bSLeila Ghaffari dv[k][j+1][i] -= wdetJ*(Fu[Fuviscidx[j][0]]*dXdx[k][0] + 457a515125bSLeila Ghaffari Fu[Fuviscidx[j][1]]*dXdx[k][1] + 458a515125bSLeila Ghaffari Fu[Fuviscidx[j][2]]*dXdx[k][2]); 459a515125bSLeila Ghaffari // -- Total Energy Density 460a515125bSLeila Ghaffari // ---- (E + P) u 461a515125bSLeila Ghaffari for (int j=0; j<3; j++) 462a515125bSLeila Ghaffari dv[j][4][i] += wdetJ * (E + P) * (u[0]*dXdx[j][0] + u[1]*dXdx[j][1] + 463a515125bSLeila Ghaffari u[2]*dXdx[j][2]); 464a515125bSLeila Ghaffari // ---- Fevisc 465a515125bSLeila Ghaffari for (int j=0; j<3; j++) 466a515125bSLeila Ghaffari dv[j][4][i] -= wdetJ * (Fe[0]*dXdx[j][0] + Fe[1]*dXdx[j][1] + 467a515125bSLeila Ghaffari Fe[2]*dXdx[j][2]); 468a515125bSLeila Ghaffari // Body Force 469a515125bSLeila Ghaffari for (int j=0; j<5; j++) 470a515125bSLeila Ghaffari v[j][i] = wdetJ * body_force[j]; 471a515125bSLeila Ghaffari 472a515125bSLeila Ghaffari //Stabilization 473a515125bSLeila Ghaffari CeedScalar uX[3]; 474*139613f2SLeila Ghaffari for (int j=0; j<3; j++) 475*139613f2SLeila Ghaffari uX[j] = dXdx[j][0]*u[0] + dXdx[j][1]*u[1] + dXdx[j][2]*u[2]; 476a515125bSLeila Ghaffari const CeedScalar uiujgij = uX[0]*uX[0] + uX[1]*uX[1] + uX[2]*uX[2]; 477a515125bSLeila Ghaffari const CeedScalar Cc = 1.; 478a515125bSLeila Ghaffari const CeedScalar Ce = 1.; 479a515125bSLeila Ghaffari const CeedScalar f1 = rho * sqrt(uiujgij); 480a515125bSLeila Ghaffari const CeedScalar TauC = (Cc * f1) / 481a515125bSLeila Ghaffari (8 * (dXdxdXdxT[0][0] + dXdxdXdxT[1][1] + dXdxdXdxT[2][2])); 482a515125bSLeila Ghaffari const CeedScalar TauM = 1. / (f1>1. ? f1 : 1.); 483a515125bSLeila Ghaffari const CeedScalar TauE = TauM / (Ce * cv); 484a515125bSLeila Ghaffari const CeedScalar Tau[5] = {TauC, TauM, TauM, TauM, TauE}; 485a515125bSLeila Ghaffari CeedScalar stab[5][3]; 486a515125bSLeila Ghaffari switch (context->stabilization) { 487a515125bSLeila Ghaffari case 0: // Galerkin 488a515125bSLeila Ghaffari break; 489a515125bSLeila Ghaffari case 1: // SU 490a515125bSLeila Ghaffari for (int j=0; j<3; j++) 491a515125bSLeila Ghaffari for (int k=0; k<5; k++) 492a515125bSLeila Ghaffari for (int l=0; l<5; l++) 493a515125bSLeila Ghaffari stab[k][j] = jacob_F_conv_T[j][k][l] * Tau[l] * strong_conv[l]; 494a515125bSLeila Ghaffari 495a515125bSLeila Ghaffari for (int j=0; j<5; j++) 496a515125bSLeila Ghaffari for (int k=0; k<3; k++) 497a515125bSLeila Ghaffari dv[k][j][i] -= wdetJ*(stab[j][0] * dXdx[k][0] + 498a515125bSLeila Ghaffari stab[j][1] * dXdx[k][1] + 499a515125bSLeila Ghaffari stab[j][2] * dXdx[k][2]); 500a515125bSLeila Ghaffari break; 501a515125bSLeila Ghaffari case 2: // SUPG is not implemented for explicit scheme 502a515125bSLeila Ghaffari break; 503a515125bSLeila Ghaffari } 504a515125bSLeila Ghaffari 505a515125bSLeila Ghaffari } // End Quadrature Point Loop 506a515125bSLeila Ghaffari 507a515125bSLeila Ghaffari // Return 508a515125bSLeila Ghaffari return 0; 509a515125bSLeila Ghaffari } 510a515125bSLeila Ghaffari 511a515125bSLeila Ghaffari // ***************************************************************************** 512a515125bSLeila Ghaffari // This QFunction implements the Navier-Stokes equations (mentioned above) with 513a515125bSLeila Ghaffari // implicit time stepping method 514a515125bSLeila Ghaffari // 515a515125bSLeila Ghaffari // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 516a515125bSLeila Ghaffari // SUPG = Galerkin + grad(v) . ( Ai^T * Tau * (q_dot + Aj q,j - body force) ) 517a515125bSLeila Ghaffari // (diffussive terms will be added later) 518a515125bSLeila Ghaffari // 519a515125bSLeila Ghaffari // ***************************************************************************** 520a515125bSLeila Ghaffari CEED_QFUNCTION(IFunction_DC)(void *ctx, CeedInt Q, 521a515125bSLeila Ghaffari const CeedScalar *const *in, 522a515125bSLeila Ghaffari CeedScalar *const *out) { 523a515125bSLeila Ghaffari // *INDENT-OFF* 524a515125bSLeila Ghaffari // Inputs 525a515125bSLeila Ghaffari const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 526a515125bSLeila Ghaffari (*dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 527a515125bSLeila Ghaffari (*q_dot)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 528a515125bSLeila Ghaffari (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 529a515125bSLeila Ghaffari (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 530a515125bSLeila Ghaffari // Outputs 531a515125bSLeila Ghaffari CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 532a515125bSLeila Ghaffari (*dv)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 533a515125bSLeila Ghaffari // *INDENT-ON* 534a515125bSLeila Ghaffari // Context 535a515125bSLeila Ghaffari DCContext context = (DCContext)ctx; 536a515125bSLeila Ghaffari const CeedScalar lambda = context->lambda; 537a515125bSLeila Ghaffari const CeedScalar mu = context->mu; 538a515125bSLeila Ghaffari const CeedScalar k = context->k; 539a515125bSLeila Ghaffari const CeedScalar cv = context->cv; 540a515125bSLeila Ghaffari const CeedScalar cp = context->cp; 541a515125bSLeila Ghaffari const CeedScalar g = context->g; 542a515125bSLeila Ghaffari const CeedScalar gamma = cp / cv; 543a515125bSLeila Ghaffari 544a515125bSLeila Ghaffari CeedPragmaSIMD 545a515125bSLeila Ghaffari // Quadrature Point Loop 546a515125bSLeila Ghaffari for (CeedInt i=0; i<Q; i++) { 547a515125bSLeila Ghaffari // Setup 548a515125bSLeila Ghaffari // -- Interp in 549a515125bSLeila Ghaffari const CeedScalar rho = q[0][i]; 550a515125bSLeila Ghaffari const CeedScalar u[3] = {q[1][i] / rho, 551a515125bSLeila Ghaffari q[2][i] / rho, 552a515125bSLeila Ghaffari q[3][i] / rho 553a515125bSLeila Ghaffari }; 554a515125bSLeila Ghaffari const CeedScalar E = q[4][i]; 555a515125bSLeila Ghaffari // -- Grad in 556a515125bSLeila Ghaffari const CeedScalar drho[3] = {dq[0][0][i], 557a515125bSLeila Ghaffari dq[1][0][i], 558a515125bSLeila Ghaffari dq[2][0][i] 559a515125bSLeila Ghaffari }; 560a515125bSLeila Ghaffari // *INDENT-OFF* 561a515125bSLeila Ghaffari const CeedScalar dU[3][3] = {{dq[0][1][i], 562a515125bSLeila Ghaffari dq[1][1][i], 563a515125bSLeila Ghaffari dq[2][1][i]}, 564a515125bSLeila Ghaffari {dq[0][2][i], 565a515125bSLeila Ghaffari dq[1][2][i], 566a515125bSLeila Ghaffari dq[2][2][i]}, 567a515125bSLeila Ghaffari {dq[0][3][i], 568a515125bSLeila Ghaffari dq[1][3][i], 569a515125bSLeila Ghaffari dq[2][3][i]} 570a515125bSLeila Ghaffari }; 571a515125bSLeila Ghaffari // *INDENT-ON* 572a515125bSLeila Ghaffari const CeedScalar dE[3] = {dq[0][4][i], 573a515125bSLeila Ghaffari dq[1][4][i], 574a515125bSLeila Ghaffari dq[2][4][i] 575a515125bSLeila Ghaffari }; 576a515125bSLeila Ghaffari // -- Interp-to-Interp q_data 577a515125bSLeila Ghaffari const CeedScalar wdetJ = q_data[0][i]; 578a515125bSLeila Ghaffari // -- Interp-to-Grad q_data 579a515125bSLeila Ghaffari // ---- Inverse of change of coordinate matrix: X_i,j 580a515125bSLeila Ghaffari // *INDENT-OFF* 581a515125bSLeila Ghaffari const CeedScalar dXdx[3][3] = {{q_data[1][i], 582a515125bSLeila Ghaffari q_data[2][i], 583a515125bSLeila Ghaffari q_data[3][i]}, 584a515125bSLeila Ghaffari {q_data[4][i], 585a515125bSLeila Ghaffari q_data[5][i], 586a515125bSLeila Ghaffari q_data[6][i]}, 587a515125bSLeila Ghaffari {q_data[7][i], 588a515125bSLeila Ghaffari q_data[8][i], 589a515125bSLeila Ghaffari q_data[9][i]} 590a515125bSLeila Ghaffari }; 591a515125bSLeila Ghaffari // *INDENT-ON* 592a515125bSLeila Ghaffari // -- Grad-to-Grad q_data 593a515125bSLeila Ghaffari // dU/dx 594a515125bSLeila Ghaffari CeedScalar du[3][3] = {{0}}; 595a515125bSLeila Ghaffari CeedScalar drhodx[3] = {0}; 596a515125bSLeila Ghaffari CeedScalar dEdx[3] = {0}; 597a515125bSLeila Ghaffari CeedScalar dUdx[3][3] = {{0}}; 598a515125bSLeila Ghaffari CeedScalar dXdxdXdxT[3][3] = {{0}}; 599a515125bSLeila Ghaffari for (int j=0; j<3; j++) { 600a515125bSLeila Ghaffari for (int k=0; k<3; k++) { 601a515125bSLeila Ghaffari du[j][k] = (dU[j][k] - drho[k]*u[j]) / rho; 602a515125bSLeila Ghaffari drhodx[j] += drho[k] * dXdx[k][j]; 603a515125bSLeila Ghaffari dEdx[j] += dE[k] * dXdx[k][j]; 604a515125bSLeila Ghaffari for (int l=0; l<3; l++) { 605a515125bSLeila Ghaffari dUdx[j][k] += dU[j][l] * dXdx[l][k]; 606a515125bSLeila Ghaffari dXdxdXdxT[j][k] += dXdx[j][l]*dXdx[k][l]; //dXdx_j,k * dXdx_k,j 607a515125bSLeila Ghaffari } 608a515125bSLeila Ghaffari } 609a515125bSLeila Ghaffari } 610a515125bSLeila Ghaffari CeedScalar dudx[3][3] = {{0}}; 611a515125bSLeila Ghaffari for (int j=0; j<3; j++) 612a515125bSLeila Ghaffari for (int k=0; k<3; k++) 613a515125bSLeila Ghaffari for (int l=0; l<3; l++) 614a515125bSLeila Ghaffari dudx[j][k] += du[j][l] * dXdx[l][k]; 615a515125bSLeila Ghaffari // -- grad_T 616a515125bSLeila Ghaffari const CeedScalar grad_T[3] = {(dEdx[0]/rho - E*drhodx[0]/(rho*rho) - /* *NOPAD* */ 617a515125bSLeila Ghaffari (u[0]*dudx[0][0] + u[1]*dudx[1][0] + u[2]*dudx[2][0]))/cv, 618a515125bSLeila Ghaffari (dEdx[1]/rho - E*drhodx[1]/(rho*rho) - /* *NOPAD* */ 619a515125bSLeila Ghaffari (u[0]*dudx[0][1] + u[1]*dudx[1][1] + u[2]*dudx[2][1]))/cv, 620a515125bSLeila Ghaffari (dEdx[2]/rho - E*drhodx[2]/(rho*rho) - /* *NOPAD* */ 621a515125bSLeila Ghaffari (u[0]*dudx[0][2] + u[1]*dudx[1][2] + u[2]*dudx[2][2]) - g)/cv 622a515125bSLeila Ghaffari }; 623a515125bSLeila Ghaffari // -- Fuvisc 624a515125bSLeila Ghaffari // ---- Symmetric 3x3 matrix 625a515125bSLeila Ghaffari const CeedScalar Fu[6] = {mu*(dudx[0][0] * (2 + lambda) + /* *NOPAD* */ 626a515125bSLeila Ghaffari lambda * (dudx[1][1] + dudx[2][2])), 627a515125bSLeila Ghaffari mu*(dudx[0][1] + dudx[1][0]), /* *NOPAD* */ 628a515125bSLeila Ghaffari mu*(dudx[0][2] + dudx[2][0]), /* *NOPAD* */ 629a515125bSLeila Ghaffari mu*(dudx[1][1] * (2 + lambda) + /* *NOPAD* */ 630a515125bSLeila Ghaffari lambda * (dudx[0][0] + dudx[2][2])), 631a515125bSLeila Ghaffari mu*(dudx[1][2] + dudx[2][1]), /* *NOPAD* */ 632a515125bSLeila Ghaffari mu*(dudx[2][2] * (2 + lambda) + /* *NOPAD* */ 633a515125bSLeila Ghaffari lambda * (dudx[0][0] + dudx[1][1])) 634a515125bSLeila Ghaffari }; 635a515125bSLeila Ghaffari // -- Fevisc 636a515125bSLeila Ghaffari const CeedScalar Fe[3] = {u[0]*Fu[0] + u[1]*Fu[1] + u[2]*Fu[2] + /* *NOPAD* */ 637a515125bSLeila Ghaffari k*grad_T[0], /* *NOPAD* */ 638a515125bSLeila Ghaffari u[0]*Fu[1] + u[1]*Fu[3] + u[2]*Fu[4] + /* *NOPAD* */ 639a515125bSLeila Ghaffari k*grad_T[1], /* *NOPAD* */ 640a515125bSLeila Ghaffari u[0]*Fu[2] + u[1]*Fu[4] + u[2]*Fu[5] + /* *NOPAD* */ 641a515125bSLeila Ghaffari k*grad_T[2] /* *NOPAD* */ 642a515125bSLeila Ghaffari }; 643*139613f2SLeila Ghaffari // Pressure 644*139613f2SLeila Ghaffari const CeedScalar 645*139613f2SLeila Ghaffari E_kinetic = 0.5 * rho * (u[0]*u[0] + u[1]*u[1] + u[2]*u[2]), 646*139613f2SLeila Ghaffari E_potential = rho*g*x[2][i], 647*139613f2SLeila Ghaffari E_internal = E - E_kinetic - E_potential, 648*139613f2SLeila Ghaffari P = E_internal * (gamma - 1.); // P = pressure 649a515125bSLeila Ghaffari 650a515125bSLeila Ghaffari // jacob_F_conv[3][5][5] = dF(convective)/dq at each direction 651*139613f2SLeila Ghaffari CeedScalar jacob_F_conv[3][5][5] = {{{0.}}}; 652*139613f2SLeila Ghaffari computeFluxJacobian_NS(jacob_F_conv, rho, u, E, gamma, g, x[2][i]); 653a515125bSLeila Ghaffari 654a515125bSLeila Ghaffari // jacob_F_conv_T = jacob_F_conv^T 655a515125bSLeila Ghaffari CeedScalar jacob_F_conv_T[3][5][5]; 656a515125bSLeila Ghaffari for (int j=0; j<3; j++) 657a515125bSLeila Ghaffari for (int k=0; k<5; k++) 658a515125bSLeila Ghaffari for (int l=0; l<5; l++) 659a515125bSLeila Ghaffari jacob_F_conv_T[j][k][l] = jacob_F_conv[j][l][k]; 660a515125bSLeila Ghaffari // dqdx collects drhodx, dUdx and dEdx in one vector 661a515125bSLeila Ghaffari CeedScalar dqdx[5][3]; 662a515125bSLeila Ghaffari for (int j=0; j<3; j++) { 663a515125bSLeila Ghaffari dqdx[0][j] = drhodx[j]; 664a515125bSLeila Ghaffari dqdx[4][j] = dEdx[j]; 665a515125bSLeila Ghaffari for (int k=0; k<3; k++) 666a515125bSLeila Ghaffari dqdx[k+1][j] = dUdx[k][j]; 667a515125bSLeila Ghaffari } 668a515125bSLeila Ghaffari // strong_conv = dF/dq * dq/dx (Strong convection) 669a515125bSLeila Ghaffari CeedScalar strong_conv[5] = {0}; 670a515125bSLeila Ghaffari for (int j=0; j<3; j++) 671a515125bSLeila Ghaffari for (int k=0; k<5; k++) 672a515125bSLeila Ghaffari for (int l=0; l<5; l++) 673a515125bSLeila Ghaffari strong_conv[k] += jacob_F_conv[j][k][l] * dqdx[l][j]; 674a515125bSLeila Ghaffari 675a515125bSLeila Ghaffari // Body force 676a515125bSLeila Ghaffari const CeedScalar body_force[5] = {0, 0, 0, -rho*g, 0}; 677a515125bSLeila Ghaffari 678a515125bSLeila Ghaffari // Strong residual 679a515125bSLeila Ghaffari CeedScalar strong_res[5]; 680a515125bSLeila Ghaffari for (int j=0; j<5; j++) 681a515125bSLeila Ghaffari strong_res[j] = q_dot[j][i] + strong_conv[j] - body_force[j]; 682a515125bSLeila Ghaffari 683a515125bSLeila Ghaffari // The Physics 684a515125bSLeila Ghaffari //-----mass matrix 685a515125bSLeila Ghaffari for (int j=0; j<5; j++) 686a515125bSLeila Ghaffari v[j][i] = wdetJ*q_dot[j][i]; 687a515125bSLeila Ghaffari 688a515125bSLeila Ghaffari // Zero dv so all future terms can safely sum into it 689a515125bSLeila Ghaffari for (int j=0; j<5; j++) 690a515125bSLeila Ghaffari for (int k=0; k<3; k++) 691a515125bSLeila Ghaffari dv[k][j][i] = 0; 692a515125bSLeila Ghaffari 693a515125bSLeila Ghaffari // -- Density 694a515125bSLeila Ghaffari // ---- u rho 695a515125bSLeila Ghaffari for (int j=0; j<3; j++) 696a515125bSLeila Ghaffari dv[j][0][i] -= wdetJ*(rho*u[0]*dXdx[j][0] + rho*u[1]*dXdx[j][1] + 697a515125bSLeila Ghaffari rho*u[2]*dXdx[j][2]); 698a515125bSLeila Ghaffari // -- Momentum 699a515125bSLeila Ghaffari // ---- rho (u x u) + P I3 700a515125bSLeila Ghaffari for (int j=0; j<3; j++) 701a515125bSLeila Ghaffari for (int k=0; k<3; k++) 702a515125bSLeila Ghaffari dv[k][j+1][i] -= wdetJ*((rho*u[j]*u[0] + (j==0?P:0))*dXdx[k][0] + 703a515125bSLeila Ghaffari (rho*u[j]*u[1] + (j==1?P:0))*dXdx[k][1] + 704a515125bSLeila Ghaffari (rho*u[j]*u[2] + (j==2?P:0))*dXdx[k][2]); 705a515125bSLeila Ghaffari // ---- Fuvisc 706a515125bSLeila Ghaffari const CeedInt Fuviscidx[3][3] = {{0, 1, 2}, {1, 3, 4}, {2, 4, 5}}; // symmetric matrix indices 707a515125bSLeila Ghaffari for (int j=0; j<3; j++) 708a515125bSLeila Ghaffari for (int k=0; k<3; k++) 709a515125bSLeila Ghaffari dv[k][j+1][i] += wdetJ*(Fu[Fuviscidx[j][0]]*dXdx[k][0] + 710a515125bSLeila Ghaffari Fu[Fuviscidx[j][1]]*dXdx[k][1] + 711a515125bSLeila Ghaffari Fu[Fuviscidx[j][2]]*dXdx[k][2]); 712a515125bSLeila Ghaffari // -- Total Energy Density 713a515125bSLeila Ghaffari // ---- (E + P) u 714a515125bSLeila Ghaffari for (int j=0; j<3; j++) 715a515125bSLeila Ghaffari dv[j][4][i] -= wdetJ * (E + P) * (u[0]*dXdx[j][0] + u[1]*dXdx[j][1] + 716a515125bSLeila Ghaffari u[2]*dXdx[j][2]); 717a515125bSLeila Ghaffari // ---- Fevisc 718a515125bSLeila Ghaffari for (int j=0; j<3; j++) 719a515125bSLeila Ghaffari dv[j][4][i] += wdetJ * (Fe[0]*dXdx[j][0] + Fe[1]*dXdx[j][1] + 720a515125bSLeila Ghaffari Fe[2]*dXdx[j][2]); 721a515125bSLeila Ghaffari // Body Force 722a515125bSLeila Ghaffari for (int j=0; j<5; j++) 723a515125bSLeila Ghaffari v[j][i] -= wdetJ*body_force[j]; 724a515125bSLeila Ghaffari 725a515125bSLeila Ghaffari //Stabilization 726a515125bSLeila Ghaffari CeedScalar uX[3]; 727*139613f2SLeila Ghaffari for (int j=0; j<3; j++) 728*139613f2SLeila Ghaffari uX[j] = dXdx[j][0]*u[0] + dXdx[j][1]*u[1] + dXdx[j][2]*u[2]; 729a515125bSLeila Ghaffari const CeedScalar uiujgij = uX[0]*uX[0] + uX[1]*uX[1] + uX[2]*uX[2]; 730a515125bSLeila Ghaffari const CeedScalar Cc = 1.; 731a515125bSLeila Ghaffari const CeedScalar Ce = 1.; 732a515125bSLeila Ghaffari const CeedScalar f1 = rho * sqrt(uiujgij); 733a515125bSLeila Ghaffari const CeedScalar TauC = (Cc * f1) / 734a515125bSLeila Ghaffari (8 * (dXdxdXdxT[0][0] + dXdxdXdxT[1][1] + dXdxdXdxT[2][2])); 735a515125bSLeila Ghaffari const CeedScalar TauM = 1. / (f1>1. ? f1 : 1.); 736a515125bSLeila Ghaffari const CeedScalar TauE = TauM / (Ce * cv); 737a515125bSLeila Ghaffari const CeedScalar Tau[5] = {TauC, TauM, TauM, TauM, TauE}; 738*139613f2SLeila Ghaffari 739a515125bSLeila Ghaffari CeedScalar stab[5][3]; 740a515125bSLeila Ghaffari switch (context->stabilization) { 741a515125bSLeila Ghaffari case 0: // Galerkin 742a515125bSLeila Ghaffari break; 743a515125bSLeila Ghaffari case 1: // SU 744a515125bSLeila Ghaffari for (int j=0; j<3; j++) 745a515125bSLeila Ghaffari for (int k=0; k<5; k++) 746a515125bSLeila Ghaffari for (int l=0; l<5; l++) 747a515125bSLeila Ghaffari stab[k][j] = jacob_F_conv_T[j][k][l] * Tau[l] * strong_conv[l]; 748a515125bSLeila Ghaffari 749a515125bSLeila Ghaffari for (int j=0; j<5; j++) 750a515125bSLeila Ghaffari for (int k=0; k<3; k++) 751a515125bSLeila Ghaffari dv[k][j][i] += wdetJ*(stab[j][0] * dXdx[k][0] + 752a515125bSLeila Ghaffari stab[j][1] * dXdx[k][1] + 753a515125bSLeila Ghaffari stab[j][2] * dXdx[k][2]); 754a515125bSLeila Ghaffari break; 755a515125bSLeila Ghaffari case 2: // SUPG 756a515125bSLeila Ghaffari for (int j=0; j<3; j++) 757a515125bSLeila Ghaffari for (int k=0; k<5; k++) 758a515125bSLeila Ghaffari for (int l=0; l<5; l++) 759a515125bSLeila Ghaffari stab[k][j] = jacob_F_conv_T[j][k][l] * Tau[l] * strong_res[l]; 760a515125bSLeila Ghaffari 761a515125bSLeila Ghaffari for (int j=0; j<5; j++) 762a515125bSLeila Ghaffari for (int k=0; k<3; k++) 763a515125bSLeila Ghaffari dv[k][j][i] += wdetJ*(stab[j][0] * dXdx[k][0] + 764a515125bSLeila Ghaffari stab[j][1] * dXdx[k][1] + 765a515125bSLeila Ghaffari stab[j][2] * dXdx[k][2]); 766a515125bSLeila Ghaffari break; 767a515125bSLeila Ghaffari } 768a515125bSLeila Ghaffari 769a515125bSLeila Ghaffari } // End Quadrature Point Loop 770a515125bSLeila Ghaffari 771a515125bSLeila Ghaffari // Return 772a515125bSLeila Ghaffari return 0; 773a515125bSLeila Ghaffari } 774a515125bSLeila Ghaffari // ***************************************************************************** 775a515125bSLeila Ghaffari 776a515125bSLeila Ghaffari #endif // densitycurrent_h 777