PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
 
Loading...
Searching...
No Matches
Data Structures | Functions | Variables
picurv_cli.source_expressions Namespace Reference

Data Structures

class  _LogicalRewriter
 Rewrite logical operators and chained comparisons into array operations. More...
 

Functions

None validate_expression (str expression, names=EULERIAN_EXPRESSION_NAMES, random=False)
 Reject anything outside the expression language the runtime also evaluates.
 
int _series_bound (node)
 The integer a series bound denotes: an integer literal, possibly negated.
 
None _check_expression_node (node, names, indices, random)
 Check one node of a parsed expression, with the series indices enclosing it in scope.
 
None _validate_expression (str expression)
 Reject Eulerian expression syntax outside the supported language.
 
 _solver_only (str name)
 A stand-in for a function only the runtime evaluates.
 
 evaluate_values (str expression, dict values)
 Evaluate an already validated expression over named arrays or scalars.
 
str _number_text (value, dict params, str where)
 Render one numeric region parameter, which may name a declared parameter.
 
str _region_distance (dict region, dict params, str where)
 Signed distance to a region's boundary, negative inside, as expression text.
 
str _substitute_params (str expression, dict params)
 Replace declared parameter names in an expression by their values.
 
 _validate_at (str expression, names, bool random, str where)
 Validate an expression written in a configuration value, naming where it is.
 
str lower_value (spec, names=PARTICLE_EXPRESSION_NAMES, random=True, where="value")
 Turn a field value - number, expression, or structured regions - into one expression.
 

Variables

dict ALLOWED_FUNCTIONS
 
dict FUNCTION_ARITY
 
tuple SOLVER_ONLY_FUNCTIONS = ("besselj", "bessely", "ber", "bei")
 
int MAX_SERIES_TERMS = 1000000
 
int MAX_SERIES_DEPTH = 4
 
tuple RANDOM_FUNCTIONS = ("uniform", "normal")
 
 EULERIAN_EXPRESSION_NAMES = frozenset({"x", "y", "z", "xi", "eta", "zeta", "i", "j", "k"})
 
 PARTICLE_EXPRESSION_NAMES = frozenset({"x", "y", "z", "t", "xi", "eta", "zeta", "L_xi", "L_eta", "L_zeta", "pid"})
 
 ALLOWED_NAMES = set(ALLOWED_FUNCTIONS) | EULERIAN_EXPRESSION_NAMES | {"pi"}
 
 _DECIMAL_LITERAL = re.compile(r"^(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$")
 
tuple ALLOWED_AST_NODES
 
tuple REGION_SHAPES = ("half_space", "slab", "box", "ball", "cylinder")
 
dict EDGE_PROFILES
 
dict _REGION_KEYS
 
tuple _AXES = ("x", "y", "z")
 

Function Documentation

◆ validate_expression()

None picurv_cli.source_expressions.validate_expression ( str  expression,
  names = EULERIAN_EXPRESSION_NAMES,
  random = False 
)

Reject anything outside the expression language the runtime also evaluates.

Python expression syntax restricted to decimal numbers, the given names, pi, arithmetic, comparisons (chains included), and/or/not, and the documented functions at their fixed arities. uniform(n)/normal(n) are accepted only when random is true, with an optional stream n that must be a non-negative integer literal.

Parameters
[in]expressionUser expression.
[in]namesVariables in scope, besides pi.
[in]randomWhether per-particle random draws may be called.
Exceptions
ValueErrornaming the first construct outside the language.

Definition at line 92 of file source_expressions.py.

