Source code for fieldview.formula

"""Formula creation and builder helpers for FieldView.

The :mod:`fieldview.formula` namespace exposes a thin wrapper over FieldView's
native formula system. Use it to define derived scalar or vector quantities
from existing dataset functions, constants, and other formulas.

Formulas can be authored either as raw FieldView formula strings or through a
lightweight Python builder:

.. code-block:: python

    >>> import os
    >>> import fieldview as fv
    >>> data_dir = os.path.join(fv.home, "examples", "f18")
    >>> ds1 = fv.data.load_plot3d(
    ...     os.path.join(data_dir, "f18i9b_g_bin"),
    ...     os.path.join(data_dir, "f18i9b_q_bin"),
    ... )
    >>> ds2 = fv.data.load_plot3d(
    ...     os.path.join(data_dir, "f18i9b_g_bin"),
    ...     os.path.join(data_dir, "f18i9b_q_bin"),
    ... )
    >>> qcrit = fv.formula.create(
    ...     "Qcrit",
    ...     'Qcriterion("Velocity Vectors [PLOT3D]")',
    ... )
    >>> vel_mag = fv.formula.create(
    ...     "Velocity Magnitude",
    ...     fv.formula.mag("Velocity Vectors [PLOT3D]"),
    ... )
    >>> delta_p = fv.formula.create(
    ...     "Delta Pressure",
    ...     fv.formula.dataset_quantity(2, "Pressure [PLOT3D]")
    ...     - fv.formula.dataset_quantity(1, "Pressure [PLOT3D]"),
    ... )

Builder expressions support normal arithmetic operators plus helper functions
such as :func:`mag`, :func:`grad`, :func:`dot`, and :func:`qcriterion`. Bare
strings are only accepted as top-level formula text passed to :func:`create`
and as helper arguments such as ``mag("Velocity Vectors [PLOT3D]")``;
arithmetic builder expressions must use :func:`quantity` or
:func:`dataset_quantity` explicitly.
"""

from __future__ import annotations

import math
from typing import cast

from . import _core as _core_module
from ._core_utils import _core_call
from .data import _refresh_current_dataset_function_lists
from .exceptions import CoreError, InvalidArgumentError

__all__ = [
    "Formula",
    "create",
    "quantity",
    "dataset_quantity",
    "mag",
    "grad",
    "curl",
    "nrmlz",
    "exp",
    "ln",
    "log",
    "sin",
    "cos",
    "tan",
    "asin",
    "acos",
    "atan",
    "atan2",
    "sqrt",
    "abs",
    "div",
    "vecx",
    "vecy",
    "vecz",
    "dot",
    "cross",
    "qcriterion",
    "lambda2criterion",
    "pi",
    "e",
    "unit_x",
    "unit_y",
    "unit_z",
    "alpha",
    "fsmach",
    "re",
    "time",
    "gamma",
    "r",
]


def _try_refresh_current_dataset_function_lists() -> None:
    # Cache refresh should not change the outcome of a successful host-side
    # formula create/delete operation.
    try:
        _refresh_current_dataset_function_lists()
    except Exception:
        return


def _normalize_formula_name(name: str, label: str) -> str:
    if not isinstance(name, str):
        raise InvalidArgumentError(f"{label} must be a string")
    normalized = name.strip()
    if not normalized:
        raise InvalidArgumentError(f"{label} must be a non-empty string")
    if '"' in normalized:
        raise InvalidArgumentError(f"{label} must not contain double quotes")
    return normalized


def _coerce_numeric_literal(value: object) -> str:
    if isinstance(value, bool) or not isinstance(value, (int, float)):
        raise InvalidArgumentError(
            "formula literals must be numeric, Formula, or builder expressions"
        )
    return repr(float(value)) if isinstance(value, float) else repr(value)


