def _idx3d(i, j, k):
return i * _GF3_NY * _GF3_NZ + j * _GF3_NZ + k
def _kamal_sourour_rate_vec(T: np.ndarray, alpha: np.ndarray) -> np.ndarray:
T_safe = np.clip(T, _T_FLOOR, _T_CEIL)
alpha_safe = np.clip(alpha, 0.0, 1.0)
inv_RT = 1.0 / (_R_GAS * T_safe)
arg1 = np.clip(_E1 * inv_RT, 0.0, _EXP_ARG_MAX)
arg2 = np.clip(_E2 * inv_RT, 0.0, _EXP_ARG_MAX)
k1 = _A1 * np.exp(-arg1)
k2 = _A2 * np.exp(-arg2)
return (k1 + k2 * np.power(alpha_safe, _M)) * np.power(1.0 - alpha_safe, _N_ORD)
def _fp_glass_fiber_3d_rhs(t, y):
T_flat = np.clip(y[:_GF3_N3D], _T_FLOOR, _T_CEIL)
alpha_flat = np.clip(y[_GF3_N3D:], 0.0, 1.0)
dadt = _kamal_sourour_rate_vec(T_flat, alpha_flat)
dT = np.empty(_GF3_N3D)
for i in range(_GF3_NX):
for j in range(_GF3_NY):
for k in range(_GF3_NZ):
idx = _idx3d(i, j, k)
T_c = T_flat[idx]
# x-direction (fiber): Dirichlet at i=0, convective at i=NX-1
if i == 0:
lap_x = 0.0
elif i == _GF3_NX - 1:
T_ghost = T_c + (_H_CONV * _GF3_DX / _K_FIBER_G) * (_T_AMBIENT - T_c)
lap_x = (T_flat[_idx3d(i - 1, j, k)] - 2.0 * T_c + T_ghost) * _GF3_INV_DX2
else:
T_left = _GF3_T_LEFT if i == 1 else T_flat[_idx3d(i - 1, j, k)]
lap_x = (T_left - 2.0 * T_c + T_flat[_idx3d(i + 1, j, k)]) * _GF3_INV_DX2
# y-direction (transverse)
if j == 0:
T_ghost = T_c + (_H_CONV * _GF3_DY / _K_TRANS_G) * (_T_AMBIENT - T_c)
lap_y = (T_ghost - 2.0 * T_c + T_flat[_idx3d(i, j + 1, k)]) * _GF3_INV_DY2
elif j == _GF3_NY - 1:
T_ghost = T_c + (_H_CONV * _GF3_DY / _K_TRANS_G) * (_T_AMBIENT - T_c)
lap_y = (T_flat[_idx3d(i, j - 1, k)] - 2.0 * T_c + T_ghost) * _GF3_INV_DY2
else:
lap_y = (T_flat[_idx3d(i, j - 1, k)] - 2.0 * T_c + T_flat[_idx3d(i, j + 1, k)]) * _GF3_INV_DY2
# z-direction (transverse)
if k == 0:
T_ghost = T_c + (_H_CONV * _GF3_DZ / _K_TRANS_G) * (_T_AMBIENT - T_c)
lap_z = (T_ghost - 2.0 * T_c + T_flat[_idx3d(i, j, k + 1)]) * _GF3_INV_DZ2
elif k == _GF3_NZ - 1:
T_ghost = T_c + (_H_CONV * _GF3_DZ / _K_TRANS_G) * (_T_AMBIENT - T_c)
lap_z = (T_flat[_idx3d(i, j, k - 1)] - 2.0 * T_c + T_ghost) * _GF3_INV_DZ2
else:
lap_z = (T_flat[_idx3d(i, j, k - 1)] - 2.0 * T_c + T_flat[_idx3d(i, j, k + 1)]) * _GF3_INV_DZ2
dT[idx] = (_GF3_DIFF_X * lap_x + _GF3_DIFF_Y * lap_y
+ _GF3_DIFF_Z * lap_z + _SRC_COEFF * dadt[idx])
# Left face (i=0) is Dirichlet
for j in range(_GF3_NY):
for k in range(_GF3_NZ):
dT[_idx3d(0, j, k)] = 0.0
dy = np.empty(_GF3_DIM)
dy[:_GF3_N3D] = dT
dy[_GF3_N3D:] = dadt
return dy