// 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. // g = (g, 0, 0) // x = (0, x_2, x_3) // e_potential = dot(g, x) = 0 const CeedScalar x[3] = {0, X[1], X[2]}; const CeedScalar Pr = mu / (cp*k); const CeedScalar Ec = (umax*umax) / (cp*theta0); const CeedScalar theta = theta0*(1 + (Pr*Ec/3) * (1 - Square(Square((x[1]-center)/H)))); CeedScalar Y[5] = {0.}; Y[0] = P0; Y[1] = umax*(1 - Square((x[1]-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) UnpackState_Y(s.Y, q); else UnpackState_U(s.U, q); for (CeedInt j=0; j<5; j++) q0[j][i] = q[j]; } // End of Quadrature Point Loop return 0; } // ***************************************************************************** // This QFunction set the inflow boundary condition for conservative variables // ***************************************************************************** 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; NewtonianIdealGasContext gas = &context->newtonian_ctx; const CeedScalar cv = gas->cv; const CeedScalar cp = gas->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