Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

L8 2D monolithic membrane module

Background

This notebook replaces the simple one-dimensional membrane bridge with a two-dimensional shell-in-tube membrane module. The retentate occupies the inner cylindrical channel, the permeate occupies the surrounding annulus, and the membrane couples both domains at their shared radial interface.

The example focuses on the monolithic coupling pattern: each side has its own transport operators, while the membrane boundary values are eliminated into one sparse linear system.

Governing Equations

Both domains use steady axial convection with radial diffusion:

∇z⋅(vc)−∇r⋅(D∇rc)=0.\nabla_z\cdot(v c) - \nabla_r\cdot\left(D \nabla_r c\right)=0.

The retentate flows from z=0z=0 to z=Lz=L. The permeate is represented as a counter-current stream by using a negative axial velocity, so its inlet is at z=Lz=L.

At the membrane interface the coupled boundary conditions are

D∂cret∂n=P(cperm−cret),D \frac{\partial c_\mathrm{ret}}{\partial n} = P(c_\mathrm{perm}-c_\mathrm{ret}),
RpermRretD∂cperm∂n=P(cret−cperm).\frac{R_\mathrm{perm}}{R_\mathrm{ret}}D\frac{\partial c_\mathrm{perm}}{\partial n} = P(c_\mathrm{ret}-c_\mathrm{perm}).

The radius ratio accounts for the different cylindrical surface areas on each side of the thin membrane gap.

Parameters and Assumptions

The state layout is (n_z, n_r_ret + n_r_perm). The first radial block is the retentate and the second block is the permeate. Axial coordinate arrays use suffixes _f and _c for faces and cell centers; the same convention is used for radial grids.

The model is linear for the chosen membrane law, so spsolve is sufficient. The residual method is still provided because it is the most useful place to check the assembled monolithic system.

PyMRM Implementation

Results

{'residual norm': np.float64(2.4787283336991095e-11), 'retentate outlet average': np.float64(0.4568423567718699), 'permeate outlet average': np.float64(0.7246108260639192), 'integrated membrane rate': np.float64(4.271998134341268e-06), 'mass-balance error': np.float64(1.2844647303680583e-12), 'minimum concentration': np.float64(0.007716754242645528), 'Jacobian nnz': 23940}
<Figure size 1000x400 with 3 Axes>
<Figure size 1000x400 with 2 Axes>

Validation

The membrane only transfers material between the two domains, so the sum of retentate and permeate outlet molar flows should match the inlet molar flow. The solution should also remain non-negative and move material from the retentate into the initially clean permeate stream.

{'mass-balance error': np.float64(1.2844647303680583e-12), 'retentate depleted': True, 'permeate enriched': True, 'membrane flux retentate to permeate': True, 'nonnegative concentrations': True}

Discussion

The retentate and permeate operators are assembled independently, then embedded into a shared state vector. The interface matrices express the membrane boundary values in terms of neighboring cell-center values, which gives one monolithic sparse solve.