class _FormulaExpr:
    """Internal lightweight builder node."""

    def render(self) -> str:
        raise NotImplementedError

    def __str__(self) -> str:
        return self.render()

    def __add__(self, other: object) -> _FormulaExpr:
        return _BinaryExpr("+", self, _coerce_expr(other))

    def __radd__(self, other: object) -> _FormulaExpr:
        return _BinaryExpr("+", _coerce_expr(other), self)

    def __sub__(self, other: object) -> _FormulaExpr:
        return _BinaryExpr("-", self, _coerce_expr(other))

    def __rsub__(self, other: object) -> _FormulaExpr:
        return _BinaryExpr("-", _coerce_expr(other), self)

    def __mul__(self, other: object) -> _FormulaExpr:
        return _BinaryExpr("*", self, _coerce_expr(other))

    def __rmul__(self, other: object) -> _FormulaExpr:
        return _BinaryExpr("*", _coerce_expr(other), self)

    def __truediv__(self, other: object) -> _FormulaExpr:
        return _BinaryExpr("/", self, _coerce_expr(other))

    def __rtruediv__(self, other: object) -> _FormulaExpr:
        return _BinaryExpr("/", _coerce_expr(other), self)

    def __pow__(self, other: object) -> _FormulaExpr:
        return _BinaryExpr("^", self, _coerce_expr(other))

    def __rpow__(self, other: object) -> _FormulaExpr:
        return _BinaryExpr("^", _coerce_expr(other), self)

    def __neg__(self) -> _FormulaExpr:
        return _UnaryExpr("-", self)


class _LiteralExpr(_FormulaExpr):
    __slots__ = ("_text",)

    def __init__(self, text: str) -> None:
        self._text = text

    def render(self) -> str:
        return self._text


class _QuantityExpr(_FormulaExpr):
    __slots__ = ("_name",)

    def __init__(self, name: str) -> None:
        self._name = _normalize_formula_name(name, "quantity")

    def render(self) -> str:
        return f'"{self._name}"'


class _DatasetQuantityExpr(_FormulaExpr):
    __slots__ = ("_dataset", "_name")

    def __init__(self, dataset: int, name: str) -> None:
        if isinstance(dataset, bool) or not isinstance(dataset, int):
            raise InvalidArgumentError("dataset must be an integer")
        if dataset <= 0:
            raise InvalidArgumentError("dataset must be >= 1")
        self._dataset = int(dataset)
        self._name = _normalize_formula_name(name, "quantity")

    def render(self) -> str:
        return f'{self._dataset}:"{self._name}"'


class _UnaryExpr(_FormulaExpr):
    __slots__ = ("_op", "_expr")

    def __init__(self, op: str, expr: _FormulaExpr) -> None:
        self._op = op
        self._expr = expr

    def render(self) -> str:
        return f"({self._op}{self._expr.render()})"


class _BinaryExpr(_FormulaExpr):
    __slots__ = ("_op", "_lhs", "_rhs")

    def __init__(self, op: str, lhs: _FormulaExpr, rhs: _FormulaExpr) -> None:
        self._op = op
        self._lhs = lhs
        self._rhs = rhs

    def render(self) -> str:
        return f"({self._lhs.render()} {self._op} {self._rhs.render()})"


class _CallExpr(_FormulaExpr):
    __slots__ = ("_name", "_args")

    def __init__(self, name: str, *args: object) -> None:
        self._name = name
        self._args = tuple(_coerce_call_arg(arg) for arg in args)

    def render(self) -> str:
        return f"{self._name}({', '.join(arg.render() for arg in self._args)})"


