Skip to content

Repository files navigation

DwsimPy Platform

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 Quick Start

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.whl

Use 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.

Platform Direction

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.

What the Native .NET 10 Wheel Bundles

The release wheels include:

  • first-party net10.0 DWSIM 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 Automation3 API and the convenience Automation, Flowsheet, and SimulationObject wrappers.

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, or DOTNET_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.

.NET 10 Runtime Port Status

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.Interfaces
  • DWSIM.GlobalSettings
  • DWSIM.SharedClassesCSharp
  • DWSIM.SharedClasses
  • DWSIM.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-free Automation3 compatibility facade)
  • DWSIM.MathOps.SimpsonIntegrator
  • DWSIM.MathOps
  • DWSIM.MathOps.Mapack
  • DWSIM.MathOps.RandomOps
  • DWSIM.MathOps.SwarmOps
  • DWSIM.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.py

Audit 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 ./dwsim

Use prepare_dwsim_source.py --prepare only when the checkout is absent. The tool never resets or overwrites an existing checkout.

Distribution Status

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.whl

If dotnet is not on PATH, set DOTNET_ROOT to the .NET 10 installation root before importing dwsimpy.

Current Python Binding API

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() and Automation.load_flowsheet(path)
  • Automation.solve(flowsheet) and Automation.close(flowsheet)
  • Flowsheet.get_object(tag), get_objects(), connect(), and save(path)
  • SimulationObject.get_property(name), set_property(name, value), and get_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.

Building Wheels

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.

Repository Layout

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

License And Attribution

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.

Experimental .NET 10 Platform Slice

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-build

Standard, 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.dwxml

unitops 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

About

Headless DWSIM simulation engine ported to .NET 10, with native macOS ARM64 Python.NET bindings.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages