Guía de clase (Google Colab): notebook para calcular y graficar ηd y ηp durante un día de secado
# Secado solar — Eficiencias horarias (ηd, ηp)
Caso base: Apéndice 7 de *Solar Dryers*. Extensión a perfil horario en un día.
# Parámetros “macro” del caso
Mi_kg = 100.0 # masa inicial
wi_bh = 0.80 # humedad inicial base húmeda
wf_bh = 0.05 # humedad final base húmeda
A_m2 = 15.0 # área del colector
dias = 3.0 # duración del secado (Apéndice 7)
Lv_funC = lambda T: 2501.0 - 2.361*T # kJ/kg (aprox) en función de T (°C)
# Cálculo del agua total a evaporar (W_total)
Md_kg = Mi_kg*(1-wi_bh) # masa seca
Mf_kg = Md_kg/(1-wf_bh) # masa final
W_total_kg = Mi_kg - Mf_kg # agua a remover total
W_total_kg
import math
import numpy as np
import pandas as pd
def esat_Pa(T_C):
"""Presión de vapor de saturación (Pa). Fórmula tipo Tetens/Magnus, 0–50 °C."""
return 0.61078 * math.exp((17.2694*T_C)/(T_C+237.3)) * 1000.0
def omega(Pv_Pa, P_atm_Pa=101325.0):
"""Razón de humedad ω = kg_vapor/kg_aire_seco."""
return 0.62198 * Pv_Pa / max(P_atm_Pa - Pv_Pa, 1e-6)
def omega_from_T_RH(T_C, RH_frac, P_atm_Pa=101325.0):
"""ω a partir de T y HR."""
return omega(RH_frac*esat_Pa(T_C), P_atm_Pa)
Prompt A — Insolación y horario solar efectivo
Genera una serie horaria para un día despejado de 6:00 a 18:00 con paso 1 h de irradiación global en el plano del colector [MJ/m²·h], con forma campana (máximo al mediodía) y suma aproximada 20 MJ/m²·día. Devuélvelo como lista de 13 valores desde la hora 6 a 18.
Prompt B — Temperatura y HR ambiente
Propón perfiles horarios plausibles de temperatura ambiente [°C] y humedad relativa [%] de 6:00 a 18:00 en clima cálido-húmedo, con T subiendo 26→34 °C y HR bajando 85→60 %. Entrega dos listas sincronizadas de 13 valores.
Prompt C — Temperatura de secado y caudal
Considerando un colector solar, fija T_aire_secado [°C] ~ T_amb + 8 °C con tope 45 °C y un caudal constante V=0.5 m³/s. Devuelve la lista de T_secado de 6:00 a 18:00.
# Rango horario: 6 a 18 (13 puntos)
horas = np.arange(6, 19)
n = len(horas)
# Insolación horaria [MJ/m2·h] con forma aproximada
I_h = np.array([0.3, 0.8, 1.3, 1.8, 2.2, 2.6, 2.8, 2.6, 2.2, 1.6, 1.0, 0.6, 0.2])
I_day_total = I_h.sum() # ≈ 20 MJ/m2·día
# Temperatura ambiente y HR propuestas
T_amb = np.array([26,27,28,29,30,31,32,33,34,34,33,31,29], dtype=float)
HR = np.array([85,83,80,78,75,72,70,68,66,64,63,62,60], dtype=float)/100.0
# Temperatura de secado (ambiente + 8 °C, tope 45 °C)
T_sec = np.minimum(T_amb + 8.0, 45.0)
# Otros parámetros
V_m3s = 0.5 # caudal
rho_air = 1.28 # kg/m3
P_atm = 101325.0 # Pa
dt_s = 3600.0 # 1 hora
Idea: el aire recoge humedad hasta un máximo teórico. Tomamos:
# Razones de humedad
w_in = np.array([omega_from_T_RH(T_amb[i], HR[i], P_atm) for i in range(n)])
w_sat = np.array([omega(esat_Pa(T_sec[i]), P_atm) for i in range(n)])
# Capacidad teórica por hora: m_da * (w_sat - w_in)
m_da_h = rho_air * V_m3s * dt_s * np.ones(n) # kg aire ~ aire seco (aprox)
cap_teor_h = m_da_h * np.maximum(w_sat - w_in, 0.0)
# Evaporación real por hora: aquí dos opciones
# Opción 1: Limitada por capacidad del aire (psicrométrica)
dW_psic_h = cap_teor_h.copy()
# Opción 2: Proporcional a la energía solar de la hora (distribución por insolación)
E_req_total_MJ = Lv_funC(T_sec.mean()) * W_total_kg / 1000.0
frac_I = I_h / I_h.sum()
dW_ener_h = frac_I * W_total_kg
# Selección del método base para ηp: psicrométrico
dW_h = dW_psic_h.copy()
# Para no exceder W_total_kg en un día, se puede escalar:
scale = min(1.0, W_total_kg / dW_h.sum()) if dW_h.sum() > 0 else 1.0
dW_h *= scale
W_dia = dW_h.sum()
W_dia
Definición (hora a hora): [ _{p,h} = ] Acumulada de 6:00→t: [ _{p,acum}(t) = ]
den_p_h = m_da_h * np.maximum(w_sat - w_in, 1e-12)
eta_p_h = dW_h / den_p_h
eta_p_h = np.clip(eta_p_h, 0.0, 1.0)
eta_p_acum = np.cumsum(dW_h) / np.cumsum(den_p_h)
Hora h: [ _{d,h} = ] Acumulada: [ _{d,acum}(t) = ]
Lv_h_kJkg = np.array([Lv_funC(T_sec[i]) for i in range(n)])
E_evap_h_MJ = dW_h * Lv_h_kJkg / 1000.0 # MJ
E_solar_h_MJ = I_h * A_m2 # MJ
eta_d_h = np.divide(E_evap_h_MJ, E_solar_h_MJ, out=np.zeros(n), where=E_solar_h_MJ>0)
eta_d_acum = np.cumsum(E_evap_h_MJ) / np.maximum(np.cumsum(E_solar_h_MJ), 1e-12)
import matplotlib.pyplot as plt
df = pd.DataFrame({
"hora": horas,
"I_h_MJm2h": I_h,
"T_amb_C": T_amb,
"HR_frac": HR,
"T_sec_C": T_sec,
"w_in": w_in,
"w_sat": w_sat,
"m_da_kg": m_da_h,
"dW_h_kg": dW_h,
"eta_p_h": eta_p_h,
"eta_p_acum": eta_p_acum,
"eta_d_h": eta_d_h,
"eta_d_acum": eta_d_acum
})
df.round(4)
# Graficar eficiencias horarias
plt.figure()
plt.plot(horas, eta_d_h, marker='o', label='ηd hora')
plt.plot(horas, eta_p_h, marker='s', label='ηp hora')
plt.xlabel("Hora del día")
plt.ylabel("Eficiencia [-]")
plt.title("Eficiencias horarias")
plt.legend()
plt.grid(True)
plt.show()
# Graficar eficiencias acumuladas
plt.figure()
plt.plot(horas, eta_d_acum, marker='o', label='ηd acumulada')
plt.plot(horas, eta_p_acum, marker='s', label='ηp acumulada')
plt.xlabel("Hora del día")
plt.ylabel("Eficiencia acumulada [-]")
plt.title("Eficiencias acumuladas")
plt.legend()
plt.grid(True)
plt.show()
Ejemplo de conmutador de método:
# Cambiar entre psicrométrico y energético
use_psic = True
dW_h = (dW_psic_h if use_psic else dW_ener_h) * scale
app.py.