Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

Issue with absorber column

Abierto
#330 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
4/5
Tiempo estimado
3-5 días
Aptitud para principiantes
25/100
Tipo de issue
Error
Claridad
Necesita aclaración
Estado de actividad
Estancado
Stack tecnológico
numpy, python
Área
backend

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
Image Image
Lenguaje dominante
Python
Estrellas
115
Forks
28
Merge medio
2 min
PR fusionados (30 d)
1

Preparar el entorno

Abrir en Codespaces

Inicia el contenedor de desarrollo del proyecto en tu navegador, con tu propia cuenta de GitHub.

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de equinor/neqsim-python

Todos los issues de equinor/neqsim-python

Issues similares

Más issues de Python

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.