92def validate_expression(expression: str, names=EULERIAN_EXPRESSION_NAMES, random=False) -> None:
93 """!
94 @brief Reject anything outside the expression language the runtime also evaluates.
95 @details Python expression syntax restricted to decimal numbers, the given names, `pi`,
96 arithmetic, comparisons (chains included), `and`/`or`/`not`, and the
97 documented functions at their fixed arities. `uniform(n)`/`normal(n)` are
98 accepted only when @p random is true, with an optional stream `n` that must be
99 a non-negative integer literal.
100 @param[in] expression User expression.
101 @param[in] names Variables in scope, besides `pi`.
102 @param[in] random Whether per-particle random draws may be called.
103 @throws ValueError naming the first construct outside the language.
104 """
105 if not isinstance(expression, str) or not expression.strip():
106 raise ValueError("an expression must be a non-empty string.")
107 if "\n" in expression or "\r" in expression:
108 raise ValueError("an expression must fit on one line.")
109 try:
110 tree = ast.parse(expression, mode="eval")
111 tokens = list(tokenize.generate_tokens(io.StringIO(expression).readline))
112 except (SyntaxError, tokenize.TokenError) as exc:
113 raise ValueError(f"expression '{expression}' is not valid syntax: {exc}.") from exc
114 for token in tokens:
115 if token.type == tokenize.NUMBER and not _DECIMAL_LITERAL.match(token.string):
116 raise ValueError(f"'{token.string}' is not a decimal number; write numbers like 1, 0.5, or 2e-3.")
117 _check_expression_node(tree.body, frozenset(names) | {"pi"}, (), random)
118
119
Head of a generic C-style linked list.
Definition variables.h:478
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _series_bound()

int picurv_cli.source_expressions._series_bound (   node)
protected

The integer a series bound denotes: an integer literal, possibly negated.

Parameters
[in]nodeBound node.
Returns
The bound.
Exceptions
ValueErrorfor anything else.

Definition at line 120 of file source_expressions.py.

120def _series_bound(node) -> int:
121 """!
122 @brief The integer a series bound denotes: an integer literal, possibly negated.
123 @param[in] node Bound node.
124 @return The bound.
125 @throws ValueError for anything else.
126 """
127 sign = 1
128 if isinstance(node, ast.UnaryOp) and isinstance(node.op, (ast.USub, ast.UAdd)):
129 sign, node = (-1 if isinstance(node.op, ast.USub) else 1), node.operand
130 if (not isinstance(node, ast.Constant) or type(node.value) not in (int, float)
131 or node.value != int(node.value)):
132 raise ValueError("series bounds must be integer numbers.")
133 return sign * int(node.value)
134
135
Here is the caller graph for this function:

◆ _check_expression_node()

None picurv_cli.source_expressions._check_expression_node (   node,
  names,
  indices,
  random 
)
protected

Check one node of a parsed expression, with the series indices enclosing it in scope.

Parameters
[in]nodeAST node.
[in]namesVariables in scope, pi included.
[in]indicesIndices of the enclosing series, outermost first.
[in]randomWhether per-particle random draws may be called.
Exceptions
ValueErrornaming the first construct outside the language.

Definition at line 136 of file source_expressions.py.

136def _check_expression_node(node, names, indices, random) -> None:
137 """!
138 @brief Check one node of a parsed expression, with the series indices enclosing it in scope.
139 @param[in] node AST node.
140 @param[in] names Variables in scope, `pi` included.
141 @param[in] indices Indices of the enclosing series, outermost first.
142 @param[in] random Whether per-particle random draws may be called.
143 @throws ValueError naming the first construct outside the language.
144 """
145 if not isinstance(node, ALLOWED_AST_NODES):
146 raise ValueError(f"unsupported expression syntax: {type(node).__name__}.")
147 if isinstance(node, ast.Constant) and type(node.value) not in (int, float):
148 raise ValueError(f"only numbers may appear as constants, not {node.value!r}.")
149 if isinstance(node, ast.Name):
150 if node.id not in names and node.id not in indices:
151 raise ValueError(f"unsupported expression name '{node.id}'.")
152 return
153 if isinstance(node, ast.Call):
154 name = node.func.id if isinstance(node.func, ast.Name) else None
155 if node.keywords:
156 raise ValueError("functions take positional arguments only.")
157 if name in RANDOM_FUNCTIONS and random:
158 if len(node.args) > 1:
159 raise ValueError(f"{name}() takes at most one stream argument.")
160 if node.args:
161 stream = node.args[0]
162 if (not isinstance(stream, ast.Constant) or type(stream.value) not in (int, float)
163 or stream.value < 0 or stream.value != int(stream.value)):
164 raise ValueError(f"the stream of {name}() must be a non-negative integer literal.")
165 return
166 if name not in FUNCTION_ARITY:
167 raise ValueError(f"'{name}' is not an available function.")
168 if len(node.args) != FUNCTION_ARITY[name]:
169 raise ValueError(f"{name}() takes {FUNCTION_ARITY[name]} argument(s).")
170 if name == "sum":
171 index, lower, upper, body = node.args
172 if not isinstance(index, ast.Name):
173 raise ValueError("a series sum(k, lo, hi, body) needs an index name first.")
174 if index.id in names or index.id in indices:
175 raise ValueError(f"the series index '{index.id}' reuses a name already in scope.")
176 if len(indices) == MAX_SERIES_DEPTH:
177 raise ValueError(f"series may nest at most {MAX_SERIES_DEPTH} deep.")
178 if _series_bound(upper) - _series_bound(lower) + 1 > MAX_SERIES_TERMS:
179 raise ValueError(f"a series may add at most {MAX_SERIES_TERMS} terms.")
180 _check_expression_node(body, names, indices + (index.id,), random)
181 return
182 for argument in node.args:
183 _check_expression_node(argument, names, indices, random)
184 return
185 for child in ast.iter_child_nodes(node):
186 _check_expression_node(child, names, indices, random)
187
188
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _validate_expression()

