demo/Pourbaix.R

# CHNOSZ/demo/Pourbaix.R
# Eh-pH diagram for Fe-O-H with equisolubility lines
# After Pourbaix (1974, p. 312)
# 20210301 jmd first version

library(CHNOSZ)
# Load OBIGT database without organic species
# (speeds up and reduces memory needed for C diagram)
OBIGT(no.organics = TRUE)

### PARAMETERS (to be changed by the user) ###

# Choose an element
# Some mostly working ones: Fe, Cu, Au, Rh, Mn, C
# Incomplete: Al (no native metal), Ni, ...
# Not working: Cr, ...
#  (Cr has no solids in OBIGT)
element <- "Fe"

# Set temperature and pressure
T <- 25
# Can use "Psat" for T >= 100 degC
P <- 1
# Ionic strength (mol/kg)
IS <- 0

# Set plot limits and resolution
pH <- c(-2, 16)
Eh <- c(-2, 2)
res <- 700

# Assign levels for equisolubility lines
levels <- seq(-6, 0, 2)

# Switches for using colors
color.fields <- TRUE
color.water <- TRUE
color.lines <- TRUE
color.names <- TRUE

# Names of aqueous species to move down
# (to avoid conflict with water lines or mineral names)
namesdown <- c("MnOH+", "MnO", "Cu+2", "CuO")
# Names of aqueous species to move down even more
namesdown2 <- c("Fe+3", "FeOH+2", "FeO+", "HFeO2", "FeO2-",
"HMnO2-", "MnO2-2")

### SCRIPT (can also be changed by the user if wanted!) ###

# Find a species with this element
# (to be used as a basis species)
elem_basis <- element
if(is.na(suppressMessages(info(elem_basis)))) {
  elem_basis <- paste0(element, "+")
  if(is.na(suppressMessages(info(elem_basis)))) {
    elem_basis <- paste0(element, "+2")
    if(is.na(suppressMessages(info(elem_basis)))) {
      elem_basis <- paste0(element, "+3")
    }
  }
}

# Define system
basis(c(elem_basis, "H2O", "H+", "e-"))

# Find species
icr <- retrieve(element, c("O", "H"), "cr", T = T, P = P)
iaq <- retrieve(element, c("O", "H"), "aq", T = T, P = P)

# Add solids with unit activity
species(icr, 0)
# Add aqueous species with activity for first equisolubility line
species(iaq, levels[1], add = TRUE)

# Calculate affinities of formation of species
# from basis species as a function of Eh and pH
a_all <- affinity(pH = c(pH, res), Eh = c(Eh, res), T = T, P = P, IS = IS)

# Plot diagram (LAYER 1: colors for all fields)
limit.water <- fill <- NULL
if(!color.water) limit.water <- FALSE
if(!color.fields) fill <- NA
d_all <- diagram(a_all, names = FALSE, lty = 0, min.area = 0.1, limit.water = limit.water, fill = fill)

# Calculate affinities for minerals
species(icr)
# Calculate overall solubility (i.e. minimum solubility given all candidate minerals)
s <- solubility(iaq, pH = c(pH, res), Eh = c(Eh, res), T = T, P = P, IS = IS, in.terms.of = element)

# Plot diagram (LAYER 2: equisolubility lines)
diagram(s, levels = levels, contour.method = "flattest", add = TRUE, lwd = 1.5)

# Calculate affinities for aqueous species
# FIXME: should be able to remove cr species from previous affinity object
species(iaq, 0)
a_aq <- affinity(pH = c(pH, res), Eh = c(Eh, res), T = T, P = P, IS = IS)

# Plot diagram (LAYER 3: equal-activity lines for aqueous species)
col <- ifelse(color.lines, 4, 1)
# Use a white background to improve contrast
# (so the line remains visible if it coincides with an equisolubility contour)
diagram(a_aq, add = TRUE, col = "white", lwd = 1.3, names = FALSE)

# Plot diagram (LAYER 4: labels for aqueous species fields)
# Apply y offset for specified names
dy <- rep(0, nrow(a_aq$species))
dy[a_aq$species$name %in% namesdown] <- -0.3
dy[a_aq$species$name %in% namesdown2] <- -0.5
# Use a white background for names
rx <- diff(par("usr")[1:2])
for(ddx in c(-rx/700, rx/700))
  diagram(a_aq, add = TRUE, lty = 2, lwd = 0.6, col = col, dx = ddx, dy = dy, col.names = "white", bold = TRUE)
ry <- diff(par("usr")[3:4])
for(ddy in c(-ry/700, ry/700))
  diagram(a_aq, add = TRUE, lty = 2, lwd = 0.6, col = col, dy = dy + ddy, col.names = "white", bold = TRUE)
col.names <- ifelse(color.names, 4, 1)
diagram(a_aq, add = TRUE, lty = 0, col = col, dy = dy, col.names = col.names)

# Add solids with unit activity
species(icr, 0)
# Add aqueous species with activity for last equisolubility line
# (i.e. unit activity)
species(iaq, levels[length(levels)], add = TRUE)

# Calculate affinities of formation of species
# from basis species as a function of Eh and pH
a_all_0 <- affinity(pH = c(pH, res), Eh = c(Eh, res), T = T, P = P, IS = IS)

# Plot diagram (LAYER 5: mineral stability boundaries and water lines)
d_all_0 <- diagram(a_all_0, fill = NA, names = FALSE, lty = 0, lty.cr = 1, lwd = 3, add = TRUE)
water.lines(d_all_0, lty = 5, lwd = 1.3)

# Plot diagram (LAYER 6: large bold labels for all mineral fields)
# (this is the last layer, so names are above equal-activity lines,
# but we use positions calculated with the first equisolubility line
# so that names are within the shrunken parts of the mineral fields)
# Create labels using chemical formulas instead of name of minerals
formulas <- info(a_all$species$ispecies, check.it = FALSE)$formula
formulas[a_all$species$state == "aq"] <- ""
diagram(a_all, fill = NA, names = formulas, bold = TRUE, cex.names = 1.2, lty = 0, add = TRUE)

# Add title
Texpr <- lT(T)
Pexpr <- lP(P)
main <- bquote(.(element)*"-O-H at "*.(Texpr)*" and "*.(Pexpr))
title(main = main)

# Reset OBIGT database to run other demos
reset()

Try the CHNOSZ package in your browser

Any scripts or data that you put into this service are public.

CHNOSZ documentation built on March 31, 2023, 7:54 p.m.