PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
 
Loading...
Searching...
No Matches
Data Structures | Typedefs | Enumerations | Functions | Variables
expression.h File Reference

The expression language shared by every configured field, and the keyed hashes its random draws and other reproducible draws are built from. More...

#include <stdint.h>
#include <petscsys.h>
#include "variables.h"
Include dependency graph for expression.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  PicurvExpressionDrawKey
 What a random draw is keyed on, besides the particle and its stream. More...
 
struct  PicurvVelocitySource
 A prescribed velocity, for any target: one compiled expression per value, the frame they are in, and the bulk velocity it is scaled to, if any. More...
 
struct  PicurvSourceFaceSlots
 What a source reads at each boundary-face slot this rank owns, gathered once. More...
 

Typedefs

typedef struct PicurvExpression PicurvExpression
 A compiled expression: postfix code for a small stack evaluator.
 

Enumerations

enum  PicurvDrawSpace {
  PICURV_DRAW_SPACE_FIELD = 0 , PICURV_DRAW_SPACE_NAMED_STREAM = 1 , PICURV_DRAW_SPACE_BROWNIAN = 2 , PICURV_DRAW_SPACE_PLACEMENT = 3 ,
  PICURV_DRAW_SPACE_INLET = 4
}
 Disjoint key spaces of the keyed particle draws, so draws made for different purposes never coincide for one particle. More...
 
enum  PicurvSourceVariable {
  PICURV_SOURCE_VAR_X = 0 , PICURV_SOURCE_VAR_Y , PICURV_SOURCE_VAR_Z , PICURV_SOURCE_VAR_T ,
  PICURV_SOURCE_VAR_XI , PICURV_SOURCE_VAR_ETA , PICURV_SOURCE_VAR_ZETA , PICURV_SOURCE_VAR_L_XI ,
  PICURV_SOURCE_VAR_L_ETA , PICURV_SOURCE_VAR_L_ZETA , PICURV_SOURCE_VAR_CELL_COUNT , PICURV_SOURCE_VAR_R = PICURV_SOURCE_VAR_CELL_COUNT ,
  PICURV_SOURCE_VAR_COUNT
}
 Variables a prescribed velocity source may use, in the order of values[]. More...
 
enum  PicurvSourceFrame { PICURV_SOURCE_FRAME_CARTESIAN = 0 , PICURV_SOURCE_FRAME_CURVILINEAR = 1 , PICURV_SOURCE_FRAME_NORMAL = 2 , PICURV_SOURCE_FRAME_CONTRAVARIANT = 3 }
 How a source's values are read. More...
 

Functions

uint64_t PicurvMix64 (uint64_t z)
 splitmix64 finalizer: a bijective mix of 64 bits.
 
PetscReal PicurvUnitFromHash (uint64_t hash)
 Uniform on [0, 1) from the top 53 bits of a hash.
 
uint64_t PicurvParticleDrawHash (PetscInt64 seed, PicurvDrawSpace space, uint64_t stream, PetscInt64 pid, PetscInt64 salt)
 Hash that keys a particle draw: a pure function of its arguments, so a draw does not depend on the rank a particle lives on, the order particles are visited, or what was drawn before it.
 
PetscErrorCode PicurvExpressionCompile (const char *text, const char *const *names, PetscInt name_count, PetscBool allow_random, PicurvExpression **expression)
 Compile one expression against a list of variable names.
 
PetscErrorCode PicurvExpressionEvaluate (const PicurvExpression *expression, const PetscReal *values, const PicurvExpressionDrawKey *key, PetscReal *result)
 Evaluate a compiled expression.
 
PetscErrorCode PicurvExpressionDestroy (PicurvExpression **expression)
 Free a compiled expression.
 
PetscErrorCode PicurvExpressionUsesVariable (const PicurvExpression *expression, PetscInt index, PetscBool *uses)
 Whether a compiled expression reads one of its variables.
 
PetscErrorCode PicurvVelocitySourceCreate (const char *prefix, PetscBool on_face, PetscBool has_data, PicurvVelocitySource *source)
 Read and compile a velocity source from the options database.
 
PetscErrorCode PicurvVelocitySourceBulkFactor (const PicurvVelocitySource *source, PetscReal physical_time, const PetscReal local[3], const char *where, PetscReal *factor)
 Factor on a source's expressions that makes a target's whole mean equal its bulk velocity.
 
static void PicurvSourceSetVariables (PetscReal *values, Cmpnts point, Cmpnts fraction, Cmpnts length, PetscReal L_ref)
 Fill a source's position and grid-line variables at one point.
 
PetscErrorCode PicurvSourceFaceSlotsCreate (UserCtx *user, BCFace face_id, Vec fraction, Vec length, PicurvSourceFaceSlots *slots)
 Gather each owned slot of a boundary face: face-centre position, the grid-line fractions and lengths of the interior cell behind it, and its directions.
 
PetscErrorCode PicurvSourceFaceSlotsDestroy (PicurvSourceFaceSlots *slots)
 Release what PicurvSourceFaceSlotsCreate() allocated.
 
PetscErrorCode PicurvVelocitySourceEvaluate (const PicurvVelocitySource *source, const PetscReal *values, const Cmpnts edges[3], Cmpnts *value)
 Evaluate a source at one point.
 
PetscErrorCode PicurvSourceSetCellPressure (UserCtx *user, const PicurvExpression *pressure, Vec fraction, Vec length, PetscReal physical_time)
 Set a block's pressure at every interior cell centre from an expression in Pa.
 
PetscErrorCode PicurvSourceCellBulkFactor (UserCtx *user, const PicurvVelocitySource *source, Vec fraction, Vec length, PetscReal physical_time, PetscReal *factor)
 Factor on a source's expressions that makes the volume mean of the whole field, along the source's own direction at each cell, equal its bulk velocity.
 
PetscErrorCode PicurvSourceAddFluxes (UserCtx *user, const PicurvVelocitySource *source, Vec fraction, Vec length, PetscReal physical_time, PetscReal factor, PetscBool boundary_faces)
 Add a source's flux to every owned face of Ucont, evaluating it at each face centre.
 
PetscErrorCode PicurvVelocitySourceDestroy (PicurvVelocitySource *source)
 Free a source's compiled expressions and bulk velocity.
 

Variables

const char *const kPicurvSourceVariableNames [PICURV_SOURCE_VAR_COUNT]
 Names of PicurvSourceVariable, in order.
 

Detailed Description

The expression language shared by every configured field, and the keyed hashes its random draws and other reproducible draws are built from.

Callers compile an expression against their own list of variable names and supply the values in that order at evaluation. generators/ic.gen validates the same language; tests/fixtures/expression_conformance.txt holds cases both implementations must agree on.

Definition in file expression.h.


Data Structure Documentation

◆ PicurvExpressionDrawKey

struct PicurvExpressionDrawKey

What a random draw is keyed on, besides the particle and its stream.

Definition at line 67 of file expression.h.

Data Fields
PetscInt64 seed Run seed (-particle_random_seed).
PetscInt64 pid Particle identity; draws are pure functions of it.
PetscInt64 salt Event that produced the particle: 0 for the t=0 population.
PetscInt64 field Field whose expression draws, the default stream's namespace.

◆ PicurvVelocitySource

struct PicurvVelocitySource

A prescribed velocity, for any target: one compiled expression per value, the frame they are in, and the bulk velocity it is scaled to, if any.

A target differs only in the points it evaluates the source at and the weight it takes a mean with.

Definition at line 155 of file expression.h.

Collaboration diagram for PicurvVelocitySource:
[legend]
Data Fields
PicurvSourceFrame frame
PetscInt count 1 for the normal frame, otherwise 3; 0 for staged data alone.
PicurvExpression * component[3]
PetscBool time_dependent Some component reads t.
PicurvExpression * bulk Target mean speed [m/s] in t, or NULL.
PetscBool bulk_time_dependent
PetscBool bulk_is_flow_rate bulk is a volumetric flow rate [m^3/s] through a face instead.

◆ PicurvSourceFaceSlots

struct PicurvSourceFaceSlots

What a source reads at each boundary-face slot this rank owns, gathered once.

Definition at line 221 of file expression.h.

Collaboration diagram for PicurvSourceFaceSlots:
[legend]
Data Fields
PetscInt normal Logical axis of the face normal.
PetscInt a
PetscInt b The two tangential axes.
PetscInt layer Index along the normal of the face's metric and flux.
PetscInt lo[2] First tangential indices of the owned slots.
PetscInt n[2] Owned slots along the two tangential axes; 0 off the face.
PetscReal(* values)[PICURV_SOURCE_VAR_COUNT] Variables per slot; t is the caller's.
Cmpnts(* edges)[3] Directions per slot, for the curvilinear frame.

Typedef Documentation

◆ PicurvExpression

A compiled expression: postfix code for a small stack evaluator.

Definition at line 64 of file expression.h.

Enumeration Type Documentation

◆ PicurvDrawSpace

Disjoint key spaces of the keyed particle draws, so draws made for different purposes never coincide for one particle.

Enumerator
PICURV_DRAW_SPACE_FIELD 

An expression's default, per-field stream.

PICURV_DRAW_SPACE_NAMED_STREAM 

uniform(k)/normal(k): a stream shared across fields.