None picurv_cli.source_expressions._validate_expression ( str  expression)
protected

Reject Eulerian expression syntax outside the supported language.

Parameters
[in]expressionUser expression.

Definition at line 189 of file source_expressions.py.

189def _validate_expression(expression: str) -> None:
190 """!
191 @brief Reject Eulerian expression syntax outside the supported language.
192 @param[in] expression User expression.
193 """
194 validate_expression(expression, EULERIAN_EXPRESSION_NAMES, random=False)
195
196
Here is the call graph for this function:

◆ _solver_only()

picurv_cli.source_expressions._solver_only ( str  name)
protected

A stand-in for a function only the runtime evaluates.

Parameters
[in]nameFunction name.
Returns
Callable that refuses evaluation.

Definition at line 272 of file source_expressions.py.

272def _solver_only(name: str):
273 """!
274 @brief A stand-in for a function only the runtime evaluates.
275 @param[in] name Function name.
276 @return Callable that refuses evaluation.
277 """
278 def refuse(*arguments):
279 """!
280 @brief Refuse to evaluate, naming the function and where it can be used.
281 @param[in] arguments The call's arguments, unused.
282 @throws ValueError always.
283 """
284 del arguments
285 raise ValueError(f"{name}() is evaluated only by the solver; use it in a velocity source, "
286 "not in an expression picurv evaluates before launch.")
287 return refuse
288
289
Here is the caller graph for this function:

◆ evaluate_values()

picurv_cli.source_expressions.evaluate_values ( str  expression,
dict  values 
)

Evaluate an already validated expression over named arrays or scalars.

Parameters
[in]expressionExpression text.
[in]valuesMapping of variable name to value or array.
Returns
Result as a float array, not yet checked for finiteness.

Definition at line 290 of file source_expressions.py.

290def evaluate_values(expression: str, values: dict):
291 """!
292 @brief Evaluate an already validated expression over named arrays or scalars.
293 @param[in] expression Expression text.
294 @param[in] values Mapping of variable name to value or array.
295 @return Result as a float array, not yet checked for finiteness.
296 """
297 tree = ast.fix_missing_locations(_LogicalRewriter().visit(ast.parse(expression, mode="eval")))
298 env = dict(ALLOWED_FUNCTIONS)
299 env.update({"logical_and": np.logical_and, "logical_or": np.logical_or,
300 "logical_not": np.logical_not, "pi": math.pi,
301 "series": lambda body, lo, hi: sum((body(k) for k in range(int(lo), int(hi) + 1)), 0.0)})
302 for name in SOLVER_ONLY_FUNCTIONS:
303 env[name] = _solver_only(name)
304 env.update(values)
305 with np.errstate(all="ignore"):
306 # Globals, not locals: a series body is a lambda, which sees only the globals.
307 value = eval(compile(tree, "<ic-expression>", "eval"), dict(env, __builtins__={}))
308 return np.asarray(value, dtype=float)
309
310
311#: Region shapes a structured field value may paint, later regions over earlier ones.
Here is the call graph for this function:

◆ _number_text()

str picurv_cli.source_expressions._number_text (   value,
dict  params,
str  where 
)
protected

Render one numeric region parameter, which may name a declared parameter.

Parameters
[in]valueNumber, or the name of a parameter.
[in]paramsDeclared parameters.
[in]whereConfiguration path, for diagnostics.
Returns
Parenthesized numeric text.

