glitchfilter commited on
Commit
771dd68
·
verified ·
1 Parent(s): 2031a0c

Sync server/reactor_sim.py

Browse files
Files changed (1) hide show
  1. server/reactor_sim.py +46 -2
server/reactor_sim.py CHANGED
@@ -86,15 +86,59 @@ _ACT = _CFG.get("actuator_limits", {})
86
  # ---------------------------------------------------------------------------
87
  R_GAS = 8.314 # J/(mol*K), universal gas constant
88
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
 
90
  def _fugacity_coefficient(T_K: float, P_bar: float, species: str = "CO") -> float:
91
  """SRK fugacity coefficient for key species at reactor conditions.
92
 
93
- Soave-Redlich-Kwong EOS correction for non-ideal gas behavior.
94
- At 50-100 bar, ideal gas assumption has ~5-10% error [LeBlanc Ch.3.2.1].
95
 
96
  Returns phi (fugacity coefficient, 0 < phi < 1 at high pressure).
97
  """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
  # Critical properties for key species
99
  Tc_K = {"H2": 33.2, "CO": 132.9, "CO2": 304.2, "CH3OH": 512.6, "H2O": 647.1}.get(species, 132.9)
100
  Pc_bar = {"H2": 13.0, "CO": 35.0, "CO2": 73.8, "CH3OH": 80.9, "H2O": 220.6}.get(species, 35.0)
 
86
  # ---------------------------------------------------------------------------
87
  R_GAS = 8.314 # J/(mol*K), universal gas constant
88
 
89
+ # ---------------------------------------------------------------------------
90
+ # Optional DWSIM backend — when available, fugacity coefficients come from
91
+ # DWSIM's industrial SRK solver instead of our internal approximation.
92
+ # Set DWSIM_PATH env var to enable. Falls back silently if unavailable.
93
+ # ---------------------------------------------------------------------------
94
+ _dwsim_backend = None
95
+ _dwsim_cache = {} # (T_K_rounded, P_bar_rounded) → {species: phi}
96
+
97
+ def _init_dwsim():
98
+ global _dwsim_backend
99
+ if _dwsim_backend is not None:
100
+ return
101
+ try:
102
+ import sys, os
103
+ # Add integration path
104
+ _int_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), "integrations")
105
+ if _int_dir not in sys.path:
106
+ sys.path.insert(0, _int_dir)
107
+ from dwsim import DWSIMIntegration
108
+ d = DWSIMIntegration()
109
+ if d.is_available:
110
+ _dwsim_backend = d
111
+ except Exception:
112
+ pass
113
+
114
+ _init_dwsim()
115
+
116
 
117
  def _fugacity_coefficient(T_K: float, P_bar: float, species: str = "CO") -> float:
118
  """SRK fugacity coefficient for key species at reactor conditions.
119
 
120
+ When DWSIM is available (DWSIM_PATH set), uses DWSIM's industrial SRK
121
+ solver via .NET interop. Falls back to internal SRK implementation.
122
 
123
  Returns phi (fugacity coefficient, 0 < phi < 1 at high pressure).
124
  """
125
+ # Try DWSIM backend first (cached per T,P to avoid repeated .NET calls)
126
+ if _dwsim_backend is not None:
127
+ cache_key = (round(T_K, 1), round(P_bar, 1))
128
+ if cache_key not in _dwsim_cache:
129
+ try:
130
+ comp = {"H2": 0.6, "CO": 0.1, "CO2": 0.05, "CH3OH": 0.02,
131
+ "H2O": 0.01, "CH4": 0.15, "N2": 0.07}
132
+ result = _dwsim_backend.get_thermodynamic_properties(
133
+ T_K, P_bar * 1e5, comp)
134
+ _dwsim_cache[cache_key] = result.fugacity_coefficients
135
+ except Exception:
136
+ _dwsim_cache[cache_key] = None
137
+ cached = _dwsim_cache.get(cache_key)
138
+ if cached and species in cached:
139
+ return cached[species]
140
+
141
+ # Internal SRK fallback
142
  # Critical properties for key species
143
  Tc_K = {"H2": 33.2, "CO": 132.9, "CO2": 304.2, "CH3OH": 512.6, "H2O": 647.1}.get(species, 132.9)
144
  Pc_bar = {"H2": 13.0, "CO": 35.0, "CO2": 73.8, "CH3OH": 80.9, "H2O": 220.6}.get(species, 35.0)