---
title: "Original Source Code (V1)"
author: "Bill Denney"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Original Source Code (V1)}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
```

Below is the original Visual Basic source code for the V1 class-based EQUIL-2
module (`clsEquil2`), the basis of the `equil2_v1()` function in this
package.  It is included to allow users to inspect the fidelity of the code
translation.

This program is intended for research use, only.  The code within is
translated from Visual Basic code based on Werness, et al 1985 to R.  The
Visual Basic code was kindly provided by Dr. John Lieske of the Mayo Clinic
and shared on the equil2 issue tracker by Lea Lerose
([issue #2](https://github.com/billdenney/equil2/issues/2)).

# Reference

Werness PG, Brown CM, Smith LH, Finlayson B. Equil2: A Basic Computer Program
for the Calculation of Urinary Saturation. Journal of Urology.
1985;134(6):1242-1244. doi:10.1016/S0022-5347(17)47703-2

# How V1 differs from V5

The V5 form-based BASIC source (in `vignette("original-source")`) is a
stripped-down version of V1.  V1 adds several pathways that V5 omits:

- **CO2 / bicarbonate / carbonate** chemistry (H2CO3, HCO3, CO3, plus the
  Na2CO3 / CaCO3 / MgCO3 complexes).
- **TRIS buffer** (HTRIS).
- **Pyrophosphate (PP)** speciation — though, see the caveat below.
- **Struvite (MgNH4PO4)** included in the Mg and NH4 mass balances (V5
  computes struvite SS but does not feed it back into the balances).
- **Sodium-urate, ammonium-urate, and potassium-urate** complexes included
  in the Na/NH4/K mass balances (V5 reports their SS but does not couple
  them back into the cation balance).
- **Chloride auto-fill** via electroneutrality when no chloride is supplied
  (V5 requires a chloride input).
- **Inputs in mmol per collection volume** (V1) vs **mg/dL** (V5).  V1's
  approach is unit-unambiguous and does not need per-species atomic-weight
  conversion factors — see issue #2 for why this matters.

V1 and V5 share the same stability constants for the core CaOx / Brushite /
HAP / Uric Acid / Sodium-urate / Ammonium-urate pathways.  The constants that
differ are concentrated in the CO2 / PP / HU pathways that V5 doesn't use
anyway (e.g. P7 for CO2 dissociation is 0.00229 in V1 vs 0.00123 in V5; the
HU formation constant is `7.943e10` in V1 vs `2.78e5` in V5).

V1 reports **activity products** (`APCaOx`, `APBr`, `APStru`, `APUA`,
`APNaU`) and **relative saturation ratios** (RSR = AP / Ksp) for **Calcium
Oxalate, Brushite, Struvite, and Uric Acid** only.  V5 additionally reports
SS values for **Hydroxyapatite, Sodium Urate, and Ammonium Urate**, plus a
negative ΔGibbs energy for each.  For those V5-only outputs use the
`equil2()` function.

V1's iteration loop is capped at **500** iterations (vs 50 in V5) and raises
a warning on non-convergence.

# Quirks preserved by the R port

Three quirks of the V1 source are preserved verbatim in `equil2_v1()` for
fidelity:

1. **Pyrophosphate is disabled.**  After reading the input, V1
   unconditionally sets `TPP = 0` and `PP = 0`, which short-circuits the
   entire pyrophosphate pathway.  The R port keeps this; users who want PP
   chemistry can edit the two `TPP <- 0` / `PP_var <- 0` lines in
   `R/equil2_v1.R`.
2. **`NH4PO4` is uninitialized.**  V1 declares `Dim NH4PO4 As Double` but
   never assigns it, so it is always zero (VBA default).  In the R port we
   make this explicit with `NH4PO4 <- 0`.
3. **Urate-cation complexes (`NaU`, `KU`, `NH4U`) are not in the cation
   mass balance.**  V1 computes them and uses them for ionic strength and
   for the chloride electroneutrality auto-fill, but `STNa` / `STK` /
   `STNH4` do *not* include them.  Effectively V1 treats them as trace
   species that don't deplete free Na, K, or NH4.  The R port matches
   this.

# Numerical verification against the V1 VBA module

The R port has been cross-validated against the original VBA module by
running `clsEquil2.bas` in LibreOffice 26.2.4 with `Option VBASupport 1`
and `Option ClassModule`, using LibreOffice's Python UNO bridge to drive
the Calc method.  On the LabCorp inputs in the package examples, ionic
strength agrees to <1 ppm and the four reported activity products /
relative saturation ratios agree to ~10 ppm.  The residual differences
are floating-point reordering noise from how mass-balance sums are
grouped in R vs the original BASIC.

# EQUIL-2 V1 source

The code below is the basis of the `equil2_v1()` function.

```{r v1-source, echo=FALSE, results='asis'}
src_path <- system.file("clsEquil2.bas.txt", package = "equil2")
if (!nzchar(src_path)) {
  # Fall back to the inst/ source if not yet installed
  # (e.g. devtools::build_vignettes() before install).
  src_path <- file.path("..", "inst", "clsEquil2.bas.txt")
}
cat("```vb\n")
cat(readLines(src_path), sep = "\n")
cat("\n```\n")
```