Definition at line 329 of file source_expressions.py.

329def _number_text(value, params: dict, where: str) -> str:
330 """!
331 @brief Render one numeric region parameter, which may name a declared parameter.
332 @param[in] value Number, or the name of a parameter.
333 @param[in] params Declared parameters.
334 @param[in] where Configuration path, for diagnostics.
335 @return Parenthesized numeric text.
336 """
337 if isinstance(value, str) and value in params:
338 return repr(float(params[value]))
339 if isinstance(value, bool) or not isinstance(value, (int, float)) or not math.isfinite(value):
340 raise ValueError(f"{where} must be a finite number or a declared parameter name.")
341 return repr(float(value))
342
343
Here is the caller graph for this function:

◆ _region_distance()

str picurv_cli.source_expressions._region_distance ( dict  region,
dict  params,
str  where 
)
protected

Signed distance to a region's boundary, negative inside, as expression text.

Parameters
[in]regionRegion mapping.
[in]paramsDeclared parameters.
[in]whereConfiguration path, for diagnostics.
Returns
Expression text for the signed distance.

Definition at line 344 of file source_expressions.py.

344def _region_distance(region: dict, params: dict, where: str) -> str:
345 """!
346 @brief Signed distance to a region's boundary, negative inside, as expression text.
347 @param[in] region Region mapping.
348 @param[in] params Declared parameters.
349 @param[in] where Configuration path, for diagnostics.
350 @return Expression text for the signed distance.
351 """
352 shape = region.get("shape")
353 if shape not in REGION_SHAPES:
354 raise ValueError(f"{where}.shape must be one of {', '.join(REGION_SHAPES)}.")
355 extra = set(region) - _REGION_KEYS[shape] - {"shape", "value", "edge"}
356 missing = _REGION_KEYS[shape] - set(region) - ({"side"} if shape == "half_space" else set())
357 if extra or missing:
358 raise ValueError(f"{where} ({shape}) takes {sorted(_REGION_KEYS[shape])}, plus value and edge.")
359
360 def num(key, value=None):
361 """!
362 @brief Render a region number (a literal or a `params` name) as expression text.
363 @param[in] key Region key, for diagnostics and as the default source of the number.
364 @param[in] value Number to render in place of `region[key]`, if given.
365 @return Expression text of the number.
366 """
367 return _number_text(region[key] if value is None else value, params, f"{where}.{key}")
368
369 def axis_of(key="axis"):
370 """!
371 @brief Return the region's axis name, refusing anything but x, y, z.
372 @param[in] key Region key holding the axis.
373 @return Axis name.
374 """
375 axis = region.get(key)
376 if axis not in _AXES:
377 raise ValueError(f"{where}.{key} must be x, y, or z.")
378 return axis
379
380 def triple(key):
381 """!
382 @brief Render a three-coordinate region entry as a list of expression texts.
383 @param[in] key Region key holding the three coordinates.
384 @return List of three expression texts.
385 """
386 values = region.get(key)
387 if not isinstance(values, list) or len(values) != 3:
388 raise ValueError(f"{where}.{key} must be a list of three coordinates.")
389 return [num(key, v) for v in values]
390
391 if shape == "half_space":
392 axis, side = axis_of(), region.get("side", "above")
393 if side not in ("above", "below"):
394 raise ValueError(f"{where}.side must be above or below.")
395 return f"({num('at')} - {axis})" if side == "above" else f"({axis} - {num('at')})"
396 if shape == "slab":
397 axis = axis_of()
398 return f"maximum({num('from')} - {axis}, {axis} - {num('to')})"
399 if shape == "box":
400 lower, upper = triple("min"), triple("max")
401 terms = [f"maximum({lo} - {a}, {a} - {hi})" for a, lo, hi in zip(_AXES, lower, upper)]
402 return f"maximum(maximum({terms[0]}, {terms[1]}), {terms[2]})"
403 if shape == "ball":
404 center = triple("center")
405 return (f"sqrt(({_AXES[0]} - {center[0]})**2 + ({_AXES[1]} - {center[1]})**2 + "
406 f"({_AXES[2]} - {center[2]})**2) - {num('radius')}")
407 axis = axis_of()
408 others = [a for a in _AXES if a != axis]
409 center = region.get("center")
410 if not isinstance(center, list) or len(center) != 2:
411 raise ValueError(f"{where}.center must list the two coordinates across the axis ({', '.join(others)}).")
412 c0, c1 = (num("center", v) for v in center)
413 return f"sqrt(({others[0]} - {c0})**2 + ({others[1]} - {c1})**2) - {num('radius')}"
414
415
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _substitute_params()

