Issue with absorber column
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 25/100
Direzione di ricerca
Il punto di ingresso è la funzione absorber(...); inizia riproducendo il comportamento usando gli input e gli output allegati, quindi traccia il bottom-up tray loop, la phase selection e la chiamata a TPflash. Il lavoro è completato quando absorber restituisce risultati validati di flow e composition per sweet_gas e rich_amine senza il problema segnalato.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
I'm not sure what's wrong here.
def absorber(feed_gas, lean_amine, component_list, n_comp, fluid, TPflash,
T_top, T_bottom, P_top, P_bottom, N_trays, EFFICIENCY, mixRule, debug=False,
max_iter=20, tolerance=1e-6):
vap_flow = np.ones(N_trays + 1) * (feed_gas.getTotalNumberOfMoles() / (N_trays+1))
vap_flow[-1] = feed_gas.getTotalNumberOfMoles()
liq_flow = np.ones(N_trays + 1) * (lean_amine.getTotalNumberOfMoles() / (N_trays+1))
liq_flow[0] = lean_amine.getTotalNumberOfMoles()
# Initial guess for compositions (assume each is the entering stream composition)
vap_comp = np.zeros((N_trays + 1, n_comp))
liq_comp = np.zeros((N_trays + 1, n_comp))
for iteration in range(max_iter):
# Store previous for convergence check
vap_flow_prev = vap_flow.copy()
liq_flow_prev = liq_flow.copy()
vap_comp_prev = vap_comp.copy()
liq_comp_prev = liq_comp.copy()
if debug:
print(f"\n=== Absorber Iteration {iteration+1} ===\n")
# Apply vapor and liquid inlet conditions
vap_flow[-1] = feed_gas.getTotalNumberOfMoles()
vap_comp[-1, :] = [feed_gas.getComponent(comp).getz() if feed_gas.getComponent(comp) is not None else 0.0 for comp in component_list]
liq_flow[0] = lean_amine.getTotalNumberOfMoles()
liq_comp[0, :] = [lean_amine.getComponent(comp).getz() if lean_amine.getComponent(comp) is not None else 0.0 for comp in component_list]
# Sweep from bottom tray up (bottom-up is standard in equilibrium stage columns)
for tray in reversed(range(N_trays)):
T_tray = T_bottom + (tray * (T_top - T_bottom) / N_trays)
P_tray = P_bottom + (tray * (P_top - P_bottom) / N_trays)
n_vap_in = vap_flow[tray + 1]
n_liq_in = liq_flow[tray]
n_total = n_vap_in + n_liq_in
if debug:
print(f"\n--- Tray {tray + 1} ---")
print(f"Temperature: {T_tray:.2f} °C | Pressure: {P_tray:.2f} bara")
print(f"Vapor in: {n_vap_in:.5f} mol | Liquid in: {n_liq_in:.5f} mol")
vap_comp = np.nan_to_num(vap_comp, nan=0.0, posinf=0.0, neginf=0.0)
liq_comp = np.nan_to_num(liq_comp, nan=0.0, posinf=0.0, neginf=0.0)
vap_comp = np.clip(vap_comp, 0.0, 1.0)
liq_comp = np.clip(liq_comp, 0.0, 1.0)
tray_fluid = fluid(feed_gas.getFluidName())
safe_total = 0.0
for j, comp in enumerate(component_list):
mole_vap = max(vap_comp[tray + 1, j], 0.0)
mole_liq = max(liq_comp[tray, j], 0.0)
moles = n_vap_in * mole_vap + n_liq_in * mole_liq
if np.isnan(moles) or moles < 1e-20:
moles = 1e-20 # enforce trace but never negative or nan
if moles > 0:
tray_fluid.addComponent(comp, moles)
safe_total += moles # will help with optional normalization debug
if safe_total == 0:
raise ValueError(f"All component moles on tray {tray+1} dropped to zero!")
tray_fluid.setTemperature(T_tray, "C")
tray_fluid.setPressure(P_tray, "bara")
tray_fluid.setMixingRule(mixRule)
tray_fluid.setMultiPhaseCheck(True)
tray_fluid.chemicalReactionInit()
print("component_list:", component_list)
print("vap_comp.shape:", vap_comp.shape)
print("liq_comp.shape:", liq_comp.shape)
if debug:
print("Sum of tray components (moles):", safe_total)
TPflash(tray_fluid)
# Identify output phases
gas_idx, aq_idx = None, None
for idx in range(tray_fluid.getNumberOfPhases()):
phase_name = str(tray_fluid.getPhase(idx).getPhaseTypeName()).lower()
if "gas" in phase_name:
gas_idx = idx
elif "aqueous" in phase_name or "liquid" in phase_name:
aq_idx = idx
if gas_idx is not None:
vap_phase = tray_fluid.getPhase(gas_idx)
n_vap_out = vap_phase.getNumberOfMolesInPhase()
vapor_out = np.array([
vap_phase.getComponent(comp).getx() if vap_phase.hasComponent(comp) else 0.0
for comp in component_list
])
vap_flow[tray] = n_vap_out
vap_comp[tray, :] = EFFICIENCY * vapor_out + (1 - EFFICIENCY) * vap_comp[tray, :]
else:
vap_flow[tray] = 0.0
vapor_out = np.zeros(n_comp)
if aq_idx is not None:
liq_phase = tray_fluid.getPhase(aq_idx)
n_liq_out = liq_phase.getNumberOfMolesInPhase()
liquid_out = np.array([
liq_phase.getComponent(comp).getx() if liq_phase.hasComponent(comp) else 0.0
for comp in component_list
])
liq_flow[tray] = n_liq_out
liq_comp[tray, :] = EFFICIENCY * liquid_out + (1 - EFFICIENCY) * liq_comp[tray, :]
else:
n_liq_out = 0.0
liquid_out = np.zeros(n_comp)
if np.sum(vapor_out) > 0:
vapor_out /= np.sum(vapor_out)
if np.sum(liquid_out) > 0:
liquid_out /= np.sum(liquid_out)
# Check convergence
flow_diff = np.max(np.abs(vap_flow - vap_flow_prev)) + np.max(np.abs(liq_flow - liq_flow_prev))
comp_diff = np.max(np.abs(vap_comp - vap_comp_prev)) + np.max(np.abs(liq_comp - liq_comp_prev))
if debug:
print(f"\nAbsorber recycle convergence check: Δflow={flow_diff:.6e}, Δcomp={comp_diff:.6e}")
if flow_diff < tolerance and comp_diff < tolerance:
if debug:
print("Absorber converged!\n")
break
# Output result
sweet_gas = {'flow': vap_flow[0], 'composition': vap_comp[0, :].copy()}
rich_amine = {'flow': liq_flow[-1], 'composition': liq_comp[-1, :].copy()}
return sweet_gas, rich_amine
- Lingua principale
- Python
- Stelle
- 113
- Fork
- 28
- Merge medio
- 1m
- PR unite (30g)
- 1
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di equinor/neqsim-python
-
Java issues Aperta
Difficoltà 4/5 3-5 giorni Idoneità per principianti 25/100
equinor/neqsim-python#339 ·
-
Pandas support Aperta
Difficoltà 5/5 Più di una settimana Idoneità per principianti 20/100
equinor/neqsim-python#50 · 7 commenti ·
Tutte le issue di equinor/neqsim-python
Issue simili
-
area: harness bug status: needs-triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
Human-Agent-Society/reef#625 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 80/100
learningequality/kolibri#15351 · 2 commenti ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
-
Name consistency Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
eellak/triplestore#65 · 1 commento ·