[docs] class Formula(_FormulaExpr): """Reference to a created FieldView formula. Instances are returned by :func:`create`. A ``Formula`` can be used inside later builder expressions, where it renders as a reference to the created formula name. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> vel_mag = fv.formula.create( ... "Velocity Magnitude", ... fv.formula.mag("Velocity Vectors [PLOT3D]"), ... ) >>> mach_like = fv.formula.create("Mach Like", vel_mag / 340.0) """ __slots__ = ("_name", "_is_deleted") def __init__(self, name: str) -> None: self._name = _normalize_formula_name(name, "name") self._is_deleted = False def _ensure_valid(self) -> None: if self._is_deleted: raise InvalidArgumentError("Formula was deleted") @property def name(self) -> str: """Return the FieldView formula name. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> formula = fv.formula.create( ... "Pressure Half", ... fv.formula.quantity("Pressure [PLOT3D]") / 2.0, ... ) >>> formula.name 'Pressure Half' """ self._ensure_valid() return self._name
[docs] def render(self) -> str: self._ensure_valid() return f'"{self._name}"'
[docs] def delete(self) -> None: """Delete the formula through the host and invalidate this handle. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> formula = fv.formula.create( ... "Temporary Pressure Half", ... fv.formula.quantity("Pressure [PLOT3D]") / 2.0, ... ) >>> formula.delete() """ if self._is_deleted: return func = getattr(_core_module, "formula_delete", None) if not callable(func): raise CoreError("FieldView host does not provide formula_delete.") _core_call(func, self._name) try: _try_refresh_current_dataset_function_lists() finally: self._is_deleted = True
def __repr__(self) -> str: state = "deleted" if self._is_deleted else f"name={self._name!r}" return f"Formula({state})"
def _coerce_expr(value: object) -> _FormulaExpr: if isinstance(value, _FormulaExpr): return value if isinstance(value, str): raise InvalidArgumentError( "bare strings are only allowed as top-level formula text or function arguments; " + "use quantity(...) or dataset_quantity(...) in builder expressions" ) return _LiteralExpr(_coerce_numeric_literal(value)) def _coerce_call_arg(value: object) -> _FormulaExpr: if isinstance(value, str): return quantity(value) return _coerce_expr(value) def _render_formula_input(expr: object) -> str: if isinstance(expr, str): rendered = expr.strip() if not rendered: raise InvalidArgumentError("formula must be a non-empty string") return rendered rendered = _coerce_expr(expr).render() if not rendered: raise InvalidArgumentError("formula expression rendered to an empty string") return rendered
[docs] def create(name: str, expr: object) -> Formula: """Create a named FieldView formula. Args: name: Unique formula name. The value must be non-empty and must not contain double quotes. expr: Either a raw FieldView formula string or a builder expression composed from :func:`quantity`, :func:`dataset_quantity`, helper operations, numeric literals, and previously created :class:`Formula` objects. Returns: Formula: Handle to the created host-side formula. Raises: InvalidArgumentError: If ``name`` or ``expr`` is invalid. CoreError: If the FieldView host rejects the formula. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> pressure_half = fv.formula.create( ... "Pressure Half", ... fv.formula.quantity("Pressure [PLOT3D]") / 2.0, ... ) """ normalized_name = _normalize_formula_name(name, "name") rendered_expr = _render_formula_input(expr) func = getattr(_core_module, "formula_create", None) if not callable(func): raise CoreError("FieldView host does not provide formula_create.") payload = _core_call(func, normalized_name, rendered_expr) payload_map = ( cast(dict[str, object], payload) if isinstance(payload, dict) else None ) created_name = ( payload_map.get("name", normalized_name) if payload_map is not None else normalized_name ) if not isinstance(created_name, str) or not created_name: raise CoreError("FieldView did not return a valid formula name.") formula = Formula(created_name) _try_refresh_current_dataset_function_lists() return formula
[docs] def quantity(name: str) -> _FormulaExpr: """Return a builder expression referencing a quantity or formula by name. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> formula = fv.formula.create( ... "Pressure Half", ... fv.formula.quantity("Pressure [PLOT3D]") / 2.0, ... ) """ return _QuantityExpr(name)
[docs] def dataset_quantity(dataset: int, name: str) -> _FormulaExpr: """Return a scene-relative dataset-comparison quantity reference. Args: dataset: 1-based dataset number in the current FieldView scene. name: Quantity or formula name to read from that dataset. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds1 = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> ds2 = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> formula = fv.formula.create( ... "Delta Pressure", ... fv.formula.dataset_quantity(2, "Pressure [PLOT3D]") ... - fv.formula.dataset_quantity(1, "Pressure [PLOT3D]"), ... ) """ return _DatasetQuantityExpr(dataset, name)
def _call(name: str, *args: object) -> _FormulaExpr: return _CallExpr(name, *args)
[docs] def mag(expr: object) -> _FormulaExpr: """Return the magnitude of a vector expression. Args: expr: Vector quantity or expression to evaluate. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> formula = fv.formula.create( ... "Velocity Magnitude", ... fv.formula.mag("Velocity Vectors [PLOT3D]"), ... ) """ return _call("MAG", expr)
[docs] def grad(expr: object) -> _FormulaExpr: """Return the gradient of a scalar expression. Args: expr: Scalar quantity or expression to differentiate. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> formula = fv.formula.create( ... "Pressure Gradient", ... fv.formula.grad("Pressure [PLOT3D]"), ... ) """ return _call("GRAD", expr)
[docs] def curl(expr: object) -> _FormulaExpr: """Return the curl of a vector expression. Args: expr: Vector quantity or expression to differentiate. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> formula = fv.formula.create( ... "Velocity Curl", ... fv.formula.curl("Velocity Vectors [PLOT3D]"), ... ) """ return _call("CURL", expr)
[docs] def nrmlz(expr: object) -> _FormulaExpr: """Return the normalized form of a vector expression. Args: expr: Vector quantity or expression to normalize. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> formula = fv.formula.create( ... "Velocity Direction", ... fv.formula.nrmlz("Velocity Vectors [PLOT3D]"), ... ) """ return _call("NRMLZ", expr)
[docs] def exp(expr: object) -> _FormulaExpr: """Return ``EXP(expr)``. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> formula = fv.formula.create( ... "Exp Pressure", ... fv.formula.exp(fv.formula.quantity("Pressure [PLOT3D]") / 1000.0), ... ) """ return _call("EXP", expr)
[docs] def ln(expr: object) -> _FormulaExpr: """Return the natural logarithm of a scalar expression. Args: expr: Scalar quantity or expression to transform. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> formula = fv.formula.create( ... "Ln Pressure", ... fv.formula.ln(fv.formula.quantity("Pressure [PLOT3D]") + 1.0), ... ) """ return _call("LN", expr)
[docs] def log(expr: object) -> _FormulaExpr: """Return the base-10 logarithm of a scalar expression. Args: expr: Scalar quantity or expression to transform. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> formula = fv.formula.create( ... "Log Pressure", ... fv.formula.log(fv.formula.quantity("Pressure [PLOT3D]") + 1.0), ... ) """ return _call("LOG", expr)
[docs] def sin(expr: object) -> _FormulaExpr: """Return ``SIN(expr)``. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> formula = fv.formula.create( ... "Sin Pressure", ... fv.formula.sin(fv.formula.quantity("Pressure [PLOT3D]") / 1000.0), ... ) """ return _call("SIN", expr)
[docs] def cos(expr: object) -> _FormulaExpr: """Return ``COS(expr)``. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> formula = fv.formula.create( ... "Cos Pressure", ... fv.formula.cos(fv.formula.quantity("Pressure [PLOT3D]") / 1000.0), ... ) """ return _call("COS", expr)
[docs] def tan(expr: object) -> _FormulaExpr: """Return ``TAN(expr)``. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> formula = fv.formula.create( ... "Tan Pressure", ... fv.formula.tan(fv.formula.quantity("Pressure [PLOT3D]") / 1000.0), ... ) """ return _call("TAN", expr)
[docs] def asin(expr: object) -> _FormulaExpr: """Return ``ASIN(expr)``. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> formula = fv.formula.create( ... "Asin Half Pressure", ... fv.formula.asin(fv.formula.quantity("Pressure [PLOT3D]") / 200000.0), ... ) """ return _call("ASIN", expr)
[docs] def acos(expr: object) -> _FormulaExpr: """Return ``ACOS(expr)``. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> formula = fv.formula.create( ... "Acos Half Pressure", ... fv.formula.acos(fv.formula.quantity("Pressure [PLOT3D]") / 200000.0), ... ) """ return _call("ACOS", expr)
[docs] def atan(expr: object) -> _FormulaExpr: """Return ``ATAN(expr)``. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> formula = fv.formula.create( ... "Atan Pressure", ... fv.formula.atan(fv.formula.quantity("Pressure [PLOT3D]") / 1000.0), ... ) """ return _call("ATAN", expr)
[docs] def atan2(lhs: object, rhs: object) -> _FormulaExpr: """Return ``ATAN2(lhs, rhs)``. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> formula = fv.formula.create( ... "Pressure Angle", ... fv.formula.atan2( ... fv.formula.quantity("Pressure [PLOT3D]"), ... fv.formula.quantity("Pressure [PLOT3D]") + 1.0, ... ), ... ) """ return _call("ATAN2", lhs, rhs)
[docs] def sqrt(expr: object) -> _FormulaExpr: """Return ``SQRT(expr)``. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> formula = fv.formula.create( ... "Sqrt Pressure", ... fv.formula.sqrt(fv.formula.quantity("Pressure [PLOT3D]")), ... ) """ return _call("SQRT", expr)
[docs] def abs(expr: object) -> _FormulaExpr: # noqa: A001 - intentional public API name """Return the absolute value of a scalar expression. Args: expr: Scalar quantity or expression to transform. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> formula = fv.formula.create( ... "Absolute Pressure Offset", ... fv.formula.abs(fv.formula.quantity("Pressure [PLOT3D]") - 100000.0), ... ) """ return _call("ABS", expr)
[docs] def div(expr: object) -> _FormulaExpr: """Return the divergence of a vector expression. Args: expr: Vector quantity or expression to differentiate. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> formula = fv.formula.create( ... "Velocity Divergence", ... fv.formula.div("Velocity Vectors [PLOT3D]"), ... ) """ return _call("DIV", expr)
[docs] def vecx(expr: object) -> _FormulaExpr: """Return the X component of a vector expression. Args: expr: Vector quantity or expression to read from. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> formula = fv.formula.create( ... "Velocity X", ... fv.formula.vecx("Velocity Vectors [PLOT3D]"), ... ) """ return _call("VECX", expr)
[docs] def vecy(expr: object) -> _FormulaExpr: """Return the Y component of a vector expression. Args: expr: Vector quantity or expression to read from. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> formula = fv.formula.create( ... "Velocity Y", ... fv.formula.vecy("Velocity Vectors [PLOT3D]"), ... ) """ return _call("VECY", expr)
[docs] def vecz(expr: object) -> _FormulaExpr: """Return the Z component of a vector expression. Args: expr: Vector quantity or expression to read from. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> formula = fv.formula.create( ... "Velocity Z", ... fv.formula.vecz("Velocity Vectors [PLOT3D]"), ... ) """ return _call("VECZ", expr)
[docs] def dot(lhs: object, rhs: object) -> _FormulaExpr: """Return the FieldView infix ``DOT`` operation between two vectors. Args: lhs: Left-hand vector quantity or expression. rhs: Right-hand vector quantity or expression. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> formula = fv.formula.create( ... "Velocity X Projection", ... fv.formula.dot("Velocity Vectors [PLOT3D]", fv.formula.unit_x), ... ) """ return _BinaryExpr("DOT", _coerce_call_arg(lhs), _coerce_call_arg(rhs))
[docs] def cross(lhs: object, rhs: object) -> _FormulaExpr: """Return the FieldView infix ``CROSS`` operation between two vectors. Args: lhs: Left-hand vector quantity or expression. rhs: Right-hand vector quantity or expression. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> formula = fv.formula.create( ... "Velocity Cross Unit X", ... fv.formula.cross("Velocity Vectors [PLOT3D]", fv.formula.unit_x), ... ) """ return _BinaryExpr("CROSS", _coerce_call_arg(lhs), _coerce_call_arg(rhs))
[docs] def qcriterion(expr: object) -> _FormulaExpr: """Return the Q-criterion of a vector expression. Args: expr: Vector quantity or expression to evaluate. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> formula = fv.formula.create( ... "Q Criterion", ... fv.formula.qcriterion("Velocity Vectors [PLOT3D]"), ... ) """ return _call("Qcriterion", expr)
[docs] def lambda2criterion(expr: object) -> _FormulaExpr: """Return the Lambda2 criterion of a vector expression. Args: expr: Vector quantity or expression to evaluate. Example: .. code-block:: python >>> import os >>> import fieldview as fv >>> data_dir = os.path.join(fv.home, "examples", "f18") >>> ds = fv.data.load_plot3d( ... os.path.join(data_dir, "f18i9b_g_bin"), ... os.path.join(data_dir, "f18i9b_q_bin"), ... ) >>> formula = fv.formula.create( ... "Lambda2 Criterion", ... fv.formula.lambda2criterion("Velocity Vectors [PLOT3D]"), ... ) """ return _call("Lambda2criterion", expr)
#: Formula constant for ``PI`` with value ``3.141592653589793``. pi = _LiteralExpr("PI") #: Euler's number with value ``2.718281828459045``, rendered as a numeric literal #: for host compatibility. e = _LiteralExpr(repr(math.e)) #: Formula vector constant for ``UNITX`` with value ``(1, 0, 0)``. unit_x = _LiteralExpr("UNITX") #: Formula vector constant for ``UNITY`` with value ``(0, 1, 0)``. unit_y = _LiteralExpr("UNITY") #: Formula vector constant for ``UNITZ`` with value ``(0, 0, 1)``. unit_z = _LiteralExpr("UNITZ") #: Dataset-dependent formula constant for ``ALPHA``. alpha = _LiteralExpr("ALPHA") #: Dataset-dependent formula constant for ``FSMACH``. fsmach = _LiteralExpr("FSMACH") #: Dataset-dependent formula constant for ``RE``. re = _LiteralExpr("RE") #: Dataset-dependent formula constant for ``TIME``. time = _LiteralExpr("TIME") #: Dataset-dependent formula constant for ``GAMMA``. gamma = _LiteralExpr("GAMMA") #: Dataset-dependent formula constant for ``R``. r = _LiteralExpr("R")