str picurv_cli.source_expressions._substitute_params ( str  expression,
dict  params 
)
protected

Replace declared parameter names in an expression by their values.

Parameters
[in]expressionExpression text.
[in]paramsDeclared parameters.
Returns
Expression text with parameters inlined.

Definition at line 416 of file source_expressions.py.

416def _substitute_params(expression: str, params: dict) -> str:
417 """!
418 @brief Replace declared parameter names in an expression by their values.
419 @param[in] expression Expression text.
420 @param[in] params Declared parameters.
421 @return Expression text with parameters inlined.
422 """
423 pieces, cursor = [], 0
424 for token in tokenize.generate_tokens(io.StringIO(expression).readline):
425 if token.type == tokenize.NAME and token.string in params:
426 start, end = token.start[1], token.end[1]
427 pieces.append(expression[cursor:start])
428 pieces.append(f"({float(params[token.string])!r})")
429 cursor = end
430 pieces.append(expression[cursor:])
431 return "".join(pieces)
432
433

◆ _validate_at()

picurv_cli.source_expressions._validate_at ( str  expression,
  names,
bool  random,
str  where 
)
protected

Validate an expression written in a configuration value, naming where it is.

Parameters
[in]expressionExpression text.
[in]namesVariables the expression may use.
[in]randomWhether random draws are allowed.
[in]whereConfiguration path of the value.
Exceptions
ValueErrornaming where if the expression is outside the language.

Definition at line 434 of file source_expressions.py.

434def _validate_at(expression: str, names, random: bool, where: str):
435 """!
436 @brief Validate an expression written in a configuration value, naming where it is.
437 @param[in] expression Expression text.
438 @param[in] names Variables the expression may use.
439 @param[in] random Whether random draws are allowed.
440 @param[in] where Configuration path of the value.
441 @throws ValueError naming `where` if the expression is outside the language.
442 """
443 try:
444 validate_expression(expression, names, random)
445 except ValueError as e:
446 raise ValueError(f"{where}: {e}") from None
447
448
Here is the call graph for this function:
Here is the caller graph for this function:

◆ lower_value()

str picurv_cli.source_expressions.lower_value (   spec,
  names = PARTICLE_EXPRESSION_NAMES,
  random = True,
  where = "value" 
)

Turn a field value - number, expression, or structured regions - into one expression.

A mapping may declare params (named numbers usable in its expressions and region parameters) and gives either value or background with regions. Regions paint in order, a later region over an earlier one: a sharp region by where(d <= 0, v, before), a smoothed one by before*(1 - s) + v*s, with d the signed distance to the region and s its edge profile over edge.width. The result is validated like any expression.

Parameters
[in]specNumber, expression string, or mapping.
[in]namesVariables in scope.
[in]randomWhether random draws may be called.
[in]whereConfiguration path, for diagnostics.
Returns
Validated expression text.

Definition at line 449 of file source_expressions.py.

