LCOV - code coverage report
Current view: top level - include/base - NekInterface.h (source / functions) Hit Total Coverage
Test: neams-th-coe/cardinal: 9f356e Lines: 8 8 100.0 %
Date: 2026-08-19 15:42:22 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /********************************************************************/
       2             : /*                  SOFTWARE COPYRIGHT NOTIFICATION                 */
       3             : /*                             Cardinal                             */
       4             : /*                                                                  */
       5             : /*                  (c) 2021 UChicago Argonne, LLC                  */
       6             : /*                        ALL RIGHTS RESERVED                       */
       7             : /*                                                                  */
       8             : /*                 Prepared by UChicago Argonne, LLC                */
       9             : /*               Under Contract No. DE-AC02-06CH11357               */
      10             : /*                With the U. S. Department of Energy               */
      11             : /*                                                                  */
      12             : /*             Prepared by Battelle Energy Alliance, LLC            */
      13             : /*               Under Contract No. DE-AC07-05ID14517               */
      14             : /*                With the U. S. Department of Energy               */
      15             : /*                                                                  */
      16             : /*                 See LICENSE for full restrictions                */
      17             : /********************************************************************/
      18             : 
      19             : #pragma once
      20             : 
      21             : #include "CardinalEnums.h"
      22             : #include "MooseTypes.h"
      23             : #include "NekBoundaryCoupling.h"
      24             : #include "NekVolumeCoupling.h"
      25             : #include "Function.h"
      26             : 
      27             : #include "inipp.hpp"
      28             : #include "nekrs.hpp"
      29             : #include "nrs.hpp"
      30             : #include "udf.hpp"
      31             : #include "inipp.hpp"
      32             : #include "mesh.h"
      33             : 
      34             : #include "libmesh/point.h"
      35             : 
      36             : #include <string>
      37             : #include <vector>
      38             : 
      39             : /**
      40             :  * \brief Cardinal-specific nekRS API
      41             :  *
      42             :  * nekRS ships with a rudimentary API in their nekrs namespace, but we need additional
      43             :  * functionality from within Cardinal. Many of these functions are quite basic and could
      44             :  * eventually be ported back into nekRS itself.
      45             :  */
      46             : namespace nekrs
      47             : {
      48             : 
      49             : static int build_only;
      50             : 
      51             : /**
      52             :  * Number of passive scalars
      53             :  * @return number of passive scalars
      54             :  */
      55             : int Nscalar();
      56             : 
      57             : /// Allocate memory for the host mesh parameters
      58             : void initializeHostMeshParameters();
      59             : 
      60             : /// Update the mesh parameters on host
      61             : void updateHostMeshParameters();
      62             : 
      63             : dfloat * host_x();
      64             : dfloat * host_y();
      65             : dfloat * host_z();
      66             : 
      67             : nrs_t * nrsPtr();
      68             : 
      69             : dfloat * getSgeo();
      70             : dfloat * getVgeo();
      71             : 
      72             : /**
      73             :  * Check that the field specified can be accessed, e.g., if a user is requesting
      74             :  * to access temperature, the problem must have a temperature variable
      75             :  * @param[in] field field to check
      76             :  */
      77             : void checkFieldValidity(const field::NekFieldEnum & field);
      78             : void checkFieldValidity(const field::NekWriteEnum & field);
      79             : 
      80             : void copyDeviceToHost();
      81             : 
      82             : /**
      83             :  * Compute the minimum distance to a wall as a mesh field
      84             :  * @param[in] boundary_id boundary(s) on which to compute the distance to the wall
      85             :  */
      86             : void computeWallDistance(const std::vector<int> & boundary_id);
      87             : 
      88             : /**
      89             :  * Compute y+ on the NekRS mesh
      90             :  * @param[in] boundary_id boundary(s) on which to compute y+
      91             :  * @return max, min, average y+
      92             :  */
      93             : std::vector<dfloat> yPlus(const std::vector<int> & boundary_id);
      94             : 
      95             : /**
      96             :  * Compute the three components of the viscous drag along a given boundary
      97             :  * @param[in] boundary boundary IDs for drag computation
      98             :  * @return components of drag (force fluid exerts on walls)
      99             :  */
     100             : std::vector<dfloat> viscousDrag(const std::vector<int> & boundary);
     101             : 
     102             : /**
     103             :  * Set the absolute tolerance for checking energy conservation in data transfers to Nek
     104             :  * @param[in] tol tolerance
     105             :  */
     106             : void setAbsoluteTol(double tol);
     107             : 
     108             : /**
     109             :  * Return the reference units for a usrwrk slot
     110             :  * @param[in] slot usrwrk slot
     111             :  * @return value by which to multiply the usrwrk slot to go from non-dimensional form into
     112             :  * dimensional form
     113             :  */
     114             : Real scratchUnits(const int slot);
     115             : 
     116             : /**
     117             :  * Inform backend if dimensionalization should be performed
     118             :  * @param[in] n if dimensionalize should be performed
     119             :  */
     120             : void nondimensional(const bool n);
     121             : 
     122             : /**
     123             :  * Set the relative tolerance for checking energy conservation in data transfers to Nek
     124             :  * @param[in] tol tolerance
     125             :  */
     126             : void setRelativeTol(double tol);
     127             : 
     128             : /**
     129             :  * Nek's runtime statistics are formed by collecting a timer of both the initialization
     130             :  * and accumulated run time. We unfortunately have to split this across multiple classes,
     131             :  * so if we want correct times we need to have NekInitAction save the value of the time
     132             :  * spent on initialization.
     133             :  * @param[in] time time spent on initialization
     134             :  */
     135             : void setNekSetupTime(const double & time);
     136             : 
     137             : /**
     138             :  * Get time spent on initialization
     139             :  * @return time spent on initialization
     140             :  */
     141             : double getNekSetupTime();
     142             : 
     143             : /**
     144             :  * Set the start time used by NekRS
     145             :  * @param[in] start start time
     146             :  */
     147             : void setStartTime(const double & start);
     148             : 
     149             : /**
     150             :  * Whether NekRS itself has been initialized yet
     151             :  * @return whether NekRS is initialized
     152             :  */
     153             : bool isInitialized();
     154             : 
     155             : /**
     156             :  * Write a field file containing a specific slot of the nrs->usrwrk scratch space;
     157             :  * this will write the field to the 'temperature' slot in a field file.
     158             :  * @param[in] slot index in the nrs->usrwrk array to write
     159             :  * @param[in] prefix prefix for file name
     160             :  * @param[in] time simulation time to write file for
     161             :  * @param[in] step time step index
     162             :  * @param[in] write_coords whether to write the mesh coordinates
     163             :  */
     164             : void write_usrwrk_field_file(const int & size,
     165             :                              const int & index,
     166             :                              const int & slot,
     167             :                              const std::string & prefix,
     168             :                              const dfloat & time,
     169             :                              const int & step,
     170             :                              const bool & write_coords);
     171             : 
     172             : /**
     173             :  * Write a field file containing pressure, velocity, and scalars with given prefix
     174             :  * @param[in] prefix three-character prefix
     175             :  * @param[in] time time
     176             :  * @param[in] step time step index
     177             :  */
     178             : void write_field_file(const std::string & prefix, const dfloat time, const int & step);
     179             : 
     180             : /**
     181             :  * Indicate whether NekRS was run in build-only mode (this doesn't actually
     182             :  * cause NekRS to run in build-only mode, but only provides an interface to
     183             :  * this information elsewhere).
     184             :  * @param[in] buildOnly whether NekRS is to be run in build-only mode
     185             :  */
     186             : void buildOnly(int buildOnly);
     187             : 
     188             : /**
     189             :  * Whether NekRS was run in JIT build-only mode
     190             :  * @return whether NekRS was run in build-only mode
     191             :  */
     192             : int buildOnly();
     193             : 
     194             : /**
     195             :  * Interpolate a volume between NekRS's GLL points and a given-order receiving/sending mesh
     196             :  */
     197             : void interpolateVolumeHex3D(const double * I, double * x, int N, double * Ix, int M);
     198             : 
     199             : /**
     200             :  * Whether nekRS's input file has CHT
     201             :  * @return whether nekRS input files model CHT
     202             :  */
     203             : bool hasCHT();
     204             : 
     205             : /**
     206             :  * Whether nekRS's input file indicates a moving mesh
     207             :  * @return whether nekRS's input file indicates a moving mesh
     208             :  */
     209             : bool hasMovingMesh();
     210             : 
     211             : /**
     212             :  * Whether nekRS's input file indicates a variable time stepping scheme
     213             :  * @return whether nekRS's input file indicates a variable time stepping
     214             :  */
     215             : bool hasVariableDt();
     216             : 
     217             : /**
     218             :  * Whether nekRS's input file has the blending mesh solver
     219             :  * @return whether nekRS's input file has a non-user [MESH] solver
     220             :  */
     221             : bool hasBlendingSolver();
     222             : 
     223             : /**
     224             :  * Whether nekRS's input file has the user mesh solver
     225             :  * @return whether nekRS's input file has [MESH] solver = user
     226             :  */
     227             : bool hasUserMeshSolver();
     228             : 
     229             : /**
     230             :  * Whether nekRS's input file intends to terminate the simulation based on a wall time
     231             :  * @return whether a wall time is used in nekRS to end the simulation
     232             :  */
     233             : bool endControlElapsedTime();
     234             : 
     235             : /**
     236             :  * Whether nekRS's input file intends to terminate the simulation based on an end time
     237             :  * @return whether an end time is used in nekRS to end the simulation
     238             :  */
     239             : bool endControlTime();
     240             : 
     241             : /**
     242             :  * Whether nekRS's input file intends to terminate the simulation based on a number of steps
     243             :  * @return whether a time step interval is used in nekRS to end the simulation
     244             :  */
     245             : bool endControlNumSteps();
     246             : 
     247             : /**
     248             :  * Offset increment for indexing into multi-volume arrays for the scalar fields.
     249             :  * This assumes that all scalars are the same length as the temperature scalar.
     250             :  * TODO: evaluate whether this works if nekRS uses CHT
     251             :  * @return scalar field offset
     252             :  */
     253             : int scalarFieldOffset();
     254             : 
     255             : /**
     256             :  * Offset increment for indexing into the velocity array
     257             :  * @return velocity field offset
     258             :  */
     259             : int velocityFieldOffset();
     260             : 
     261             : /**
     262             :  * Offset increment to use for generic slice indexing
     263             :  * @return field offset
     264             :  */
     265             : int fieldOffset();
     266             : 
     267             : /**
     268             :  * Get the "entire" NekRS mesh. For cases with a temperature scalar, this returns
     269             :  * nrs->meshT, which will cover both the fluid and solid regions if CHT is present.
     270             :  * For flow-only cases, this will return the flow mesh.
     271             :  * @return entire NekRS mesh
     272             :  */
     273             : mesh_t * entireMesh();
     274             : 
     275             : /**
     276             :  * Get the mesh for the flow solve
     277             :  * @return flow mesh
     278             :  */
     279             : mesh_t * flowMesh();
     280             : 
     281             : /**
     282             :  * Get the mesh for the temperature scalar
     283             :  * @return temperature mesh
     284             :  */
     285             : mesh_t * temperatureMesh();
     286             : 
     287             : /**
     288             :  * Get the mesh to act on
     289             :  * @param[in] pp_mesh which NekRS mesh to operate on
     290             :  * @return mesh to act on
     291             :  */
     292             : mesh_t * getMesh(const nek_mesh::NekMeshEnum pp_mesh);
     293             : 
     294             : /**
     295             :  * Get the process rank
     296             :  * @return process rank
     297             :  */
     298             : int commRank();
     299             : 
     300             : /**
     301             :  * Get the communicator size
     302             :  * @return communicator size
     303             :  */
     304             : int commSize();
     305             : 
     306             : /**
     307             :  * Whether nekRS's input file indicates that the problem has a temperature variable
     308             :  * @return whether the nekRS problem includes a temperature variable
     309             :  */
     310             : bool hasTemperatureVariable();
     311             : 
     312             : /**
     313             :  * Whether nekRS actually solves for temperature (as opposed to setting its solver to 'none')
     314             :  * @return whether nekRS will solve for temperature
     315             :  */
     316             : bool hasTemperatureSolve();
     317             : 
     318             : /**
     319             :  * Whether nekRS's input file indicates that the problem has a scalar0(scalarId) variable
     320             :  * @param[in] scalarId scalar number, i.e. for scalar03 scalarId=3
     321             :  * @return whether the nekRS problem includes the scalar0(scalarId) variable
     322             :  */
     323             : bool hasScalarVariable(int scalarId);
     324             : 
     325             : /**
     326             :  * Whether nekRS contains an OCCA kernel to apply a source to the passive scalar equations
     327             :  * @return whether nekRS has an OCCA kernel for apply a passive scalar source
     328             :  */
     329             : bool hasHeatSourceKernel();
     330             : 
     331             : /**
     332             :  * Whether the scratch space has already been allocated by the user
     333             :  * @return whether scratch space is already allocated
     334             :  */
     335             : bool scratchAvailable();
     336             : 
     337             : /**
     338             :  * Initialize scratch space for data to get sent into NekRS
     339             :  * @param[in] n_slots number of slots (for volume arrays) to allocate
     340             :  */
     341             : void initializeScratch(const unsigned int & n_slots);
     342             : 
     343             : /// Free the scratch space
     344             : void freeScratch();
     345             : 
     346             : /**
     347             :  * Get the viscosity used in the definition of the Reynolds number; note that
     348             :  * for dimensional cases, this is only guaranteed to be correct if the viscosity is constant.
     349             :  * @return constant dynamic viscosity
     350             :  */
     351             : double viscosity();
     352             : 
     353             : /**
     354             :  * Get the Prandtl number; note that for dimensional cases, this is only guaranteed
     355             :  * to be correct if the density, viscosity, heat capacity, and conductivity are constant.
     356             :  * @return constant Prandtl number
     357             :  */
     358             : double Pr();
     359             : 
     360             : /// Copy the deformation from host to device
     361             : void copyDeformationToDevice();
     362             : 
     363             : template <typename T>
     364             : void allgatherv(const std::vector<int> & base_counts,
     365             :                 const T * input,
     366             :                 T * output,
     367             :                 const int multiplier = 1);
     368             : 
     369             : /**
     370             :  * Determine the receiving counts and displacements for all gather routines
     371             :  * @param[in] base_counts unit-wise receiving counts for each process
     372             :  * @param[out] counts receiving counts from each process
     373             :  * @param[out] displacement displacement for each process's counts
     374             :  * @param[in] multiplier optional multiplier on the face-based data
     375             :  */
     376             : void displacementAndCounts(const std::vector<int> & base_counts,
     377             :                            int * counts,
     378             :                            int * displacement,
     379             :                            const int multiplier);
     380             : 
     381             : /**
     382             :  * Form the 2-D interpolation matrix from a starting GLL quadrature rule to an ending
     383             :  * GLL quadrature rule.
     384             :  * @param[out] I interpolation matrix
     385             :  * @param[in] starting_points number of points in the source quadrature rule
     386             :  * @param[in] ending_points number of points in the end quadrature rule
     387             :  */
     388             : void interpolationMatrix(double * I, int starting_points, int ending_points);
     389             : 
     390             : /**
     391             :  * Interpolate face data onto a new set of points
     392             :  * @param[in] scratch available scratch space for the calculation
     393             :  * @param[in] I interpolation matrix
     394             :  * @param[in] x face data to be interpolated
     395             :  * @param[in] N number of points in 1-D to be interpolated
     396             :  * @param[out] Ix interpolated data
     397             :  * @param[in] M resulting number of interpolated points in 1-D
     398             :  */
     399             : void interpolateSurfaceFaceHex3D(
     400             :     double * scratch, const double * I, double * x, int N, double * Ix, int M);
     401             : 
     402             : /**
     403             :  * Compute the face centroid given a local element ID and face ID (NOTE: returns in dimensional
     404             :  * form)
     405             :  * @param[in] local_elem_id local element ID on this rank
     406             :  * @param[in] local_face_id local face ID on the element
     407             :  * @return centroid
     408             :  */
     409             : Point centroidFace(int local_elem_id, int local_face_id);
     410             : 
     411             : /**
     412             :  * Compute the centroid given a local element ID (NOTE: returns in dimensional form)
     413             :  * @param[in] local_elem_id local element ID on this rank
     414             :  * @return centroid
     415             :  */
     416             : Point centroid(int local_elem_id);
     417             : 
     418             : /**
     419             :  * Get the coordinate given a local element ID and local node ID (NOTE: returns in dimensional form)
     420             :  * @param[in] local_elem_id local element ID on this rank
     421             :  * @param[in] local_node_id local node ID on this element
     422             :  * @return point
     423             :  */
     424             : Point gllPoint(int local_elem_id, int local_node_id);
     425             : 
     426             : /**
     427             :  * Get the coordinate given a local element ID, a local face ID, and local node ID (NOTE: returns in
     428             :  * dimensional form)
     429             :  * @param[in] local_elem_id local element ID on this rank
     430             :  * @param[in] local_face_id local face ID on this element
     431             :  * @param[in] local_node_id local node ID on this element
     432             :  * @return point
     433             :  */
     434             : Point gllPointFace(int local_elem_id, int local_face_id, int local_node_id);
     435             : 
     436             : /**
     437             :  * Integrate the scratch space over boundaries
     438             :  * @param[in] slot slot in scratch space
     439             :  * @param[in] boundary boundaries over which to integrate the scratch space
     440             :  * @param[in] pp_mesh portion of NekRS mesh to integrate over
     441             :  * @return boundary integrated scratch space, with one value per sideset
     442             :  */
     443             : std::vector<double> usrwrkSideIntegral(const unsigned int & slot,
     444             :                                        const std::vector<int> & boundary,
     445             :                                        const nek_mesh::NekMeshEnum pp_mesh);
     446             : 
     447             : /**
     448             :  * Volume integrate the scratch space
     449             :  * @param[in] slot slot in scratch space to i ntegrat
     450             :  * @param[in] pp_mesh NekRS mesh to integrate over
     451             :  * @return volume integrated scratch space
     452             :  */
     453             : double usrwrkVolumeIntegral(const unsigned int & slot, const nek_mesh::NekMeshEnum pp_mesh);
     454             : 
     455             : /**
     456             :  * Scale a slot in the usrwrk by a fixed value (multiplication)
     457             :  * @param[in] slot slot in usrwrk to modify
     458             :  * @param[in] value value to multiply on scratch slot
     459             :  */
     460             : void scaleUsrwrk(const unsigned int & slot, const dfloat & value);
     461             : 
     462             : /**
     463             :  * Compute the area of a set of boundary IDs
     464             :  * @param[in] boundary_id nekRS boundary IDs for which to perform the integral
     465             :  * @param[in] pp_mesh which NekRS mesh to operate on
     466             :  * @return area integral
     467             :  */
     468             : double area(const std::vector<int> & boundary_id, const nek_mesh::NekMeshEnum pp_mesh);
     469             : 
     470             : /**
     471             :  * Compute the area integral of a given integrand over a set of boundary IDs
     472             :  * @param[in] boundary_id nekRS boundary IDs for which to perform the integral
     473             :  * @param[in] integrand field to integrate
     474             :  * @param[in] pp_mesh which NekRS mesh to operate on
     475             :  * @return area integral of a field
     476             :  */
     477             : double sideIntegral(const std::vector<int> & boundary_id, const field::NekFieldEnum & integrand,
     478             :                     const nek_mesh::NekMeshEnum pp_mesh);
     479             : 
     480             : /**
     481             :  * Compute the volume over the entire scalar mesh
     482             :  * @param[in] pp_mesh which NekRS mesh to operate on
     483             :  * @return volume integral
     484             :  */
     485             : double volume(const nek_mesh::NekMeshEnum pp_mesh);
     486             : 
     487             : /**
     488             :  * Dimensionalize a volume
     489             :  * @param[in] integral integral to dimensionalize
     490             :  */
     491             : void dimensionalizeVolume(double & integral);
     492             : 
     493             : /**
     494             :  * Dimensionalize an area
     495             :  * @param[in] integral integral to dimensionalize
     496             :  */
     497             : void dimensionalizeArea(double & integral);
     498             : 
     499             : /**
     500             :  * Dimensionalize a given integral of f over volume, i.e. fdV
     501             :  * @param[in] integrand field to dimensionalize
     502             :  * @param[in] volume volume of the domain (only used for dimensionalizing temperature)
     503             :  * @param[in] integral integral to dimensionalize
     504             :  */
     505             : void dimensionalizeVolumeIntegral(const field::NekFieldEnum & integrand,
     506             :                                   const Real & volume,
     507             :                                   double & integral);
     508             : 
     509             : /**
     510             :  * Dimensionalize a given integral of f over a side, i.e. fdS
     511             :  * @param[in] integrand field to dimensionalize
     512             :  * @param[in] area area of the boundary
     513             :  * @param[in] integral integral to dimensionalize
     514             :  */
     515             : void dimensionalizeSideIntegral(const field::NekFieldEnum & integrand,
     516             :                                 const Real & area,
     517             :                                 double & integral);
     518             : 
     519             : /**
     520             :  * Dimensionalize a given integral of f over a side, i.e. fdS
     521             :  * @param[in] integrand field to dimensionalize
     522             :  * @param[in] boundary_id boundary IDs for the integral
     523             :  * @param[in] integral integral to dimensionalize
     524             :  * @param[in] pp_mesh which NekRS mesh to operate on
     525             :  */
     526             : void dimensionalizeSideIntegral(const field::NekFieldEnum & integrand,
     527             :                                 const std::vector<int> & boundary_id,
     528             :                                 double & integral,
     529             :                                 const nek_mesh::NekMeshEnum pp_mesh);
     530             : 
     531             : /**
     532             :  * Compute the volume integral of a given integrand over the entire scalar mesh
     533             :  * @param[in] integrand field to integrate
     534             :  * @param[in] volume volume of the domain (only used for dimensionalizing temperature)
     535             :  * @param[in] pp_mesh which NekRS mesh to operate on
     536             :  * @return volume integral of a field
     537             :  */
     538             : double volumeIntegral(const field::NekFieldEnum & integrand,
     539             :                       const double & volume,
     540             :                       const nek_mesh::NekMeshEnum pp_mesh);
     541             : 
     542             : /**
     543             :  * Transform the point and time passed into a function into dimensional form, because
     544             :  * the functions on the MOOSE side are defined in dimensional form.
     545             :  * @param[in] f function to query
     546             :  * @param[in] time time
     547             :  * @param[in] id element ID
     548             :  */
     549             : double evaluateFunctionOnMesh(const Function * f, const Real time, const int id);
     550             : 
     551             : /**
     552             :  * Compute the L^N norm of a given integrand over the mesh
     553             :  * @param[in] integrand field to integrate
     554             :  * @param[in] pp_mesh which NekRS mesh to operate on
     555             :  * @param[in] function MOOSE function to use to shift the field
     556             :  * @param[in] time time to evaluate function at
     557             :  * @param[in] N order of the norm
     558             :  * @return integrated L^N norm of the NekRS field, relative to a function
     559             :  */
     560             : double volumeNorm(const field::NekFieldEnum & integrand,
     561             :                   const nek_mesh::NekMeshEnum pp_mesh,
     562             :                   const Function * function,
     563             :                   const Real & time,
     564             :                   const Real & N);
     565             : 
     566             : /**
     567             :  * Compute the mass flowrate over a set of boundary IDs
     568             :  * @param[in] boundary_id nekRS boundary IDs for which to compute the mass flowrate
     569             :  * @param[in] pp_mesh which NekRS mesh to operate on
     570             :  * @return mass flowrate
     571             :  */
     572             : double massFlowrate(const std::vector<int> & boundary_id,
     573             :                     const nek_mesh::NekMeshEnum pp_mesh);
     574             : 
     575             : /**
     576             :  * Compute the mass flux weighted integral of a given integrand over a set of boundary IDs
     577             :  * @param[in] boundary_id nekRS boundary IDs for which to perform the integral
     578             :  * @param[in] integrand field to integrate and weight by mass flux
     579             :  * @param[in] pp_mesh which NekRS mesh to operate on
     580             :  * @return mass flux weighted area average of a field
     581             :  */
     582             : double sideMassFluxWeightedIntegral(const std::vector<int> & boundary_id,
     583             :                                     const field::NekFieldEnum & integrand,
     584             :                                     const nek_mesh::NekMeshEnum pp_mesh);
     585             : 
     586             : /**
     587             :  * Compute the integral of pressure on a surface, multiplied by the unit normal
     588             :  * of the surface with a specified direction vector. This represents the force
     589             :  * that the fluid exerts ON the boundary.
     590             :  * @param[in] boundary_id NekRS boundary IDs for which to perform the integral
     591             :  * @param[in] direction unit vector to dot with the boundary surface normal
     592             :  * @param[in] pp_mesh which NekRS mesh to operate on
     593             :  * @return pressure surface force, along a particular direction
     594             :  */
     595             : double pressureSurfaceForce(const std::vector<int> & boundary_id, const Point & direction, const nek_mesh::NekMeshEnum pp_mesh);
     596             : 
     597             : /**
     598             :  * Compute the heat flux over a set of boundary IDs
     599             :  * @param[in] boundary_id nekRS boundary IDs for which to perform the integral
     600             :  * @param[in] pp_mesh which NekRS mesh to operate on
     601             :  * @return heat flux area integral
     602             :  */
     603             : double heatFluxIntegral(const std::vector<int> & boundary_id,
     604             :                         const nek_mesh::NekMeshEnum pp_mesh);
     605             : 
     606             : /**
     607             :  * Limit the temperature in nekRS to within the range of [min_T, max_T]
     608             :  * @param[in] min_T minimum temperature allowable in nekRS
     609             :  * @param[in] max_T maximum temperature allowable in nekRS
     610             :  */
     611             : void limitTemperature(const double * min_T, const double * max_T);
     612             : 
     613             : /**
     614             :  * Compute the gradient of a volume field
     615             :  * @param[in] offset in the gradient field for each component (grad_x, grad_y, or grad_z)
     616             :  * @param[in] e element ID to compute gradient
     617             :  * @param[in] f field to compute the gradient of
     618             :  * @param[in] pp_mesh which NekRS mesh to operate on
     619             :  * @param[out] grad_f gradient of field
     620             :  */
     621             : void gradient(const int offset,
     622             :               const int e,
     623             :               const double * f,
     624             :               double * grad_f,
     625             :               const nek_mesh::NekMeshEnum pp_mesh);
     626             : 
     627             : /**
     628             :  * Find the extreme value of a given field over the entire nekRS domain
     629             :  * @param[in] field field to find the minimum value of
     630             :  * @param[in] pp_mesh which NekRS mesh to operate on
     631             :  * @param[in] max whether to take the maximum (or if false, the minimum)
     632             :  * @return max or min value of field in volume
     633             :  */
     634             : double volumeExtremeValue(const field::NekFieldEnum & field,
     635             :                           const nek_mesh::NekMeshEnum pp_mesh,
     636             :                           const bool max);
     637             : 
     638             : /**
     639             :  * Find the extreme of a given field over a set of boundary IDs
     640             :  * @param[in] boundary_id nekRS boundary IDs for which to find the extreme value
     641             :  * @param[in] field field to find the maximum value of
     642             :  * @param[in] pp_mesh which NekRS mesh to operate on
     643             :  * @param[in] max whether to take the maximum (or if false, the minimum)
     644             :  * @return max or min value of field on boundary
     645             :  */
     646             : double sideExtremeValue(const std::vector<int> & boundary_id, const field::NekFieldEnum & field,
     647             :                         const nek_mesh::NekMeshEnum pp_mesh, const bool max);
     648             : 
     649             : /**
     650             :  * Number of faces per element; because NekRS only supports HEX20, this should be 6
     651             :  * @return number of faces per mesh element
     652             :  */
     653             : int Nfaces();
     654             : 
     655             : /**
     656             :  * Whether the specific boundary is a flux boundary
     657             :  * @param[in] boundary boundary ID
     658             :  * @return whether boundary is a flux boundary
     659             :  */
     660             : bool isHeatFluxBoundary(const int boundary);
     661             : 
     662             : /**
     663             :  * Whether the specific boundary is a moving mesh boundary
     664             :  * @param[in] boundary boundary ID
     665             :  * @return whether boundary is a moving mesh boundary
     666             :  */
     667             : bool isMovingMeshBoundary(const int boundary);
     668             : 
     669             : /**
     670             :  * Whether the specific boundary is a specified temperature boundary
     671             :  * @param[in] boundary boundary ID
     672             :  * @return whether boundary is a temperature boundary
     673             :  */
     674             : bool isTemperatureBoundary(const int boundary);
     675             : 
     676             : /**
     677             :  * String name indicating the temperature boundary condition type on a given boundary
     678             :  * @param[in] boundary boundary ID
     679             :  * @return string name of boundary condition type
     680             :  */
     681             : const std::string temperatureBoundaryType(const int boundary);
     682             : 
     683             : /**
     684             :  * Polynomial order used in nekRS solution
     685             :  * @return polynomial order
     686             :  */
     687             : int polynomialOrder();
     688             : 
     689             : /**
     690             :  * Total number of volume elements in nekRS mesh summed over all processes
     691             :  * @return number of volume elements
     692             :  */
     693             : int Nelements();
     694             : 
     695             : /**
     696             :  * Mesh dimension
     697             :  * @return mesh dimension
     698             :  */
     699             : int dim();
     700             : 
     701             : /**
     702             :  * \brief Number of vertices required to define an element face
     703             :  * Vertices refer to the points required to place the "corners" of an element face,
     704             :  * and _not_ the quadrature points. For instance, for hexahedral elements, the number of vertices
     705             :  * per face is 4 regardless of the polynomial order.
     706             :  * @return Number of vertices per element face
     707             :  */
     708             : int NfaceVertices();
     709             : 
     710             : /**
     711             :  * Total number of element faces on a boundary of the nekRS mesh summed over all processes
     712             :  * @return number of boundary element faces
     713             :  */
     714             : int NboundaryFaces();
     715             : 
     716             : /**
     717             :  * Number of boundary IDs in the nekRS mesh
     718             :  * @return number of boundary IDs
     719             :  */
     720             : int NboundaryID();
     721             : 
     722             : /**
     723             :  * Whether the provided boundary IDs are all valid in the nekRS mesh
     724             :  * @param[in] boundary_id vector of boundary IDs to check
     725             :  * @param[out] first_invalid_id first invalid ID encountered for printing an error on the MOOSE side
     726             :  * @param[out] n_boundaries maximum valid boundary ID for printing an error on the MOOSE side
     727             :  * @return whether all boundaries are valid
     728             :  */
     729             : bool
     730             : validBoundaryIDs(const std::vector<int> & boundary_id, int & first_invalid_id, int & n_boundaries);
     731             : 
     732             : /**
     733             :  * Store the rank-local element, element-local face, and rank ownership for boundary coupling
     734             :  * @param[in] boundary_id boundaries through which nekRS will be coupled
     735             :  * @param[out] N total number of surface elements
     736             :  */
     737             : void storeBoundaryCoupling(const std::vector<int> & boundary_id, int & N);
     738             : 
     739             : /**
     740             :  * Characteristic scales assumed in nekRS if using a non-dimensional solution; initial values
     741             :  * are applied, which will be overridden by the DimensionalizeAction in Cardinal.
     742             :  */
     743             : struct characteristicScales
     744             : {
     745             :   double U_ref = 1;
     746             :   double T_ref = 0;
     747             :   double dT_ref = 1;
     748             :   double P_ref = 1;
     749             :   double L_ref = 1;
     750             :   double A_ref = 1;
     751             :   double V_ref = 1;
     752             :   double rho_ref = 1;
     753             :   double Cp_ref = 1;
     754             :   double flux_ref = 1;
     755             :   double source_ref = 1;
     756             :   double t_ref = 1;
     757             :   double s01_ref = 0;
     758             :   double ds01_ref = 1;
     759             :   double s02_ref = 0;
     760             :   double ds02_ref = 1;
     761             :   double s03_ref = 0;
     762             :   double ds03_ref = 1;
     763             : };
     764             : 
     765             : /**
     766             :  * Get pointer to various solution functions (for reading only) based on enumeration
     767             :  * @param[in] field field to return a pointer to
     768             :  * @return function pointer to method that returns said field as a function of GLL index
     769             :  */
     770             : double (*solutionPointer(const field::NekFieldEnum & field))(int, int);
     771             : double (*solutionPointer(const field::NekWriteEnum & field))(int, int);
     772             : 
     773             : /**
     774             :  * Determine the index in the scalar array for the non-temperature scalars
     775             :  * @param[in] id id of the scalar; 1 corresponds to first non-temperature scalar, etc.
     776             :  * @return slot in scalar array that holds this variable
     777             :  */
     778             : int scalarSlot(const int id);
     779             : 
     780             : /**
     781             :  * Get the scalar01 solution at given GLL index
     782             :  * @param[in] id GLL index
     783             :  * @return scalar01 value at index
     784             :  */
     785             : double get_scalar01(const int id, const int surf_offset);
     786             : 
     787             : /**
     788             :  * Get the scalar02 solution at given GLL index
     789             :  * @param[in] id GLL index
     790             :  * @return scalar02 value at index
     791             :  */
     792             : double get_scalar02(const int id, const int surf_offset);
     793             : 
     794             : /**
     795             :  * Get the scalar03 solution at given GLL index
     796             :  * @param[in] id GLL index
     797             :  * @return scalar03 value at index
     798             :  */
     799             : double get_scalar03(const int id, const int surf_offset);
     800             : 
     801             : /**
     802             :  * Get the usrwrk zeroth slice at given GLL index
     803             :  * @param[in] id GLL index
     804             :  * @return zeroth slice of usrwrk value at index
     805             :  */
     806             : double get_usrwrk00(const int id, const int surf_offset);
     807             : 
     808             : /**
     809             :  * Get the usrwrk first slice at given GLL index
     810             :  * @param[in] id GLL index
     811             :  * @return first slice of usrwrk value at index
     812             :  */
     813             : double get_usrwrk01(const int id, const int surf_offset);
     814             : 
     815             : /**
     816             :  * Get the usrwrk second slice at given GLL index
     817             :  * @param[in] id GLL index
     818             :  * @return second slice of usrwrk value at index
     819             :  */
     820             : double get_usrwrk02(const int id, const int surf_offset);
     821             : 
     822             : /**
     823             :  * Get the temperature solution at given GLL index
     824             :  * @param[in] id GLL index
     825             :  * @return temperature value at index
     826             :  */
     827             : double get_temperature(const int id, const int surf_offset);
     828             : 
     829             : /**
     830             :  * Get the pressure solution at given GLL index
     831             :  * @param[in] id GLL index
     832             :  * @return pressure value at index
     833             :  */
     834             : double get_pressure(const int id, const int surf_offset);
     835             : 
     836             : /**
     837             :  * Return unity, for cases where the integrand or operator we are generalizing acts on 1
     838             :  * @param[in] id GLL index
     839             :  * @return unity
     840             :  */
     841             : double get_unity(const int id, const int surf_offset);
     842             : 
     843             : /**
     844             :  * Get the x-velocity at given GLL index
     845             :  * @param[in] id GLL index
     846             :  * @return x-velocity at index
     847             :  */
     848             : double get_velocity_x(const int id, const int surf_offset);
     849             : 
     850             : /**
     851             :  * Get the y-velocity at given GLL index
     852             :  * @param[in] id GLL index
     853             :  * @return y-velocity at index
     854             :  */
     855             : double get_velocity_y(const int id, const int surf_offset);
     856             : 
     857             : /**
     858             :  * Get the z-velocity at given GLL index
     859             :  * @param[in] id GLL index
     860             :  * @return z-velocity at index
     861             :  */
     862             : double get_velocity_z(const int id, const int surf_offset);
     863             : 
     864             : /**
     865             :  * Get the magnitude of the velocity solution at given GLL index
     866             :  * @param[in] id GLL index
     867             :  * @return velocity magnitude at index
     868             :  */
     869             : double get_velocity(const int id, const int surf_offset);
     870             : 
     871             : /**
     872             :  * Get the x-velocity squared at given GLL index
     873             :  * @param[in] id GLL index
     874             :  * @return square of x-velocity at index
     875             :  */
     876             : double get_velocity_x_squared(const int id, const int surf_offset);
     877             : 
     878             : /**
     879             :  * Get the y-velocity squared at given GLL index
     880             :  * @param[in] id GLL index
     881             :  * @return square of y-velocity at index
     882             :  */
     883             : double get_velocity_y_squared(const int id, const int surf_offset);
     884             : 
     885             : /**
     886             :  * Get the z-velocity squared at given GLL index
     887             :  * @param[in] id GLL index
     888             :  * @return square of z-velocity at index
     889             :  */
     890             : double get_velocity_z_squared(const int id, const int surf_offset);
     891             : 
     892             : /**
     893             :  * Initialize the characteristic scales for a nondimesional solution
     894             :  * @param[in] U reference velocity
     895             :  * @param[in] T reference temperature
     896             :  * @param[in] dT reference temperature range
     897             :  * @param[in] L reference length scale
     898             :  * @param[in] rho reference density
     899             :  * @param[in] Cp reference heat capacity
     900             :  * @param[in] s01 reference scalar01
     901             :  * @param[in] ds01 reference s01 range
     902             :  * @param[in] s02 reference scalar02
     903             :  * @param[in] ds02 reference s02 range
     904             :  * @param[in] s03 reference scalar03
     905             :  * @param[in] ds03 reference s03 range
     906             :  */
     907             : void initializeDimensionalScales(const double U,
     908             :                                  const double T,
     909             :                                  const double dT,
     910             :                                  const double L,
     911             :                                  const double rho,
     912             :                                  const double Cp,
     913             :                                  const double s01,
     914             :                                  const double ds01,
     915             :                                  const double s02,
     916             :                                  const double ds02,
     917             :                                  const double s03,
     918             :                                  const double ds03);
     919             : 
     920             : /**
     921             :  * \brief Return the reference divisor scale that defines the non-dimensional field
     922             :  *
     923             :  * All fields in NekRS are assumed non-dimensionalized according to the general form
     924             :  * f (non-dimensional) = (f - f_ref) / df
     925             :  *
     926             :  * so that to define a nondimensionalization requires two scales: the divisor scale
     927             :  * (df) and the additive scale (f_ref).
     928             :  *
     929             :  * @param[in] field physical interpretation of value
     930             :  * @param[out] value nondimensional divisor scale (df)
     931             :  */
     932             : Real nondimensionalDivisor(const field::NekFieldEnum & field);
     933             : Real nondimensionalDivisor(const field::NekWriteEnum & field);
     934             : 
     935             : /**
     936             :  * All fields in NekRS are assumed non-dimensionalized according to the general form
     937             :  * f (non-dimensional) = (f - f_ref) / df
     938             :  *
     939             :  * so that to define a nondimensionalization requires two scales: the divisor scale
     940             :  * (df) and the additive scale (f_ref).
     941             :  *
     942             :  * @param[in] field physical interpretation of value
     943             :  * @param[out] value nondimensional additive scale (f_ref)
     944             :  *
     945             :  */
     946             : Real nondimensionalAdditive(const field::NekFieldEnum & field);
     947             : Real nondimensionalAdditive(const field::NekWriteEnum & field);
     948             : 
     949             : /**
     950             :  * Get the reference length scale
     951             :  * @return reference length scale
     952             :  */
     953             : double referenceLength();
     954             : 
     955             : /**
     956             :  * Get the reference time scale
     957             :  * @return reference time scale
     958             :  */
     959             : double referenceTime();
     960             : 
     961             : /**
     962             :  * Get the reference area scale
     963             :  * @return reference area scale
     964             :  */
     965             : double referenceArea();
     966             : 
     967             : /**
     968             :  * Get the reference volume scale
     969             :  * @return reference volume scale
     970             :  */
     971             : double referenceVolume();
     972             : 
     973             : // useful concept from Stack Overflow for templating MPI calls
     974             : template <typename T>
     975             : MPI_Datatype resolveType();
     976             : 
     977             : /**
     978             :  * Helper function for MPI_Allgatherv of results in NekRS
     979             :  * @param[in] base_counts once multiplied by 'multiplier', the number of counts on each rank
     980             :  * @param[in] input rank-local data
     981             :  * @param[out] output collected result
     982             :  * @param[in] multiplier constant multiplier to set on each count indicator
     983             :  */
     984             : template <typename T>
     985             : void
     986       36379 : allgatherv(const std::vector<int> & base_counts, const T * input, T * output, const int multiplier)
     987             : {
     988       36379 :   int * recvCounts = (int *)calloc(commSize(), sizeof(int));
     989       36379 :   int * displacement = (int *)calloc(commSize(), sizeof(int));
     990       36379 :   displacementAndCounts(base_counts, recvCounts, displacement, multiplier);
     991             : 
     992       36379 :   MPI_Allgatherv(input,
     993             :                  recvCounts[commRank()],
     994             :                  resolveType<T>(),
     995             :                  output,
     996             :                  (const int *)recvCounts,
     997             :                  (const int *)displacement,
     998             :                  resolveType<T>(),
     999             :                  platform->comm.mpiComm());
    1000             : 
    1001       36379 :   free(recvCounts);
    1002       36379 :   free(displacement);
    1003       36379 : }
    1004             : 
    1005             : void initializeNekHostArrays();
    1006             : 
    1007             : // Accessors for NekRS host arrays
    1008             : std::tuple<dfloat *, dfloat *, dfloat *> host_xyz();
    1009             : std::vector<dfloat> & host_U();
    1010             : std::vector<dfloat> & host_P();
    1011             : std::vector<dfloat> & host_S();
    1012             : dfloat * host_wrk();
    1013             : 
    1014             : mesh_t * createMesh2(mesh_t * _mesh, int Nc);
    1015             : 
    1016             : } // end namespace nekrs

Generated by: LCOV version 1.14