demo/yttrium.R

# CHNOSZ/demo/yttrium.R
# Make diagrams similar to Figure 11 of Guan et al. (2020)
# https://doi.org/10.1016/j.gca.2020.04.015
# 20221122 jmd version 1

library(CHNOSZ)

# Function to add Y(III)-Cl species using logB values from Table 9 of Guan et al. (2020)
add.Y.species <- function(P, plot.it = FALSE) {
  # Temperature
  T <- c(25, seq(50, 500, 50))
  if(P == 800) {
    logB <- list(
      c(1.04, 0.48, 0.13, 0.43, 1.12, 2.06, 3.21, 4.58, 6.26, 8.39, 11.14),
      c(-9.14, -7.34, -4.14, -1.37, 1.12, 3.46, 5.78, 8.24, 11.05, 14.48, 18.77),
      c(-14, -11.48, -7.06, -3.25, 0.14, 3.32, 6.45, 9.74, 13.47, 18.01, 23.65),
      c(-15.94, -13.2, -8.39, -4.27, -0.61, 2.79, 6.15, 9.67, 13.63, 18.45, 24.41)
    )
  } else if(P == 1000) {
    logB <- list(
      c(1.13, 0.54, 0.16, 0.43, 1.09, 2, 3.1, 4.39, 5.9, 7.69, 9.85),
      c(-9.33, -7.51, -4.3, -1.55, 0.9, 3.18, 5.4, 7.68, 10.15, 12.94, 16.16),
      c(-14.24, -11.71, -7.27, -3.49, -0.14, 2.95, 5.95, 9.01, 12.3, 16, 20.25),
      c(-16.19, -13.43, -8.62, -4.52, -0.91, 2.41, 5.62, 8.89, 12.4, 16.33, 20.84)
    )
  } else stop("logB values for P =", P, "are not available here")
  # Define species and coefficients in formation reactions
  species <- list(
    c("Y+3", "Cl-", "YCl+2"),
    c("Y+3", "Cl-", "YCl2+"),
    c("Y+3", "Cl-", "YCl3"),
    c("Y+3", "Cl-", "YCl4-")
  )
  coeffs <- list(
    c(-1, -1, 1),
    c(-1, -2, 1),
    c(-1, -3, 1),
    c(-1, -4, 1)
  )
  # Fit the formation constants to thermodynamic parameters and add them to OBIGT
  for(i in 1:4) logB.to.OBIGT(logB[[i]], species[[i]], coeffs[[i]], T = T, P = P, tolerance = 0.6, npar = 5)
  # Plot the given and fitted values
  if(plot.it) {
    par(mfrow = c(2, 2))
    for(i in 1:4) {
      sres <- subcrt(species[[i]], coeffs[[i]], T = T, P = P)
      plot(T, sres$out$logK, type = "l", xlab = axis.label("T"), ylab = axis.label("logK"))
      points(T, logB[[i]], pch = 19)
      title(describe.reaction(sres$reaction))
      if(i == 1) legend("topleft", c("Guan et al. (2020)", "logB.to.OBIGT()"), pch = c(19, NA), lty = c(NA, 1))
      legend("bottomright", paste(P, "bar"), bty = "n")
    }
  }
}

# Function to plot distribution of Y(III) chloride species at T and P
Y_Cl <- function() {

  # Define total molality of NaCl
  # Start at 0.1 because we can't use 0 in the logarithmic value needed for affinity()
  mNaCl <- seq(0.1, 4.9, 0.2)

  # Define T, P, and pH values
  Ts <- c(200, 350, 500)
  Ps <- c(800, 800, 1000)
  pHs <- c(3, 0.3)

  # Setup plot
  par(mfrow = c(3, 2))
  par(cex = 0.9)

  # Loop over T and P
  for(i in 1:3) {
    T <- Ts[i]
    P <- Ps[i]

    # Add new species
    add.Y.species(P)
    # Setup chemical system
    basis(c("Y+3", "Cl-", "e-"))
    species(c("Y+3", "YCl+2", "YCl2+", "YCl3", "YCl4-"))

    # Loop over pH
    for(j in 1:2) {
      pH <- pHs[j]

      # Calculate molality of Cl- and ionic strength
      NaCl_props <- suppressMessages(lapply(mNaCl, NaCl, T = T, P = P, pH = pH))
      # Turn the list into a data frame
      NaCl_props <- do.call(rbind, lapply(NaCl_props, as.data.frame))
      # Calculate affinity of formation reactions
      a <- affinity("Cl-" = log10(NaCl_props$m_Cl), IS = NaCl_props$IS, T = T, P = P)
      # Calculate species distribution for total Y(III) equal to 0.01 m
      m_Y <- 0.01
      e <- equilibrate(a, loga.balance = log10(m_Y))
      # Make x-axis show total m(NaCl) instead of logm(Cl-) 20221208
      e$vals[[1]] <- mNaCl
      # Set colors similar to Guan et al. (2020)
      col <- 2:6
      # Only label lines above 1/20 = 0.05 mol fraction
      mol <- 10^do.call(cbind, lapply(e$loga.equil, as.data.frame))
      molfrac <- mol / rowSums(mol)
      ilab <- apply(molfrac > 0.05, 2, any)
      names <- e$species$name
      names[!ilab] <- ""
      d <- diagram(e, alpha = TRUE, xlim = c(0, 5), ylim = c(0, 1),
        xlab = expr.species("NaCl", molality = TRUE), ylab = "Fraction of Y-Cl species",
        names = names, col = col, lty = 1, lwd = 2, mar = c(3, 3.5, 2.5, 3.5))
      # Calculate and plot coordination number
      CN <- 1 * d$plotvals[[2]] + 2 * d$plotvals[[3]] + 3 * d$plotvals[[4]] + 4 * d$plotvals[[5]]
      # Rescale to y-axis limits [0, 1]
      CN_scaled <- CN / 4
      lines(mNaCl, CN_scaled, lty = 3, lwd = 3, col = "darkorange")
      # Add ticks for CN
      axis(4, seq(0, 1, 0.25), labels = 0:4, lwd.ticks = 2, tcl = -0.5, mgp = c(1.7, 0.8, 0))
      mtext("Cl coordination number", 4, 1.7, las = 0, cex = par("cex"))
      # Make title
      lab <- lTP(T, P)
      lab[[4]] <- bquote(pH == .(pH))
      title(lab, cex.main = 1)

    }

    if(i==1) mtext("After Guan et al. (2020)", line = 0.8, adj = -2.7, cex = 0.9, font = 2)
  }
}

# Use non-default ion size parameters 20230309
Bdot_acirc <- thermo()$Bdot_acirc
# Cl- and Y+3 override the defaults, and YCl+2 is a new species
Bdot_acirc <- c("Cl-" = 4, "Y+3" = 5, "YCl+2" = 4, "YCl2+" = 4, "YCl3" = 4, "YCl4-" = 4, Bdot_acirc)
thermo("Bdot_acirc" = Bdot_acirc)

# Run the functions to make plots for the demo
opar <- par(no.readonly = TRUE)
add.Y.species(800, plot.it = TRUE)
add.Y.species(1000, plot.it = TRUE)
Y_Cl()

# Restore plot settings and CHNOSZ settings
par(opar)
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.