449def lower_value(spec, names=PARTICLE_EXPRESSION_NAMES, random=True, where="value") -> str:
450 """!
451 @brief Turn a field value - number, expression, or structured regions - into one expression.
452 @details A mapping may declare `params` (named numbers usable in its expressions and
453 region parameters) and gives either `value` or `background` with `regions`.
454 Regions paint in order, a later region over an earlier one: a sharp region by
455 `where(d <= 0, v, before)`, a smoothed one by `before*(1 - s) + v*s`, with `d`
456 the signed distance to the region and `s` its edge profile over `edge.width`.
457 The result is validated like any expression.
458 @param[in] spec Number, expression string, or mapping.
459 @param[in] names Variables in scope.
460 @param[in] random Whether random draws may be called.
461 @param[in] where Configuration path, for diagnostics.
462 @return Validated expression text.
463 """
464 params = {}
465 if isinstance(spec, bool):
466 raise ValueError(f"{where} must be a number, an expression, or a mapping.")
467 if isinstance(spec, (int, float)):
468 if not math.isfinite(spec):
469 raise ValueError(f"{where} must be finite.")
470 return repr(float(spec))
471 if isinstance(spec, str):
472 _validate_at(spec, names, random, where)
473 return spec
474 if not isinstance(spec, dict):
475 raise ValueError(f"{where} must be a number, an expression, or a mapping.")
476 unknown = set(spec) - {"params", "value", "background", "regions"}
477 if unknown:
478 raise ValueError(f"{where} does not take {sorted(unknown)}; it takes params, value, background, regions.")
479 params = spec.get("params") or {}
480 if not isinstance(params, dict):
481 raise ValueError(f"{where}.params must be a mapping of names to numbers.")
482 for name, number in params.items():
483 reserved = set(names) | {"pi"} | set(FUNCTION_ARITY) | set(RANDOM_FUNCTIONS) | {"and", "or", "not"}
484 if not isinstance(name, str) or not name.isidentifier() or name in reserved:
485 raise ValueError(f"{where}.params name '{name}' is not a free identifier.")
486 _number_text(number, {}, f"{where}.params.{name}")
487 scope = set(names) | set(params)
488
489 def expression_of(value, path):
490 """!
491 @brief Lower one value (number, `params` name, or expression) with parameters inlined.
492 @param[in] value Configured value.
493 @param[in] path Configuration path, for diagnostics.
494 @return Expression text.
495 """
496 if isinstance(value, str) and value not in params:
497 _validate_at(value, scope, random, path)
498 return f"({_substitute_params(value, params)})"
499 return _number_text(value, params, path)
500
501 if "value" in spec:
502 if "background" in spec or "regions" in spec:
503 raise ValueError(f"{where} gives either value, or background with regions.")
504 lowered = expression_of(spec["value"], f"{where}.value")
505 else:
506 regions = spec.get("regions")
507 if not isinstance(regions, list) or not regions:
508 raise ValueError(f"{where}.regions must be a non-empty list.")
509 lowered = expression_of(spec.get("background", 0.0), f"{where}.background")
510 for index, region in enumerate(regions):
511 path = f"{where}.regions[{index}]"
512 if not isinstance(region, dict) or "value" not in region:
513 raise ValueError(f"{path} must be a mapping with a shape and a value.")
514 distance = _region_distance(region, params, path)
515 value = expression_of(region["value"], f"{path}.value")
516 edge = region.get("edge")
517 if edge is None:
518 lowered = f"where({distance} <= 0, {value}, {lowered})"
519 continue
520 if not isinstance(edge, dict) or set(edge) != {"profile", "width"} or edge["profile"] not in EDGE_PROFILES:
521 raise ValueError(f"{path}.edge must give profile ({', '.join(EDGE_PROFILES)}) and width.")
522 width = _number_text(edge["width"], params, f"{path}.edge.width")
523 if float(width) <= 0.0:
524 raise ValueError(f"{path}.edge.width must be positive.")
525 ramp = f"maximum(0, minimum(1, 0.5 - ({distance})/{width}))"
526 blend = EDGE_PROFILES[edge["profile"]].format(s=ramp)
527 lowered = f"({lowered})*(1 - {blend}) + {value}*{blend}"
528 validate_expression(lowered, names, random)
529 return lowered
Here is the call graph for this function:

Variable Documentation

◆ ALLOWED_FUNCTIONS

dict picurv_cli.source_expressions.ALLOWED_FUNCTIONS
Initial value:
1= {
2 "abs": np.abs,
3 "atan2": np.arctan2,
4 "cos": np.cos,
5 "cosh": np.cosh,
6 "erf": np.vectorize(math.erf, otypes=[float]),
7 "exp": np.exp,
8 "floor": np.floor,
9 "log": np.log,
10 "maximum": np.maximum,
11 "minimum": np.minimum,
12 "sin": np.sin,
13 "sinh": np.sinh,
14 "sqrt": np.sqrt,
15 "tan": np.tan,
16 "tanh": np.tanh,
17 "where": np.where,
18}

Definition at line 22 of file source_expressions.py.

◆ FUNCTION_ARITY

