188626eedSJames Wright // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors. 288626eedSJames Wright // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 388626eedSJames Wright // 488626eedSJames Wright // SPDX-License-Identifier: BSD-2-Clause 588626eedSJames Wright // 688626eedSJames Wright // This file is part of CEED: http://github.com/ceed 788626eedSJames Wright 888626eedSJames Wright /// @file 988626eedSJames Wright /// Operator for Navier-Stokes example using PETSc 1088626eedSJames Wright 1188626eedSJames Wright 1288626eedSJames Wright #ifndef channel_h 1388626eedSJames Wright #define channel_h 1488626eedSJames Wright 1588626eedSJames Wright #include <math.h> 16c32eb7cbSJed Brown #include <ceed/ceed.h> 17841e4c73SJed Brown #include "newtonian_types.h" 1888626eedSJames Wright 1988626eedSJames Wright typedef struct ChannelContext_ *ChannelContext; 2088626eedSJames Wright struct ChannelContext_ { 2188626eedSJames Wright bool implicit; // !< Using implicit timesteping or not 2288626eedSJames Wright CeedScalar theta0; // !< Reference temperature 2388626eedSJames Wright CeedScalar P0; // !< Reference Pressure 2488626eedSJames Wright CeedScalar umax; // !< Centerline velocity 2588626eedSJames Wright CeedScalar center; // !< Y Coordinate for center of channel 2688626eedSJames Wright CeedScalar H; // !< Channel half-height 2788626eedSJames Wright CeedScalar B; // !< Body-force driving the flow 2888626eedSJames Wright struct NewtonianIdealGasContext_ newtonian_ctx; 2988626eedSJames Wright }; 3088626eedSJames Wright 31ba6664aeSJames Wright CEED_QFUNCTION_HELPER CeedInt Exact_Channel(CeedInt dim, CeedScalar time, 3288626eedSJames Wright const CeedScalar X[], CeedInt Nf, CeedScalar q[], void *ctx) { 3388626eedSJames Wright 3488626eedSJames Wright const ChannelContext context = (ChannelContext)ctx; 3588626eedSJames Wright const CeedScalar theta0 = context->theta0; 3688626eedSJames Wright const CeedScalar P0 = context->P0; 3788626eedSJames Wright const CeedScalar umax = context->umax; 3888626eedSJames Wright const CeedScalar center = context->center; 3988626eedSJames Wright const CeedScalar H = context->H; 4088626eedSJames Wright const CeedScalar cv = context->newtonian_ctx.cv; 4188626eedSJames Wright const CeedScalar cp = context->newtonian_ctx.cp; 4288626eedSJames Wright const CeedScalar Rd = cp - cv; 4388626eedSJames Wright const CeedScalar mu = context->newtonian_ctx.mu; 4488626eedSJames Wright const CeedScalar k = context->newtonian_ctx.k; 4588626eedSJames Wright 4688626eedSJames Wright const CeedScalar y=X[1]; 4788626eedSJames Wright 4888626eedSJames Wright const CeedScalar Pr = mu / (cp*k); 4988626eedSJames Wright const CeedScalar Ec = (umax*umax) / (cp*theta0); 50c32eb7cbSJed Brown const CeedScalar theta = theta0*(1 + (Pr*Ec/3) 51c32eb7cbSJed Brown * (1 - Square(Square((y-center)/H)))); 5288626eedSJames Wright 5388626eedSJames Wright const CeedScalar p = P0; 5488626eedSJames Wright 5588626eedSJames Wright const CeedScalar rho = p / (Rd*theta); 5688626eedSJames Wright 5788626eedSJames Wright q[0] = rho; 58c32eb7cbSJed Brown q[1] = rho * umax*(1 - Square((y-center)/H)); 5988626eedSJames Wright q[2] = 0; 6088626eedSJames Wright q[3] = 0; 6188626eedSJames Wright q[4] = rho * (cv*theta) + .5 * (q[1]*q[1] + q[2]*q[2] + q[3]*q[3]) / rho; 6288626eedSJames Wright 6388626eedSJames Wright return 0; 6488626eedSJames Wright } 6588626eedSJames Wright 6688626eedSJames Wright // ***************************************************************************** 6788626eedSJames Wright // This QFunction sets the initial condition 6888626eedSJames Wright // ***************************************************************************** 6988626eedSJames Wright CEED_QFUNCTION(ICsChannel)(void *ctx, CeedInt Q, 7088626eedSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 7188626eedSJames Wright // Inputs 7288626eedSJames Wright const CeedScalar (*X)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 7388626eedSJames Wright 7488626eedSJames Wright // Outputs 7588626eedSJames Wright CeedScalar (*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 7688626eedSJames Wright 7788626eedSJames Wright // Quadrature Point Loop 7888626eedSJames Wright CeedPragmaSIMD 7988626eedSJames Wright for (CeedInt i=0; i<Q; i++) { 8088626eedSJames Wright const CeedScalar x[] = {X[0][i], X[1][i], X[2][i]}; 8188626eedSJames Wright CeedScalar q[5] = {0.}; 8288626eedSJames Wright Exact_Channel(3, 0., x, 5, q, ctx); 8388626eedSJames Wright 8488626eedSJames Wright for (CeedInt j=0; j<5; j++) 8588626eedSJames Wright q0[j][i] = q[j]; 8688626eedSJames Wright } // End of Quadrature Point Loop 8788626eedSJames Wright return 0; 8888626eedSJames Wright } 8988626eedSJames Wright 9088626eedSJames Wright // ***************************************************************************** 9188626eedSJames Wright CEED_QFUNCTION(Channel_Inflow)(void *ctx, CeedInt Q, 9288626eedSJames Wright const CeedScalar *const *in, 9388626eedSJames Wright CeedScalar *const *out) { 9488626eedSJames Wright // *INDENT-OFF* 9588626eedSJames Wright // Inputs 9688626eedSJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 97*e8b03feeSJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 98*e8b03feeSJames Wright (*X)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 9988626eedSJames Wright 10088626eedSJames Wright // Outputs 10188626eedSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 10288626eedSJames Wright // *INDENT-ON* 10388626eedSJames Wright const ChannelContext context = (ChannelContext)ctx; 10488626eedSJames Wright const bool implicit = context->implicit; 10588626eedSJames Wright const CeedScalar cv = context->newtonian_ctx.cv; 10688626eedSJames Wright const CeedScalar cp = context->newtonian_ctx.cp; 10788626eedSJames Wright const CeedScalar gamma = cp/cv; 10888626eedSJames Wright 10988626eedSJames Wright CeedPragmaSIMD 11088626eedSJames Wright // Quadrature Point Loop 11188626eedSJames Wright for (CeedInt i=0; i<Q; i++) { 11288626eedSJames Wright // Setup 11388626eedSJames Wright // -- Interp-to-Interp q_data 11488626eedSJames Wright // For explicit mode, the surface integral is on the RHS of ODE q_dot = f(q). 11588626eedSJames Wright // For implicit mode, it gets pulled to the LHS of implicit ODE/DAE g(q_dot, q). 11688626eedSJames Wright // We can effect this by swapping the sign on this weight 11788626eedSJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 11888626eedSJames Wright 11988626eedSJames Wright // Calcualte prescribed inflow values 12088626eedSJames Wright const CeedScalar x[3] = {X[0][i], X[1][i], X[2][i]}; 12188626eedSJames Wright CeedScalar q_exact[5] = {0.}; 12288626eedSJames Wright Exact_Channel(3, 0., x, 5, q_exact, ctx); 12388626eedSJames Wright const CeedScalar E_kinetic_exact = 0.5*(q_exact[1]*q_exact[1] + 12488626eedSJames Wright q_exact[2]*q_exact[2] + 12588626eedSJames Wright q_exact[3]*q_exact[3]) / q_exact[0]; 12688626eedSJames Wright const CeedScalar velocity[3] = {q_exact[1]/q_exact[0], 12788626eedSJames Wright q_exact[2]/q_exact[0], 12888626eedSJames Wright q_exact[3]/q_exact[0] 12988626eedSJames Wright }; 13088626eedSJames Wright const CeedScalar theta = (q_exact[4] - E_kinetic_exact) / (q_exact[0]*cv); 13188626eedSJames Wright 13288626eedSJames Wright // Find pressure using state inside the domain 13388626eedSJames Wright const CeedScalar rho = q[0][i]; 13488626eedSJames Wright const CeedScalar u[3] = {q[1][i]/rho, q[2][i]/rho, q[3][i]/rho}; 13588626eedSJames Wright const CeedScalar E_internal = q[4][i] - .5 * rho * (u[0]*u[0] + u[1]*u[1] + 13688626eedSJames Wright u[2]*u[2]); 13788626eedSJames Wright const CeedScalar P = E_internal * (gamma - 1.); 13888626eedSJames Wright 13988626eedSJames Wright // Find inflow state using calculated P and prescribed velocity, theta0 14088626eedSJames Wright const CeedScalar e_internal = cv * theta; 14188626eedSJames Wright const CeedScalar rho_in = P / ((gamma - 1) * e_internal); 14288626eedSJames Wright const CeedScalar E_kinetic = .5 * rho_in * (velocity[0]*velocity[0] + 14388626eedSJames Wright velocity[1]*velocity[1] + 14488626eedSJames Wright velocity[2]*velocity[2]); 14588626eedSJames Wright const CeedScalar E = rho_in * e_internal + E_kinetic; 14688626eedSJames Wright // ---- Normal vect 14788626eedSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], 14888626eedSJames Wright q_data_sur[2][i], 14988626eedSJames Wright q_data_sur[3][i] 15088626eedSJames Wright }; 15188626eedSJames Wright 15288626eedSJames Wright // The Physics 15388626eedSJames Wright // Zero v so all future terms can safely sum into it 154ba6664aeSJames Wright for (CeedInt j=0; j<5; j++) v[j][i] = 0.; 15588626eedSJames Wright 15688626eedSJames Wright const CeedScalar u_normal = norm[0]*velocity[0] + 15788626eedSJames Wright norm[1]*velocity[1] + 15888626eedSJames Wright norm[2]*velocity[2]; 15988626eedSJames Wright 16088626eedSJames Wright // The Physics 16188626eedSJames Wright // -- Density 16288626eedSJames Wright v[0][i] -= wdetJb * rho_in * u_normal; 16388626eedSJames Wright 16488626eedSJames Wright // -- Momentum 165ba6664aeSJames Wright for (CeedInt j=0; j<3; j++) 16688626eedSJames Wright v[j+1][i] -= wdetJb * (rho_in * u_normal * velocity[j] + 16788626eedSJames Wright norm[j] * P); 16888626eedSJames Wright 16988626eedSJames Wright // -- Total Energy Density 17088626eedSJames Wright v[4][i] -= wdetJb * u_normal * (E + P); 17188626eedSJames Wright 17288626eedSJames Wright } // End Quadrature Point Loop 17388626eedSJames Wright return 0; 17488626eedSJames Wright } 17588626eedSJames Wright 17688626eedSJames Wright // ***************************************************************************** 17788626eedSJames Wright CEED_QFUNCTION(Channel_Outflow)(void *ctx, CeedInt Q, 17888626eedSJames Wright const CeedScalar *const *in, 17988626eedSJames Wright CeedScalar *const *out) { 18088626eedSJames Wright // *INDENT-OFF* 18188626eedSJames Wright // Inputs 18288626eedSJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 183*e8b03feeSJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2]; 184*e8b03feeSJames Wright 18588626eedSJames Wright // Outputs 18688626eedSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 18788626eedSJames Wright // *INDENT-ON* 18888626eedSJames Wright 18988626eedSJames Wright const ChannelContext context = (ChannelContext)ctx; 19088626eedSJames Wright const bool implicit = context->implicit; 19188626eedSJames Wright const CeedScalar P0 = context->P0; 19288626eedSJames Wright 19388626eedSJames Wright CeedPragmaSIMD 19488626eedSJames Wright // Quadrature Point Loop 19588626eedSJames Wright for (CeedInt i=0; i<Q; i++) { 19688626eedSJames Wright // Setup 19788626eedSJames Wright // -- Interp in 19888626eedSJames Wright const CeedScalar rho = q[0][i]; 19988626eedSJames Wright const CeedScalar u[3] = {q[1][i] / rho, 20088626eedSJames Wright q[2][i] / rho, 20188626eedSJames Wright q[3][i] / rho 20288626eedSJames Wright }; 20388626eedSJames Wright const CeedScalar E = q[4][i]; 20488626eedSJames Wright 20588626eedSJames Wright // -- Interp-to-Interp q_data 20688626eedSJames Wright // For explicit mode, the surface integral is on the RHS of ODE q_dot = f(q). 20788626eedSJames Wright // For implicit mode, it gets pulled to the LHS of implicit ODE/DAE g(q_dot, q). 20888626eedSJames Wright // We can effect this by swapping the sign on this weight 20988626eedSJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 21088626eedSJames Wright 21188626eedSJames Wright // ---- Normal vect 21288626eedSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], 21388626eedSJames Wright q_data_sur[2][i], 21488626eedSJames Wright q_data_sur[3][i] 21588626eedSJames Wright }; 21688626eedSJames Wright 21788626eedSJames Wright // The Physics 21888626eedSJames Wright // Zero v so all future terms can safely sum into it 219ba6664aeSJames Wright for (CeedInt j=0; j<5; j++) v[j][i] = 0.; 22088626eedSJames Wright 22188626eedSJames Wright // Implementing outflow condition 22288626eedSJames Wright const CeedScalar P = P0; // pressure 22388626eedSJames Wright const CeedScalar u_normal = norm[0]*u[0] + norm[1]*u[1] + 22488626eedSJames Wright norm[2]*u[2]; // Normal velocity 22588626eedSJames Wright // The Physics 22688626eedSJames Wright // -- Density 22788626eedSJames Wright v[0][i] -= wdetJb * rho * u_normal; 22888626eedSJames Wright 22988626eedSJames Wright // -- Momentum 230ba6664aeSJames Wright for (CeedInt j=0; j<3; j++) 23188626eedSJames Wright v[j+1][i] -= wdetJb *(rho * u_normal * u[j] + norm[j] * P); 23288626eedSJames Wright 23388626eedSJames Wright // -- Total Energy Density 23488626eedSJames Wright v[4][i] -= wdetJb * u_normal * (E + P); 23588626eedSJames Wright 23688626eedSJames Wright } // End Quadrature Point Loop 23788626eedSJames Wright return 0; 23888626eedSJames Wright } 23988626eedSJames Wright #endif // channel_h 240