Issue with absorber column
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 25/100
Línea de trabajo
El punto de entrada es la función absorber(...); empieza reproduciendo el comportamiento usando las entradas y las salidas adjuntas, y luego sigue el bottom-up tray loop, la phase selection y la llamada a TPflash. El trabajo estará terminado cuando absorber devuelva resultados validados de flow y composition para sweet_gas y rich_amine sin el problema indicado.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
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
- Lenguaje dominante
- Python
- Estrellas
- 115
- Forks
- 28
- Merge medio
- 2 min
- PR fusionados (30 d)
- 1
Preparar el entorno
Inicia el contenedor de desarrollo del proyecto en tu navegador, con tu propia cuenta de GitHub.
- Sin Dockerfile ni archivo de Docker Compose
- Sin plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de equinor/neqsim-python
-
Java issuesAbierto
Dificultad 4/5 3-5 días Aptitud para principiantes 25/100
equinor/neqsim-python#339 ·
-
Pandas supportAbierto
Dificultad 5/5 Más de una semana Aptitud para principiantes 20/100
equinor/neqsim-python#50 · 7 comentarios ·
Todos los issues de equinor/neqsim-python
Issues similares
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
Deltares/imod-python#1940 ·
Los mantenedores suelen responder en 1 día
-
effort: low prio: low ready
Dificultad 1/5 Menos de una hora Aptitud para principiantes 82/100
digitalfabrik/integreat-cms#4621 ·
Los mantenedores suelen responder en 5 días
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 88/100
ioos/compliance-checker#1375 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
Los mantenedores suelen responder en 1 día
-
netbox status: backlog topic: testing type: housekeeping
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
netbox-community/netbox#23395 ·
Los mantenedores suelen responder en 1 día