dict picurv_cli.source_expressions.FUNCTION_ARITY
Initial value:
1= {"abs": 1, "cos": 1, "cosh": 1, "erf": 1, "exp": 1, "floor": 1, "log": 1, "sin": 1,
2 "sinh": 1, "sqrt": 1, "tan": 1, "tanh": 1, "atan2": 2, "maximum": 2, "minimum": 2,
3 "where": 3, "besselj": 2, "bessely": 2, "ber": 1, "bei": 1, "sum": 4}

Definition at line 42 of file source_expressions.py.

◆ SOLVER_ONLY_FUNCTIONS

tuple picurv_cli.source_expressions.SOLVER_ONLY_FUNCTIONS = ("besselj", "bessely", "ber", "bei")

Definition at line 47 of file source_expressions.py.

◆ MAX_SERIES_TERMS

int picurv_cli.source_expressions.MAX_SERIES_TERMS = 1000000

Definition at line 49 of file source_expressions.py.

◆ MAX_SERIES_DEPTH

int picurv_cli.source_expressions.MAX_SERIES_DEPTH = 4

Definition at line 51 of file source_expressions.py.

◆ RANDOM_FUNCTIONS

tuple picurv_cli.source_expressions.RANDOM_FUNCTIONS = ("uniform", "normal")

Definition at line 54 of file source_expressions.py.

◆ EULERIAN_EXPRESSION_NAMES

picurv_cli.source_expressions.EULERIAN_EXPRESSION_NAMES = frozenset({"x", "y", "z", "xi", "eta", "zeta", "i", "j", "k"})

Definition at line 56 of file source_expressions.py.

◆ PARTICLE_EXPRESSION_NAMES

picurv_cli.source_expressions.PARTICLE_EXPRESSION_NAMES = frozenset({"x", "y", "z", "t", "xi", "eta", "zeta", "L_xi", "L_eta", "L_zeta", "pid"})

Definition at line 59 of file source_expressions.py.

◆ ALLOWED_NAMES

picurv_cli.source_expressions.ALLOWED_NAMES = set(ALLOWED_FUNCTIONS) | EULERIAN_EXPRESSION_NAMES | {"pi"}

Definition at line 60 of file source_expressions.py.

◆ _DECIMAL_LITERAL

picurv_cli.source_expressions._DECIMAL_LITERAL = re.compile(r"^(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$")
protected

Definition at line 61 of file source_expressions.py.

◆ ALLOWED_AST_NODES

tuple picurv_cli.source_expressions.ALLOWED_AST_NODES
Initial value:
1= (
2 ast.Expression,
3 ast.BinOp,
4 ast.UnaryOp,
5 ast.Call,
6 ast.Name,
7 ast.Load,
8 ast.Constant,
9 ast.Add,
10 ast.Sub,
11 ast.Mult,
12 ast.Div,
13 ast.Pow,
14 ast.Mod,
15 ast.Compare,
16 ast.Eq,
17 ast.NotEq,
18 ast.Lt,
19 ast.LtE,
20 ast.Gt,
21 ast.GtE,
22 ast.USub,
23 ast.UAdd,
24 ast.BoolOp,
25 ast.And,
26 ast.Or,
27 ast.Not,
28)

Definition at line 62 of file source_expressions.py.

◆ REGION_SHAPES

tuple picurv_cli.source_expressions.REGION_SHAPES = ("half_space", "slab", "box", "ball", "cylinder")

Definition at line 312 of file source_expressions.py.

◆ EDGE_PROFILES

dict picurv_cli.source_expressions.EDGE_PROFILES
Initial value:
1= {
2 "linear": "({s})",
3 "smoothstep": "({s})*({s})*(3 - 2*({s}))",
4 "cosine": "0.5*(1 - cos(pi*({s})))",
5}

Definition at line 314 of file source_expressions.py.

◆ _REGION_KEYS

dict picurv_cli.source_expressions._REGION_KEYS
protected
Initial value:
1= {
2 "half_space": {"axis", "at", "side"},
3 "slab": {"axis", "from", "to"},
4 "box": {"min", "max"},
5 "ball": {"center", "radius"},
6 "cylinder": {"axis", "center", "radius"},
7}

Definition at line 319 of file source_expressions.py.

◆ _AXES

tuple picurv_cli.source_expressions._AXES = ("x", "y", "z")
protected

Definition at line 326 of file source_expressions.py.