1bb8a0c61SJames Wright // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors. 2bb8a0c61SJames Wright // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 3bb8a0c61SJames Wright // 4bb8a0c61SJames Wright // SPDX-License-Identifier: BSD-2-Clause 5bb8a0c61SJames Wright // 6bb8a0c61SJames Wright // This file is part of CEED: http://github.com/ceed 7bb8a0c61SJames Wright 8bb8a0c61SJames Wright /// @file 9bb8a0c61SJames Wright /// Operator for Navier-Stokes example using PETSc 10bb8a0c61SJames Wright 11bb8a0c61SJames Wright #ifndef channel_h 12bb8a0c61SJames Wright #define channel_h 13bb8a0c61SJames Wright 14d0cce58aSJeremy L Thompson #include <ceed.h> 15bb8a0c61SJames Wright #include <math.h> 162b916ea7SJeremy L Thompson 17cbe60e31SLeila Ghaffari #include "newtonian_state.h" 18d0cce58aSJeremy L Thompson #include "newtonian_types.h" 19704b8bbeSJames Wright #include "utils.h" 20bb8a0c61SJames Wright 21bb8a0c61SJames Wright typedef struct ChannelContext_ *ChannelContext; 22bb8a0c61SJames Wright struct ChannelContext_ { 23bb8a0c61SJames Wright bool implicit; // !< Using implicit timesteping or not 24bb8a0c61SJames Wright CeedScalar theta0; // !< Reference temperature 25bb8a0c61SJames Wright CeedScalar P0; // !< Reference Pressure 26bb8a0c61SJames Wright CeedScalar umax; // !< Centerline velocity 27bb8a0c61SJames Wright CeedScalar center; // !< Y Coordinate for center of channel 28bb8a0c61SJames Wright CeedScalar H; // !< Channel half-height 29bb8a0c61SJames Wright CeedScalar B; // !< Body-force driving the flow 30bb8a0c61SJames Wright struct NewtonianIdealGasContext_ newtonian_ctx; 31bb8a0c61SJames Wright }; 32bb8a0c61SJames Wright 332b916ea7SJeremy L Thompson CEED_QFUNCTION_HELPER State Exact_Channel(CeedInt dim, CeedScalar time, const CeedScalar X[], CeedInt Nf, void *ctx) { 34bb8a0c61SJames Wright const ChannelContext context = (ChannelContext)ctx; 35bb8a0c61SJames Wright const CeedScalar theta0 = context->theta0; 36bb8a0c61SJames Wright const CeedScalar P0 = context->P0; 37bb8a0c61SJames Wright const CeedScalar umax = context->umax; 38bb8a0c61SJames Wright const CeedScalar center = context->center; 39bb8a0c61SJames Wright const CeedScalar H = context->H; 40cbe60e31SLeila Ghaffari NewtonianIdealGasContext gas = &context->newtonian_ctx; 41cbe60e31SLeila Ghaffari const CeedScalar cp = gas->cp; 42cbe60e31SLeila Ghaffari const CeedScalar mu = gas->mu; 43cbe60e31SLeila Ghaffari const CeedScalar k = gas->k; 44cbe60e31SLeila Ghaffari // There is a gravity body force but it is excluded from 45cbe60e31SLeila Ghaffari // the potential energy due to periodicity. 46d1b9ef12SLeila Ghaffari // g = (g, 0, 0) 47d1b9ef12SLeila Ghaffari // x = (0, x_2, x_3) 48d1b9ef12SLeila Ghaffari // e_potential = dot(g, x) = 0 49d1b9ef12SLeila Ghaffari const CeedScalar x[3] = {0, X[1], X[2]}; 50bb8a0c61SJames Wright 51bb8a0c61SJames Wright const CeedScalar Pr = mu / (cp * k); 52bb8a0c61SJames Wright const CeedScalar Ec = (umax * umax) / (cp * theta0); 532b916ea7SJeremy L Thompson const CeedScalar theta = theta0 * (1 + (Pr * Ec / 3) * (1 - Square(Square((x[1] - center) / H)))); 54cbe60e31SLeila Ghaffari CeedScalar Y[5] = {0.}; 55cbe60e31SLeila Ghaffari Y[0] = P0; 56d1b9ef12SLeila Ghaffari Y[1] = umax * (1 - Square((x[1] - center) / H)); 57cbe60e31SLeila Ghaffari Y[2] = 0.; 58cbe60e31SLeila Ghaffari Y[3] = 0.; 59cbe60e31SLeila Ghaffari Y[4] = theta; 60bb8a0c61SJames Wright 61*edcfef1bSKenneth E. Jansen return StateFromY(gas, Y); 62bb8a0c61SJames Wright } 63bb8a0c61SJames Wright 64bb8a0c61SJames Wright // ***************************************************************************** 65cbe60e31SLeila Ghaffari // This QFunction set the initial condition 66bb8a0c61SJames Wright // ***************************************************************************** 672b916ea7SJeremy L Thompson CEED_QFUNCTION(ICsChannel)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 68bb8a0c61SJames Wright // Inputs 69bb8a0c61SJames Wright const CeedScalar(*X)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 70bb8a0c61SJames Wright 71bb8a0c61SJames Wright // Outputs 72bb8a0c61SJames Wright CeedScalar(*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 73bb8a0c61SJames Wright 74cbe60e31SLeila Ghaffari // Context 75cbe60e31SLeila Ghaffari const ChannelContext context = (ChannelContext)ctx; 76cbe60e31SLeila Ghaffari 77bb8a0c61SJames Wright // Quadrature Point Loop 782b916ea7SJeremy L Thompson CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 79bb8a0c61SJames Wright const CeedScalar x[] = {X[0][i], X[1][i], X[2][i]}; 80cbe60e31SLeila Ghaffari State s = Exact_Channel(3, 0., x, 5, ctx); 81d1b9ef12SLeila Ghaffari CeedScalar q[5] = {0}; 823636f6a4SJames Wright switch (context->newtonian_ctx.state_var) { 833636f6a4SJames Wright case STATEVAR_CONSERVATIVE: 84d1b9ef12SLeila Ghaffari UnpackState_U(s.U, q); 853636f6a4SJames Wright break; 863636f6a4SJames Wright case STATEVAR_PRIMITIVE: 873636f6a4SJames Wright UnpackState_Y(s.Y, q); 883636f6a4SJames Wright break; 893636f6a4SJames Wright } 90d1b9ef12SLeila Ghaffari 912b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 5; j++) q0[j][i] = q[j]; 92bb8a0c61SJames Wright 93bb8a0c61SJames Wright } // End of Quadrature Point Loop 94bb8a0c61SJames Wright return 0; 95bb8a0c61SJames Wright } 96bb8a0c61SJames Wright 97bb8a0c61SJames Wright // ***************************************************************************** 98d1b9ef12SLeila Ghaffari // This QFunction set the inflow boundary condition for conservative variables 99d1b9ef12SLeila Ghaffari // ***************************************************************************** 1002b916ea7SJeremy L Thompson CEED_QFUNCTION(Channel_Inflow)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 101bb8a0c61SJames Wright // Inputs 1023d65b166SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 103ade49511SJames Wright const CeedScalar(*q_data_sur) = in[2]; 1043d65b166SJames Wright const CeedScalar(*X)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 105bb8a0c61SJames Wright 106bb8a0c61SJames Wright // Outputs 107bb8a0c61SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 1083d65b166SJames Wright 109bb8a0c61SJames Wright const ChannelContext context = (ChannelContext)ctx; 110ade49511SJames Wright const bool is_implicit = context->implicit; 111d1b9ef12SLeila Ghaffari NewtonianIdealGasContext gas = &context->newtonian_ctx; 112d1b9ef12SLeila Ghaffari const CeedScalar cv = gas->cv; 1133d65b166SJames Wright const CeedScalar gamma = HeatCapacityRatio(&context->newtonian_ctx); 114bb8a0c61SJames Wright 115bb8a0c61SJames Wright // Quadrature Point Loop 1163d65b166SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 117ade49511SJames Wright CeedScalar wdetJb, norm[3]; 118ade49511SJames Wright QdataBoundaryUnpack_3D(Q, i, q_data_sur, &wdetJb, NULL, norm); 119ade49511SJames Wright wdetJb *= is_implicit ? -1. : 1.; 120bb8a0c61SJames Wright 121d1b9ef12SLeila Ghaffari // There is a gravity body force but it is excluded from 122d1b9ef12SLeila Ghaffari // the potential energy due to periodicity. 123d1b9ef12SLeila Ghaffari // g = (g, 0, 0) 124d1b9ef12SLeila Ghaffari // x = (0, x_2, x_3) 125d1b9ef12SLeila Ghaffari // e_potential = dot(g, x) = 0 126d1b9ef12SLeila Ghaffari const CeedScalar x[3] = {0, X[1][i], X[2][i]}; 127d1b9ef12SLeila Ghaffari 128bb8a0c61SJames Wright // Calcualte prescribed inflow values 129d1b9ef12SLeila Ghaffari State s_exact = Exact_Channel(3, 0., x, 5, ctx); 130bb8a0c61SJames Wright CeedScalar q_exact[5] = {0.}; 131d1b9ef12SLeila Ghaffari UnpackState_U(s_exact.U, q_exact); 132bb8a0c61SJames Wright 133bb8a0c61SJames Wright // Find pressure using state inside the domain 134d1b9ef12SLeila Ghaffari CeedScalar q_inside[5] = {0}; 1352b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 5; j++) q_inside[j] = q[j][i]; 136*edcfef1bSKenneth E. Jansen State s_inside = StateFromU(gas, q_inside); 137d1b9ef12SLeila Ghaffari const CeedScalar P = s_inside.Y.pressure; 138bb8a0c61SJames Wright 139bb8a0c61SJames Wright // Find inflow state using calculated P and prescribed velocity, theta0 140d1b9ef12SLeila Ghaffari const CeedScalar e_internal = cv * s_exact.Y.temperature; 141bb8a0c61SJames Wright const CeedScalar rho_in = P / ((gamma - 1) * e_internal); 1422b916ea7SJeremy L Thompson const CeedScalar E_kinetic = .5 * rho_in * Dot3(s_exact.Y.velocity, s_exact.Y.velocity); 143bb8a0c61SJames Wright const CeedScalar E = rho_in * e_internal + E_kinetic; 144d1b9ef12SLeila Ghaffari 145bb8a0c61SJames Wright // The Physics 146bb8a0c61SJames Wright // Zero v so all future terms can safely sum into it 147493642f1SJames Wright for (CeedInt j = 0; j < 5; j++) v[j][i] = 0.; 148bb8a0c61SJames Wright 149d1b9ef12SLeila Ghaffari const CeedScalar u_normal = Dot3(norm, s_exact.Y.velocity); 150bb8a0c61SJames Wright 151bb8a0c61SJames Wright // The Physics 152bb8a0c61SJames Wright // -- Density 153bb8a0c61SJames Wright v[0][i] -= wdetJb * rho_in * u_normal; 154bb8a0c61SJames Wright 155bb8a0c61SJames Wright // -- Momentum 1562b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 3; j++) v[j + 1][i] -= wdetJb * (rho_in * u_normal * s_exact.Y.velocity[j] + norm[j] * P); 157bb8a0c61SJames Wright 158bb8a0c61SJames Wright // -- Total Energy Density 159bb8a0c61SJames Wright v[4][i] -= wdetJb * u_normal * (E + P); 160bb8a0c61SJames Wright 161bb8a0c61SJames Wright } // End Quadrature Point Loop 162bb8a0c61SJames Wright return 0; 163bb8a0c61SJames Wright } 164bb8a0c61SJames Wright 165bb8a0c61SJames Wright // ***************************************************************************** 166d1b9ef12SLeila Ghaffari // This QFunction set the outflow boundary condition for conservative variables 167d1b9ef12SLeila Ghaffari // ***************************************************************************** 1682b916ea7SJeremy L Thompson CEED_QFUNCTION(Channel_Outflow)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 169bb8a0c61SJames Wright // Inputs 1703d65b166SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 171ade49511SJames Wright const CeedScalar(*q_data_sur) = in[2]; 172dd64951cSJames Wright 173bb8a0c61SJames Wright // Outputs 174bb8a0c61SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 175bb8a0c61SJames Wright 176bb8a0c61SJames Wright const ChannelContext context = (ChannelContext)ctx; 177ade49511SJames Wright const bool is_implicit = context->implicit; 178bb8a0c61SJames Wright const CeedScalar P0 = context->P0; 179bb8a0c61SJames Wright 180bb8a0c61SJames Wright // Quadrature Point Loop 1813d65b166SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 182ade49511SJames Wright CeedScalar wdetJb, norm[3]; 183ade49511SJames Wright QdataBoundaryUnpack_3D(Q, i, q_data_sur, &wdetJb, NULL, norm); 184ade49511SJames Wright wdetJb *= is_implicit ? -1. : 1.; 185ade49511SJames Wright 186bb8a0c61SJames Wright const CeedScalar rho = q[0][i]; 1872b916ea7SJeremy L Thompson const CeedScalar u[3] = {q[1][i] / rho, q[2][i] / rho, q[3][i] / rho}; 188bb8a0c61SJames Wright const CeedScalar E = q[4][i]; 189bb8a0c61SJames Wright 190bb8a0c61SJames Wright // The Physics 191bb8a0c61SJames Wright // Zero v so all future terms can safely sum into it 192493642f1SJames Wright for (CeedInt j = 0; j < 5; j++) v[j][i] = 0.; 193bb8a0c61SJames Wright 194bb8a0c61SJames Wright // Implementing outflow condition 195bb8a0c61SJames Wright const CeedScalar P = P0; // pressure 196704b8bbeSJames Wright const CeedScalar u_normal = Dot3(norm, u); // Normal velocity 197bb8a0c61SJames Wright // The Physics 198bb8a0c61SJames Wright // -- Density 199bb8a0c61SJames Wright v[0][i] -= wdetJb * rho * u_normal; 200bb8a0c61SJames Wright 201bb8a0c61SJames Wright // -- Momentum 2022b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 3; j++) v[j + 1][i] -= wdetJb * (rho * u_normal * u[j] + norm[j] * P); 203bb8a0c61SJames Wright 204bb8a0c61SJames Wright // -- Total Energy Density 205bb8a0c61SJames Wright v[4][i] -= wdetJb * u_normal * (E + P); 206bb8a0c61SJames Wright 207bb8a0c61SJames Wright } // End Quadrature Point Loop 208bb8a0c61SJames Wright return 0; 209bb8a0c61SJames Wright } 210cbe60e31SLeila Ghaffari 211cbe60e31SLeila Ghaffari // ***************************************************************************** 212bb8a0c61SJames Wright #endif // channel_h 213