PFD Diagram System: Architecture Alignment and DEXPI Synergy
1. Architectural Fit Assessment
1.1 Current NeqSim Process Model Architecture
neqsim.process
├── equipment/ # Individual unit operations (150+ classes)
│ ├── EquipmentEnum # Canonical equipment type enumeration
│ └── ProcessEquipmentInterface
├── processmodel/
│ ├── ProcessSystem # Main flowsheet container
│ ├── graph/ # Graph representation layer
│ │ ├── ProcessGraph # DAG with cycle detection
│ │ ├── ProcessNode # Equipment nodes
│ │ ├── ProcessEdge # Stream edges
│ │ └── ProcessGraphBuilder
│ ├── diagram/ # PFD visualization layer
│ │ ├── ProcessDiagramGraphAdapter
│ │ ├── ProcessDiagramExporter
│ │ ├── PFDLayoutPolicy
│ │ ├── EquipmentRole
│ │ ├── DiagramDetailLevel
│ │ └── EquipmentVisualStyle
│ ├── dexpi/ # DEXPI integration layer
│ │ ├── DexpiXmlReader
│ │ ├── DexpiXmlWriter
│ │ ├── DexpiProcessUnit
│ │ ├── DexpiStream
│ │ ├── DexpiMetadata
│ │ └── DexpiRoundTripProfile
│ └── lifecycle/ # Phase/state management
├── engineering/model/ # Exchange-neutral engineering topology
│ ├── EngineeringGraph
│ ├── EngineeringNode
│ └── EngineeringEdge
└── thermo/ # Thermodynamic models
1.2 Diagram System Integration Points
The PFD diagram system integrates at four architectural levels:
| Layer | Integration Point | Relationship |
|---|---|---|
| ProcessSystem | toDOT(), createDiagramExporter() |
Facade methods for convenience |
| ProcessGraph | ProcessGraphBuilder.buildGraph() |
Diagram uses graph for topology |
| EngineeringGraph | ProcessDiagramGraphAdapter |
Stable plant, area, endpoint, and connection contract |
| Equipment | ProcessEquipmentInterface |
Visual styles keyed by class name |
Key Design Decisions:
- Shared canonical topology -
EngineeringGraphis the exchange-independent foundation for PFD and DEXPI evolution - Execution topology reuse -
ProcessDiagramGraphAdapterderives local connections fromProcessGraphBuilder - Separation of concerns - Canonical topology, layout, rendering, and exchange stay distinct
- Deterministic output - The same model and revision produce the same topology fingerprint
- Honest qualification boundary - Current Graphviz exports are simulator-style views, not ISO-qualified drawings
1.3 Alignment with NeqSim Principles
| Principle | Diagram System Compliance |
|---|---|
Equipment extends ProcessEquipmentBaseClass |
✓ Uses interfaces only, no tight coupling |
| Mixing rules before init | ✓ Works on run() output, not during setup |
Cloning with system.clone() |
✓ No shared mutable state |
| Java 8 compatibility | ✓ No var, no List.of(), streams used correctly |
| Serialization support | ✓ All classes serializable |
| Package boundaries | ✓ Located in processmodel.diagram |
2. DEXPI Synergy Analysis
2.1 Current DEXPI Capabilities
NeqSim already has comprehensive DEXPI support:
| Component | Purpose |
|---|---|
DexpiXmlReader |
Import DEXPI P&ID XML → ProcessSystem |
DexpiXmlWriter |
Export ProcessSystem → DEXPI XML (with nozzles, connections, simulation results) |
DexpiProcessUnit |
Lightweight placeholder for imported equipment |
DexpiStream |
Runnable stream with DEXPI metadata |
DexpiMetadata |
Shared constants (tag names, line numbers, sizing, etc.) |
DexpiRoundTripProfile |
Validation for round-trip fidelity |
DexpiSimulationBuilder |
High-level builder: DEXPI XML → runnable ProcessSystem (with instrument wiring) |
DexpiTopologyResolver |
Nozzle/connection graph parsing, topological sort, edge collapsing, cycle detection |
DexpiEquipmentFactory |
Converts placeholders to real equipment including distillation columns |
DexpiMappingLoader |
Thread-safe cached loader for mapping properties files |
dexpi_equipment_mapping.properties |
DEXPI class → EquipmentEnum mapping (~65 entries) |
dexpi_piping_component_mapping.properties |
Piping component → EquipmentEnum mapping (~28 entries) |
2.2 Synergy Opportunities
2.2.1 Shared Equipment Type Registry
Current State:
EquipmentVisualStyleuses class names:"Separator","Compressor", etc.dexpi_equipment_mapping.propertiesmaps DEXPI classes →EquipmentEnum- Two separate mapping systems with potential inconsistency
Opportunity: Unify equipment type handling through EquipmentEnum:
// EquipmentVisualStyle could use EquipmentEnum as key
public static EquipmentVisualStyle getStyle(EquipmentEnum type) {
return STYLE_CACHE.get(type);
}
// DexpiProcessUnit already has getMappedEquipment() → EquipmentEnum
DexpiProcessUnit unit = ...;
EquipmentVisualStyle style = EquipmentVisualStyle.getStyle(unit.getMappedEquipment());
2.2.2 DEXPI-Aware Diagram Export
Current State:
ProcessDiagramExportergenerates Graphviz DOTDexpiXmlWritergenerates DEXPI XML- No direct connection between them
Opportunity: Add DEXPI-aware export options:
public class ProcessDiagramExporter {
// Export to DEXPI XML with embedded layout hints
public void exportDexpiWithLayout(Path path) throws IOException {
// 1. Generate ProcessGraph with layout
// 2. Add layout coordinates as GenericAttributes
// 3. Write via DexpiXmlWriter with coordinates
}
// Import DEXPI and preserve P&ID layout
public static ProcessDiagramExporter fromDexpi(Path dexpiXml) {
ProcessSystem system = DexpiXmlReader.read(dexpiXml, template);
return new ProcessDiagramExporter(system)
.preserveDexpiLayout(true); // Use DEXPI positions if available
}
}
2.2.3 Metadata Preservation
Current State:
DexpiMetadatadefines: TAG_NAME, LINE_NUMBER, FLUID_CODE, etc.ProcessDiagramExporterdoesn’t use these
Opportunity: Enrich diagram labels with DEXPI metadata:
private String buildNodeLabel(ProcessEquipmentInterface equipment) {
StringBuilder label = new StringBuilder(equipment.getName());
if (equipment instanceof DexpiProcessUnit) {
DexpiProcessUnit dexpi = (DexpiProcessUnit) equipment;
if (dexpi.getLineNumber() != null) {
label.append("\\nLine: ").append(dexpi.getLineNumber());
}
if (dexpi.getFluidCode() != null) {
label.append("\\nFluid: ").append(dexpi.getFluidCode());
}
}
return label.toString();
}
2.2.4 Symbol Standardization (ISO 10628 / DEXPI)
Current State:
EquipmentVisualStyleuses Graphviz shapes (circle, rectangle, etc.)- DEXPI references ISO 10628-2 (P&ID symbols)
Opportunity: Map to ISO 10628 symbol classes:
public enum EquipmentSymbol {
// ISO 10628-2 Section 5: Process equipment
VESSEL(5.1, "cylinder", "#90EE90"),
COLUMN(5.2, "cylinder", "#90EE90"),
HEAT_EXCHANGER(5.3, "rectangle", "#FFD700"),
// ISO 10628-2 Section 6: Piping components
VALVE(6.1, "diamond", "#FFB6C1"),
PUMP(6.2, "circle", "#4169E1"),
COMPRESSOR(6.3, "parallelogram", "#87CEEB");
private final String isoSection;
private final String graphvizShape;
private final String defaultColor;
}
2.3 Implementation Roadmap
Phase 1: Type Registry Unification (Low effort, high impact)
- Refactor
EquipmentVisualStyleto acceptEquipmentEnumas primary key - Add fallback to class name for custom equipment
- Ensure DEXPI imports render with correct visual styles
// Before
EquipmentVisualStyle style = EquipmentVisualStyle.getStyle("Separator");
// After
EquipmentVisualStyle style = EquipmentVisualStyle.getStyle(EquipmentEnum.Separator);
// or
EquipmentVisualStyle style = EquipmentVisualStyle.getStyle(unit.getMappedEquipment());
Phase 2: DEXPI Metadata in Diagrams (Medium effort)
- Detect
DexpiProcessUnitandDexpiStreaminstances - Extract and display DEXPI metadata (tag names, line numbers)
- Add legend entry for DEXPI-originated equipment
Phase 3: Bidirectional DEXPI-Diagram Integration (Higher effort)
- Add layout coordinates to DEXPI export via GenericAttributes
- Parse layout hints from DEXPI imports
- Round-trip: DEXPI → NeqSim → PFD → DEXPI with layout preserved
3. Architectural Recommendations
3.1 Adopt the Shared Canonical Topology
EngineeringGraph is the common semantic foundation. ProcessDiagramGraphAdapter maps one
ProcessSystem or all areas in a ProcessModel into that graph with stable identifiers, explicit
ports, connection segments, and structured diagnostics. Renderers and DEXPI materializers can evolve
independently while sharing the same topology contract.
The adapter intentionally does not render, assign document numbers, or assert standards compliance. The existing exporters remain in place until they are migrated and compared against representative fixtures.
3.2 Create Shared Equipment Type Service
package neqsim.process.equipment;
/**
* Unified equipment type resolution service.
*/
public final class EquipmentTypeResolver {
/**
* Resolves equipment to canonical EquipmentEnum.
*/
public static EquipmentEnum resolve(ProcessEquipmentInterface equipment) {
if (equipment instanceof DexpiProcessUnit) {
return ((DexpiProcessUnit) equipment).getMappedEquipment();
}
// Fall back to class name mapping
String className = equipment.getClass().getSimpleName();
return EquipmentEnum.valueOf(className);
}
/**
* Resolves DEXPI class name to EquipmentEnum using mapping file.
*/
public static EquipmentEnum resolveFromDexpi(String dexpiClassName) {
// Load from dexpi_equipment_mapping.properties
}
}
3.3 Add DEXPI-Diagram Bridge Class
package neqsim.process.processmodel.diagram;
/**
* Bridge between DEXPI metadata and PFD visualization.
*/
public class DexpiDiagramBridge {
/**
* Creates diagram exporter optimized for DEXPI-imported processes.
*/
public static ProcessDiagramExporter createExporter(ProcessSystem system) {
return new ProcessDiagramExporter(system)
.setShowDexpiMetadata(true)
.setPreserveDexpiLayout(true);
}
/**
* Exports ProcessSystem to DEXPI XML with embedded layout coordinates.
*/
public static void exportWithLayout(ProcessSystem system, Path output) {
// Calculate layout via ProcessDiagramExporter
// Inject coordinates as GenericAttributes
// Write via DexpiXmlWriter
}
}
4. Summary
Architectural Fit
The canonical foundation is now explicit:
ProcessGraphremains the runnable local-topology sourceEngineeringGraphprovides exchange-neutral engineering identities and relationshipsProcessDiagramGraphAdapterbridges single- and multi-area process models into one plant graph- DOT rendering and DEXPI exchange remain separate consumers pending migration
DEXPI Synergy: ✅ Implemented
| Synergy Area | Status | Implementation |
|---|---|---|
| EquipmentEnum unification | ✅ Complete | EquipmentVisualStyle.getStyle(EquipmentEnum) |
| DEXPI metadata in labels | ✅ Complete | appendDexpiMetadata(), setShowDexpiMetadata() |
| DexpiDiagramBridge | ✅ Complete | DexpiDiagramBridge class with round-trip support |
| ISO 10628 symbol mapping | ⏳ Future | Planned for P&ID compliance |
Available Features
EquipmentVisualStyle.getStyle(EquipmentEnum)- Unified styling via canonical enumEquipmentVisualStyle.getStyleForEquipment(equipment)- Auto-detects DEXPI unitsProcessDiagramExporter.setShowDexpiMetadata(true)- Display line numbers/fluid codesDexpiDiagramBridge.createExporter(system)- Pre-configured DEXPI-aware exporterDexpiDiagramBridge.importAndCreateExporter(path)- One-step DEXPI → diagramDexpiDiagramBridge.roundTrip(input, dotOutput, dexpiOutput)- Full import/simulate/export