Skip to content

Releases: sinagilassi/PyCUC

PyCUC v3.0.0

Choose a tag to compare

@sinagilassi sinagilassi released this 07 Sep 17:26

New: dimensional unit conversion

PyCUC 3.0.0 adds pycuc.from_to(), a general-purpose converter for
dimensionally compatible unit expressions. It is intended for equation
outputs and engineering expressions which were not practical to enumerate in
the legacy fixed-reference tables.

import pycuc

pycuc.from_to(1, "kg.m/s^2", "N")               # 1.0
pycuc.from_to(1, "kg/(m.s^2)", "Pa")            # 1.0
pycuc.from_to(1, "kJ/(mol.K)", "J/(mol.K)")     # 1000.0
pycuc.from_to(1, "kg.m^2/s^3", "W")             # 1.0

The engine parses every atom, recursively reduces it to the seven SI base
dimensions, checks dimensional compatibility, then applies the factor ratio.
It does not treat a complete engineering expression as an opaque lookup key.

Independent RefsX catalog

The new engine uses pycuc.docs.refsx.RefsX, an independent catalog of SI,
derived, process-engineering, and legacy-compatible unit definitions. It does
not depend on the legacy Refs category tables, so from_to() is suitable for
blind dimensional conversion of supported units.

Examples of supported engineering conversions:

# Heat-transfer coefficient; both denominator styles are accepted.
pycuc.from_to(1, "W/(m^2.K)", "BTU/(hr.ft^2.F)")
# 0.176110183682...

pycuc.from_to(1, "BTU/hr/ft^2/F", "W/m^2/K")
# 5.67826334111...

# Pressure, energy, viscosity, flow, and power.
pycuc.from_to(1, "torr", "Pa")                  # 133.322368421...
pycuc.from_to(1, "kg/cm2", "bar")               # 0.980665
pycuc.from_to(1, "erg", "J")                    # 1e-7
pycuc.from_to(1, "cP", "Pa.s")                  # 0.001
pycuc.from_to(10, "gal(US)/min", "L/min")       # 37.85411784
pycuc.from_to(1, "hp", "W")                     # 745.699871582...

Expression syntax

# Multiplication: `.` and `*` are equivalent.
pycuc.from_to(1, "kg.m/s^2", "N")
pycuc.from_to(1, "kg*m/s^2", "N")

# Integer powers: caret and legacy compact forms.
pycuc.from_to(1, "m^2", "cm2")
pycuc.from_to(1, "kg.m2/s2", "J")

# Parentheses and repeated division.
pycuc.from_to(1, "(m/s)^2", "m^2/s^2")
pycuc.from_to(1, "kg/m/s^2", "Pa")

At one expression level, factors following the first / remain in the
denominator. Thus kg/m/s^2 means kg/(m.s^2). Parentheses may be used to
make grouping explicit.

Unicode superscripts are deliberately rejected. Write m^2, not a Unicode
superscript form such as square-metre notation.

Concentration names

The catalog uses clear, case-sensitive concentration symbols:

pycuc.from_to(1, "M", "mol/L")         # molar concentration
pycuc.from_to(1, "ML", "mol/kg")       # molal concentration
pycuc.from_to(1, "molality", "mol/kg")

m remains metre and is never overloaded as molality.

Rules for blind conversion

from_to() is a blind dimensional converter. It can convert without a
quantity category only when every rule below is satisfied:

  1. Both expressions use units defined by RefsX (including documented SI
    prefixes and expression aliases).
  2. Both expressions parse under the strict grammar: units, . or *, /,
    balanced parentheses, and integer exponents.
  3. Both expressions reduce to exactly the same seven-element SI dimension
    vector.
  4. The conversion is multiplicative; no unprovided material property,
    reference condition, density, gravity convention, or semantic assumption is
    required.
  5. The caller supplies the intended target unit. Matching dimensions do not
    prove physical meaning--for example, J and N.m share dimensions but can
    represent energy and torque respectively.

When a rule is not met, the converter raises a precise error such as
UnknownUnitError, UnitSyntaxError, or DimensionMismatchError rather than
guessing.

