// 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 /// Advection initial condition and operator for Navier-Stokes example using PETSc #ifndef advection_h #define advection_h #include #include typedef struct SetupContext_ *SetupContext; struct SetupContext_ { CeedScalar rc; CeedScalar lx; CeedScalar ly; CeedScalar lz; CeedScalar wind[3]; CeedScalar time; int wind_type; // See WindType: 0=ROTATION, 1=TRANSLATION int bubble_type; // See BubbleType: 0=SPHERE, 1=CYLINDER int bubble_continuity_type; // See BubbleContinuityType: 0=SMOOTH, 1=BACK_SHARP 2=THICK }; typedef struct AdvectionContext_ *AdvectionContext; struct AdvectionContext_ { CeedScalar CtauS; CeedScalar strong_form; CeedScalar E_wind; bool implicit; int stabilization; // See StabilizationType: 0=none, 1=SU, 2=SUPG }; CEED_QFUNCTION_HELPER CeedScalar Square(CeedScalar x) { return x*x; } // ***************************************************************************** // This QFunction sets the initial conditions and the boundary conditions // for two test cases: ROTATION and TRANSLATION // // -- ROTATION (default) // Initial Conditions: // Mass Density: // Constant mass density of 1.0 // Momentum Density: // Rotational field in x,y // Energy Density: // Maximum of 1. x0 decreasing linearly to 0. as radial distance // increases to (1.-r/rc), then 0. everywhere else // // Boundary Conditions: // Mass Density: // 0.0 flux // Momentum Density: // 0.0 // Energy Density: // 0.0 flux // // -- TRANSLATION // Initial Conditions: // Mass Density: // Constant mass density of 1.0 // Momentum Density: // Constant rectilinear field in x,y // Energy Density: // Maximum of 1. x0 decreasing linearly to 0. as radial distance // increases to (1.-r/rc), then 0. everywhere else // // Boundary Conditions: // Mass Density: // 0.0 flux // Momentum Density: // 0.0 // Energy Density: // Inflow BCs: // E = E_wind // Outflow BCs: // E = E(boundary) // Both In/Outflow BCs for E are applied weakly in the // QFunction "Advection_Sur" // // ***************************************************************************** // ***************************************************************************** // This helper function provides support for the exact, time-dependent solution // (currently not implemented) and IC formulation for 3D advection // ***************************************************************************** CEED_QFUNCTION_HELPER CeedInt Exact_Advection(CeedInt dim, CeedScalar time, const CeedScalar X[], CeedInt Nf, CeedScalar q[], void *ctx) { const SetupContext context = (SetupContext)ctx; const CeedScalar rc = context->rc; const CeedScalar lx = context->lx; const CeedScalar ly = context->ly; const CeedScalar lz = context->lz; const CeedScalar *wind = context->wind; // Setup const CeedScalar x0[3] = {0.25*lx, 0.5*ly, 0.5*lz}; const CeedScalar center[3] = {0.5*lx, 0.5*ly, 0.5*lz}; // -- Coordinates const CeedScalar x = X[0]; const CeedScalar y = X[1]; const CeedScalar z = X[2]; // -- Energy CeedScalar r = 0.; switch (context->bubble_type) { // original sphere case 0: { // (dim=3) r = sqrt(Square(x - x0[0]) + Square(y - x0[1]) + Square(z - x0[2])); } break; // cylinder (needs periodicity to work properly) case 1: { // (dim=2) r = sqrt(Square(x - x0[0]) + Square(y - x0[1])); } break; } // Initial Conditions switch (context->wind_type) { case 0: // Rotation q[0] = 1.; q[1] = -(y - center[1]); q[2] = (x - center[0]); q[3] = 0; break; case 1: // Translation q[0] = 1.; q[1] = wind[0]; q[2] = wind[1]; q[3] = wind[2]; break; } switch (context->bubble_continuity_type) { // original continuous, smooth shape case 0: { q[4] = r <= rc ? (1.-r/rc) : 0.; } break; // discontinuous, sharp back half shape case 1: { q[4] = ((r <= rc) && (yCtauS; const CeedScalar strong_form = context->strong_form; CeedPragmaSIMD // Quadrature Point Loop for (CeedInt i=0; iCtauS; const CeedScalar strong_form = context->strong_form; CeedPragmaSIMD // Quadrature Point Loop for (CeedInt i=0; istabilization) { case 0: break; case 1: dv[j][4][i] += wdetJ * TauS * strong_conv * uX[j]; //SU break; case 2: dv[j][4][i] += wdetJ * TauS * strong_res * uX[j]; //SUPG break; } } // End Quadrature Point Loop return 0; } // ***************************************************************************** // This QFunction implements consistent outflow and inflow BCs // for 3D advection // // Inflow and outflow faces are determined based on sign(dot(wind, normal)): // sign(dot(wind, normal)) > 0 : outflow BCs // sign(dot(wind, normal)) < 0 : inflow BCs // // Outflow BCs: // The validity of the weak form of the governing equations is extended // to the outflow and the current values of E are applied. // // Inflow BCs: // A prescribed Total Energy (E_wind) is applied weakly. // // ***************************************************************************** CEED_QFUNCTION(Advection_InOutFlow)(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]; // Outputs CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; // *INDENT-ON* AdvectionContext context = (AdvectionContext)ctx; const CeedScalar E_wind = context->E_wind; const CeedScalar strong_form = context->strong_form; const bool implicit = context->implicit; CeedPragmaSIMD // Quadrature Point Loop for (CeedInt i=0; i 0) { // outflow v[4][i] = -(1 - strong_form) * wdetJb * E * u_normal; } else { // inflow v[4][i] = -(1 - strong_form) * wdetJb * E_wind * u_normal; } } // End Quadrature Point Loop return 0; } // ***************************************************************************** #endif // advection_h