from keecas import symbols, u, pc, show_eqn
# Basic parameter substitution
F, A_load = symbols(r"F, A_{load}")
_p = {
F: 100*u.kN,
A_load: 20*u.cm**2,
}
sigma = symbols(r"\sigma")
_e = {
sigma: "F / A_load" | pc.parse_expr,
}
# Substitute parameters into expression
result = _e[sigma] | pc.subs(_p)pipe_command
Pipe commands for functional composition of mathematical operations.
This module provides @Pipe decorated functions that enable chain operations like: expr | pc.subs(vals) | pc.convert_to(units) | pc.N
All functions are designed to work with SymPy expressions and support functional programming patterns for mathematical computation workflows.
Functions
| Name | Description |
|---|---|
| order_subs | Reorder substitutions using topological order for dependency resolution. |
| subs | Substitute variables in symbolic expressions with values or other expressions. |
| rebuild | Rebuild an expression tree so that leftover numeric pieces are evaluated. |
| N | Numerically evaluate symbolic expressions to floating-point values. |
| convert_to | Convert quantities to different units while preserving values. |
| doit | Evaluate unevaluated operations in symbolic expressions. |
| parse_expr | Parse mathematical expression strings into SymPy symbolic objects. |
| quantity_simplify | Simplify expressions with units by combining and reducing quantities. |
| as_two_terms | Split expression into magnitude and units components. |
| as_Mul | Create unevaluated multiplication from tuple of expressions. |
order_subs
order_subs(subs)Reorder substitutions using topological order for dependency resolution.
Substitutions are applied one after the other, so a key must be replaced before any other key it brings into the expression or contains:
- a key whose value contains another key comes first (
y: 2*xis applied beforex: 3, so thexit introduces is replaced too); - a key that contains another key comes first:
MatrixSymbol("A", n, m)is applied beforenandm, andf(x)beforex. Replacingnfirst would turn the expression’sAintoMatrixSymbol("A", 2, m), which no longer matches the keyA(keecas#124).
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| subs | dict[Basic, Any] |
Dictionary of substitutions where keys are variables and values are expressions | required |
Returns
| Name | Type | Description |
|---|---|---|
list[tuple[Basic, Any]] |
Ordered list of substitution tuples for exhaustive application |
Raises
| Name | Type | Description |
|---|---|---|
ValueError |
If the dependencies form a cycle, e.g. x: y and y: x, or x: f(x) and f(x): 3 (the value of x contains f(x), and f(x) contains x). The message names the keys of each cycle. |
subs
subs(expression, substitution, sorted=True)Substitute variables in symbolic expressions with values or other expressions.
Applies substitutions to SymPy expressions while handling dependencies between variables. Commonly used in workflows to evaluate symbolic equations with parameters from _p dicts or intermediate expressions from _e dicts. Integrates with pipe operations for functional composition.
NOTE: Returns None if input expression is None, allowing chain operations to gracefully handle missing values.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| expression | Basic |
SymPy expression to apply substitutions to. Can be any symbolic expression containing variables to be replaced. | required |
| substitution | dict[Basic, Any] |
Dictionary mapping variables (symbols) to their replacement values (numeric values, quantities with units, or other expressions). Non-Basic keys and None values are automatically filtered out. | required |
| sorted | bool |
Whether to apply topological sorting for dependency resolution. When True (default), automatically orders substitutions so that dependent variables are substituted in correct order (e.g., if y depends on x, the x introduced by y is substituted too, and a MatrixSymbol with a symbolic shape is substituted before its shape symbols; see order_subs). When False, the dict is passed to SymPy’s subs unchanged, which does not resolve dependencies between entries. Defaults to True. |
True |
Returns
| Name | Type | Description |
|---|---|---|
Basic |
SymPy expression with substitutions applied, or None if input is None. |
Examples
# Multi-step workflow with merged dicts
_v = {
k: v | pc.subs(_p | _e) | pc.convert_to([u.MPa]) | pc.N
for k, v in _e.items()
}
show_eqn([_p | _e, _v])\[\begin{align} F & = 100{\,}\text{kN} & \\[8pt] A_{load} & = 20{\,}\text{cm}^{2} & \\[8pt] \sigma & = \dfrac{F}{A_{load}} & = 50.0{\,}\text{MPa} \end{align}\]
# Dependency resolution with sorted=True
x, y, z = symbols(r"x, y, z")
# y depends on x, z depends on y
_e = {
z: "x + y" | pc.parse_expr,
y: "2 * x" | pc.parse_expr,
x: 5,
}
# Automatic ordering: x first, then y, then z
result = z | pc.subs(_e) # sorted=True by defaultNotes
- Automatically filters out None values and non-Basic keys from substitution dict
- Topological sorting handles complex dependency chains automatically
- Works seamlessly with Pint quantities through SymPy integration
- Common pattern:
_p | _emerges parameters and expressions for substitution
rebuild
rebuild(expression)Rebuild an expression tree so that leftover numeric pieces are evaluated.
parse_expr keeps the expression as typed (evaluate=False), so n - 1 is stored as n + (-1)*1. After subs() replaces n with 3, the result still reads 3 - 1*1: the (-1)*1 holds no symbol, so subs() never rebuilds it. Most steps do not mind, but Sum and Product iterate only when their limits are plain integers, so doit() leaves them unevaluated. The same happens with any unevaluated literal, such as Abs(-3) or sqrt(4).
rebuild calls every constructor in the tree again (SymPy’s sympy.strategies.rl.rebuild), giving the same tree as parsing with evaluate=True. Quantities, matrices, arrays, indexed objects and UnevaluatedExpr are kept. Use it as a step after subs() in the _v pipeline; the _e dict keeps the typed form for show_eqn().
NOTE: Returns None if input expression is None, like subs().
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| expression | Any |
Expression to rebuild, typically the output of subs(). Non-SymPy input (numbers, mutable matrices) is sympified first, as subs() does. |
required |
Returns
| Name | Type | Description |
|---|---|---|
Basic |
Rebuilt SymPy expression, or None if input is None. |
Examples
from keecas import symbols, pc
n = symbols(r"n")
after_subs = "n - 1" | pc.parse_expr | pc.subs({n: 3})
print(after_subs) # 3 - 1*1, as typed
print(after_subs | pc.rebuild) # 23 - 1*1
2
# A sum whose upper limit depends on a parameter
from keecas import u, show_eqn
from sympy import Array, Idx, IndexedBase
F = symbols(r"F", cls=IndexedBase)
i = symbols(r"i", cls=Idx)
n, F_tot = symbols(r"n, F_{tot}")
_p = {
F: Array([10, 20, 30]) * u.kN,
n: 3,
}
_e = {
F_tot: "Sum(F[i], (i, 0, n - 1))" | pc.parse_expr,
}
# Without pc.rebuild, pc.doit would leave the Sum unevaluated
_v = {
k: v | pc.subs(_p | _e) | pc.rebuild | pc.doit | pc.convert_to([u.kN]) | pc.N
for k, v in _e.items()
}
show_eqn([_p | _e, _v])\[\begin{align} F & = \left[\begin{matrix}10{\,}\text{kN} & 20{\,}\text{kN} & 30{\,}\text{kN}\end{matrix}\right] & \\[8pt] n & = 3 & \\[8pt] F_{tot} & = \sum_{i=0}^{n - 1} {F}_{i} & = 60.0{\,}\text{kN} \end{align}\]
Notes
- Needed only when a
SumorProductlimit is a formula such asn - 1: other expressions give the same result without it, sinceN()evaluates the leftovers. A missingrebuildshows as an unevaluatedSum(...)in the result - Not applied inside
subs(): its output is sometimes displayed as an intermediate step, and rebuilding can reorder the terms N()beforedoit()is not a substitute: on a singleSumit tries a numeric estimate and can fail
N
N(expression, precision=15)Numerically evaluate symbolic expressions to floating-point values.
Converts symbolic expressions containing irrational numbers, constants, or unevaluated operations into numeric approximations. Commonly used as final step in calculation workflows before display with show_eqn().
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| expression | Basic |
SymPy expression to evaluate numerically. Can contain symbolic math operations, constants (pi, e, etc.), or quantities with units. | required |
| precision | int |
Number of decimal digits for evaluation. Controls internal calculation precision, not display formatting (use float_format in show_eqn for display). Defaults to 15. | 15 |
Returns
| Name | Type | Description |
|---|---|---|
Basic |
Numerically evaluated SymPy expression as floating-point approximation. |
Examples
from keecas import symbols, u, pc, show_eqn
from sympy import pi
# Basic numeric evaluation
r = symbols(r"r")
A_circle = symbols(r"A_{circle}")
_p = {
r: 5*u.cm,
}
_e = {
A_circle: "pi * r**2" | pc.parse_expr,
}
# Evaluate symbolic pi to numeric value
_v = {
k: v | pc.subs(_p | _e) | pc.N
for k, v in _e.items()
}
show_eqn([_p | _e, _v])\[\begin{align} r & = 5{\,}\text{cm} & \\[8pt] A_{circle} & = \pi{\,}r^{2} & = 78.5398163397448{\,}\text{cm}^{2} \end{align}\]
# Control precision for high-accuracy calculations
import sympy as sp
expr = sp.sqrt(2)
# Default precision (15 digits)
result_default = expr | pc.N
# High precision (50 digits)
result_high = expr | pc.N(precision=50)# Typical workflow: subs -> convert_to -> N
F, A_load, sigma_Sd = symbols(r"F, A_{load}, \sigma_{Sd}")
_p = {
F: 850*u.kN,
A_load: 120*u.cm**2,
}
_e = {
sigma_Sd: "F / A_load" | pc.parse_expr,
}
_v = {
k: v | pc.subs(_p | _e) | pc.convert_to([u.MPa]) | pc.N
for k, v in _e.items()
}
show_eqn([_p | _e, _v])\[\begin{align} F & = 850{\,}\text{kN} & \\[8pt] A_{load} & = 120{\,}\text{cm}^{2} & \\[8pt] \sigma_{Sd} & = \dfrac{F}{A_{load}} & = 70.8333333333333{\,}\text{MPa} \end{align}\]
Notes
- Precision parameter controls internal calculation accuracy, not display
- For display formatting, use float_format parameter in show_eqn()
- Works with Pint quantities, preserving units in output
- Commonly chained after subs() and convert_to() in evaluation workflows
convert_to
convert_to(expression, units=1)Convert quantities to different units while preserving values.
Converts SymPy expressions with units to target units, handling both prefixed units (kN, daN, cm) and compound units (MPa, kN/m). Commonly used in engineering workflows to standardize units before display or comparison. Integrates seamlessly with Pint unit definitions.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| expression | Basic |
SymPy expression with units to convert. Must contain dimensional quantities (e.g., force, pressure, length). | required |
| units | Any |
Target units for conversion. Can be: - Single unit (e.g., u.MPa) - List of units (e.g., [u.kN, u.mm]) - Compound units (e.g., u.kN/u.m) Defaults to 1 (dimensionless). | 1 |
Returns
| Name | Type | Description |
|---|---|---|
Basic |
Expression converted to target units with same magnitude in new units. |
Examples
from keecas import symbols, u, pc, show_eqn
# Basic unit conversion
F, A_load = symbols(r"F, A_{load}")
_p = {
F: 5000*u.N, # Newtons
A_load: 120*u.cm**2,
}
# Convert to kilonewtons
_v = {
F: _p[F] | pc.convert_to(u.kN),
A_load: _p[A_load] | pc.convert_to(u.m),
}
show_eqn([_p, _v])\[\begin{align} F & = 5000{\,}\text{N} & = 5{\,}\text{kN} \\[8pt] A_{load} & = 120{\,}\text{cm}^{2} & = \dfrac{3}{250}{\,}\text{m}^{2} \end{align}\]
# Compound unit conversion
sigma = symbols(r"\sigma")
_p = {
F: 850*u.kN,
A_load: 120*u.cm**2,
}
_e = {
sigma: "F / A_load" | pc.parse_expr,
}
# Convert pressure to MPa
_v = {
k: v | pc.subs(_p | _e) | pc.convert_to(u.MPa) | pc.N
for k, v in _e.items()
}
show_eqn([_p | _e, _v])\[\begin{align} F & = 850{\,}\text{kN} & \\[8pt] A_{load} & = 120{\,}\text{cm}^{2} & \\[8pt] \sigma & = \dfrac{F}{A_{load}} & = 70.8333333333333{\,}\text{MPa} \end{align}\]
# List of target units for flexibility
L, delta = symbols(r"L, \delta")
_p = {
L: 8*u.m,
}
_e = {
delta: "L / 400" | pc.parse_expr,
}
# Try converting to mm, fallback to other units if needed
_v = {
k: v | pc.subs(_p | _e) | pc.convert_to([u.mm]) | pc.N
for k, v in _e.items()
}
show_eqn([_p | _e, _v])\[\begin{align} L & = 8{\,}\text{m} & \\[8pt] \delta & = \dfrac{L}{400} & = 20.0{\,}\text{mm} \end{align}\]
# Sums with units and exact constants: pi stays symbolic until pc.N
b_f, A_r, g_s, w = symbols(r"b_f, A_r, \gamma_s, w")
_p = {
b_f: 50*u.mm,
g_s: 78.5*u.kN/u.m**3,
}
_e = {
A_r: "2*b_f**2 - (4 - pi)*b_f**2/10" | pc.parse_expr,
w: "A_r * g_s" | pc.parse_expr,
}
_v = {
A_r: A_r | pc.subs(_p | _e) | pc.convert_to([u.mm]), # (4000 + 250*pi) mm**2, exact
w: w | pc.subs(_p | _e) | pc.convert_to([u.kN, u.m]) | pc.N, # kN/m
}
show_eqn([_p | _e, _v])\[\begin{align} b_{f} & = 50{\,}\text{mm} & \\[8pt] \gamma_{s} & = 78.5{\,}\dfrac{\text{kN}}{\text{m}^{3}} & \\[8pt] A_{r} & = 2{\,}b_{f}^{2} - \dfrac{\left(4 - \pi\right){\,}b_{f}^{2}}{10} & = \left(4000 + 250{\,}\pi\right){\,}\text{mm}^{2} \\[8pt] w & = A_{r}{\,}\gamma_{s} & = 0.3756537558267{\,}\dfrac{\text{kN}}{\text{m}} \end{align}\]
Notes
- Prefixed units (kN, cm, MPa) handled automatically via SymPy prefix system
- Non-prefixed units (kgf, lbf) use scale factors from Pint definitions
- All Pint units convert correctly through SymPy integration
- Commonly chained between subs() and N() in evaluation workflows
- List of units allows flexible conversion with fallback options
- A sum whose terms share a dimension is converted as a whole, also when it is a factor of a product (
(4 - pi)*b**2,h - c - 5*u.mm), soN()is not needed beforeconvert_to(); sympy’s ownconvert_togets the unit wrong there (keecas#118) - Exact numbers and constants such as
pistay symbolic; chainN()afterconvert_to()to evaluate them
doit
doit(expression)Evaluate unevaluated operations in symbolic expressions.
Forces evaluation of operations that SymPy keeps in symbolic form, such as derivatives, integrals, summations, or limits. Useful when symbolic operations need numeric results or simplified forms.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| expression | Basic |
SymPy expression containing unevaluated operations (derivatives, integrals, summations, limits, etc.) that should be evaluated. | required |
Returns
| Name | Type | Description |
|---|---|---|
Basic |
Expression with all unevaluated operations evaluated to their results. |
Examples
from keecas import symbols, pc
import sympy as sp
# Evaluate derivative
x = symbols(r"x")
expr = sp.Derivative(x**2, x)
# Without doit: shows Derivative(x**2, x)
print(expr)
# With doit: evaluates to 2*x
result = expr | pc.doit
print(result)Derivative(x**2, x)
2*x
# Evaluate integral
integral_expr = sp.Integral(sp.sin(x), x)
# Evaluates to -cos(x)
result = integral_expr | pc.doit# Use in calculation workflow
from keecas import u, show_eqn
F, x_coord = symbols(r"F, x")
_p = {
F: 100*u.kN,
}
# Expression with derivative
_e = {
symbols(r"dF/dx"): sp.Derivative(F * x_coord**2, x_coord),
}
# Evaluate derivative then substitute
_v = {
k: v | pc.doit | pc.subs(_p) | pc.N
for k, v in _e.items()
}
show_eqn([_p | _e, _v])\[\begin{align} F & = 100{\,}\text{kN} & \\[8pt] dF/dx & = \dfrac{\partial}{\partial x} F{\,}x^{2} & = 200.0{\,}x{\,}\text{kN} \end{align}\]
# Sum over an IndexedBase substituted with a matrix expression
from sympy import Idx, ImmutableMatrix, IndexedBase, MatrixSymbol
q = symbols(r"q", cls=IndexedBase)
i, j = symbols(r"i, j", cls=Idx)
gamma_Q, Q_tot = symbols(r"\gamma_Q, Q_{tot}")
Q_k = symbols(r"Q_k", cls=MatrixSymbol, n=2, m=3)
_p = {
gamma_Q: 1.5,
Q_k: ImmutableMatrix([[1, 2, 3], [4, 5, 6]]) * u.kN,
}
_e = {
q: "gamma_Q * Q_k" | pc.parse_expr,
Q_tot: "Sum(q[i, j], (i, 0, 1), (j, 0, 2))" | pc.parse_expr,
}
# q becomes 1.5*Q_k with Q_k a Matrix: the Sum still evaluates
_v = {
Q_tot: Q_tot | pc.subs(_p | _e) | pc.doit | pc.convert_to(u.kN) | pc.N,
}
show_eqn([_p | _e, _v])\[\begin{align} \gamma_{Q} & = 1.5 & \\[8pt] Q_{k} & = \left[\begin{matrix}\text{kN} & 2{\,}\text{kN} & 3{\,}\text{kN}\\[8pt]4{\,}\text{kN} & 5{\,}\text{kN} & 6{\,}\text{kN}\end{matrix}\right] & \\[8pt] q & = \gamma_{Q} Q_{k} & \\[8pt] Q_{tot} & = \sum_{\substack{0 \leq i \leq 1\\[8pt]0 \leq j \leq 2}} {q}_{i,j} & = 31.5{\,}\text{kN} \end{align}\]
Notes
- Works with derivatives, integrals, limits, summations, and products
- May be needed before subs() to properly substitute into evaluated forms
- Not all operations can be evaluated symbolically (may return unchanged)
- Combines well with other pipe commands in calculation workflows
- An
IndexedBasesuch asx[i, j]can be substituted with a 2-D Matrix or a matrix expression (k*B, a Hadamard product, a scalar with units times a Matrix), not only with anArray: before evaluating, suchIndexedobjects are rebuilt over an explicitArrayso aSumover them resolves (keecas#126). A matrix expression that still contains aMatrixSymbolis left symbolic. - A
SumorProductwhose limit is a formula (n - 1) also needsrebuild()aftersubs():pc.subs | pc.rebuild | pc.doit | pc.convert_to | pc.N - With a
Sum, putdoit()beforeconvert_to(): on an unevaluatedSum,convert_to()converts each quantity inside it separately, and a target such as[u.kN]cannot express akPathere - A literal index on both axes of a 2-D Matrix (
x[0, 1]) fails earlier, insubs()(keecas#134)
parse_expr
parse_expr(expression, local_dict=None, evaluate=False, **kwargs)Parse mathematical expression strings into SymPy symbolic objects.
Converts string representations of mathematical expressions into SymPy expressions that can be manipulated symbolically. Most commonly used with pipe operator to define expressions in _e dicts using readable string notation instead of verbose SymPy syntax.
NOTE: Automatically captures the caller’s variables when local_dict is None, both with | pc.parse_expr and with arguments (| pc.parse_expr(evaluate=True)), enabling clean string-based expression definitions.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| expression | str |
String representation of mathematical expression using standard notation (e.g., “F / A”, “pi * r**2”, “sqrt(x2 + y2)”). Supports operators: +, -, *, /, **, parentheses, and common functions. | required |
| local_dict | dict[str, Any] | None |
Dictionary of local variables for parsing context (symbol definitions, parameters, functions). If None, automatically uses the caller’s local and module variables. Defaults to None. | None |
| evaluate | bool |
Whether to evaluate the expression during parsing (e.g., simplify numeric operations). When False, preserves structure as written. Defaults to False. | False |
| **kwargs | Any |
Additional arguments passed to SymPy’s parse_expr: - transformations: List of parsing transformations (defaults to T[:11]) - global_dict: Global symbol dictionary | {} |
Returns
| Name | Type | Description |
|---|---|---|
Basic |
Parsed SymPy expression object ready for symbolic manipulation. |
Examples
from keecas import symbols, u, pc, show_eqn
# Most common pattern: define expressions as strings
F, A_load, sigma = symbols(r"F, A_{load}, \sigma")
_p = {
F: 100*u.kN,
A_load: 20*u.cm**2,
}
# Use parse_expr to convert string to SymPy expression
_e = {
sigma: "F / A_load" | pc.parse_expr,
}
_v = {
k: v | pc.subs(_p | _e) | pc.convert_to([u.MPa]) | pc.N
for k, v in _e.items()
}
show_eqn([_p | _e, _v])\[\begin{align} F & = 100{\,}\text{kN} & \\[8pt] A_{load} & = 20{\,}\text{cm}^{2} & \\[8pt] \sigma & = \dfrac{F}{A_{load}} & = 50.0{\,}\text{MPa} \end{align}\]
# Complex expressions with functions
from sympy import pi
r, A_circle, V_sphere = symbols(r"r, A_{circle}, V_{sphere}")
_p = {
r: 5*u.cm,
}
_e = {
A_circle: "pi * r**2" | pc.parse_expr,
V_sphere: "(4/3) * pi * r**3" | pc.parse_expr,
}
_v = {
k: v | pc.subs(_p | _e) | pc.N
for k, v in _e.items()
}
show_eqn([_p | _e, _v])\[\begin{align} r & = 5{\,}\text{cm} & \\[8pt] A_{circle} & = \pi{\,}r^{2} & = 78.5398163397448{\,}\text{cm}^{2} \\[8pt] V_{sphere} & = \dfrac{4{\,}\pi{\,}r^{3}}{3} & = 523.598775598299{\,}\text{cm}^{3} \end{align}\]
# Custom local_dict for additional functions
from sympy import sqrt
custom_locals = {
'special_func': lambda x: sqrt(x**2 + 1),
}
expr = "special_func(5)" | pc.parse_expr(local_dict=custom_locals)# Multiple dependent expressions
x, y, z, result = symbols(r"x, y, z, result")
_p = {
x: 3,
y: 4,
}
# Expressions can reference each other
_e = {
z: "sqrt(x**2 + y**2)" | pc.parse_expr,
result: "z * 2" | pc.parse_expr,
}
# tip: automatic dependency resolution with pc.subs
_v = {
k: v | pc.subs(_p | _e) | pc.N
for k, v in _e.items()
}
show_eqn([_p | _e, _v])\[\begin{align} x & = 3 & \\[8pt] y & = 4 & \\[8pt] z & = \sqrt{x^{2} + y^{2}} & = 5.0 \\[8pt] result & = z{\,}2 & = 10.0 \end{align}\]
Notes
- Uses transformations T[:11] by default for standard mathematical parsing
- Automatically captures caller’s local scope for symbol resolution; inside a generator expression only its own variables and the module globals are visible, so pass local_dict there
- Common functions supported: sin, cos, sqrt, log, exp, abs, etc.
- Operators: +, -, *, /, ** (power), parentheses for grouping
- Cleaner than verbose SymPy syntax: “F/A” vs sp.Div(F, A)
- Idiomatic pattern: define symbols, then use string expressions in _e dict
quantity_simplify
quantity_simplify(
expression,
across_dimensions=True,
unit_system='SI',
**kwargs,
)Simplify expressions with units by combining and reducing quantities.
Applies SymPy’s quantity simplification to combine terms with compatible units and reduce complex unit expressions. Useful for cleaning up expressions with multiple unit terms or dimensional analysis.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| expression | Basic |
SymPy expression to simplify, typically containing multiple terms with units that can be combined or reduced. | required |
| across_dimensions | bool |
Whether to simplify across different dimensions (e.g., combine force and length into energy). When True, allows broader simplifications. Defaults to True. | True |
| unit_system | str |
Unit system for simplification, determines which base units to use. Options include “SI”, “CGS”, “imperial”. Defaults to “SI”. | 'SI' |
| **kwargs | Any |
Additional arguments passed to SymPy’s quantity_simplify: - across_dimensions: Override the across_dimensions parameter - unit_system: Override the unit_system parameter | {} |
Returns
| Name | Type | Description |
|---|---|---|
Basic |
Simplified SymPy expression with combined and reduced unit terms. |
Examples
from keecas import symbols, u, pc, show_eqn
# Simplify expression with multiple force terms
F_1, F_2, F_total = symbols(r"F_1, F_2, F_{total}")
_p = {
F_1: 100*u.kN,
F_2: 50000*u.N,
}
_e = {
F_total: "F_1 + F_2" | pc.parse_expr,
}
# Simplify combines terms with compatible units
_v = {
k: v | pc.subs(_p | _e) | pc.quantity_simplify | pc.convert_to([u.kN]) | pc.N
for k, v in _e.items()
}
show_eqn([_p | _e, _v])\[\begin{align} F_{1} & = 100{\,}\text{kN} & \\[8pt] F_{2} & = 50000{\,}\text{N} & \\[8pt] F_{total} & = F_{1} + F_{2} & = 150.0{\,}\text{kN} \end{align}\]
# Dimensional analysis with unit simplification
F, d, E = symbols(r"F, d, E")
_p = {
F: 500*u.N,
d: 2*u.m,
}
# Work (energy) from force and distance
_e = {
E: "F * d" | pc.parse_expr,
}
# Simplify to base energy units
_v = {
k: v | pc.subs(_p | _e) | pc.quantity_simplify | pc.convert_to([u.J]) | pc.N
for k, v in _e.items()
}
show_eqn([_p | _e, _v])\[\begin{align} F & = 500{\,}\text{N} & \\[8pt] d & = 2{\,}\text{m} & \\[8pt] E & = F{\,}d & = 1000.0{\,}\text{J} \end{align}\]
# Different unit systems
from sympy import sympify
from sympy.physics.units import newton, kilonewton
# Create expression with different unit prefixes
expr = 100*kilonewton + 5000*newton
# Simplify combines compatible units
result = expr | pc.quantity_simplify(unit_system="SI")
print(result) # Combines to single unit105000*newton
Notes
- Combines terms with compatible units (e.g., kN + N -> kN)
- Simplifies compound units to base units when appropriate
- across_dimensions=True enables dimensional analysis simplifications
- Works with both SI and other unit systems
- May need convert_to() afterward to get desired output units
as_two_terms
as_two_terms(expression, as_mul=False)Split expression into magnitude and units components.
Separates multiplicative expressions or matrices into two terms, typically magnitude and units for cleaner display.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| expression | Basic |
SymPy expression to split | required |
| as_mul | bool |
If True, return as unevaluated multiplication | False |
Returns
| Name | Type | Description |
|---|---|---|
Basic | tuple[Basic, Basic] |
Two-term tuple or unevaluated multiplication, depending on as_mul. | |
Basic | tuple[Basic, Basic] |
Returns original expression if splitting is not applicable. |
Notes
For matrices, splits only if all elements share the same units.
as_Mul
as_Mul(expression)Create unevaluated multiplication from tuple of expressions.
Multiplies two expressions while keeping them visually separated, ideal for displaying magnitude and units distinctly.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| expression | tuple[Basic, Basic] |
Tuple containing two SymPy expressions to multiply | required |
Returns
| Name | Type | Description |
|---|---|---|
Basic |
Unevaluated multiplication expression for clean display |