Explicit non-blind cases

Absolute temperature is affine and must continue to use the existing API:

pycuc.convert_from_to(25, "C", "K")  # 298.15

For temperature intervals, use explicit delta-style symbols:

pycuc.from_to(1, "dC", "dK")  # 1.0
pycuc.from_to(1, "dF", "dC")  # 0.555555...

Likewise, ppm is a dimensionless ratio. Converting ppm directly to
mg/L is not blind because it requires a density assumption; provide that
assumption in the calling calculation instead.

🚀 Mapper Input Data

Choose a tag to compare

@sinagilassi sinagilassi released this 09 Dec 20:22

🚀 Mapper: mapper.py

We’ve added a new example script, mapper.py, to help users understand and utilize the mapping and reference-checking features of PyCUC! Here’s what’s included:

🧩 Reference Checking

Easily check for reference types, available units, and unit availability using PyCUC’s built-in functions:

# Check if a reference exists
print(pycuc.check_reference('PRESSURE'))

# List all units for a reference
print(pycuc.all_units('PRESSURE'))

# List all available reference units
print(pycuc.all_units())

# Check if a unit is available for a reference
print(pycuc.is_unit_available('bar', 'PRESSURE'))
print(pycuc.is_unit_available('C', 'TEMPERATURE'))
print(pycuc.is_unit_available('kg/m3'))

These functions help you validate and explore the supported references and units in your application.

🔄 Mapping Inputs to References

Map your input data to a reference schema, handling unit conversions and symbol mapping automatically:

from pycuc.utils.tools import map_to_reference

inputs = {
    'Tc': {'value': 0, 'unit': 'K', 'symbol': 'Tc'},
    'T': {'value': None, 'unit': 'K', 'symbol': 'T'}
}

reference = {
    'Tc': {'name': 'critical temperature', 'symbol': 'Tc', 'unit': 'C'},
    'T': {'name': 'temperature', 'symbol': 'T', 'unit': 'F'}
}

print(map_to_reference(inputs=inputs, reference=reference, verbose=True))

# Output:
{'Tc': {'value': -273.15, 'symbol': 'Tc', 'unit': 'C'}, 'T': {'value': None, 'symbol': 'T', 'unit': 'F'}}

This example shows how to align your input data with a reference definition, including unit conversion and symbol matching, with detailed output when verbose=True.

📚 Usage Guide

  • The script is well-commented and structured for easy understanding.
  • Use it as a template to integrate PyCUC’s mapping and reference utilities into your own projects.

New References

Choose a tag to compare

@sinagilassi sinagilassi released this 21 Apr 21:49

New Features:

We updated the reference with the following sections: density, energy, heat capacity, volume, mass, power, length, and force.

Example Usage:

  1. Check references:
print(pycuc.check_reference('PRESSURE'))
print(pycuc.check_reference('TEMPERATURE'))
print(pycuc.check_reference('DENSITY'))
print(pycuc.check_reference('ENERGY'))
print(pycuc.check_reference('HEAT_CAPACITY'))
print(pycuc.check_reference('VOLUME'))
print(pycuc.check_reference('MASS'))
print(pycuc.check_reference('POWER'))
print(pycuc.check_reference('LENGTH'))
print(pycuc.check_reference('FORCE'))
  1. Convert from to (short format)
# ! pressure
print(pycuc.to(125, 'MPa => Pa'))
# ! temperature
print(pycuc.to(360, 'K => C'))
print(pycuc.to(250, 'C => K'))
# same unit test
print(pycuc.to(275, 'K => K'))
# ! density
print(pycuc.to(1, 'g/cm3 => kg/m3'))
# ! energy
print(pycuc.to(1, 'kcal => J'))
# ! heat capacity
print(pycuc.to(1, 'J/kg.K => kJ/kg.K'))
# ! volume
print(pycuc.to(1, 'L => m3'))
# ! mass
print(pycuc.to(1, 'kg => g'))
# ! power
print(pycuc.to(1, 'kW => W'))
# ! length
print(pycuc.to(1, 'cm => m'))
# ! force
print(pycuc.to(1, 'N => kN'))