The invention
What the device is, and the one thing that makes it different.
PD20 is a continuous-flow regenerative peritoneal dialysis device. Instead of instilling a bag of fresh dialysate, letting it dwell, and draining it, it circulates dialysate continuously through the peritoneal cavity and regenerates the spent fluid by reverse osmosis, returning recovered water and re-dosing the solutes that need replacing.
The clinically important consequence is that ultrafiltration and solute clearance are decoupled from the osmotic agent. In conventional peritoneal dialysis, water removal is bought with dextrose, and sodium leaves the body mainly by being dragged along with that water. If ultrafiltration falls, sodium removal falls with it. A continuous-flow regenerative system removes solute by exchanging a large volume of dialysate across the membrane rather than by concentrating an osmotic gradient, so the two are no longer chained together.
The simulator on this site exists to test whether that claim survives contact with physiology, across a cohort of patients whose behaviour a nephrologist can predict in advance.
The physics engine
Fourteen solutes, ten flux laws, conservation by construction.
Conservation is structural, not checked afterwards
Every physical process in the model moves mass through exactly two primitives: a paired water-plus-carried-solute transfer, and a paired solute-only transfer. Both are atomic and clamped to the source pool, so total water and total per-solute quantity are invariant under any sequence of transfers — mass cannot be created or destroyed by a modelling error, only moved to the wrong place. Measured conservation residuals across a 30-day ten-patient cohort are of order 10-8, which is floating-point noise rather than physics.
The species, and their transport coefficients
σ is the osmotic reflection coefficient (how strongly the membrane opposes that solute's osmotic pull), S is the convective sieving coefficient (what fraction of the solute is dragged through with ultrafiltrate), and MTAC is the diffusive mass-transfer-area coefficient.
| Solute | Charge | σ | S | MTAC (mL/min) |
|---|---|---|---|---|
| Sodium | +1 | 0.050 | 0.550 | 4.5000 |
| Chloride | -1 | 0.050 | 0.588 | 4.5000 |
| Glucose | 0 | 0.049 | 0.382 | 12.0000 |
| Potassium | +1 | 0.050 | 0.535 | 10.0000 |
| Urea | 0 | 0.020 | 0.688 | 20.0000 |
| Albumin | -18.6 | 0.840 | 0.010 | 0.1000 |
| Globulin | 0 | 0.900 | 0.005 | 0.0500 |
| Icodextrin | 0 | 0.500 | 0.020 | 0.1000 |
| Bicarbonate | -1 | 0.050 | 0.535 | 10.0000 |
| Lactate | -1 | 0.050 | 0.611 | 10.0000 |
| Calcium | +2 | 0.050 | 0.458 | 6.0000 |
| Magnesium | +2 | 0.050 | 0.458 | 6.0000 |
| Phosphate | -1.8 | 0.050 | 0.497 | 5.0000 |
| Sulfate | -2 | 0.050 | 0.458 | 4.0000 |
Plasma colloid osmotic pressure is not van't Hoff
Plasma protein is strongly non-ideal at physiologic concentration, so the ideal-solution law underestimates the oncotic pressure that opposes ultrafiltration by roughly 40%. The model uses the standard empirical replacement:
COP (mmHg) = 2.1·C + 0.16·C² + 0.009·C³ C = total plasma protein, g/dL
Landis EM & Pappenheimer JR, Handbook of Physiology, Section 2: Circulation, Vol II, American Physiological Society, 1963, p.975.
At a normal total protein of 7.0 g/dL this gives 25.6 mmHg, the textbook plasma value; the ideal law gives 15.8 on the same protein mass. Both albumin and globulin are tracked as separate species, because peritoneal dialysis removes the smaller albumin preferentially and so the albumin fraction of plasma protein falls over a long treatment — a fixed albumin-to-globulin ratio would freeze exactly the quantity that ought to move.
Other laws
- Ultrafiltration — Starling across the peritoneal membrane, driven by the hydrostatic difference between capillary and intraperitoneal pressure plus the summed osmotic terms.
- Intraperitoneal pressure — linear in intraperitoneal volume, anchored to Durand's measurement of 13 cmH2O at 2.82 L supine in 34 CAPD patients (PMID 8105960), with linearity to 5 L from PMID 7999866.
- Diffusion — MTAC-driven, with a Gibbs–Donnan correction: albumin cannot cross, so diffusible ions equilibrate to a ratio set by the impermeant protein charge rather than 1:1.
- Total peritoneal fluid absorption — 1.07 mL/min (Imholz et al., Kidney Int 1993;44:1078-85, PMID 8264138). Note this is total absorption; true lymphatic flow is only 0.2–0.3 mL/min, and the model's variable name should not be read as claiming otherwise.
- Cavity geometry — an ovoid cavity divided into horizontal slabs, with per-slab area-weighted transport and implicit backward-Euler inter-layer diffusion, so a vertical concentration gradient can form and clearance is independent of the slab count.
- Whole-body physiology — intracellular potassium with aldosterone-mediated regulation, a skeletal reservoir for calcium/phosphate/magnesium, hepatic albumin and globulin replacement, endogenous acid production, dietary intake, residual renal function, stool and insensible losses, and osmotic thirst.
Literature calibration
Every constant checked against a published measurement, and the ones that are not measured are labelled as such.
The model carries an automated audit that compares each physical constant against its published range and fails the build if one drifts outside without a recorded justification. The point is not that every number is measured — several genuinely are not — but that the unmeasured ones are named rather than quietly presented as if they were.
| Constant | Model value | Published range | Status | Source |
|---|---|---|---|---|
| MTAC urea | 20.000 mL/min | 15.9-30.0 | verified | Selgas 2005: 22.9 +/- 7.04 mL/min |
| MTAC glucose | 12.000 mL/min | 10.0-17.0 | verified | Douma 1995 (nitrate, 180 Da proxy): 11.5 (10.0-17.0) |
| MTAC sodium | 4.500 mL/min | 3.5-6.0 | verified | Oberg & Rippe 2017 (PMC5733752 T1), human: PS for Na+ and anions = 4.5 mL/min (DIRECT) |
| MTAC potassium | 10.000 mL/min | 5.0-15.0 | inferred | INFERRED from the small-monovalent-ion argument — NO measured source exists for potassium |
| lymphatic absorption | 1.070 mL/min | 1.0-1.35 | verified | Imholz 1993 1.07+/-0.18; Monquil 1995 1.01-1.34; Rippe 2001 ~1 |
| reflection sigma glucose | 0.049 | — | not verified | cited to Rippe 2004 in physics_core.py:20 |
| reflection sigma Na | 0.05 | — | not verified | cited to Rippe 2004 |
| reflection sigma albumin | 0.84 | — | not verified | cited to Rippe 2004 |
| sieving Na (convective) | 0.550 - | 0.39-0.71 | verified | derived from Bernardo 2012 FWT 0.45+/-0.16 -> Na sieving 1-FWT = 0.39-0.71 (centre 0.55); Helman 2024 PMC10914194 independently puts free-water transport at a fixed 40-50%% of UF and adopts 50%%, implying 0.50-0.60 — the two agree on ~0.55 |
| cp_beta_ref | 1 | — | not verified | SEARCHED AND NOT FOUND 2026-07-19 — do not repeat these dead ends: PubMed returns a CFD paper that explicitly AVOIDS film theory, and two targeted PubMed queries returned ZERO results (it is a chemical-engineering topic, barely indexed in a biomedical database); MDPI and pubs.acs.org both 403; lenntech and DuPont design-manual URLs 404. The right sources are J. Membrane Science or a manufacturer design manual, neither reachable from the allowed domains. DOES NOT BLOCK ANY DECISION: exp_polarization.py sweeps 1.0-1.4 and the conclusion (2 passes fails, 3 passes holds) is IDENTICAL at every point in that range. |
| Kf | 0.08 mL/min/mmHg | — | not verified | human LpS not located in the 2026-07-18 fetch (the hit was Zakaria & Rippe 1993, a RAT study). Open item — do not cite a human source for this until one is actually read. |
| R*T (van't Hoff) | 19.342 mmHg/(mmol/L) | 19.2-19.5 | verified | R=62.3637 L.mmHg/(mol.K) x T=310.15 K / 1000 — arithmetic, not empirical |
| net endogenous acid | 0.800 mmol/kg/d | 0.7-1.0 | verified | Remer & Manz 1995 PMID 7797810 and Frassetto 1998 PMID 9734733 give 0.7-1.0 mEq/kg/d on a Western diet; dialysis cohorts measure 42.7 +/- 10.1 (HD) and 58.2 +/- 24.3 (CKD) mEq/d (PMID 26508542). 0.80 mmol/kg/d gives 56 mEq/d at 70 kg. |
Results — PD20, ten patients, thirty days
A deliberately varied cohort: typical, high and low transporters, anuric, small and large body size, high-MTAC, and diabetic.
Each patient is simulated minute by minute for 30 days with dietary intake, residual renal function where present, osmotic thirst, endogenous acid production and stool losses all active. The figures below are the pinned published outcomes — an automated test re-runs the whole cohort and fails if any of them moves.
| Patient | Na mmol/L | K mmol/L | HCO₃ mmol/L |
BUN mg/dL | Glucose mmol/L | Cum. UF L/30d |
Glucose abs. g/day | Net Na mmol/day |
|---|---|---|---|---|---|---|---|---|
| P1_typical_M70 | 142.9 | 4.79 | 25.8 | 20 | 6.0 | +42.7 | 191 | +4 |
| P2_high_transporter | 142.5 | 4.67 | 26.5 | 18 | 6.3 | +47.1 | 268 | +4 |
| P3_low_transporter | 143.3 | 4.91 | 24.2 | 26 | 5.7 | +42.7 | 131 | +5 |
| P4_anuric | 142.9 | 5.03 | 25.6 | 23 | 6.1 | +59.4 | 212 | +4 |
| P5_smaller_F50 | 143.5 | 4.83 | 27.1 | 15 | 6.5 | +32.6 | 177 | +3 |
| P6_large_M90 | 142.8 | 4.77 | 24.4 | 27 | 5.8 | +56.4 | 208 | +5 |
| P7_small_M55 | 143.1 | 4.83 | 26.7 | 16 | 6.1 | +28.2 | 165 | +4 |
| P8_anuric_small_F45 | 143.9 | 5.17 | 26.9 | 17 | 6.5 | +43.8 | 159 | +3 |
| P9_HighMTAC_F60 | 142.6 | 4.82 | 27.5 | 14 | 7.2 | +46.0 | 307 | +3 |
| P10_diabetic_M80 | 140.9 | 5.01 | 24.7 | 26 | 10.6 | +71.3 | 203 | +4 |
Body water is held to within a fraction of a litre over the month in every patient, with no restriction placed on what they drink — the cohort drinks 1.9–2.6 L/day, thirst-driven.
Contemporary peritoneal dialysis, same ten patients
The comparator arm: a conventional night cycler, five 2-litre exchanges over nine hours, dry day, filling and draining through the bottom lumen as a real catheter does.
The same ten patients are run on conventional automated peritoneal dialysis, each on the bag strength that suits them best (1.5%, 2.5% or 4.25% dextrose), at three different drinking behaviours. A prescription counts as held only if body water stays within ±1.5 L over 30 days — dehydration counts as failure exactly as overload does.
| Drinking behaviour | Intake | Held | Died |
|---|---|---|---|
| free | thirst-driven | 3/10 | 0/10 |
| moderate | 1.5 L/day | 1/10 | 6/10 |
| low | 1.0 L/day | 0/10 | 10/10 |
Fluid restriction does not fail gently — it kills by hypernatraemia
This is the result that most deserves attention, and it is not the one we expected. At a restricted intake of 1.0 L/day, every patient dies, and none of them dies of dehydration. Body water at death spans −3.5 to +1.0 L, nowhere near the fatal volume threshold. They die of serum sodium reaching 165 mmol/L.
| Patient | Bag | UF L/day | Δ body water L | Outcome |
|---|---|---|---|---|
| P1_typical_M70 | 2.5% | -0.07 | -2.35 | DIED d8.3 FATAL high Sodium=165.0 (>165) |
| P2_high_transporter | 2.5% | -0.23 | 0.35 | DIED d11.7 FATAL high Sodium=165.0 (>165) |
| P3_low_transporter | 2.5% | 0.07 | -3.49 | DIED d6.7 FATAL high Sodium=165.0 (>165) |
| P4_anuric | 2.5% | 0.06 | 1.04 | DIED d11.2 FATAL high Sodium=165.0 (>165) |
| P5_smaller_F50 | 2.5% | -0.08 | -1.24 | DIED d7.3 FATAL high Sodium=165.0 (>165) |
| P6_large_M90 | 2.5% | -0.04 | -1.89 | DIED d9.0 FATAL high Sodium=165.0 (>165) |
| P7_small_M55 | 2.5% | -0.16 | -2.86 | DIED d7.2 FATAL high Sodium=165.0 (>165) |
| P8_anuric_small_F45 | 2.5% | 0.13 | 0.18 | DIED d8.2 FATAL high Sodium=165.0 (>165) |
| P9_HighMTAC_F60 | 4.25% | 0.82 | -4.25 | DIED d6.3 FATAL high Sodium=165.0 (>165) |
| P10_diabetic_M80 | 2.5% | 0.06 | 1.03 | DIED d11.3 FATAL high Sodium=165.0 (>165) |
The mechanism is visible in the ultrafiltration column. Restricting intake collapses ultrafiltration to zero or below, against 0.72–2.09 L/day when the same patients drink freely. Conventional peritoneal dialysis removes sodium principally by convection — solvent drag with the ultrafiltrate — so when ultrafiltration stops, sodium removal stops with it, whatever the dialysate sodium concentration is. Sodium then accumulates while body water stays normal.
And the process is self-reinforcing: less body water raises serum osmolality, which shrinks the dialysate-to-serum osmotic gradient, which further reduces ultrafiltration, which removes still less sodium. That spiral is what turns six deaths at 1.5 L/day into ten at 1.0 L/day.
Validation — does it behave like the patients we know?
Forty arms: five levels of renal function × two potassium diets × two fluid-compliance behaviours × two phosphate-management behaviours.
A simulator that reproduces its own assumptions proves nothing. The test that matters is whether it reproduces the behaviour of patients whose direction of travel is already known clinically. Each expectation below is asserted in code, and the run exits with an error if the engine contradicts it.
| Verdict | Clinical expectation | Measured |
|---|---|---|
| OK | BUN rises as renal function falls | normal -> anuric: 30 < 61 < 70 < 73 < 75 mg/dL |
| OK | serum K rises with dietary K (anuric) | delta +1.21 mmol/L |
| OK | that rise is STEEPEST when anuric | anuric +1.21 vs normal +0.93 mmol/L — residual renal secretion is the missing buffer |
| OK | fluid non-compliance gains water (anuric) | delta +5.87 L |
| OK | and it hurts the anuric patient more | anuric +5.87 L vs normal +0.90 L |
| OK | serum phosphate rises with intake | delta +1.05 mmol/L |
The phosphate expectation is worth singling out: conventional peritoneal dialysis must fail to control phosphate in a non-compliant anuric patient, because that is precisely why phosphate binders exist. The engine reproduces that failure, which is also what settles an open question about the phosphate transport coefficient — a higher published value would have controlled phosphate without binders, and would therefore have been wrong.
Reproduce every number on this page
The simulator is deterministic. Same inputs, same outputs, bit for bit.
Environment
# Python 3.11+, numpy. Single-threaded execution is required for bit-reproducibility.
export OMP_NUM_THREADS=1 OPENBLAS_NUM_THREADS=1 MKL_NUM_THREADS=1 PARALLEL=1
The full verification sequence, in order
# 1. The automated test suite — 37 enforcing tests covering conservation, every flux law,
# the literature calibration, device blindness, and the pinned published results.
bash run_testsuite.sh
# 2. Regenerate the controller from the physics (deterministic given unchanged physics).
python3 pretrain_robust.py
# 3. Re-run the ten-patient cohort and regenerate the per-patient report data.
python3 run_cohort.py
python3 gen_report_data.py
# 4. Confirm every published number still reproduces.
python3 test_published_regression.py
# 5. The contemporary-PD comparator arm.
python3 exp_conventional_apd.py
# 6. The forty-arm clinical validation matrix.
python3 exp_validation_matrix.py
Verification state of this build
| Test suite | 37 passed, 0 failed |
|---|---|
| Cohort | 10 of 10 patients survive 30 days; conservation residual ~10-8 |
| Controller build | md5 a730b25bef2234c2ae2026a44ca6fde5 |
| Solute species | 14 |
| Peritoneal Kf | 8.00e-05 L/min/mmHg per unit area |
| Total peritoneal absorption | 0.00107 L/min |
The controller build hash is stamped because the trained controller is a function of the physics: if a physical constant changes, retraining produces a different controller and every downstream number moves. Quoting a result without the hash of the controller that produced it is not reproducible.
What is withheld, and what is not
Stated plainly so that nobody has to guess where the line is.
Fully disclosed
- The complete physics model — every flux law, every constant, every citation, and every limitation, as set out above.
- All simulation results, for both the device and the contemporary comparator, including the results that are unflattering.
- The full reproduction sequence, so a third party can rebuild every figure independently.
- The device's operating principle: continuous-flow circulation with reverse-osmosis regeneration of spent dialysate.
- The control interface — what the device is permitted to sense (bulk physical properties of the circulating fluid, and patient weight) and what it commands. This is disclosed because it is what makes the results reproducible and because the concentration-blind constraint is itself part of the claimed invention.
Withheld as pending patent matter
- The control algorithm's internal structure, its gains and set-points, and the procedure used to build it from the physics.
This boundary is enforced mechanically, not by good intentions: an automated firewall scans every outward-facing artifact — including this page — for the withheld identifiers, for the numeric set-points, and for descriptions of the control logic written in plain English that a token scan would miss. The build fails if any of them appear.