DwsimPy is a headless, platform-independent port of the pinned DWSIM simulation engine to .NET 10. It is intended to create, load, manipulate, solve, inspect, and save DWSIM flowsheets without installing or launching the desktop GUI.
Python.NET is the first in-process language binding, not a replacement calculation engine. The same .NET 10 core can later be exposed to other languages and engineering applications through stable bindings or transports. Thermodynamics and unit-operation equations remain owned by the source-ported DWSIM engine.
macOS ARM64 is the current stable release target. Linux x86_64 and Windows x86_64 packaging are paused.
Install the Apple Silicon wheel:
| Wheel | Host | Native calculation closure |
|---|---|---|
macosx_11_0_arm64 |
macOS 11+ | Core engine, ARM64 CoolProp, and source-built ARM64 IPOPT |
The single wheel includes the IPOPT-backed Gibbs minimization path while retaining a macOS 11 deployment target.
Download the wheel from the
v2.0.1 release, then
install it into a native ARM64 Python environment:
python3 -c 'import platform; print(platform.machine())' # must print arm64
python3 -m venv .venv
source .venv/bin/activate
python -m pip install dwsimpy-2.0.1-py3-none-macosx_11_0_arm64.whlUse the familiar raw DWSIM Automation API:
import dwsimpy
dwsimpy.load_dotnet()
from DWSIM.Automation import Automation3
automation = Automation3()
flowsheet = automation.LoadFlowsheet("Plant.dwxmz")
feed = flowsheet.GetObject("Feed")
feed.SetPropertyValue2("Temperature", "", "", 330.0)
errors = automation.CalculateFlowsheet2(flowsheet)
if errors.Count:
raise RuntimeError("; ".join(str(error) for error in errors))
product = flowsheet.GetObject("Product")
print([str(name) for name in product.GetProperties2()])
print(float(product.GetPropertyValue2("Molar Flow", "", "")))
automation.SaveFlowsheet(flowsheet, "Plant-solved.dwxmz", True)The DWSIM desktop application, Mono, Rosetta, and x86_64 Python are not needed.
A .NET 10 runtime is required. Installation, convenience-wrapper usage,
property access, package audit details, build commands, and current release
boundaries are documented in
docs/PYTHON_NET10_ARM64.md.
The target architecture has four layers:
- Simulation Core (.NET 10): thermodynamics, solvers, unit operations, flowsheet graph, and persistence;
- Runtime API: the native DWSIM Automation and interface surface for live flowsheet mutation, introspection, solve orchestration, and persistence;
- Language Bindings and Transports: direct in-process bindings such as Python.NET, plus separately versioned REST, ZeroMQ, product CLI, and future transport contracts; and
- Plugin SDK: versioned extension contracts for unit operations, property packages, solvers, objective/evaluation functions, reports, and import/export.
The approved sequencing and exit gates are in
docs/PLATFORM_ROADMAP.md. The detailed source-port
ledger remains in docs/NET10_PORT_PLAN.md, and the
project-level upstream build method is in
docs/HEADLESS_ENGINE_PORT.md.
Exact beta and stable qualification gates are in
docs/RELEASE_CRITERIA.md.
The release wheels include:
- first-party
net10.0DWSIM engine, flowsheet, solver, and Automation facade assemblies; - third-party portable managed dependencies required by that closure;
- the active platform's native closure: ARM64 CoolProp on macOS, or x86_64 CoolProp, PetAz, and IPOPT on Linux; and
- Python.NET bindings for the raw
Automation3API and the convenienceAutomation,Flowsheet, andSimulationObjectwrappers.
You do not need to install the DWSIM desktop application to use a wheel. You do need:
- Python 3.10 or newer
- .NET 10 available through
dotnet, Homebrew, a standard system location, orDOTNET_ROOT
Fresh flowsheets can be created programmatically; an existing .dwxml or
.dwxmz file is not required. The wheel starts CoreCLR from its checked-in
dwsimpy/.runtimeconfig.json and never writes runtime configuration at import.
The old 1.0.1 wheel is the legacy compatibility payload. The locally
qualified 2.0.0 stable candidate replaces it with the source-ported
first-party .NET 10 closure and a UI-free DWSIM.Automation.Automation3 facade. Installed-wheel
tests prove in-process create/edit/connect/solve/read/save/reload through both
the raw and convenience Python APIs. The concrete host also accepts upstream
Automation names such as Material Stream, Stream Mixer, and Pipe Segment,
and exposes process-state snapshots and flowsheet result values without a GUI.
The macOS ARM64 stable matrix passes Carbon Combustion 59/59, Gibbs and Equilibrium
Reactors 85/85, Natural Gas Processing 445/445, Simple Absorber 58/58, and
Petroleum Distillation 100/100, Heat Exchanger Sizing 47/47, plus a
programmatic Pump/Valve model 44/44 and a Beggs-Brill Pipe model 25/25.
The programmatic Material Recycle model also passes 56/56.
A temperature Specification block passes 20/20 and simultaneous Adjust passes
26/26. A programmatic nested FlowsheetUO passes 18/18.
Three calls against one live Natural Gas model
also pass 1335/1335 comparisons, and Petroleum Distillation fresh
save/reload/recalculate passes 200/200. The complete 43-file upstream sample set passes
object-graph load/save/reload validation. These results validate the listed
paths, not every engineering family or target platform. The unmodified Carbon
fixture still differs where current DWSIM honors ForcedSolids that the legacy
wheel ignored.
The initial six-object proof of concept is frozen as narrow regression scaffolding. The active full build now compiles the pinned upstream Thermodynamics and UnitOperations sources with explicit UI-boundary adaptations; it does not reimplement Heater, Cooler, Mixer, Splitter, or other engineering equations in the Python or Runtime layers.
The full test host currently constructs 36 concrete upstream unit-operation
classes, registers 48 headless object types, constructs 24 in-assembly
property-package implementations, and exposes 25 Automation catalog names.
The stable qualification manifest records PT/PH/PS/PV/TV evidence and measured
negative cases for every name. The typed Runtime descriptor
catalog is intentionally less complete than this engine inventory. Types without
a typed convenience contract remain accessible through raw IFlowsheet,
ISimulationObject, and DWSIM property codes; they are not falsely advertised
as differential-validated.
The repo now also contains first-party ported DWSIM assemblies built as
SDK-style .NETCoreApp,Version=v10.0 projects:
DWSIM.InterfacesDWSIM.GlobalSettingsDWSIM.SharedClassesCSharpDWSIM.SharedClassesDWSIM.XMLSerializer(portable persistence subset)DWSIM.ExtensionMethods(portable helper subset plus upstream SIMD helpers)DWSIM.Inspector(diagnostic data model without windows)DWSIM.FlowsheetSolver(ported original sequential-solver sources)DWSIM.UnitOperations(full pinned upstream headless source build)DWSIM.Thermodynamics(full pinned upstream headless source build)DWSIM.FlowsheetBase(headless graph, XML codec, and deterministic solver)DWSIM.Automation(UI-freeAutomation3compatibility facade)DWSIM.MathOps.SimpsonIntegratorDWSIM.MathOpsDWSIM.MathOps.MapackDWSIM.MathOps.RandomOpsDWSIM.MathOps.SwarmOpsDWSIM.MathOps.DotNumerics
The main VB DWSIM.MathOps port retains the original IPOPT solver wrapper. Its
former binary Cureos.Numerics dependency is now an EPL-1.0,
source-controlled .NET 10 compatibility project. The macOS ARM64 wheel bundles
the source-built native IPOPT implementation. The unrelated legacy
LibOptimizationWrappers/LibOptimization binary boundary is not included.
The portable numerical core is covered by the MathOps test runner.
The original pinned DWSIM.FlowsheetSolver sources now compile as a first-party
net10.0 assembly against dedicated headless XMLSerializer, ExtensionMethods,
and Inspector projects. Assembly-reference tests reject desktop dependencies,
and the original static and instance solvers agree on a simple headless graph's
calculation order. The product Runtime now defaults to the full pinned upstream
Thermodynamics, UnitOperations, and headless flowsheet closure; the narrow local
proof-of-concept graph is retained only as an explicit regression profile.
DWSIM.Interfaces is ported as a headless contract assembly. Desktop-specific
contract points that previously exposed WinForms or System.Drawing types now use
Object so downstream solver code does not need desktop assemblies.
DWSIM.GlobalSettings is also ported as a headless settings/state assembly. It
keeps the existing settings surface but does not reference Python.Runtime,
Cudafy, DWSIM.Logging, or the legacy Nini DLL.
DWSIM.SharedClassesCSharp is ported as a headless subset for AI convergence
DTOs, solid particle data classes, and injectable file picker services. The old
WinForms connection editor and Windows dialog picker are not part of this
runtime boundary.
DWSIM.SharedClasses has started as a headless VB subset for unit systems,
unit conversion, dimensions, flowsheet options/results, transition restore
metadata, weather data, exception processing, optimization cases, and
sensitivity-analysis cases, plus bulk and distillation-curve petroleum assays.
The subset also includes the GHG emission composition model and its molecular
weight calculations, plus renderer-neutral chart, axis, series, and point data.
Chart XML remains available without loading OxyPlot; a web or desktop adapter
can render the headless model. Foundational runtime helpers now include task
dispatch, connection-port and flowsheet-bag contracts, tabular data,
spreadsheet-cell metadata, watch/undo records, AI convergence hooks, and CAPE
component metadata. The shared simulation-object base now provides dynamic
properties, dirty/solve state, connection metadata, balance hooks, debug output,
and System.Text.Json-backed XML persistence without WinForms or Newtonsoft.
These models preserve their DWSIM XML fields and use .NET 10-safe deep copies;
expression compilation remains a solver-layer responsibility. The old editor
forms, resources, update checks, weather providers, IronPython snippets, and
desktop helpers remain outside this runtime boundary.
DWSIM.UnitOperations now has a pure .NET 10 base layer containing
UnitOpBaseClass, SpecialOpBaseClass, and SpecialOpObjectInfo. It preserves
dimensions, extension points, solver metadata, property-package selection,
dynamic state, and accumulation-stream XML without referencing CAPE-OPEN,
IronPython, XMLUnit, WinForms, or the concrete thermodynamics assembly. The
headless flowsheet now constructs concrete material streams; the optional
accumulation-stream factory remains an explicit injection seam for later
accumulation scenarios.
DWSIM.Thermodynamics now has a first pure .NET 10 foundation containing the
ideal-mixture model, phase-envelope options, activity-coefficient contract,
ChemSep ID conversion, localized thermodynamics strings, and the small legacy
interaction tables. The neutral resource is explicitly emitted as
DWSIM.Thermodynamics.Strings.resources, with English and German satellite
assemblies, preventing the missing-resource failure seen in the legacy payload.
The assembly also includes headless compound, phase, phase-property,
interaction-parameter, and property-package-method models. Their dynamic values
use System.Text.Json-backed XML, and interaction-parameter cloning no longer
uses BinaryFormatter. The complete ConstantProperties interface is now in the
net10 assembly, including DWSIM property correlations, element/group data,
XML/JSON roundtrips, tabular values, and a dependency-free Open XML .xlsx
exporter. Legacy named UNIFAC/MODFAC groups are preserved until a group-name
resolver is supplied.
The mixed upstream ThermodynamicsBase.vb domain is now represented by
headless compound, phase, constant-property, reaction, and reaction-set types.
Reaction constants retain the original constant path and delegate Gibbs energy
to the selected DWSIM property package. Free-form equilibrium expressions use
an explicit IReactionExpressionEvaluator host instead of embedding Flee or
Mages in the core. Reaction and reaction-set XML roundtrips and deep copies no
longer use BinaryFormatter, and the CAPE-OPEN reaction-package surface is not
part of this runtime boundary. This is an adapted domain closure, not completion
of the original PropertyPackage, flash, or MaterialStream engine paths.
The current partial slices of the original PropertyPackage.vb now compile the
global phase/state/flash/package enums, nested calculation-mode enums, Henry
parameter record, calculation-setting defaults, and portable package state on
.NET 10. The state slice includes identity and capability flags, flash settings,
the upstream phase-equilibrium mode setter and forced-phase bypass decision,
calculation-override delegates, forced solids, flowsheet/material-stream
references, compound-ID caching, missing-property diagnostics, the overall
property-name list, object identity adaptation, legacy-name-aware type factory,
the upstream post-stream hook, and the component-temperature and stoichiometric
reaction Gibbs helpers used by IPropertyPackage. The source-authoritative
common-helper slice adds compound constant-property lists,
phase/composition/property vectors, phase-ID mapping,
composition basis conversion, mixture critical-property aggregation, and
component molar/mass-flow updates. COSTALD characteristic-volume and acentric
factor vectors preserve the upstream zero-value fallbacks needed by the liquid
density path. The vapor-pressure slice restores the upstream property-package
API for built-in correlations, compound/name/index lookup, sublimation below the
fusion point, vectors, and phase/overall composition weighting while delegating
the actual correlations to the existing DWSIM constant-property engine. Free-
form property expressions still require an injected host evaluator. The pinned
saturation-temperature Brent routes and sublimation-temperature inverse are
also present, including their original search ranges and tolerances. The
liquid-density slice restores the upstream per-compound and mixture routing for
experimental data, Rackett, COSTALD, and EOS modes without moving those equations
out of DWSIM's correlation/property-package implementations. The pinned
FORCE_EOS parameter remains behaviorally inert pending differential evidence.
The K-value slice now routes liquid/vapor or liquid/liquid fugacity-coefficient
ratios, user overrides, Wilson/vapor-pressure fallback, consistency checks, and
Henry constants while leaving fugacity calculations in the selected concrete
property package. DW_CalcKvalue3 remains upstream-unimplemented, and the pinned
flash-result overload remains deferred because its trivial fallback advances the
component index twice.
The common equilibrium helpers also preserve phase-composition K-value updates
and route component fugacity, activity, and partial-pressure updates through the
selected concrete property package. The IronPython property-override hook stays
excluded. Explicit physical-phase component volumetric flow now preserves
partial-volume calculation, normalization, and overall aggregation. The
phaseID = -1 path remains deferred because pinned source calculates partial
volumes for only the default liquid phase before consuming every phase.
Per-compound transport helpers now route liquid/vapor viscosity, liquid/vapor
thermal conductivity, and surface tension through DWSIM constant-property
calculations while preserving package mode and fallback selection. Mixture
liquid viscosity preserves all four pinned mixing rules, liquid conductivity
uses DWSIM's Li route, and vapor viscosity uses its Jossi-Stiel-Thodos pressure
correction. The source-authoritative caloric vector slice now routes named
ideal-gas Cp through DWSIM constant properties, preserves the pinned missing-Cp
fallback and midpoint integration, and exposes composition-vector ideal
enthalpy, entropy, and Gibbs-energy helpers plus the component ideal-Gibbs
helper needed by concrete packages. Upstream PhaseLabel heat-capacity and
molecular-weight calls now adapt to the matching internal phase routes.
Phase formation Gibbs/enthalpy/entropy and composition-vector formation
Gibbs/enthalpy helpers are also retained. Liquid Cp now preserves correlated,
supercritical-surrogate, and Rowlinson/Bondi routes plus midpoint component and
composition-vector integrations.
Mixture surface tension, phase caloric overloads,
liquid-Cp-derived vapor helpers, and composition-vector formation entropy remain
deferred: pinned source has order-dependent normalization, conditional phase
accumulation, repeated per-component pressure terms, a missing composition-index
increment and an unreachable ChEDL Cp branch that require differential evidence.
Vapor-mixture thermal conductivity now follows DWSIM's per-compound data route
and Ely-Hanley fallback; its virtual DW_CalcCv_ISOL dependency is verified for
the pinned Raoult package and remains the responsibility of each future concrete
package.
The first pinned RaoultPropertyPackage calculation core now compiles as a
concrete headless type. It preserves DWSIM's direct ideal/liquid/solid
enthalpy and entropy routing, departure functions, Raoult/Henry fugacity,
ideal-gas vapor density, compressibility, and component partial volumes.
Its source-authoritative single-property dispatch now hydrates molecular weight,
caloric, ideal-gas Cp/heat-capacity-ratio, formation, fugacity, density,
viscosity, conductivity, internal-energy, Gibbs-energy, and Helmholtz-energy
values. The pinned isothermal-compressibility,
bulk-modulus, speed-of-sound, and vapor/liquid Joule-Thomson routes are also
active. Diffusion, formation-entropy orchestration, and mixture surface tension
remain explicit unsupported boundaries. Desktop forms and Inspector logging are excluded. The
original DW_CalcPhaseProps path now hydrates vapor and concrete liquid phases
with flows, fugacity, density, caloric, ideal-gas Cp/heat-capacity-ratio,
transport, and volumetric properties.
Positive liquid-vapor overall-mixture hydration now aggregates density, caloric,
transport, and molar values while preserving DWSIM's null mixture-viscosity
routing. Null or multi-compound-solid overall mixtures, bubble/dew orchestration,
and Liquid3/null overall-liquid hydration remain explicit unsupported boundaries. Correlation-backed
single-compound solid hydration is active with DWSIM's direct nonzero enthalpy,
density, Cp/Cv, flow, and pinned transport routes; multi-compound solid density
and the zero-enthalpy Cp fallback remain explicit. The hydrated single-solid
phase also participates in overall-mixture aggregation. The Runtime registry now
exposes this upstream package as Ideal (Raoult's Law) with an explicit maximum
of one compound. A real ChemSep Water model solves, saves to DWXMZ, reloads, and
solves again through this boundary; multi-compound configuration is rejected
before flowsheet mutation. This is a bounded Ported capability, not legacy
differential Validated evidence. The local IdealPropertyPackage continues to
be the frozen PoC path rather than silently becoming production authority.
The upstream overall-liquid aggregation formulas now cover positive active
liquid inventories without Liquid3, including phase fractions, flows,
compositions, density, caloric values, and volume-weighted transport. The pinned
null-stream division path and Liquid3 conductivity/viscosity term mismatch
remain explicit unsupported boundaries. The preflight-checked local test domain is now wired into
Raoult DW_CalcPhaseProps(Liquid) with preflight validation before stream
mutation.
Solid-property helpers now delegate per-compound density and heat capacity to
DWSIM constant properties and preserve the original mass-weighted solid Cp
aggregation. Mixture solid density remains deferred because the pinned missing-
density renormalization appears inverted and needs differential evidence.
Phase-change helpers likewise preserve DWSIM's mass-weighted vaporization and
fusion enthalpy aggregation, delegating component vaporization and solid heat
capacity to the existing constant-property engine. The common critical-volume
AUX_KIJ helper retains its pinned geometric route. Component vaporization-
enthalpy and COSMO identifier/fallback vectors are available for original model
and property-package consumers.
Composition utilities now include named phase-basis conversion, normalization,
erasure, vector/phase single-component checks with the black-oil exclusion, and
the cached zero interaction-parameter matrix used by packages without binary
parameters. The phase overload of AUX_SINGLECOMPIDX remains deferred because
the pinned loop never increments its component index.
Overall mass, molar, and volumetric flow update helpers now retain the pinned
unit conversions and invalid-density fallback. The common concentration pass
hydrates each compound's molarity from phase volume and molality from the
configured reference-solvent mass flow. The obsolete *_ISOL methods are
present only as throwing virtual override points required by original concrete
property packages; they are not a second calculation engine or public runtime
path.
The
phase-state slice adds the upstream
calculated-property, phase-distribution, composition, two-phase, and overall-flow
reset semantics used before equilibrium calculations. Its original abstract
enthalpy, entropy, and corresponding departure-function signatures now define
the calculation boundary that concrete upstream packages must supply; the base
does not replace those package calculations. Zero-default additional-enthalpy
and reaction-enthalpy methods preserve the original virtual extension points
for specialized packages. The empty two-phase hook is also retained for
package-specific overrides, while the common Gibbs helper delegates liquid and
vapor fugacity coefficients to the concrete package before applying DWSIM's
forced/minimum-phase selection. The remaining original abstract
engine contract now also covers property/phase calculation entry points,
fugacity coefficients, component support, partial volumes, compressibility, and
vapor density. The optional model hook returns no model by default, while the
temperature/volume fugacity and pressure methods remain throwing virtual
extension points until a concrete EOS package overrides them. Source-compatible
temperature derivatives for enthalpy, entropy, K-values, and fugacity use the
pinned 0.01 K forward step and continue to delegate every property evaluation to
that concrete package. Mole-number derivatives remain deferred with formation
orchestration. Standalone
overall-density hydration remains deferred because pinned pure-liquid branches
also activate the vapor volume fraction. The first original
FlashAlgorithm base slice supplies all 35 upstream default settings, stability
search accessors, metadata, isolated settings cloning, and an injectable
IFlashAlgorithm reference on PropertyPackage. Its original
FlashCalculationResult companion now carries flash specifications, component
properties, phase mole amounts, and upstream mole/mass fraction conversions;
newer interface-only energy and mechanical fields remain passive result data.
Common PropertyPackage state now roundtrips the pinned XML element names for
identity, calculation modes, scalar flags, forced solids, parameters, and flash
settings. Loading older partial flash payloads fills every current default;
script overrides are intentionally not retained. The upstream XML-based clone
path now creates a fresh package identity, clones calculation delegates, and
isolates the flash algorithm and persisted collections without BinaryFormatter.
Phase/CAPE mappings,
multi-compound concrete flash factories, package-specific interaction-parameter persistence,
fugacity, partial-volume, and flash calculation methods remain outside these
slices. The flash lifecycle now preserves its
upstream XML setting format, deterministically writes all settings, and fills
missing settings in older payloads from the complete current default set. The
base also exposes the original abstract PT, PH, PS, PV, and TV flash
method contract required of future concrete upstream algorithms; this is a
calculation extension boundary, not an independent flash implementation. The
upstream diagnostic callback crosses an optional headless Action<string> host
boundary instead of a global calculator console. The upstream dispatcher now
routes P/T/H/S/VAP/SF specification pairs to those
methods, packages phase amounts and K-values, applies PropertyPackage-owned
enthalpy/entropy, and captures calculation failures in the result. Upstream
V-* optimization helpers remain explicitly deferred with a headless error
until their remaining compressibility/numerical dependencies and pinned-source
ambiguities close. The first concrete pinned algorithm, SingleCompFlash, now
retains DWSIM's PT/PH/PS/PV/TV and solid-phase branches. Local analytical tests
cover phase selection, forced solids, quality flashes, enthalpy/entropy flashes,
and dispatcher integration. PropertyPackage.FlashBase now preserves the pinned
single-compound selection rule, including its black-oil exclusion, and creates a
fresh SingleCompFlash that shares the package flash settings. This is not
legacy differential validation; it is local source-authoritative evidence for
the single-compound branch. The
PropertyPackage flash wrapper now maps the public calculation-type enum onto the
upstream dispatcher; multi-compound streams require an explicitly injected
original FlashAlgorithm, and no local replacement algorithm is constructed.
The headless Raoult factory now supplies the retained upstream NestedLoops
algorithm for that role. The pinned duplicate
PressureEntropy switch typo is corrected to the intended VolumeEntropy case.
The original bubble/dew pressure and temperature helpers now delegate quality
0/1 requests to the same injected TV/PV flash methods. The abstract
PropertyPackage base now implements the headless IPropertyPackage boundary:
interface calls delegate to the retained calculations, clones remain isolated,
and GUI editor calls fail explicitly. This structural closure makes the
Raoult/SingleComp path available for one compound and the Raoult/NestedLoops
path available within its declared multi-compound PT vapor/liquid boundary.
The current Ideal package remains the frozen local PoC boundary.
The pinned ForcedPhaseFlash is now the second retained concrete flash
algorithm. Direct stream and flowsheet-global vapor, liquid, or solid forcing is
selected before single- and multi-compound equilibrium algorithms. Its PT and
iterative PH/PS branches pass local analytical tests; the upstream unsupported
PV/TV boundary remains explicit. This closes forced-phase routing without
introducing local thermodynamic equations and is not legacy differential
validation.
The pinned shared flash phase/compound heuristic is now retained unchanged in a
headless partial. Tests cover solid detection, the default-mode HandleSolids
gate, forced solids, and the Water/hydrocarbon liquid-split rule. This closes a
managed dependency for later flash algorithms; the heuristic does not itself
enable SLE or turn its result into an equilibrium calculation.
The pinned multi-compound NestedLoops VLE algorithm now has a bounded managed
slice. Its original PT, ConvergeVF, and ConvergeVF2 calculations pass an
analytical Rachford-Rice test through both direct and dispatcher paths. The
original PH/PS wrappers and fast Newton paths are retained for direct use; a
multi-compound, single-liquid-phase Water/Ethanol PT target is recovered through
both PH and PS within 1e-3 K. The normal/default Flash_PH_2 and Flash_PS_2
paths, including their managed PV objective branches, are also retained. Direct
calls and the public selectors with NL_FastMode=False recover a two-phase
Water/Ethanol PT target within 1e-3 K. Their three pinned SLE delegations are
restored; a low-pressure Water/Ethanol fixture forces the solid heuristic and
directly covers the PH/PS objective routes. The source-identical rigorous PH
partial-vapor route compiles but still needs its own convergent public fixture.
The complete managed TV path is retained
unchanged and recovers a two-phase Water/Ethanol PT pressure within 2 Pa. The
public PV wrapper and main managed iteration path recover the same two-phase
target temperature within 1e-3 K. Their PropertyPackage closure restores managed disposal and the
flash-result K-value overload, with an explicit correction for the pinned
fallback loop's redundant index increment. The pure-managed azeotrope and
alternate bubble-point PV helpers are retained exactly; the latter has a local
initialization and phase-balance test, while the azeotrope helper still needs a
non-ideal fixture before it has functional evidence. Saturated-Newton is
retained behind the source-built native IPOPT dependency. The headless Raoult
property-package factory selects this
algorithm for multi-compound PT calculations. A fresh ChemSep Water/Ethanol
flowsheet solves and survives DWXMZ save/reload; this remains local Ported
evidence, not legacy differential validation.
The pinned pure-managed NestedLoopsImmiscible algorithm is now retained
unchanged after source-encoding normalization. A direct ChemSep Water/N-hexane
PT test produces hydrocarbon-rich and water-rich liquid phases, closes the total
phase balance, and returns finite K-values. This is local Ported evidence; the
Runtime property-package selection boundary has not yet been expanded to expose
immiscible VLLE during a solve. The algorithm is discoverable through the
flash-algorithm registry and schema as a direct Ported capability.
The complete pure-managed pinned NestedLoopsSLE source also compiles with two
explicit headless adaptations: a portable MathOps namespace import and a
runtime full-name check for the deferred IdealElectrolytePropertyPackage type.
Direct tests cover frozen and melted pure-Water PT states, PH/PS temperature
recovery, PSF fusion temperature, the solid-solution mode, and a Water/Ethanol
liquid-solid split with phase and composition balances. This is direct local
Ported evidence only. Electrolyte SLE is not available. Eutectic and
solid-solution variants are discoverable through Runtime metadata, but
property-package/flowsheet selection is not exposed and no legacy differential
validation is claimed.
The pinned Thermodynamics source is now inventoried at file level: all 308
tracked project, engine, data, language, editor, and build files have an
explicit retained, adapted, optional, deferred, or desktop-excluded
disposition. The first retained non-ideal engine source is upstream
WilsonModel.vb, compiled unchanged apart from formatting normalization with
its 366-row BIP dataset. Tests verify 364 unique interaction pairs, directional
ethanol/water parameters, and activity coefficients at 298.15 K. This does not
yet expose a complete Wilson Property Package; original PropertyPackage, flash,
and MaterialStream closure remains in progress.
The embedded compound-database layer now exposes the legacy-compatible
Databases.DWSIM, Databases.ChemSep, Databases.Biodiesel, and
Databases.Electrolyte, Databases.CoolProp, and
Databases.ChEDL_Thermo providers through a shared ICompoundDatabase
contract. It loads 37 built-in DWSIM, 558 ChemSep, 14 Biodiesel, 84
electrolyte, 90 CoolProp metadata, and 1053 ChEDL records directly from
assembly resources. All providers support case-insensitive single-compound
lookup. DWSIM's named UNIFAC/MODFAC groups are retained for later resolver
injection, and Biodiesel unit conversions preserve the legacy correlation
contract. The CoolProp provider reads fitted metadata only; it does not call
the native CoolProp library. The parsers do not depend on FileHelpers, the
managed CoolProp wrapper, Newtonsoft.Json, or desktop assemblies. Fields
without a direct ICompoundConstantProperties counterpart are retained under
ExtraProperties instead of being discarded. User/FoodProp databases,
interaction-parameter files, non-ideal property-package families, and their
flash algorithms remain subsequent port slices.
The first pure net10 proof-of-concept solve slice is implemented through the
historical Ported level: ideal property package, material streams, and
mixer/splitter/heater/cooler topology can be constructed, solved, and persisted.
The four unit-operation calculations are explicitly marked
LocalProofOfConcept: they preserve the development baseline but are not the
source-authoritative DWSIM algorithms. Each registry entry identifies its pinned
upstream DWSIM source file and commit. It must be replaced by a selective
source-authoritative engine path and pass pinned upstream differential fixtures
before it can be marked Validated.
The material-stream object for the completed slice is
DWSIM.Thermodynamics.Streams.MaterialStream: it stores PT, flow, composition,
compound flows, phase data, property-code access, clone, and XML roundtrips in
the pure net10 assembly. It now preserves DWSIM's canonical phase IDs 0 through
7, legacy <Phase><ID>...</ID></Phase> serialization, property-package IDs,
and distinct loaded vapor/liquid compositions.
The first flash path is now available through
DWSIM.Thermodynamics.PropertyPackages.IdealPropertyPackage: PT flashes use
Raoult-law K-values from the ported compound vapor-pressure correlations and a
bounded Rachford-Rice solve. MaterialStream.Calculate() writes vapor/liquid
phase compositions, fractions, and flows for this path. Ideal-gas heat
capacities are integrated from a 298.15 K, 101325 Pa reference state; liquid
enthalpy and entropy include the ported heat-of-vaporization correction. PH
and PS flashes reuse the PT kernel through a bracketed 100-2000 K temperature
solve. Temperature-enthalpy, vapor-fraction, solid, and non-ideal flashes
remain explicitly unsupported.
DWSIM.FlowsheetBase now provides the headless flowsheet layer. Its concrete
HeadlessFlowsheetHost implements the required IFlowsheet contracts and owns live
simulation/graphic object collections, constructs material streams, resolves
objects by ID or tag, and
connects/disconnects typed inlet and outlet ports without SkiaSharp, Eto, or
WinForms. It retains compounds, property packages, reactions, settings,
results, dynamic properties, stored solutions, and unknown DWXMZ payloads
across supported load/save workflows. Whole-flowsheet calculation is routed to
the original sequential solver. Background requests are serialized around
DWSIM's global calculator state while nested FlowsheetUO calculations remain
reentrant.
The first solved proof-of-concept unit operation is
DWSIM.UnitOperations.UnitOperations.Splitter (NodeOut). The headless
flowsheet constructs its one-inlet/three-outlet topology, and the operation
copies pressure, temperature, enthalpy, composition, and property-package state
to connected product streams while applying explicit molar-flow ratios. Ratios
for connected outlets must sum to one; invalid or incomplete balances fail
instead of being silently normalized. Splitter ratio persistence, material and
molar balances, and de-calculation are covered by the runtime regression suite.
DWSIM.UnitOperations.UnitOperations.Mixer (NodeIn) provides the inverse
vertical slice for up to six connected feeds and one product. It calculates
the outlet composition on a molar-flow basis, closes the mass and enthalpy-flow
balances, applies an explicit minimum/maximum/molar-weighted pressure policy,
and solves the product state with a PH flash. Compound-order mismatches,
missing property packages, zero flow, and invalid topology fail explicitly.
The current proof-of-concept Heater and Cooler share a headless thermal
unit-operation kernel. Both
support specified outlet temperature with calculated duty and specified
positive duty with a PH outlet flash. Heater duty is added; Cooler duty is
removed. The current headless operation uses Pa for pressure drop and kW for
heat duty. The future canonical Runtime boundary will expose units including W
for duty through explicit tested conversion adapters; it will not
silently reinterpret existing persistence or released-client values. The
runtime checks flow direction, compound compatibility, pressure validity, mass
conservation, and signed energy balance, and persists the selected mode and
specifications without desktop assemblies.
These local kernels are frozen migration scaffolding, not the long-term calculation authority. Runtime and language bindings only write specifications, ask the flowsheet to solve, and read state/results. The final .NET 10 engine builds the pinned upstream Thermodynamics, FlowsheetSolver, UnitOperations, and FlowsheetBase source at project boundaries, removing or adapting UI-only dependencies while preserving engineering algorithms. New equations must not be recreated in Runtime, Python, transport, or web layers.
In the retained narrow regression profile, HeadlessFlowsheetSolver provides
the first whole-graph solve path. Material
streams act as graph edges, independent feed streams are flashed first, and
ported Mixer, Splitter, Heater, and Cooler objects are topologically sorted by
their upstream producers with ordinal-name ordering for deterministic ties.
The existing IFlowsheet.RequestCalculation* methods expose this solver in the
frozen narrow profile. Cycles and unported unit-operation types are rejected before unit
calculations begin; calculation failures populate Solved and ErrorMessage
instead of being reported as partial success. This paragraph describes the
test-only narrow profile, not the full upstream product closure used by the
Python wheel.
That narrow profile also has a strict XML codec for its typed runtime boundary.
SaveToXML() and LoadFromXML() roundtrip selected compound payloads,
the ideal property package, MaterialStream/Mixer/Splitter/Heater/Cooler state,
headless graphic geometry, connector indices, and graph attachments. Unknown
simulation or property-package types fail during hydration. The embedded
HeadlessHeater.dwxml fixture is loaded and solved from scratch against a
checked-in expected-output JSON file. This proves pure .NET 10 persistence; it
is not yet a legacy DWSIM differential validation.
XmlFlowsheetEngine.Solve() remains experimental narrow-regression tooling. It
hydrates a private flowsheet, solves it, projects deterministic stream and
thermal-unit results, and replaces the editable document only after success.
The Python wheel does not use or bundle this engine: it keeps one live
IFlowsheet object graph and calls DWSIM.Automation.Automation3 directly.
Future out-of-process transports may adopt a separately versioned contract
without changing that in-process compatibility API.
The default full profile invokes the pinned original DWSIM.FlowsheetSolver.
DwsimPyNarrowRegression=true retains the local solver only for frozen
regression tests; it is not the wheel's calculation path.
Pinned legacy differential execution is now available through
scripts/differential/run_differential.py. The pinned 2026 upstream source
loads the sample's ForcedSolids = ["Carbon"] setting while the legacy
dwsimpy 1.0.1 engine ignores it, so the unmodified Carbon Combustion file
intentionally follows different phase behavior. After the fixture is explicitly
restricted to the common legacy feature set, all 59 native DWSIM values match
within the declared tolerances. This is one validated fixture, not broad family
or cross-platform validation; unlisted families remain Ported in the beta.
Solver-ready nodes added through XmlFlowsheetEngine.AddNode() are initialized
with the canonical headless serializer instead of the generic draft XML
skeleton. ConfigureMaterialStream(), ConfigureThermalUnit(), and
ConfigureSplitter() provide strongly typed, atomic mutations with current
per-method validation and replace the document only after hydration and
serialization both succeed. These typed
mutations currently require the whole document to contain only ported types;
draft palette nodes can coexist in the editor but must be removed or ported
before typed hydration and solving.
Fresh headless flowsheets can now query the embedded ChemSep catalog and call
ConfigureThermodynamics() to select compounds and install the ported ideal
property package. MaterialStream is tracked as solver-ready, and subsequently
created streams and unit operations inherit the single configured package. A
runtime test builds, solves, compresses, reloads, and solves a Water -> Heater
flowsheet without starting from a DWSIM desktop file.
The pure .NET 10 codebase is intended to remain extensible independently of the frozen upstream baseline. New unit operations should implement the headless simulation contracts, register an explicit solver-support state, provide XML serialization, and ship calculation plus roundtrip tests. A loadable external plugin ABI is not implemented yet; until that boundary is added, new operations are compiled into the runtime assemblies.
The upstream source baseline used for compatibility work is pinned in
upstream/dwsim-source.json. Ported behavior should be compared against that
commit and an upstream-style fixture instead of relying only on self-generated
roundtrips.
The full legacy PROPS fluid-correlation class now compiles inside the pure
.NET 10 assembly, backed by the ported MathOps cubic-root implementation.
Built-in DWSIM temperature-dependent equation numbers are exposed through
PropertyEquationEvaluator. Free-form property expressions remain explicitly
unsupported until a small host-injected evaluator replaces the old Flee/Mages
path. Inspector reporting is a headless no-op adapter and does not add a UI
dependency. The constant-property path does not reference BinaryFormatter,
Newtonsoft.Json, EPPlus, or the legacy UNIFAC model objects.
Audit the current payload with:
python3 dwsimpy_package/scripts/audit_managed_runtime.pyAudit a local ignored DWSIM source checkout with:
python3 dwsimpy_package/scripts/prepare_dwsim_source.py
python3 dwsimpy_package/scripts/validate_headless_build.py
python3 dwsimpy_package/scripts/audit_dwsim_source.py --source-dir ./dwsimUse prepare_dwsim_source.py --prepare only when the checkout is absent. The
tool never resets or overwrites an existing checkout.
The stable Apple Silicon distribution is
v2.0.1:
dwsimpy-2.0.1-py3-none-macosx_11_0_arm64.whl
SBOM.cdx.json
SHA256SUMS-macos-arm64.txt
This is the source-ported .NET 10 build described above. The GitHub v1.0.1
release is the older compatibility payload and must not be confused with this
wheel. The macOS 11 wheel contains the CoolProp and source-built IPOPT native
closure. Pinned
DWSIM does not provide source for an Apple Silicon PetAz build, so the
non-authoritative replacement is not distributed. The wheel passes
package/architecture validation, clean-install Automation3 smoke tests, and the
complete 16-case/2596-comparison matrix. The Linux x86_64
wheel has equivalent local evidence from the previous build, but Linux release
work is paused and it is not an active support target. Windows x86_64 build and
execution work is also paused.
Verify the downloaded artifact with the release asset
SHA256SUMS-macos-arm64.txt; it is generated from the exact CI-produced
wheels uploaded to that release.
Install the downloaded macOS wheel with:
python -m pip install \
./dwsimpy-2.0.1-py3-none-macosx_11_0_arm64.whlIf dotnet is not on PATH, set DOTNET_ROOT to the .NET 10 installation
root before importing dwsimpy.
The primary compatibility surface is the raw DWSIM.Automation.Automation3
facade shown in the quick start. It returns real IFlowsheet and
ISimulationObject objects and exposes both the human-readable Automation API
and the native DWSIM property-code API. This is the appropriate surface for
existing Python.NET integrations and broad unit operation access.
The package also provides the smaller Python convenience API:
dwsimpy.Automation()Automation.create_flowsheet()andAutomation.load_flowsheet(path)Automation.solve(flowsheet)andAutomation.close(flowsheet)Flowsheet.get_object(tag),get_objects(),connect(), andsave(path)SimulationObject.get_property(name),set_property(name, value), andget_property_unit(name)
The convenience layer is a thin wrapper over the same live DWSIM objects and
native property codes. It does not serialize or rehydrate the flowsheet, and it
does not replace or recalculate upstream thermodynamics or unit-operation
equations. Unmapped properties remain available through the raw interfaces. See
docs/PYTHON_NET10_ARM64.md for complete usage,
validation boundaries, and local build commands.
Native capability boundaries are discoverable before solving:
simulation = dwsimpy.Automation()
print(simulation.native_capabilities)
# macOS ARM64: {'CoolProp': True, 'Ipopt': True, 'PetalasAziz': False}examples/optimization_loop.py demonstrates
how to keep one live flowsheet loaded while repeatedly writing a decision,
solving the complete sequential flowsheet, and reading objective and constraint
properties. It is a grid-search example; another optimizer can call the same
evaluation loop without reloading the model on every property access.
Release boundaries and distribution decisions are recorded in
docs/SUPPORT_MATRIX.md,
docs/API_COMPATIBILITY.md,
CHANGELOG.md,
docs/adr/0001-macos-ipopt-distribution.md,
docs/CODESIGN_NOTARIZATION.md, and
docs/SOURCE_AND_LICENSES.md.
The macOS ARM64 wheel is built and validated locally first. Its release gate is native architecture/content validation, installation into a clean ARM64 Python environment, an in-process Automation3 create/edit/connect/solve/read/ save/reload smoke test, and all 16 declared fixtures against the checked-in legacy goldens, plus 1000 solves against one live flowsheet instance. Linux x86_64 and Windows x86_64 workflows remain available for later platform work, but both targets are currently paused and are not part of the macOS release gate.
dwsimpy_package/
dwsimpy/
__init__.py
.runtimeconfig.json
libs/
scripts/
prepare_dwsim_source.py
validate_headless_build.py
stage_platform_runtime.py
audit_managed_runtime.py
audit_dwsim_source.py
validate_native_artifacts.py
validate_wheel_contents.py
smoke_test.py
docs/
HEADLESS_ENGINE_PORT.md
NET10_PORT_PLAN.md
PLATFORM_ROADMAP.md
upstream/
dwsim-source.json
headless-build.json
headless-source-dispositions.json
src/
DWSIM.Interfaces/
DWSIM.GlobalSettings/
DWSIM.XMLSerializer/
DWSIM.ExtensionMethods/
DWSIM.Inspector/
DWSIM.FlowsheetSolver/
DWSIM.SharedClassesCSharp/
DWSIM.SharedClasses/
DWSIM.Thermodynamics/
DWSIM.UnitOperations/
DWSIM.FlowsheetBase/
DWSIM.MathOps/
DWSIM.MathOps.DotNumerics/
DWSIM.MathOps.Mapack/
DWSIM.MathOps.RandomOps/
DWSIM.MathOps.SimpsonIntegrator/
DWSIM.MathOps.SwarmOps/
DwsimPy.Runtime/
DwsimPy.Runtime.Cli/
DwsimPy.MathOps.Tests/
DwsimPy.Runtime.Tests/
examples/
solve_existing_flowsheet.py
native_libs_arm64/
PetAz.c # non-authoritative experiment; excluded from release wheels
.github/workflows/build-native.yml
This repository redistributes DWSIM runtime binaries. DWSIM is developed by
Daniel Wagner and contributors and is licensed under the GNU General Public
License, version 3. See LICENSE and the upstream DWSIM source repository:
https://github.com/DanWBR/dwsim
This project is an independent experimental .NET 10 platform port and Python compatibility distribution. It is not an official DWSIM distribution.
src/DwsimPy.Runtime is the current pure .NET 10 preview boundary. It can
create, open, inspect, edit, solve, and save .dwxml/.dwxmz documents without
pythonnet, Mono, WinForms, Eto, or IronPython. The product build hydrates the full
pinned source closure through the 48-entry object catalog and exposes broad
native property access. All 47 Runtime registrations available in the full
headless binary are covered by a create-and-introspect regression. The stable
typed descriptor/evaluator contract remains
complete only for the transitional MaterialStream, EnergyStream, Mixer,
Splitter, Heater, Cooler, and retained package slices; the explicit narrow
regression mode still rejects unported object/package types.
The optional CoolProp path retains upstream SWIG bindings and loads only the
active platform library. To stage a native library into build/publish output,
set DwsimPyCoolPropNativePath; to use a separately installed or unpacked
library at runtime, set DWSIM_NATIVE_LIBRARY_PATH. CI pins CoolProp revision
01c67752d613a014dc06067685fa54a23032d38f and verifies the loaded revision.
The macOS ARM64 direct ABI and DWSIM CoolProp PT-flash gate currently passes:
dotnet build src/DwsimPy.UpstreamRuntime.Tests -c Release \
-p:DwsimPyCoolPropNativePath="$PWD/native_libs_arm64/libCoolProp.dylib"
DWSIM_COOLPROP_NATIVE_TEST=1 \
DWSIM_NATIVE_LIBRARY_PATH="$PWD/native_libs_arm64" \
dotnet run --project src/DwsimPy.UpstreamRuntime.Tests -c Release --no-buildStandard, incompressible-pure, and LiBr/Water incompressible-mixture DWSIM PT
fixtures pass on macOS ARM64 and Linux x86_64. Windows x86_64 remains an open
execution gate; this is Ported evidence, not legacy differential validation.
The embedded Databases.CoolProp provider described earlier is only compound
metadata and remains distinct from these native property packages.
The managed specialized-package gates also run source-authoritative DWSIM code.
Ideal Electrolyte solves a Water/LiBr/Li+/Br- system with its retained
equilibrium reaction set, while Black Oil solves a synthetic assay carrying the
upstream SGG, SGO, GOR, BSW, and PNA input contract. Both fixtures pass PT solve
and save/load/re-solve locally. Together with the standard managed families,
this gives 21 managed property-package PT gates. These are local Ported
fixtures, not pinned legacy differential validation.
SolveResult preserves the compatibility Errors list and also exposes
structured Diagnostics. Calculation cycles receive a stable code, while a
failure raised by an original DWSIM simulation object includes its object ID,
label, CLR type, calculation stage, and underlying exception type. This makes
headless service and language-binding error handling independent of localized
message parsing.
The existing UnitOperationRegistry covers palette identity, aliases, connector
counts, energy-connector capability, geometry, solver status, and runtime-owned
descriptors for the current ported boundary. Schema, generated documentation,
and the complete-palette coverage ledger derive from that metadata.
Phase 1 descriptor work is complete for the pure .NET 10 Runtime API boundary.
The versioned preview runtime
contracts describe MaterialStream properties and connectors, Ideal Property
Package capabilities, stable object IDs versus display tags, model/object
introspection, and read/write-filtered variable paths. Mixer, Splitter, Heater,
and Cooler descriptors now include connector topology, modes, current units,
and mode-dependent writable/calculated thermal specifications. Catalog integrity
checks and structured unknown/read-only/conditional-access diagnostics run
without entering the solver. Phase 2 is complete for the current ported boundary.
Solver-ready unit-operation registrations own their runtime descriptors,
PropertyPackageRegistry owns package identity and capabilities, and
FlashAlgorithmRegistry owns factory-backed descriptors for the six retained
algorithm variants. The runtime catalog is derived from these registries instead
of duplicating metadata.
Writable properties carry
typed defaults and constraints, object/package capabilities avoid advertising
unimplemented behavior, and catalog validation checks default/constraint
consistency.
Phase 3 is complete for the current Runtime API contract. The developer CLI can
emit deterministic registry-derived JSON with schema and generated Markdown
with reference; flash-algorithms exposes the same descriptor inventory
directly. Checked-in artifacts live under docs/generated/ and byte-
stable snapshot tests prevent
runtime metadata, schema, and reference documentation from drifting apart. The
schema-check command enforces the additive, deprecated, and breaking-change
policy documented in Runtime Schema Compatibility.
Future evaluator plans, fixtures, plugins, and clients must record the schema
version they consume. Phase 4 selective and compiled evaluator work is in
progress.
Phase 4 is now in progress. The preview Runtime API exposes typed named
Evaluate requests with ordered inputs, selective outputs, schema-versioned
results, and errors-only/summary/full diagnostics. Evaluation validates all
paths before mutation, applies calculation-mode selectors first, solves against
an isolated flowsheet instance, and commits state only after success. Requested
outputs are read directly; the evaluator does not build the broad Solve
projection. CompileEvaluator now resolves paths and typed adapters once, records
schema version plus fixed input/output order and quantity/unit metadata, and
supports sequential stateful reuse with named-path numerical parity. Compiled
plans are engine/model-bound, commit only successful evaluations, reject bound-
object structural drift, disallow concurrent use, and become invalid after
disposal. EvaluateRaw accepts fixed ReadOnlySpan<double>/Span<double>
buffers for scalar-number-only plans, uses precompiled unboxed numeric adapters,
and rejects incompatible binding types and buffer lengths before solve. Output
buffer contents are undefined after a failed raw call; model state still commits
only on success. Reset restores the complete compile-time DWXML snapshot byte-
for-byte, including structural edits, and keeps the same plan usable. Reset uses
the evaluator's single-operation lock and is rejected after disposal or after
the flowsheet is closed. Performance evidence remains future Phase 4 work.
Registry-owned property accessors are complete for the six transitional object types: named, compiled, raw, and conditional evaluation use the same descriptor- checked accessor sets. Further local engineering calculations are frozen. The next implementation work closes original shared/persistence dependencies, then compiles the upstream thermodynamics, sequential solver, all built-in unit operations, and flowsheet host in the order defined by the headless build inventory.
The first MaterialStream engineering-field slice is now exposed through schema
1.0.0-preview.2: PT/PH/PS flash selection, molar/mass flow inputs with an
explicit active basis, volumetric-flow results, mole and mass compositions,
enthalpy/entropy specifications, energy flow,
equilibrium status, phase fractions, and vapor/liquid compositions. Runtime
conditions expose only the active caloric specification, and enum-valued stream
settings now survive both legacy numeric and named XML roundtrips.
Schema 1.0.0-preview.3 adds the headless EnergyStream contract. Energy flow is
read/write in the current kW persistence boundary, survives DWXML roundtrips,
and can be evaluated through named, compiled, and raw Runtime API paths.
Headless energy-aware connectivity now preserves unit-operation energy ports;
Heater and Cooler publish calculated duty to a connected output EnergyStream.
Schema 1.0.0-preview.4 expands MaterialStream read results with mixture
molecular weight, compound molar/mass-flow arrays, vapor/liquid molar and mass
flows, and vapor/liquid mass-fraction arrays. Compound arrays use the same
configured-compound order as mole/mass composition arrays. Runtime tests enforce
overall compound-flow closure, vapor/liquid phase-flow closure, and the
molecular-weight relation between molar and mass flow. Transport and detailed
phase caloric properties remain pending until the solver computes them.
Schema 1.0.0-preview.5 carries phase-specific mass enthalpy and entropy from
the Ideal flash result into vapor and overall-liquid phase state. Runtime and
direct flash tests verify that phase mass-flow-weighted enthalpy and entropy
close to the overall stream values for PT, PH, and PS paths. Phase heat
capacities and transport properties remain outside the contract.
Schema 1.0.0-preview.6 makes unavailable calculated results explicit. Vapor
and liquid mass enthalpy/entropy are nullable: named and compiled named
evaluation return null when the corresponding phase is absent instead of
fabricating 0. Compiled plans containing nullable bindings remain usable by
the named evaluator but advertise raw incompatibility; EvaluateRaw rejects
such plans before solving because a double buffer cannot represent null.
Schema 1.0.0-preview.7 adds nullable vapor/liquid density, mass heat capacity
at constant pressure, dynamic viscosity, and thermal conductivity. The Ideal
package uses the ideal-gas relation for vapor density, mass-fraction mixing for
heat capacity and transport properties, and specific-volume mixing for liquid
density. Missing phase or invalid compound correlation data remains null;
tests cover analytical mixing rules and named Runtime API projection.
Schema 1.0.0-preview.8 derives nullable ideal-vapor mechanical results: mass
heat capacity Cv, Cp/Cv ratio, speed of sound, isothermal compressibility,
adiabatic bulk modulus, and compressibility factor. These values follow the
ideal-gas identities and remain null when vapor is absent or Cp data is
unavailable. Liquid mechanical properties are intentionally not exposed
because the current Ideal package has no liquid compressibility model.
Schema 1.0.0-preview.9 adds nullable liquid surface tension in N/m. The
Ideal package follows DWSIM's molar-average rule over subcritical liquid-phase
components and uses each compound's experimental correlation or Brock-Bird
fallback. The result remains null when no liquid phase or valid contributing
correlation is available.
Schema 1.0.0-preview.10 adds ordered compound names, equilibrium K/logK
arrays, and nullable vapor/liquid arrays for fugacity coefficients, activity
coefficients, and partial pressures. Ideal-package identities are calculated in
the flash result and then hydrated into MaterialStream phase compounds. Every
array follows compoundNames order; absent-phase arrays remain null.
Schema 1.0.0-preview.11 derives nullable vapor/liquid compound fugacities in
Pa, activities, molar concentrations in mol/m3, and mass concentrations in
kg/m3. Fugacity and activity follow the hydrated phase coefficients;
concentrations use phase compound flow divided by phase volumetric flow. Arrays
remain ordered by compoundNames, and an absent phase or unavailable phase
volume produces null. Molality, partial molar volume, and per-compound
volumetric-flow fields remain pending until their solvent basis,
unit boundary, and calculation models are explicit; diffusion coefficients also
remain pending an explicit calculation model.
Schema 1.0.0-preview.12 adds nullable vapor/liquid phase molecular weight,
volumetric flow, molar enthalpy, molar entropy, and kinematic viscosity. The
Runtime boundary uses kg/kmol, m3/s, kJ/kmol, kJ/(kmol K), and m2/s.
Tests close these values against phase mass/molar flow, density, mass-basis
caloric properties, and dynamic viscosity. Every result is null when its phase
is absent. Persisted stream flags such as forced phase, electrolyte mode, and
reference solvent are not exposed as active Runtime controls until the headless
solver implements their behavior.
Schema 1.0.0-preview.13 hydrates and exposes vapor/liquid mass phase
fractions separately from molar phase fractions. The Ideal flash result remains
the source of truth, matching the upstream DWSIM phase-mass calculation. Runtime
tests close both mass fractions to one and tie each value to its phase mass-flow
share; single-phase results remain the meaningful 1/0 pair rather than
nullable values.
Schema 1.0.0-preview.14 exposes nullable vapor/liquid internal, Gibbs, and
Helmholtz energies on both mass and molar bases. The selected property package
owns these calculations and publishes them through the flash result;
MaterialStream only hydrates that result and Runtime only projects it. The
Ideal package follows the upstream identities u = h - Pv, g = h - Ts, and
a = u - Ts; its Pv term uses phase pressure and density with an explicit
kJ/kg conversion. Molar results use phase molecular weight and are reported
in kJ/kmol. Missing phases or required density/caloric state remain null.
Excess properties and Joule-Thomson coefficients remain outside the contract
until their package-specific models are implemented.
Schema 1.0.0-preview.15 adds calculation provenance and pinned upstream source
metadata to every Runtime object descriptor. Mixer, Splitter, Heater, and Cooler
remain solver-ready local regression seeds, but are explicitly
LocalProofOfConcept; this provenance can never satisfy the Validated gate.
Schema 1.0.0-preview.16 extends the same provenance contract to property
packages and adds a machine-readable maximum-compound capability. The upstream
Raoult package was registered at that preview as Ported with
MaximumCompoundCount = 1; Runtime rejected larger compound sets before
mutation and generated schema/reference artifacts exposed the restriction.
Schema 1.0.0-preview.17 removes that provisional one-compound limit and
narrows the advertised Raoult contract to vapor/liquid PT. The headless factory
injects the retained upstream NestedLoops algorithm, and a fresh ChemSep
Water/Ethanol model passes solve plus DWXMZ save/reload. PH/PS/PV/TV remain
unadvertised until their Runtime specification semantics and full pinned
dependency closures are complete.
Schema 1.0.0-preview.18 adds registry-owned flash-algorithm descriptors and
factories. Single-component, forced-phase, NestedLoops VLE, immiscible VLLE,
SLE eutectic, and SLE solid-solution variants expose conservative tested
specifications, phases, native-dependency flags, calculation provenance, and
pinned source metadata. This is introspection infrastructure; it does not add a
flowsheet-level algorithm-selection setting.
Schema 1.0.0-preview.19 aligns Refluxed/Reboiled Absorber connector metadata
with the pinned upstream rigorous-column graphic: 11 inputs and 11 outputs,
with duty carried on indexed port 10 rather than a separate side connector.
The product DwsimPy.Runtime project now builds against the full pinned
Thermodynamics and UnitOperations source closure by default. Runtime object
creation uses the 48-entry headless catalog and has direct full-assembly coverage
for FlowsheetUO and RefluxedAbsorber. The narrow PoC dependency graph remains an
explicit test-only regression mode, not the product default. Repository-wide
build defaults live in Directory.Build.props; narrow tests opt in with
DwsimPyNarrowRegression=true. The checked-in HeadlessHeater.dwxml fixture is
only a narrow local golden seed and is not a full-engine compatibility fixture.
MSBuild outputs are isolated under each project's bin/full|narrow and
obj/full|narrow directories, so running the narrow regression cannot replace
assemblies or generated sources used by the full product profile.
Runtime also exposes DWSIM's native simulation-object property surface as a
broad introspection and compatibility bridge. ListNativeProperties,
GetNativeProperty, and SetNativeProperty delegate to the pinned object's own
GetProperties, GetPropertyValue, and SetPropertyValue implementations, so
properties outside the current typed descriptors are not silently discarded.
The full-source regression creates every one of the 47 Runtime registrations
available in the headless binary and reads its native property inventory; this
includes 45 direct catalog matches plus the MaterialStream and EnergyStream
specialized creation paths. Draft XML-only integrations are deliberately outside
this bridge.
Native codes such as PROP_HT_0 are upstream identifiers and use DWSIM's SI
convention, including Pa, K, kW, and kJ/kg. This bridge is not the final
stable optimizer contract: typed, versioned descriptors and explicit conversion
adapters will provide the future canonical W/J Runtime boundary.
Try the CLI:
dotnet run --project src/DwsimPy.Runtime.Cli -- inspect path/to/file.dwxmz
dotnet run --project src/DwsimPy.Runtime.Cli -- unitops
dotnet run --project src/DwsimPy.Runtime.Cli -- flash-algorithms
dotnet run --project src/DwsimPy.Runtime.Cli -- coverage
dotnet run --project src/DwsimPy.Runtime.Cli -- schema
dotnet run --project src/DwsimPy.Runtime.Cli -- schema-check path/to/previous-runtime-schema.json
dotnet run --project src/DwsimPy.Runtime.Cli -- create /tmp/new.dwxml
dotnet run --project src/DwsimPy.Runtime.Cli -- add-node /tmp/new.dwxml MaterialStream Feed 40 80 /tmp/with-feed.dwxml
dotnet run --project src/DwsimPy.Runtime.Cli -- native-properties /tmp/with-heater.dwxml Heater-1
dotnet run --project src/DwsimPy.Runtime.Cli -- get-native-property /tmp/with-heater.dwxml Heater-1 PROP_HT_0
dotnet run --project src/DwsimPy.Runtime.Cli -- set-native-property /tmp/with-heater.dwxml Heater-1 PROP_HT_0 25000 /tmp/updated.dwxmlunitops returns JSON descriptors from the current developer validation harness:
object type, display name, category, simulation type, graphic type, connector
counts, aliases, and build-profile-aware IsHeadlessAvailable state. Solver
support and current-binary availability are separate: the former records
engineering evidence, while the latter says whether this build can instantiate
the source object. For example, Mixer resolves to DWSIM's canonical NodeIn
type.
flash-algorithms returns the factory-backed Runtime descriptors for the
currently ported algorithm variants; it does not imply that every property
package can select every listed algorithm.
native-properties reports the upstream property code, unit, and DWSIM access
classification for one hydrated object. Native property reads and writes are an
escape hatch for broad engine coverage; clients that need a stable schema should
continue to use typed Runtime paths as those family descriptors are completed.
coverage returns the timestamp-free checked-in ledger from
docs/generated/runtime-coverage.json, including incomplete property families
and explicit Port, Replace, Review, or non-simulation exclusion decisions.
This harness is distinct from the future product CLI transport.
Run the .NET 10 runtime tests:
dotnet build src/DwsimPy.Runtime.Tests -c Release --no-restore -m:1 \
-p:UseSharedCompilation=false -p:DwsimPyNarrowRegression=true
dotnet run --project src/DwsimPy.Runtime.Tests -c Release \
--no-build --no-restore -p:DwsimPyNarrowRegression=true
dotnet build src/DwsimPy.MathOps.Tests -c Release --no-restore -m:1 \
-p:UseSharedCompilation=false
dotnet run --project src/DwsimPy.MathOps.Tests -c Release \
--no-build --no-restore