PICURV_DRAW_SPACE_BROWNIAN 

Brownian increments; the salt is the step.

PICURV_DRAW_SPACE_PLACEMENT 

Seeding points; the salt is the rejection attempt.

PICURV_DRAW_SPACE_INLET 

Injection at an inlet: stream 0 counts per face cell, stream 1 distance in.

Definition at line 27 of file expression.h.

27 {
28 PICURV_DRAW_SPACE_FIELD = 0, /**< An expression's default, per-field stream. */
29 PICURV_DRAW_SPACE_NAMED_STREAM = 1, /**< `uniform(k)`/`normal(k)`: a stream shared across fields. */
30 PICURV_DRAW_SPACE_BROWNIAN = 2, /**< Brownian increments; the salt is the step. */
31 PICURV_DRAW_SPACE_PLACEMENT = 3, /**< Seeding points; the salt is the rejection attempt. */
32 PICURV_DRAW_SPACE_INLET = 4 /**< Injection at an inlet: stream 0 counts per face cell, stream 1 distance in. */
PicurvDrawSpace
Disjoint key spaces of the keyed particle draws, so draws made for different purposes never coincide ...
Definition expression.h:27
@ PICURV_DRAW_SPACE_FIELD
An expression's default, per-field stream.
Definition expression.h:28
@ PICURV_DRAW_SPACE_BROWNIAN
Brownian increments; the salt is the step.
Definition expression.h:30
@ PICURV_DRAW_SPACE_INLET
Injection at an inlet: stream 0 counts per face cell, stream 1 distance in.
Definition expression.h:32
@ PICURV_DRAW_SPACE_NAMED_STREAM
uniform(k)/normal(k): a stream shared across fields.
Definition expression.h:29
@ PICURV_DRAW_SPACE_PLACEMENT
Seeding points; the salt is the rejection attempt.
Definition expression.h:31

◆ PicurvSourceVariable

Variables a prescribed velocity source may use, in the order of values[].

Enumerator
PICURV_SOURCE_VAR_X 

Physical x of the point [m].

PICURV_SOURCE_VAR_Y 

Physical y [m].

PICURV_SOURCE_VAR_Z 

Physical z [m].

PICURV_SOURCE_VAR_T 

Physical time [s].

PICURV_SOURCE_VAR_XI 

Arc-length fraction along the xi grid line, 0 at the - face.

PICURV_SOURCE_VAR_ETA 

Arc-length fraction along the eta grid line.

PICURV_SOURCE_VAR_ZETA 

Arc-length fraction along the zeta grid line.

PICURV_SOURCE_VAR_L_XI 

Physical length of that xi grid line [m].

PICURV_SOURCE_VAR_L_ETA 

Physical length of that eta grid line [m].

PICURV_SOURCE_VAR_L_ZETA 

Physical length of that zeta grid line [m].

PICURV_SOURCE_VAR_CELL_COUNT 

Variables a source reads on every target.

PICURV_SOURCE_VAR_R 

On a face, distance from the face's centre [m].

PICURV_SOURCE_VAR_COUNT 

Definition at line 126 of file expression.h.

126 {
127 PICURV_SOURCE_VAR_X = 0, /**< Physical x of the point [m]. */
128 PICURV_SOURCE_VAR_Y, /**< Physical y [m]. */
129 PICURV_SOURCE_VAR_Z, /**< Physical z [m]. */
130 PICURV_SOURCE_VAR_T, /**< Physical time [s]. */
131 PICURV_SOURCE_VAR_XI, /**< Arc-length fraction along the xi grid line, 0 at the - face. */
132 PICURV_SOURCE_VAR_ETA, /**< Arc-length fraction along the eta grid line. */
133 PICURV_SOURCE_VAR_ZETA, /**< Arc-length fraction along the zeta grid line. */
134 PICURV_SOURCE_VAR_L_XI, /**< Physical length of that xi grid line [m]. */
135 PICURV_SOURCE_VAR_L_ETA, /**< Physical length of that eta grid line [m]. */
136 PICURV_SOURCE_VAR_L_ZETA, /**< Physical length of that zeta grid line [m]. */
137 PICURV_SOURCE_VAR_CELL_COUNT, /**< Variables a source reads on every target. */
138 PICURV_SOURCE_VAR_R = PICURV_SOURCE_VAR_CELL_COUNT, /**< On a face, distance from the face's centre [m]. */
PicurvSourceVariable
Variables a prescribed velocity source may use, in the order of values[].
Definition expression.h:126
@ PICURV_SOURCE_VAR_L_XI
Physical length of that xi grid line [m].
Definition expression.h:134
@ PICURV_SOURCE_VAR_L_ZETA
Physical length of that zeta grid line [m].
Definition expression.h:136
@ PICURV_SOURCE_VAR_XI
Arc-length fraction along the xi grid line, 0 at the - face.
Definition expression.h:131
@ PICURV_SOURCE_VAR_T
Physical time [s].
Definition expression.h:130
@ PICURV_SOURCE_VAR_R
On a face, distance from the face's centre [m].
Definition expression.h:138
@ PICURV_SOURCE_VAR_ZETA
Arc-length fraction along the zeta grid line.
Definition expression.h:133
@ PICURV_SOURCE_VAR_Y
Physical y [m].
Definition expression.h:128
@ PICURV_SOURCE_VAR_X
Physical x of the point [m].
Definition expression.h:127
@ PICURV_SOURCE_VAR_L_ETA
Physical length of that eta grid line [m].
Definition expression.h:135
@ PICURV_SOURCE_VAR_ETA
Arc-length fraction along the eta grid line.
Definition expression.h:132
@ PICURV_SOURCE_VAR_COUNT
Definition expression.h:139
@ PICURV_SOURCE_VAR_CELL_COUNT
Variables a source reads on every target.
Definition expression.h:137
@ PICURV_SOURCE_VAR_Z
Physical z [m].
Definition expression.h:129

◆ PicurvSourceFrame

How a source's values are read.

Enumerator
PICURV_SOURCE_FRAME_CARTESIAN 

Three values: x, y, z velocity components.

PICURV_SOURCE_FRAME_CURVILINEAR 

Three values along the unit xi, eta, zeta grid-line directions.

PICURV_SOURCE_FRAME_NORMAL 

One value: the speed into the domain through a face.

PICURV_SOURCE_FRAME_CONTRAVARIANT 

Three values: the volume flux through the xi, eta, zeta faces; cells only.

Definition at line 143 of file expression.h.

143 {
144 PICURV_SOURCE_FRAME_CARTESIAN = 0, /**< Three values: x, y, z velocity components. */
145 PICURV_SOURCE_FRAME_CURVILINEAR = 1, /**< Three values along the unit xi, eta, zeta grid-line directions. */
146 PICURV_SOURCE_FRAME_NORMAL = 2, /**< One value: the speed into the domain through a face. */
147 PICURV_SOURCE_FRAME_CONTRAVARIANT = 3 /**< Three values: the volume flux through the xi, eta, zeta faces; cells only. */
PicurvSourceFrame
How a source's values are read.
Definition expression.h:143
@ PICURV_SOURCE_FRAME_NORMAL
One value: the speed into the domain through a face.
Definition expression.h:146
@ PICURV_SOURCE_FRAME_CONTRAVARIANT
Three values: the volume flux through the xi, eta, zeta faces; cells only.
Definition expression.h:147
@ PICURV_SOURCE_FRAME_CARTESIAN
Three values: x, y, z velocity components.
Definition expression.h:144
@ PICURV_SOURCE_FRAME_CURVILINEAR
Three values along the unit xi, eta, zeta grid-line directions.
Definition expression.h:145

Function Documentation

◆ PicurvMix64()

uint64_t PicurvMix64 ( uint64_t  z)

splitmix64 finalizer: a bijective mix of 64 bits.

Parameters
[in]zBits to mix.
Returns
The mixed bits.

splitmix64 finalizer: a bijective mix of 64 bits.

See also
PicurvMix64()

Definition at line 587 of file expression.c.

588{
589 z += 0x9E3779B97F4A7C15ULL;
590 z = (z ^ (z >> 30)) * 0xBF58476D1CE4E5B9ULL;
591 z = (z ^ (z >> 27)) * 0x94D049BB133111EBULL;
592 return z ^ (z >> 31);
593}
Here is the caller graph for this function:

◆ PicurvUnitFromHash()

PetscReal PicurvUnitFromHash ( uint64_t  hash)

Uniform on [0, 1) from the top 53 bits of a hash.

Parameters
[in]hashMixed bits.
Returns
A value in [0, 1).

Uniform on [0, 1) from the top 53 bits of a hash.

See also
PicurvUnitFromHash()

Definition at line 599 of file expression.c.

600{
601 return (PetscReal)(hash >> 11) * (1.0 / 9007199254740992.0);
602}
Here is the caller graph for this function:

◆ PicurvParticleDrawHash()

uint64_t PicurvParticleDrawHash ( PetscInt64  seed,
PicurvDrawSpace  space,
uint64_t  stream,
PetscInt64  pid,
PetscInt64  salt 
)

Hash that keys a particle draw: a pure function of its arguments, so a draw does not depend on the rank a particle lives on, the order particles are visited, or what was drawn before it.

Parameters
[in]seedRun seed (-particle_random_seed).
[in]spacePurpose of the draw.
[in]streamStream within the space.
[in]pidParticle identity.
[in]saltEvent that distinguishes repeated draws for one particle.
Returns
64 mixed bits; derive further independent values with PicurvMix64().

Hash that keys a particle draw: a pure function of its arguments, so a draw does not depend on the rank a particle lives on, the order particles are visited, or what was drawn before it.

See also
PicurvParticleDrawHash()

Definition at line 608 of file expression.c.

610{
611 uint64_t hash = PicurvMix64((uint64_t)seed);
612 hash = PicurvMix64(hash ^ (uint64_t)space);
613 hash = PicurvMix64(hash ^ stream);
614 hash = PicurvMix64(hash ^ (uint64_t)pid);
615 return PicurvMix64(hash ^ (uint64_t)salt);
616}
uint64_t PicurvMix64(uint64_t z)
Implementation of PicurvMix64().
Definition expression.c:587
Here is the call graph for this function:
Here is the caller graph for this function:

◆ PicurvExpressionCompile()

PetscErrorCode PicurvExpressionCompile ( const char *  text,
const char *const *  names,
PetscInt  name_count,
PetscBool  allow_random,
PicurvExpression **  expression 
)

Compile one expression against a list of variable names.

The grammar is Python's expression syntax restricted to numbers, the given names, pi, arithmetic (+ - * / % **), comparisons (chained ones included), and/or/not, and the functions abs atan2 cos cosh erf exp floor log maximum minimum sin sinh sqrt tan tanh where, plus uniform and normal when allow_random is true. Comparisons and logical operators yield 1 or 0; % takes the sign of the divisor; ** binds tighter than a unary minus on its left and groups to the right.

Parameters
[in]textExpression text.
[in]namesVariable names, in the order evaluation supplies their values.
[in]name_countNumber of names.
[in]allow_randomWhether uniform and normal may be called.
[out]expressionCompiled expression, owned by the caller.
Returns
Zero on success; PETSC_ERR_ARG_WRONG for a syntax error or an unknown name or function, with the offending position in the message.

Compile one expression against a list of variable names.

See also
PicurvExpressionCompile()

Definition at line 549 of file expression.c.

551{
552 ExpressionParser parser;
553 PetscInt root, depth = 0;
554
555 PetscFunctionBeginUser;
557 PetscCheck(text && expression, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Expression text and output are required.");
558 PetscCall(PetscMemzero(&parser, sizeof(parser)));
559 parser.text = text;
560 parser.names = names;
561 parser.name_count = name_count;
562 parser.allow_random = allow_random;
563 parser.capacity = 4 * (PetscInt)strlen(text) + 8;
564 PetscCall(PetscMalloc1(parser.capacity, &parser.nodes));
565
566 root = ParseOr(&parser);
567 SkipSpace(&parser);
568 if (!parser.error[0] && parser.text[parser.pos]) ParserFail(&parser, "unexpected text");
569 if (parser.error[0]) {
570 PetscCall(PetscFree(parser.nodes));
571 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid expression: %s.", parser.error);
572 }
573
574 PetscCall(PetscNew(expression));
575 (*expression)->length = 0;
576 PetscCall(PetscMalloc1(CountCode(&parser, root), &(*expression)->code));
577 EmitNode(&parser, root, *expression, &depth);
578 PetscCall(PetscFree(parser.nodes));
580 PetscFunctionReturn(0);
581}
static void EmitNode(const ExpressionParser *parser, PetscInt index, PicurvExpression *expression, PetscInt *depth)
Emit postfix code for a subtree and track the stack depth it needs.
Definition expression.c:501
static void SkipSpace(ExpressionParser *parser)
Skip whitespace before the next token.
Definition expression.c:119
PetscBool allow_random
Definition expression.c:101
static PetscInt CountCode(const ExpressionParser *parser, PetscInt index)
Count the instructions a subtree emits (shared subtrees count per use).
Definition expression.c:534
const char *const * names
Definition expression.c:99
const char * text
Definition expression.c:94
static void ParserFail(ExpressionParser *parser, const char *message)
Record the first parse error with its position; later ones are consequences.
Definition expression.c:108
ExpressionNode * nodes
Definition expression.c:96
PetscInt capacity
Definition expression.c:98
char error[256]
Definition expression.c:104
static PetscInt ParseOr(ExpressionParser *parser)
and ('or' and)*
Definition expression.c:489
PetscInt name_count
Definition expression.c:100
Parser state: the text, a cursor, the node pool, and the names in scope.
Definition expression.c:93
#define PROFILE_FUNCTION_END
Marks the end of a profiled code block.
Definition logging.h:1033
#define PROFILE_FUNCTION_BEGIN
Marks the beginning of a profiled function: an always-on aggregate timer.
Definition logging.h:1004
Here is the call graph for this function:
Here is the caller graph for this function:

◆ PicurvExpressionEvaluate()

PetscErrorCode PicurvExpressionEvaluate ( const PicurvExpression *  expression,
const PetscReal *  values,
const PicurvExpressionDrawKey *  key,
PetscReal *  result 
)

Evaluate a compiled expression.

Parameters
[in]expressionCompiled expression.
[in]valuesOne value per compiled name, in compile order.
[in]keyDraw key, required when the expression draws; may be NULL otherwise.
[out]resultValue of the expression; may be non-finite, which the caller judges.
Returns
Zero on success.

Evaluate a compiled expression.

See also
PicurvExpressionEvaluate()

Definition at line 695 of file expression.c.

697{
698 PetscReal stack[expression->max_depth + 1];
699 PetscReal index[EXPRESSION_MAX_SERIES_DEPTH];
700 PetscInt top = 0;
701
702 PetscFunctionBeginUser;
704 PetscCheck(!expression->draws || key, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
705 "An expression that draws random numbers needs a draw key.");
706 for (PetscInt i = 0; i < expression->length; ++i) {
707 const ExpressionInstruction *instruction = &expression->code[i];
708 PetscReal a, b, c;
709
710 switch (instruction->op) {
711 case OP_CONST: stack[top++] = instruction->value; break;
712 case OP_VAR: stack[top++] = values[instruction->arg]; break;
713 case OP_UNIFORM:
714 case OP_NORMAL: stack[top++] = Draw(key, instruction); break;
715 case OP_NEG: stack[top - 1] = -stack[top - 1]; break;
716 case OP_POS: break;
717 case OP_NOT: stack[top - 1] = (stack[top - 1] == 0.0) ? 1.0 : 0.0; break;
718 case OP_ABS: stack[top - 1] = PetscAbsReal(stack[top - 1]); break;
719 case OP_COS: stack[top - 1] = PetscCosReal(stack[top - 1]); break;
720 case OP_EXP: stack[top - 1] = PetscExpReal(stack[top - 1]); break;
721 case OP_SIN: stack[top - 1] = PetscSinReal(stack[top - 1]); break;
722 case OP_SQRT: stack[top - 1] = PetscSqrtReal(stack[top - 1]); break;
723 case OP_TAN: stack[top - 1] = PetscTanReal(stack[top - 1]); break;
724 case OP_ERF: stack[top - 1] = (PetscReal)erf((double)stack[top - 1]); break;
725 case OP_TANH: stack[top - 1] = PetscTanhReal(stack[top - 1]); break;
726 case OP_COSH: stack[top - 1] = PetscCoshReal(stack[top - 1]); break;
727 case OP_SINH: stack[top - 1] = PetscSinhReal(stack[top - 1]); break;
728 case OP_LOG: stack[top - 1] = PetscLogReal(stack[top - 1]); break;
729 case OP_FLOOR: stack[top - 1] = PetscFloorReal(stack[top - 1]); break;
730 case OP_BER: stack[top - 1] = Kelvin(stack[top - 1], PETSC_FALSE); break;
731 case OP_BEI: stack[top - 1] = Kelvin(stack[top - 1], PETSC_TRUE); break;
732 case OP_LOCAL: stack[top++] = index[instruction->arg]; break;
733 case OP_SUM_START:
734 stack[top++] = 0.0;
735 index[instruction->arg] = instruction->value;
736 /* An empty range skips the body and its ACC. */
737 if (instruction->value > expression->code[i + 1].value) i += 2 + expression->code[i + 1].arg;
738 else i += 1;
739 break;
740 case OP_SUM_ACC: {
741 const PetscInt body = (PetscInt)instruction->value;
742 const PetscReal upper = expression->code[i - body - 1].value;
743 const PetscReal term = stack[--top];
744 stack[top - 1] += term;
745 index[instruction->arg] += 1.0;
746 if (index[instruction->arg] <= upper) i -= body + 1;
747 } break;
748 case OP_WHERE:
749 c = stack[--top]; b = stack[--top]; a = stack[top - 1];
750 stack[top - 1] = (a != 0.0) ? b : c;
751 break;
752 default:
753 b = stack[--top]; a = stack[top - 1];
754 switch (instruction->op) {
755 case OP_ADD: a = a + b; break;
756 case OP_SUB: a = a - b; break;
757 case OP_MUL: a = a * b; break;
758 case OP_DIV: a = a / b; break;
759 /* Python's modulus takes the sign of the divisor. */
760 case OP_MOD: a = (b == 0.0) ? NAN : a - b * PetscFloorReal(a / b); break;
761 case OP_POW: a = PetscPowReal(a, b); break;
762 case OP_EQ: a = (a == b) ? 1.0 : 0.0; break;
763 case OP_NE: a = (a != b) ? 1.0 : 0.0; break;
764 case OP_LT: a = (a < b) ? 1.0 : 0.0; break;
765 case OP_LE: a = (a <= b) ? 1.0 : 0.0; break;
766 case OP_GT: a = (a > b) ? 1.0 : 0.0; break;
767 case OP_GE: a = (a >= b) ? 1.0 : 0.0; break;
768 case OP_AND: a = (a != 0.0 && b != 0.0) ? 1.0 : 0.0; break;
769 case OP_OR: a = (a != 0.0 || b != 0.0) ? 1.0 : 0.0; break;
770 case OP_ATAN2: a = PetscAtan2Real(a, b); break;
771 case OP_MAXIMUM: a = Extreme(a, b, PETSC_TRUE); break;
772 case OP_MINIMUM: a = Extreme(a, b, PETSC_FALSE); break;
773 case OP_BESSELJ: a = Bessel(a, b, PETSC_FALSE); break;
774 case OP_BESSELY: a = Bessel(a, b, PETSC_TRUE); break;
775 default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unknown expression opcode %d.", (int)instruction->op);
776 }
777 stack[top - 1] = a;
778 }
779 }
780 *result = stack[0];
782 PetscFunctionReturn(0);
783}
PetscBool draws
Definition expression.c:89
#define EXPRESSION_MAX_SERIES_DEPTH
Series that may nest inside one another, and terms one series may add.
Definition expression.c:65
static PetscReal Bessel(PetscReal order, PetscReal x, PetscBool second)
Bessel function of the first or second kind of integer order; NaN for another order.
Definition expression.c:673
PetscInt max_depth
Definition expression.c:88
static PetscReal Kelvin(PetscReal x, PetscBool imaginary)
Kelvin functions of order zero, ber(x) + i bei(x) = J0(x e^{3 pi i / 4}).
Definition expression.c:643
ExpressionInstruction * code
Definition expression.c:86
static PetscReal Draw(const PicurvExpressionDrawKey *key, const ExpressionInstruction *instruction)
A draw keyed on the particle, the event, the stream, and the function.
Definition expression.c:619
static PetscReal Extreme(PetscReal a, PetscReal b, PetscBool maximum)
Maximum or minimum that propagates NaN, as numpy does.
Definition expression.c:683
@ OP_ATAN2
Definition expression.c:34
@ OP_TAN
Definition expression.c:33
@ OP_NE
Definition expression.c:32
@ OP_MINIMUM
Definition expression.c:34
@ OP_WHERE
Definition expression.c:34
@ OP_BER
Definition expression.c:36
@ OP_EQ
Definition expression.c:32
@ OP_SUM_ACC
Definition expression.c:39
@ OP_MAXIMUM
Definition expression.c:34
@ OP_CONST
Definition expression.c:30
@ OP_GE
Definition expression.c:32
@ OP_POW
Definition expression.c:31
@ OP_POS
Definition expression.c:30
@ OP_NOT
Definition expression.c:30
@ OP_SQRT
Definition expression.c:33
@ OP_MOD
Definition expression.c:31
@ OP_BESSELJ
Definition expression.c:36
@ OP_COS
Definition expression.c:33
@ OP_VAR
Definition expression.c:30
@ OP_SUB
Definition expression.c:31
@ OP_DIV
Definition expression.c:31
@ OP_LOCAL
Definition expression.c:39
@ OP_LT
Definition expression.c:32
@ OP_TANH
Definition expression.c:33
@ OP_BEI
Definition expression.c:36
@ OP_ADD
Definition expression.c:31
@ OP_MUL
Definition expression.c:31
@ OP_COSH
Definition expression.c:33
@ OP_SIN
Definition expression.c:33
@ OP_UNIFORM
Definition expression.c:35
@ OP_NEG
Definition expression.c:30
@ OP_GT
Definition expression.c:32
@ OP_BESSELY
Definition expression.c:36
@ OP_ERF
Definition expression.c:33
@ OP_SUM_START
Definition expression.c:39
@ OP_LE
Definition expression.c:32
@ OP_ABS
Definition expression.c:33
@ OP_AND
Definition expression.c:32
@ OP_LOG
Definition expression.c:33
@ OP_OR
Definition expression.c:32
@ OP_FLOOR
Definition expression.c:33
@ OP_SINH
Definition expression.c:33
@ OP_EXP
Definition expression.c:33
@ OP_NORMAL
Definition expression.c:35
PetscInt length
Definition expression.c:87
One postfix instruction.
Definition expression.c:79
#define PROFILE_HELPER_BEGIN
Marks the beginning of a profiled helper: timed only when enabled by name.
Definition logging.h:1018
#define PROFILE_HELPER_END
Alias of PROFILE_FUNCTION_END for a function that began with PROFILE_HELPER_BEGIN.
Definition logging.h:1037
Here is the call graph for this function:
Here is the caller graph for this function:

◆ PicurvExpressionDestroy()

PetscErrorCode PicurvExpressionDestroy ( PicurvExpression **  expression)

Free a compiled expression.

Parameters
[in,out]expressionExpression to free; set to NULL.
Returns
Zero on success.

Free a compiled expression.

See also
PicurvExpressionDestroy()

Definition at line 789 of file expression.c.

790{
791 PetscFunctionBeginUser;
793 if (!expression || !*expression) { PROFILE_HELPER_END; PetscFunctionReturn(0); }
794 PetscCall(PetscFree((*expression)->code));
795 PetscCall(PetscFree(*expression));
797 PetscFunctionReturn(0);
798}
Here is the caller graph for this function:

◆ PicurvExpressionUsesVariable()

PetscErrorCode PicurvExpressionUsesVariable ( const PicurvExpression *  expression,
PetscInt  index,
PetscBool *  uses 
)

Whether a compiled expression reads one of its variables.

Parameters
[in]expressionCompiled expression.
[in]indexPosition of the variable in the compile-time name list.
[out]usesTrue when some instruction loads that variable.
Returns
Zero on success.

Whether a compiled expression reads one of its variables.

See also
PicurvExpressionUsesVariable()

Definition at line 805 of file expression.c.

806{
807 PetscFunctionBeginUser;
809 *uses = PETSC_FALSE;
810 for (PetscInt i = 0; i < expression->length && !*uses; ++i) {
811 if (expression->code[i].op == OP_VAR && expression->code[i].arg == index) *uses = PETSC_TRUE;
812 }
814 PetscFunctionReturn(0);
815}
Here is the caller graph for this function:

◆ PicurvVelocitySourceCreate()

PetscErrorCode PicurvVelocitySourceCreate ( const char *  prefix,
PetscBool  on_face,
PetscBool  has_data,
PicurvVelocitySource *  source 
)

Read and compile a velocity source from the options database.

Reads -<prefix>_frame (cartesian, curvilinear, on a face normal, otherwise contravariant), one expression per value, -<prefix>_expr_<c>, written in physical units over the names of PicurvSourceVariable, and the optional -<prefix>_bulk_velocity, an expression in t. Random draws are not available.

Parameters
[in]prefixOption prefix without its dash, e.g. ic_source or face_source_0.
[in]on_faceWhether the target is a face, where the normal frame means something.
[in]has_dataWhether the target also has staged data, which makes the expressions optional; without a frame, data on a face is a normal speed.
[out]sourceCompiled source; release it with PicurvVelocitySourceDestroy().
Returns
Zero on success; PETSC_ERR_USER_INPUT for a missing option or unknown frame, PETSC_ERR_ARG_WRONG for a malformed expression.

Read and compile a velocity source from the options database.

See also
PicurvVelocitySourceCreate()

Definition at line 830 of file expression.c.

832{
833 static const char *const kTime[] = {"t"};
834 char option[PETSC_MAX_PATH_LEN], frame[32], text[PICURV_SOURCE_EXPRESSION_LENGTH];
835 PetscBool found = PETSC_FALSE;
836
837 PetscFunctionBeginUser;
839 PetscCall(PetscMemzero(source, sizeof(*source)));
840 PetscCall(PetscSNPrintf(option, sizeof(option), "-%s_frame", prefix));
841 PetscCall(PetscOptionsGetString(NULL, NULL, option, frame, sizeof(frame), &found));
842 PetscCheck(found || has_data, PETSC_COMM_WORLD, PETSC_ERR_USER_INPUT, "Velocity source option %s is required.", option);
843 if (!found) PetscCall(PetscStrncpy(frame, on_face ? "normal" : "cartesian", sizeof(frame)));
844 if (!strcmp(frame, "cartesian")) source->frame = PICURV_SOURCE_FRAME_CARTESIAN;
845 else if (!strcmp(frame, "curvilinear")) source->frame = PICURV_SOURCE_FRAME_CURVILINEAR;
846 else if (!strcmp(frame, "normal") && on_face) source->frame = PICURV_SOURCE_FRAME_NORMAL;
847 else if (!strcmp(frame, "contravariant") && !on_face) source->frame = PICURV_SOURCE_FRAME_CONTRAVARIANT;
848 else SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_USER_INPUT, "%s is '%s'; expected cartesian, curvilinear, or %s.",
849 option, frame, on_face ? "normal" : "contravariant");
850 source->count = (source->frame == PICURV_SOURCE_FRAME_NORMAL) ? 1 : 3;
851 for (PetscInt c = 0; c < source->count; ++c) {
852 PetscBool uses_t = PETSC_FALSE;
853 PetscCall(PetscSNPrintf(option, sizeof(option), "-%s_expr_%d", prefix, (int)c));
854 PetscCall(PetscOptionsGetString(NULL, NULL, option, text, sizeof(text), &found));
855 if (!found && has_data && c == 0) { source->count = 0; break; }
856 PetscCheck(found, PETSC_COMM_WORLD, PETSC_ERR_USER_INPUT, "Velocity source option %s is required.", option);
859 &source->component[c]));
860 PetscCall(PicurvExpressionUsesVariable(source->component[c], PICURV_SOURCE_VAR_T, &uses_t));
861 source->time_dependent = (PetscBool)(source->time_dependent || uses_t);
862 }
863 PetscCall(PetscSNPrintf(option, sizeof(option), "-%s_bulk_velocity", prefix));
864 PetscCall(PetscOptionsGetString(NULL, NULL, option, text, sizeof(text), &found));
865 if (!found && on_face) {
866 PetscCall(PetscSNPrintf(option, sizeof(option), "-%s_flow_rate", prefix));
867 PetscCall(PetscOptionsGetString(NULL, NULL, option, text, sizeof(text), &source->bulk_is_flow_rate));
868 found = source->bulk_is_flow_rate;
869 }
870 if (found) {
871 PetscCall(PicurvExpressionCompile(text, kTime, 1, PETSC_FALSE, &source->bulk));
872 PetscCall(PicurvExpressionUsesVariable(source->bulk, 0, &source->bulk_time_dependent));
873 }
875 PetscFunctionReturn(0);
876}
PetscErrorCode PicurvExpressionUsesVariable(const PicurvExpression *expression, PetscInt index, PetscBool *uses)
Implementation of PicurvExpressionUsesVariable().
Definition expression.c:805
const char *const kPicurvSourceVariableNames[PICURV_SOURCE_VAR_COUNT]
Names of PicurvSourceVariable, in order.
Definition expression.c:821
PetscErrorCode PicurvExpressionCompile(const char *text, const char *const *names, PetscInt name_count, PetscBool allow_random, PicurvExpression **expression)
Implementation of PicurvExpressionCompile().
Definition expression.c:549
#define PICURV_SOURCE_EXPRESSION_LENGTH
Definition expression.c:824
PicurvExpression * bulk
Target mean speed [m/s] in t, or NULL.
Definition expression.h:160
PetscBool bulk_time_dependent
Definition expression.h:161
PicurvExpression * component[3]
Definition expression.h:158
PetscBool time_dependent
Some component reads t.
Definition expression.h:159
PicurvSourceFrame frame
Definition expression.h:156
PetscBool bulk_is_flow_rate
bulk is a volumetric flow rate [m^3/s] through a face instead.
Definition expression.h:162
PetscInt count
1 for the normal frame, otherwise 3; 0 for staged data alone.
Definition expression.h:157
Here is the call graph for this function:
Here is the caller graph for this function:

◆ PicurvVelocitySourceBulkFactor()

PetscErrorCode PicurvVelocitySourceBulkFactor ( const PicurvVelocitySource *  source,
PetscReal  physical_time,
const PetscReal  local[3],
const char *  where,
PetscReal *  factor 
)

Factor on a source's expressions that makes a target's whole mean equal its bulk velocity.

Solves factor * expressions + data = bulk, over the target's points and weight. Collective.

Parameters
[in]sourceSource with a bulk velocity.
[in]physical_timeTime the bulk velocity is read at [s].
[in]localThis rank's weighted sums, physical: the expressions' speed, the staged data's speed along it, and the weight, an area [m^2] for a flow rate.
[in]whereThe target, for the error messages.
[out]factorFactor on the expressions.
Returns
Zero on success; PETSC_ERR_ARG_WRONGSTATE for no weight or a zero mean.

Factor on a source's expressions that makes a target's whole mean equal its bulk velocity.

See also
PicurvVelocitySourceBulkFactor()

Definition at line 882 of file expression.c.

884{
885 PetscReal global[3], target;
886
887 PetscFunctionBeginUser;
889 PetscCallMPI(MPI_Allreduce(local, global, 3, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD));
890 PetscCheck(global[2] > 0.0, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE,
891 "%s has no open area or volume to set a bulk velocity on.", where);
892 PetscCheck(global[0] != 0.0, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE,
893 "%s: the source's mean speed is zero, so it cannot be scaled to a bulk velocity.", where);
894 PetscCall(PicurvExpressionEvaluate(source->bulk, &physical_time, NULL, &target));
895 if (source->bulk_is_flow_rate) target /= global[2];
896 *factor = (target * global[2] - global[1]) / global[0];
897 LOG_ALLOW(GLOBAL, LOG_DEBUG, "%s: bulk velocity %g, source mean %g, data mean %g, factor %g.\n", where,
898 (double)target, (double)(global[0] / global[2]), (double)(global[1] / global[2]), (double)*factor);
900 PetscFunctionReturn(0);
901}
PetscErrorCode PicurvExpressionEvaluate(const PicurvExpression *expression, const PetscReal *values, const PicurvExpressionDrawKey *key, PetscReal *result)
Implementation of PicurvExpressionEvaluate().
Definition expression.c:695
#define GLOBAL
Scope for global logging across all processes.
Definition logging.h:46
#define LOG_ALLOW(scope, level, fmt,...)
Logging macro that checks both the log level and whether the calling function is in the allowed-funct...
Definition logging.h:214
@ LOG_DEBUG
Detailed debugging information.
Definition logging.h:32
Here is the call graph for this function:
Here is the caller graph for this function:

◆ PicurvSourceSetVariables()

static void PicurvSourceSetVariables ( PetscReal *  values,
Cmpnts  point,
Cmpnts  fraction,
Cmpnts  length,
PetscReal  L_ref 
)
inlinestatic

Fill a source's position and grid-line variables at one point.

Parameters
[out]valuesArray of PICURV_SOURCE_VAR_COUNT; t is left to the caller.
[in]pointSolver-unit position.
[in]fractionGrid-line fractions there, from ComputeGridLineFractions().
[in]lengthSolver-unit grid-line lengths there.
[in]L_refLength reference [m].

Definition at line 206 of file expression.h.

208{
209 values[PICURV_SOURCE_VAR_X] = point.x * L_ref;
210 values[PICURV_SOURCE_VAR_Y] = point.y * L_ref;
211 values[PICURV_SOURCE_VAR_Z] = point.z * L_ref;
212 values[PICURV_SOURCE_VAR_XI] = fraction.x;
213 values[PICURV_SOURCE_VAR_ETA] = fraction.y;
214 values[PICURV_SOURCE_VAR_ZETA] = fraction.z;
215 values[PICURV_SOURCE_VAR_L_XI] = length.x * L_ref;
216 values[PICURV_SOURCE_VAR_L_ETA] = length.y * L_ref;
217 values[PICURV_SOURCE_VAR_L_ZETA] = length.z * L_ref;
218}
PetscScalar x
Definition variables.h:142
PetscScalar z
Definition variables.h:142
PetscScalar y
Definition variables.h:142
Here is the caller graph for this function:

◆ PicurvSourceFaceSlotsCreate()

PetscErrorCode PicurvSourceFaceSlotsCreate ( UserCtx *  user,
BCFace  face_id,
Vec  fraction,
Vec  length,
PicurvSourceFaceSlots *  slots 
)

Gather each owned slot of a boundary face: face-centre position, the grid-line fractions and lengths of the interior cell behind it, and its directions.

A curvilinear component is the speed through the grid face, as on every target, so along the face's own axis the direction follows the face metric rather than the cell's edge.

Parameters
[in]userBlock with current metric and face-centre ghosts.
[in]face_idFace.
[in]fractionGrid-line fractions, from ComputeGridLineFractions().
[in]lengthGrid-line lengths, from ComputeGridLineFractions().
[out]slotsThe slots; release with PicurvSourceFaceSlotsDestroy().
Returns
PETSc error code.

Gather each owned slot of a boundary face: face-centre position, the grid-line fractions and lengths of the interior cell behind it, and its directions.

See also
PicurvSourceFaceSlotsCreate()

Definition at line 1124 of file expression.c.

1126{
1127 const DMDALocalInfo *info = &user->info;
1128 const PetscInt start[3] = {info->xs, info->ys, info->zs};
1129 const PetscInt end[3] = {info->xs + info->xm, info->ys + info->ym, info->zs + info->zm};
1130 const PetscInt nodes[3] = {info->mx, info->my, info->mz};
1131 const PetscReal L_ref = user->simCtx->scaling.L_ref;
1132 const PetscBool negative = (PetscBool)((PetscInt)face_id % 2 == 0);
1133 PetscBool can_service = PETSC_FALSE;
1134 PetscInt n_slots;
1135 Cmpnts face_centre;
1136 PetscReal face_area;
1137
1138 PetscFunctionBeginUser;
1140 PetscCall(CalculateFaceCenterAndArea(user, face_id, &face_centre, &face_area));
1141 slots->normal = (PetscInt)face_id / 2;
1142 slots->a = (slots->normal == 0) ? 1 : 0;
1143 slots->b = (slots->normal == 2) ? 1 : 2;
1144 const PetscInt normal = slots->normal, a = slots->a, b = slots->b;
1145 PetscCall(CanRankServiceFace(info, user->IM, user->JM, user->KM, face_id, &can_service));
1146 slots->layer = negative ? start[normal] : nodes[normal] - 2;
1147 slots->lo[0] = (start[a] == 0) ? 1 : start[a];
1148 slots->lo[1] = (start[b] == 0) ? 1 : start[b];
1149 slots->n[0] = can_service ? ((end[a] == nodes[a]) ? nodes[a] - 1 : end[a]) - slots->lo[0] : 0;
1150 slots->n[1] = can_service ? ((end[b] == nodes[b]) ? nodes[b] - 1 : end[b]) - slots->lo[1] : 0;
1151 n_slots = slots->n[0] * slots->n[1];
1152 PetscCall(PetscMalloc2(n_slots, &slots->values, n_slots, &slots->edges));
1153
1154 if (n_slots > 0) {
1155 /* The interior cell behind the slot layer. */
1156 const PetscInt cell = negative ? slots->layer + 1 : slots->layer;
1157 const Vec centres = (normal == 0) ? user->lCentx : (normal == 1) ? user->lCenty : user->lCentz;
1158 const Cmpnts ***cent, ***frac, ***len, ***csi, ***eta, ***zet;
1159 const PetscReal ***aj;
1160 PetscCall(DMDAVecGetArrayRead(user->fda, centres, &cent));
1161 PetscCall(DMDAVecGetArrayRead(user->fda, fraction, &frac));
1162 PetscCall(DMDAVecGetArrayRead(user->fda, length, &len));
1163 PetscCall(DMDAVecGetArrayRead(user->fda, user->lCsi, &csi));
1164 PetscCall(DMDAVecGetArrayRead(user->fda, user->lEta, &eta));
1165 PetscCall(DMDAVecGetArrayRead(user->fda, user->lZet, &zet));
1166 PetscCall(DMDAVecGetArrayRead(user->da, user->lAj, &aj));
1167 for (PetscInt q = 0; q < slots->n[1]; ++q)
1168 for (PetscInt p = 0; p < slots->n[0]; ++p) {
1169 const PetscInt s = p + slots->n[0] * q;
1170 PetscInt f[3], c[3];
1171 f[normal] = slots->layer; f[a] = slots->lo[0] + p; f[b] = slots->lo[1] + q;
1172 c[normal] = cell; c[a] = f[a]; c[b] = f[b];
1173 PicurvSourceSetVariables(slots->values[s], cent[f[2]][f[1]][f[0]], frac[c[2]][c[1]][c[0]], len[c[2]][c[1]][c[0]], L_ref);
1174 slots->values[s][PICURV_SOURCE_VAR_T] = 0.0;
1175 /* On the face itself the fraction along the normal line is exactly 0 or 1. */
1176 slots->values[s][PICURV_SOURCE_VAR_XI + normal] = negative ? 0.0 : 1.0;
1177 {
1178 const Cmpnts X = cent[f[2]][f[1]][f[0]];
1179 const PetscReal dx = X.x - face_centre.x, dy = X.y - face_centre.y, dz = X.z - face_centre.z;
1180 slots->values[s][PICURV_SOURCE_VAR_R] = PetscSqrtReal(dx * dx + dy * dy + dz * dz) * L_ref;
1181 }
1182 PetscCall(ComputeCellEdgeVectors(aj[c[2]][c[1]][c[0]], csi[c[2]][c[1]][c[0]], eta[c[2]][c[1]][c[0]], zet[c[2]][c[1]][c[0]], slots->edges[s]));
1183 const Cmpnts m = (normal == 0) ? csi[f[2]][f[1]][f[0]] : (normal == 1) ? eta[f[2]][f[1]][f[0]] : zet[f[2]][f[1]][f[0]];
1184 const Cmpnts through = {user->GridOrientation * m.x, user->GridOrientation * m.y, user->GridOrientation * m.z};
1185 slots->edges[s][normal] = through;
1186 }
1187 PetscCall(DMDAVecRestoreArrayRead(user->da, user->lAj, &aj));
1188 PetscCall(DMDAVecRestoreArrayRead(user->fda, user->lZet, &zet));
1189 PetscCall(DMDAVecRestoreArrayRead(user->fda, user->lEta, &eta));
1190 PetscCall(DMDAVecRestoreArrayRead(user->fda, user->lCsi, &csi));
1191 PetscCall(DMDAVecRestoreArrayRead(user->fda, length, &len));
1192 PetscCall(DMDAVecRestoreArrayRead(user->fda, fraction, &frac));
1193 PetscCall(DMDAVecRestoreArrayRead(user->fda, centres, &cent));
1194 }
1196 PetscFunctionReturn(0);
1197}
PetscErrorCode CanRankServiceFace(const DMDALocalInfo *info, PetscInt IM_nodes_global, PetscInt JM_nodes_global, PetscInt KM_nodes_global, BCFace face_id, PetscBool *can_service_out)
Determines if the current MPI rank owns any part of a specified global face.
Definition Boundaries.c:22
PetscErrorCode ComputeCellEdgeVectors(PetscReal ajc, Cmpnts csi, Cmpnts eta, Cmpnts zet, Cmpnts edges[3])
Computes a cell's edge vectors along its three grid directions.
Definition Metric.c:710
PetscInt normal
Logical axis of the face normal.
Definition expression.h:222
PetscInt n[2]
Owned slots along the two tangential axes; 0 off the face.
Definition expression.h:226
PetscInt b
The two tangential axes.
Definition expression.h:223
PetscInt layer
Index along the normal of the face's metric and flux.
Definition expression.h:224
PetscReal(* values)[PICURV_SOURCE_VAR_COUNT]
Variables per slot; t is the caller's.
Definition expression.h:227
static void PicurvSourceSetVariables(PetscReal *values, Cmpnts point, Cmpnts fraction, Cmpnts length, PetscReal L_ref)
Fill a source's position and grid-line variables at one point.
Definition expression.h:206
Cmpnts(* edges)[3]
Directions per slot, for the curvilinear frame.
Definition expression.h:228
PetscInt lo[2]
First tangential indices of the owned slots.
Definition expression.h:225
PetscErrorCode CalculateFaceCenterAndArea(UserCtx *user, BCFace face_id, Cmpnts *face_center, PetscReal *face_area)
Calculates the geometric center and total area of a specified boundary face.
Definition grid.c:1211
SimCtx * simCtx
Back-pointer to the master simulation context.
Definition variables.h:1126
PetscInt KM
Definition variables.h:1137
PetscReal L_ref
Definition variables.h:870
ScalingCtx scaling
Definition variables.h:973
PetscInt JM
Definition variables.h:1137
Vec lCentx
Definition variables.h:1218
PetscInt GridOrientation
Definition variables.h:1141
DMDALocalInfo info
Definition variables.h:1135
PetscInt IM
Definition variables.h:1137
A 3D point or vector with PetscScalar components.
Definition variables.h:141
Here is the call graph for this function:
Here is the caller graph for this function:

◆ PicurvSourceFaceSlotsDestroy()

PetscErrorCode PicurvSourceFaceSlotsDestroy ( PicurvSourceFaceSlots *  slots)

Release what PicurvSourceFaceSlotsCreate() allocated.

Parameters
[in,out]slotsThe slots.
Returns
PETSc error code.

Release what PicurvSourceFaceSlotsCreate() allocated.

See also
PicurvSourceFaceSlotsDestroy()

Definition at line 1203 of file expression.c.

1204{
1205 PetscFunctionBeginUser;
1207 PetscCall(PetscFree2(slots->values, slots->edges));
1209 PetscFunctionReturn(0);
1210}
Here is the caller graph for this function:

◆ PicurvVelocitySourceEvaluate()

PetscErrorCode PicurvVelocitySourceEvaluate ( const PicurvVelocitySource *  source,
const PetscReal *  values,
const Cmpnts  edges[3],
Cmpnts *  value 
)

Evaluate a source at one point.

Parameters
[in]sourceCompiled source.
[in]valuesOne value per PicurvSourceVariable.
[in]edgesCell edge vectors along xi, eta, zeta (any length); read only in the curvilinear frame.
[out]valuePhysical Cartesian velocity, or for the normal frame the speed in x.
Returns
Zero on success; PETSC_ERR_FP for a non-finite value.

Evaluate a source at one point.

See also
PicurvVelocitySourceEvaluate()

Definition at line 907 of file expression.c.

909{
910 PetscReal v[3] = {0.0, 0.0, 0.0};
911
912 PetscFunctionBeginUser;
914 for (PetscInt c = 0; c < source->count; ++c) {
915 PetscCall(PicurvExpressionEvaluate(source->component[c], values, NULL, &v[c]));
916 PetscCheck(!PetscIsInfOrNanReal(v[c]), PETSC_COMM_SELF, PETSC_ERR_FP,
917 "Velocity source value %" PetscInt_FMT " is %g at (x, y, z) = (%g, %g, %g), t = %g.",
918 c, (double)v[c], (double)values[PICURV_SOURCE_VAR_X], (double)values[PICURV_SOURCE_VAR_Y],
919 (double)values[PICURV_SOURCE_VAR_Z], (double)values[PICURV_SOURCE_VAR_T]);
920 }
921 if (source->frame == PICURV_SOURCE_FRAME_CURVILINEAR) {
922 /* Values are components along the unit grid-line directions. */
923 value->x = value->y = value->z = 0.0;
924 for (PetscInt a = 0; a < 3; ++a) {
925 const PetscReal norm = PetscSqrtReal(edges[a].x * edges[a].x + edges[a].y * edges[a].y + edges[a].z * edges[a].z);
926 PetscCheck(norm > 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "A cell edge has zero length.");
927 value->x += v[a] * edges[a].x / norm;
928 value->y += v[a] * edges[a].y / norm;
929 value->z += v[a] * edges[a].z / norm;
930 }
931 } else {
932 value->x = v[0];
933 value->y = v[1];
934 value->z = v[2];
935 }
937 PetscFunctionReturn(0);
938}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ PicurvSourceSetCellPressure()

PetscErrorCode PicurvSourceSetCellPressure ( UserCtx *  user,
const PicurvExpression *  pressure,
Vec  fraction,
Vec  length,
PetscReal  physical_time 
)

Set a block's pressure at every interior cell centre from an expression in Pa.

Dummy cells are left to the caller's boundary pass.

Parameters
[in]userBlock with current cell centres.
[in]pressureExpression over the cell variables, physical.
[in]fractionGrid-line fractions, from ComputeGridLineFractions().
[in]lengthGrid-line lengths, from ComputeGridLineFractions().
[in]physical_timeTime [s].
Returns
PETSc error code.

Set a block's pressure at every interior cell centre from an expression in Pa.

See also
PicurvSourceSetCellPressure()

Definition at line 1086 of file expression.c.

1088{
1089 const DMDALocalInfo *info = &user->info;
1090 const ScalingCtx *scaling = &user->simCtx->scaling;
1091 const PetscInt xs = info->xs, xe = info->xs + info->xm, mx = info->mx;
1092 const PetscInt ys = info->ys, ye = info->ys + info->ym, my = info->my;
1093 const PetscInt zs = info->zs, ze = info->zs + info->zm, mz = info->mz;
1094 const Cmpnts ***cent, ***frac, ***len;
1095 PetscReal ***p, values[PICURV_SOURCE_VAR_COUNT];
1096
1097 PetscFunctionBeginUser;
1099 PetscCall(DMDAVecGetArrayRead(user->fda, user->Cent, &cent));
1100 PetscCall(DMDAVecGetArrayRead(user->fda, fraction, &frac));
1101 PetscCall(DMDAVecGetArrayRead(user->fda, length, &len));
1102 PetscCall(DMDAVecGetArray(user->da, user->P, &p));
1103 values[PICURV_SOURCE_VAR_T] = physical_time;
1104 for (PetscInt k = (zs == 0) ? 1 : zs; k < ((ze == mz) ? mz - 1 : ze); ++k)
1105 for (PetscInt j = (ys == 0) ? 1 : ys; j < ((ye == my) ? my - 1 : ye); ++j)
1106 for (PetscInt i = (xs == 0) ? 1 : xs; i < ((xe == mx) ? mx - 1 : xe); ++i) {
1107 PetscReal value;
1108 PicurvSourceSetVariables(values, cent[k][j][i], frac[k][j][i], len[k][j][i], scaling->L_ref);
1109 PetscCall(PicurvExpressionEvaluate(pressure, values, NULL, &value));
1110 p[k][j][i] = value / scaling->P_ref;
1111 }
1112 PetscCall(DMDAVecRestoreArray(user->da, user->P, &p));
1113 PetscCall(DMDAVecRestoreArrayRead(user->fda, length, &len));
1114 PetscCall(DMDAVecRestoreArrayRead(user->fda, fraction, &frac));
1115 PetscCall(DMDAVecRestoreArrayRead(user->fda, user->Cent, &cent));
1117 PetscFunctionReturn(0);
1118}
PetscReal P_ref
Definition variables.h:873
Here is the call graph for this function:
Here is the caller graph for this function:

◆ PicurvSourceCellBulkFactor()

PetscErrorCode PicurvSourceCellBulkFactor ( UserCtx *  user,
const PicurvVelocitySource *  source,
Vec  fraction,
Vec  length,
PetscReal  physical_time,
PetscReal *  factor 
)

Factor on a source's expressions that makes the volume mean of the whole field, along the source's own direction at each cell, equal its bulk velocity.

Collective.

Parameters
[in]userBlock; its Ucat holds whatever is staged.
[in]sourceSource with a bulk velocity.
[in]fractionGrid-line fractions, from ComputeGridLineFractions().
[in]lengthGrid-line lengths, from ComputeGridLineFractions().
[in]physical_timeTime [s].
[out]factorFactor on the expressions.
Returns
PETSc error code.

Factor on a source's expressions that makes the volume mean of the whole field, along the source's own direction at each cell, equal its bulk velocity.

See also
PicurvSourceCellBulkFactor()

Definition at line 944 of file expression.c.

946{
947 const DMDALocalInfo *info = &user->info;
948 const PetscReal L_ref = user->simCtx->scaling.L_ref, U_ref = user->simCtx->scaling.U_ref;
949 const PetscInt xs = info->xs, xe = info->xs + info->xm, mx = info->mx;
950 const PetscInt ys = info->ys, ye = info->ys + info->ym, my = info->my;
951 const PetscInt zs = info->zs, ze = info->zs + info->zm, mz = info->mz;
952 PetscReal values[PICURV_SOURCE_VAR_COUNT], local[3] = {0.0, 0.0, 0.0};
953 const Cmpnts ***cent, ***frac, ***len, ***csi, ***eta, ***zet, ***ucat;
954 const PetscReal ***aj;
955
956 PetscFunctionBeginUser;
958 PetscCall(DMDAVecGetArrayRead(user->fda, user->Cent, &cent));
959 PetscCall(DMDAVecGetArrayRead(user->fda, fraction, &frac));
960 PetscCall(DMDAVecGetArrayRead(user->fda, length, &len));
961 PetscCall(DMDAVecGetArrayRead(user->fda, user->lCsi, &csi));
962 PetscCall(DMDAVecGetArrayRead(user->fda, user->lEta, &eta));
963 PetscCall(DMDAVecGetArrayRead(user->fda, user->lZet, &zet));
964 PetscCall(DMDAVecGetArrayRead(user->da, user->lAj, &aj));
965 PetscCall(DMDAVecGetArrayRead(user->fda, user->Ucat, &ucat));
966 values[PICURV_SOURCE_VAR_T] = physical_time;
967 for (PetscInt k = (zs == 0) ? 1 : zs; k < ((ze == mz) ? mz - 1 : ze); ++k)
968 for (PetscInt j = (ys == 0) ? 1 : ys; j < ((ye == my) ? my - 1 : ye); ++j)
969 for (PetscInt i = (xs == 0) ? 1 : xs; i < ((xe == mx) ? mx - 1 : xe); ++i) {
970 const PetscReal volume = 1.0 / PetscAbsReal(aj[k][j][i]);
971 Cmpnts edges[3], v;
972 PicurvSourceSetVariables(values, cent[k][j][i], frac[k][j][i], len[k][j][i], L_ref);
973 PetscCall(ComputeCellEdgeVectors(aj[k][j][i], csi[k][j][i], eta[k][j][i], zet[k][j][i], edges));
974 PetscCall(PicurvVelocitySourceEvaluate(source, values, edges, &v));
975 const PetscReal speed = PetscSqrtReal(v.x * v.x + v.y * v.y + v.z * v.z);
976 local[0] += speed * volume;
977 if (speed > 0.0) local[1] += U_ref * (ucat[k][j][i].x * v.x + ucat[k][j][i].y * v.y +
978 ucat[k][j][i].z * v.z) / speed * volume;
979 local[2] += volume;
980 }
981 PetscCall(DMDAVecRestoreArrayRead(user->fda, user->Ucat, &ucat));
982 PetscCall(DMDAVecRestoreArrayRead(user->da, user->lAj, &aj));
983 PetscCall(DMDAVecRestoreArrayRead(user->fda, user->lZet, &zet));
984 PetscCall(DMDAVecRestoreArrayRead(user->fda, user->lEta, &eta));
985 PetscCall(DMDAVecRestoreArrayRead(user->fda, user->lCsi, &csi));
986 PetscCall(DMDAVecRestoreArrayRead(user->fda, length, &len));
987 PetscCall(DMDAVecRestoreArrayRead(user->fda, fraction, &frac));
988 PetscCall(DMDAVecRestoreArrayRead(user->fda, user->Cent, &cent));
989 PetscCall(PicurvVelocitySourceBulkFactor(source, physical_time, local, "The field", factor));
991 PetscFunctionReturn(0);
992}
PetscErrorCode PicurvVelocitySourceBulkFactor(const PicurvVelocitySource *source, PetscReal physical_time, const PetscReal local[3], const char *where, PetscReal *factor)
Implementation of PicurvVelocitySourceBulkFactor().
Definition expression.c:882
PetscErrorCode PicurvVelocitySourceEvaluate(const PicurvVelocitySource *source, const PetscReal *values, const Cmpnts edges[3], Cmpnts *value)
Implementation of PicurvVelocitySourceEvaluate().
Definition expression.c:907
PetscReal U_ref
Definition variables.h:871
Here is the call graph for this function:
Here is the caller graph for this function:

◆ PicurvSourceAddFluxes()

PetscErrorCode PicurvSourceAddFluxes ( UserCtx *  user,
const PicurvVelocitySource *  source,
Vec  fraction,
Vec  length,
PetscReal  physical_time,
PetscReal  factor,
PetscBool  boundary_faces 
)

Add a source's flux to every owned face of Ucont, evaluating it at each face centre.

A Cartesian velocity is dotted with the face metric; a curvilinear component is the speed through the face, times its area; a contravariant component is the flux itself.

Parameters
[in,out]userBlock whose Ucont receives the fluxes.
[in]sourceSource with expressions.
[in]fractionGrid-line fractions, from ComputeGridLineFractions().
[in]lengthGrid-line lengths, from ComputeGridLineFractions().
[in]physical_timeTime [s].
[in]factorFactor on the expressions.
[in]boundary_facesWhether the boundary - faces are set too; each cell's + face always is.
Returns
PETSc error code.

Add a source's flux to every owned face of Ucont, evaluating it at each face centre.

See also
PicurvSourceAddFluxes()

Definition at line 998 of file expression.c.

1000{
1001 const DMDALocalInfo *info = &user->info;
1002 const PetscReal L_ref = user->simCtx->scaling.L_ref, U_ref = user->simCtx->scaling.U_ref;
1003 const PetscInt start[3] = {info->xs, info->ys, info->zs};
1004 const PetscInt end[3] = {info->xs + info->xm, info->ys + info->ym, info->zs + info->zm};
1005 const PetscInt nodes[3] = {info->mx, info->my, info->mz};
1006 const PetscInt lo[3] = {(start[0] == 0) ? 1 : start[0], (start[1] == 0) ? 1 : start[1], (start[2] == 0) ? 1 : start[2]};
1007 const PetscInt hi[3] = {(end[0] == nodes[0]) ? nodes[0] - 1 : end[0], (end[1] == nodes[1]) ? nodes[1] - 1 : end[1],
1008 (end[2] == nodes[2]) ? nodes[2] - 1 : end[2]};
1009 const Cmpnts ***frac, ***len, ***csi, ***eta, ***zet, ***centx, ***centy, ***centz;
1010 const PetscReal ***aj;
1011 Cmpnts ***ucont;
1012 PetscReal values[PICURV_SOURCE_VAR_COUNT];
1013
1014 PetscFunctionBeginUser;
1016 PetscCall(DMDAVecGetArrayRead(user->fda, fraction, &frac));
1017 PetscCall(DMDAVecGetArrayRead(user->fda, length, &len));
1018 PetscCall(DMDAVecGetArrayRead(user->fda, user->lCsi, &csi));
1019 PetscCall(DMDAVecGetArrayRead(user->fda, user->lEta, &eta));
1020 PetscCall(DMDAVecGetArrayRead(user->fda, user->lZet, &zet));
1021 PetscCall(DMDAVecGetArrayRead(user->fda, user->lCentx, &centx));
1022 PetscCall(DMDAVecGetArrayRead(user->fda, user->lCenty, &centy));
1023 PetscCall(DMDAVecGetArrayRead(user->fda, user->lCentz, &centz));
1024 PetscCall(DMDAVecGetArrayRead(user->da, user->lAj, &aj));
1025 PetscCall(DMDAVecGetArray(user->fda, user->Ucont, &ucont));
1026 values[PICURV_SOURCE_VAR_T] = physical_time;
1027 for (PetscInt k = lo[2]; k < hi[2]; ++k)
1028 for (PetscInt j = lo[1]; j < hi[1]; ++j)
1029 for (PetscInt i = lo[0]; i < hi[0]; ++i) {
1030 const PetscInt cell[3] = {i, j, k};
1031 const PetscReal lengths[3] = {len[k][j][i].x, len[k][j][i].y, len[k][j][i].z};
1032 Cmpnts edges[3];
1033 PetscCall(ComputeCellEdgeVectors(aj[k][j][i], csi[k][j][i], eta[k][j][i], zet[k][j][i], edges));
1034 for (PetscInt a = 0; a < 3; ++a) {
1035 const PetscReal half = 0.5 * PetscSqrtReal(edges[a].x * edges[a].x + edges[a].y * edges[a].y +
1036 edges[a].z * edges[a].z) / lengths[a];
1037 /* Each cell owns its + face; the first cell of a line also owns the boundary - face. */
1038 const PetscInt sides = (boundary_faces && start[a] == 0 && cell[a] == 1) ? 2 : 1;
1039 for (PetscInt side = 0; side < sides; ++side) {
1040 const PetscInt offset = side ? -1 : 0;
1041 const PetscInt fi = i + (a == 0 ? offset : 0), fj = j + (a == 1 ? offset : 0), fk = k + (a == 2 ? offset : 0);
1042 const Cmpnts metric = (a == 0) ? csi[fk][fj][fi] : (a == 1) ? eta[fk][fj][fi] : zet[fk][fj][fi];
1043 const Cmpnts centre = (a == 0) ? centx[fk][fj][fi] : (a == 1) ? centy[fk][fj][fi] : centz[fk][fj][fi];
1044 PetscReal flux;
1045 PicurvSourceSetVariables(values, centre, frac[k][j][i], len[k][j][i], L_ref);
1046 values[PICURV_SOURCE_VAR_XI + a] += side ? -half : half;
1048 PetscReal value;
1049 PetscCall(PicurvExpressionEvaluate(source->component[a], values, NULL, &value));
1050 flux = factor * value / (U_ref * L_ref * L_ref);
1051 } else if (source->frame == PICURV_SOURCE_FRAME_CURVILINEAR) {
1052 const PetscReal area = PetscSqrtReal(metric.x * metric.x + metric.y * metric.y + metric.z * metric.z);
1053 PetscReal value;
1054 PetscCall(PicurvExpressionEvaluate(source->component[a], values, NULL, &value));
1055 flux = factor * (value / U_ref) * user->GridOrientation * area;
1056 } else {
1057 Cmpnts v;
1058 PetscCall(PicurvVelocitySourceEvaluate(source, values, edges, &v));
1059 flux = (factor * v.x / U_ref) * metric.x + (factor * v.y / U_ref) * metric.y +
1060 (factor * v.z / U_ref) * metric.z;
1061 }
1062 if (a == 0) ucont[fk][fj][fi].x += flux;
1063 if (a == 1) ucont[fk][fj][fi].y += flux;
1064 if (a == 2) ucont[fk][fj][fi].z += flux;
1065 }
1066 }
1067 }
1068 PetscCall(DMDAVecRestoreArray(user->fda, user->Ucont, &ucont));
1069 PetscCall(DMDAVecRestoreArrayRead(user->da, user->lAj, &aj));
1070 PetscCall(DMDAVecRestoreArrayRead(user->fda, user->lCentz, &centz));
1071 PetscCall(DMDAVecRestoreArrayRead(user->fda, user->lCenty, &centy));
1072 PetscCall(DMDAVecRestoreArrayRead(user->fda, user->lCentx, &centx));
1073 PetscCall(DMDAVecRestoreArrayRead(user->fda, user->lZet, &zet));
1074 PetscCall(DMDAVecRestoreArrayRead(user->fda, user->lEta, &eta));
1075 PetscCall(DMDAVecRestoreArrayRead(user->fda, user->lCsi, &csi));
1076 PetscCall(DMDAVecRestoreArrayRead(user->fda, length, &len));
1077 PetscCall(DMDAVecRestoreArrayRead(user->fda, fraction, &frac));
1079 PetscFunctionReturn(0);
1080}
Vec Ucont
Definition variables.h:1162
Vec lCenty
Definition variables.h:1218
Vec lCentz
Definition variables.h:1218
Here is the call graph for this function:
Here is the caller graph for this function:

