// Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors. // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. // // SPDX-License-Identifier: BSD-2-Clause // // This file is part of CEED: http://github.com/ceed /// @file /// Operator for Navier-Stokes example using PETSc #ifndef channel_h #define channel_h #include #include #include "newtonian_types.h" #include "newtonian_state.h" #include "utils.h" typedef struct ChannelContext_ *ChannelContext; struct ChannelContext_ { bool implicit; // !< Using implicit timesteping or not CeedScalar theta0; // !< Reference temperature CeedScalar P0; // !< Reference Pressure CeedScalar umax; // !< Centerline velocity CeedScalar center; // !< Y Coordinate for center of channel CeedScalar H; // !< Channel half-height CeedScalar B; // !< Body-force driving the flow struct NewtonianIdealGasContext_ newtonian_ctx; }; CEED_QFUNCTION_HELPER State Exact_Channel(CeedInt dim, CeedScalar time, const CeedScalar X[], CeedInt Nf, void *ctx) { const ChannelContext context = (ChannelContext)ctx; const CeedScalar theta0 = context->theta0; const CeedScalar P0 = context->P0; const CeedScalar umax = context->umax; const CeedScalar center = context->center; const CeedScalar H = context->H; NewtonianIdealGasContext gas = &context->newtonian_ctx; const CeedScalar cp = gas->cp; const CeedScalar mu = gas->mu; const CeedScalar k = gas->k; // There is a gravity body force but it is excluded from // the potential energy due to periodicity. gas->g[0] = 0.; gas->g[1] = 0.; gas->g[2] = 0.; const CeedScalar y = X[1]; const CeedScalar Pr = mu / (cp*k); const CeedScalar Ec = (umax*umax) / (cp*theta0); const CeedScalar theta = theta0*(1 + (Pr*Ec/3) * (1 - Square(Square((y-center)/H)))); CeedScalar Y[5] = {0.}; Y[0] = P0; Y[1] = umax*(1 - Square((y-center)/H)); Y[2] = 0.; Y[3] = 0.; Y[4] = theta; return StateFromY(gas, Y, X); } // ***************************************************************************** // This QFunction set the initial condition // ***************************************************************************** CEED_QFUNCTION(ICsChannel)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { // Inputs const CeedScalar (*X)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; // Outputs CeedScalar (*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; // Context const ChannelContext context = (ChannelContext)ctx; // Quadrature Point Loop CeedPragmaSIMD for (CeedInt i=0; inewtonian_ctx.is_primitive) { q0[0][i] = s.Y.pressure; for (CeedInt j=0; j<3; j++) q0[j+1][i] = s.Y.velocity[j]; q0[4][i] = s.Y.temperature; } else { q0[0][i] = s.U.density; for (CeedInt j=0; j<3; j++) q0[j+1][i] = s.U.momentum[j]; q0[4][i] = s.U.E_total; } } // End of Quadrature Point Loop return 0; } // ***************************************************************************** CEED_QFUNCTION(Channel_Inflow)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { // *INDENT-OFF* // Inputs const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], (*X)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; // Outputs CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; // *INDENT-ON* const ChannelContext context = (ChannelContext)ctx; const bool implicit = context->implicit; const CeedScalar cv = context->newtonian_ctx.cv; const CeedScalar cp = context->newtonian_ctx.cp; const CeedScalar gamma = cp/cv; CeedPragmaSIMD // Quadrature Point Loop for (CeedInt i=0; iimplicit; const CeedScalar P0 = context->P0; CeedPragmaSIMD // Quadrature Point Loop for (CeedInt i=0; i