◆ PicurvVelocitySourceDestroy()

PetscErrorCode PicurvVelocitySourceDestroy ( PicurvVelocitySource *  source)

Free a source's compiled expressions and bulk velocity.

Parameters
[in,out]sourceSource to release; left empty.
Returns
Zero on success.

Free a source's compiled expressions and bulk velocity.

See also
PicurvVelocitySourceDestroy()

Definition at line 1216 of file expression.c.

1217{
1218 PetscFunctionBeginUser;
1220 for (PetscInt c = 0; c < 3; ++c) PetscCall(PicurvExpressionDestroy(&source->component[c]));
1221 PetscCall(PicurvExpressionDestroy(&source->bulk));
1222 source->count = 0;
1224 PetscFunctionReturn(0);
1225}
PetscErrorCode PicurvExpressionDestroy(PicurvExpression **expression)
Implementation of PicurvExpressionDestroy().
Definition expression.c:789
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ kPicurvSourceVariableNames

const char* const kPicurvSourceVariableNames[PICURV_SOURCE_VAR_COUNT]
extern

Names of PicurvSourceVariable, in order.

Definition at line 821 of file expression.c.

821 {
822 "x", "y", "z", "t", "xi", "eta", "zeta", "L_xi", "L_eta", "L_zeta", "r"};