From noreply at r-forge.r-project.org Sat May 4 13:38:52 2019 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Sat, 4 May 2019 13:38:52 +0200 (CEST) Subject: [CHNOSZ-commits] r456 - in pkg/CHNOSZ: . R inst man tests/testthat Message-ID: <20190504113852.D1F2418487A@r-forge.r-project.org> Author: jedick Date: 2019-05-04 13:38:52 +0200 (Sat, 04 May 2019) New Revision: 456 Modified: pkg/CHNOSZ/DESCRIPTION pkg/CHNOSZ/R/mosaic.R pkg/CHNOSZ/inst/NEWS pkg/CHNOSZ/man/mosaic.Rd pkg/CHNOSZ/tests/testthat/test-mosaic.R Log: mosaic(): equilibrate using specified total activity; return e.out Modified: pkg/CHNOSZ/DESCRIPTION =================================================================== --- pkg/CHNOSZ/DESCRIPTION 2019-04-28 08:31:52 UTC (rev 455) +++ pkg/CHNOSZ/DESCRIPTION 2019-05-04 11:38:52 UTC (rev 456) @@ -1,6 +1,6 @@ -Date: 2019-04-28 +Date: 2019-05-04 Package: CHNOSZ -Version: 1.3.2-3 +Version: 1.3.2-4 Title: Thermodynamic Calculations and Diagrams for Geochemistry Authors at R: c( person("Jeffrey", "Dick", , "j3ffdick at gmail.com", role = c("aut", "cre"), Modified: pkg/CHNOSZ/R/mosaic.R =================================================================== --- pkg/CHNOSZ/R/mosaic.R 2019-04-28 08:31:52 UTC (rev 455) +++ pkg/CHNOSZ/R/mosaic.R 2019-05-04 11:38:52 UTC (rev 456) @@ -75,7 +75,12 @@ for(i in 1:length(bases)) { message("mosaic: calculating affinities of basis species group ", i, ": ", paste(bases[[i]], collapse=" ")) species(delete = TRUE) - species(bases[[i]]) + # 20190504: when equilibrating the changing basis species, use a total activity equal to the activity from the basis definition + act.total <- 10^basis0$logact[ibasis0[i]] + # for now, assume that the changing basis species react with a 1:1 stoichiometry + # TODO: retrieve the actual balancing coefficients + logact.each <- log10(act.total / length(bases[[i]])) + species(bases[[i]], logact.each) A.bases[[i]] <- suppressMessages(affinity(..., sout = sout)) } @@ -98,6 +103,7 @@ # calculate equilibrium mole fractions for each group of basis species group.fraction <- list() if(blend) { + e.out <- list() for(i in 1:length(A.bases)) { # this isn't needed (and doesn't work) if all the affinities are NA 20180925 if(any(!sapply(A.bases[[1]]$values, is.na))) { @@ -106,6 +112,8 @@ a.equil <- lapply(e$loga.equil, function(x) 10^x) a.tot <- Reduce("+", a.equil) group.fraction[[i]] <- lapply(a.equil, function(x) x / a.tot) + # include the equilibrium activities in the output of this function 20190504 + e.out[[1]] <- e } else { group.fraction[[i]] <- A.bases[[i]]$values } @@ -156,5 +164,6 @@ # for argument recall, include all arguments in output 20190120 allargs <- c(list(bases = bases, blend = blend, mixing = mixing), list(...)) # return the affinities for the species and basis species - return(list(fun = "mosaic", args = allargs, A.species = A.species, A.bases = A.bases)) + if(blend) return(list(fun = "mosaic", args = allargs, A.species = A.species, A.bases = A.bases, e.out = e.out)) + else return(list(fun = "mosaic", args = allargs, A.species = A.species, A.bases = A.bases)) } Modified: pkg/CHNOSZ/inst/NEWS =================================================================== --- pkg/CHNOSZ/inst/NEWS 2019-04-28 08:31:52 UTC (rev 455) +++ pkg/CHNOSZ/inst/NEWS 2019-05-04 11:38:52 UTC (rev 456) @@ -1,9 +1,14 @@ -CHANGES IN CHNOSZ 1.3.2-3 (2019-04-28) +CHANGES IN CHNOSZ 1.3.2-4 (2019-05-04) -------------------------------------- - demo/aluminum.R: add calculations using Si(OH)4 from Akinfiev-Diamond model (SiO2 in these reactions is replaced by Si(OH)4 - 2 H2O). +- In mosaic(), equilibrate groups of changing basis species using total + activity taken from the corresponding basis species in the incoming + basis() definition, and return the result of equilibrate() in the + output. + CHANGES IN CHNOSZ 1.3.2 (2019-04-20) ------------------------------------ Modified: pkg/CHNOSZ/man/mosaic.Rd =================================================================== --- pkg/CHNOSZ/man/mosaic.Rd 2019-04-28 08:31:52 UTC (rev 455) +++ pkg/CHNOSZ/man/mosaic.Rd 2019-05-04 11:38:52 UTC (rev 456) @@ -20,7 +20,7 @@ \details{ -\code{mosaic} can be used to calculate the affinities of formation of species when the relative abundances of basis species listed in \code{bases} changes over the range of conditions, due to e.g. ionization, complexation or redox reactions. +\code{mosaic} can be used to calculate the affinities of formation of species when the relative abundances of the basis species listed in \code{bases} change over the range of conditions, due to e.g. ionization, complexation or redox reactions. This is a way to \dQuote{speciate the basis species}. For example, the speciation of sulfur (\samp{SO4-2}, \samp{HSO4-}, \samp{HS-} and \samp{H2S}) as a function of Eh and pH affects the formation affinities, and therefore relative stabilities of iron oxide and sulfide minerals. Chemical activity diagrams constructed by assembling sub-diagrams corresponding to the predominant basis species can described as \dQuote{mosaic diagrams}. @@ -28,10 +28,11 @@ The function calculates the affinities using all combination of basis species given as vector arguments to \code{bases} and \code{bases2}. The first species listed in each group should be in the current basis definition, and all the basis species in each group should be related to the first basis species there (i.e. all share the same element). A second, independent set of basis species can be provided in \code{bases2} (for example \samp{CO3-2}, \samp{HCO3-}, \samp{CO2}, if the first set of basis species are the sulfur-bearing ones listed above). -The arguments in \code{...} are passed to \code{affinity} to specify the conditions. +The arguments in \code{...} are passed to \code{affinity} to specify the variable conditions, such as temperature, pressure, and activities of other basis species. -If \code{blend} is TRUE (the default), the function combines the affinities of the formation reactions in proportion to the relative abundances of the basis species at each condition. -Additionally, if \code{mixing} is TRUE (the default), a term is included to account for the Gibbs energy of ideal mixing. +If \code{blend} is TRUE (the default), the relative abundances of the basis species in each group are calculated using \code{\link{equilibrate}}, with the total activity taken from the corresponding basis species in the incoming \code{\link{basis}} definition. +Then, the function calculates overall affinities of the formation reactions of each species by combining reactions written using individual basis species in proportion to the relative abundances of the basis species. +Additionally, if \code{mixing} is TRUE (the default), a term is included to account for the Gibbs energy of ideal mixing of the basis species. See the second example in \code{\link{solubility}} for a numerical test of the calculations using \code{blend} and \code{mixing}. If \code{blend} is FALSE, the function returns the affinities calculated using the single predominant basis species in \code{bases} at each condition (in this case, the \code{mixing} argument has no effect). @@ -45,7 +46,8 @@ \value{ A list containing \code{A.species} (affinities of formation of the species with changing basis species) and \code{A.bases} (affinities of formation of the basis species in terms of the first basis species), each having same structure as the list returned by \code{\link{affinity}}. -If \code{bases2} is provided, the list also contains \code{A.bases2} (affinities of formation of the second set of basis species). +If \code{blend} is TRUE, the output also contains \code{e.out} (the output of \code{\link{equilibrate}} for each group of basis species) +If \code{bases2} is provided, the list also contains \code{A.bases2} (affinities of formation of the second group of basis species). } \seealso{ Modified: pkg/CHNOSZ/tests/testthat/test-mosaic.R =================================================================== --- pkg/CHNOSZ/tests/testthat/test-mosaic.R 2019-04-28 08:31:52 UTC (rev 455) +++ pkg/CHNOSZ/tests/testthat/test-mosaic.R 2019-05-04 11:38:52 UTC (rev 456) @@ -23,7 +23,7 @@ test_that("blend=TRUE produces reasonable values", { # a more rigorous test than above. this was failing because loga.tot (actually, a.tot) - # was computed incorrectly, by sum'ing an unlist'ed list (the affinities of basis species) + # was computed incorrectly, by sum()ing an unlist()ed list (the affinities of basis species) # to produce a single value; corrected by using Reduce for addition of vectors/arrays in the list. # example adapted from ?mosaic basis(c("FeO", "SO4-2", "H2O", "H+", "e-")) From noreply at r-forge.r-project.org Sun May 5 04:49:43 2019 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Sun, 5 May 2019 04:49:43 +0200 (CEST) Subject: [CHNOSZ-commits] r457 - in pkg/CHNOSZ: . R inst man tests/testthat Message-ID: <20190505024944.06E82182DA4@r-forge.r-project.org> Author: jedick Date: 2019-05-05 04:49:37 +0200 (Sun, 05 May 2019) New Revision: 457 Modified: pkg/CHNOSZ/DESCRIPTION pkg/CHNOSZ/R/mosaic.R pkg/CHNOSZ/inst/NEWS pkg/CHNOSZ/man/mosaic.Rd pkg/CHNOSZ/tests/testthat/test-mosaic.R Log: mosaic(): bug fix: mole fractions of basis species affect their activities in affinity calculations Modified: pkg/CHNOSZ/DESCRIPTION =================================================================== --- pkg/CHNOSZ/DESCRIPTION 2019-05-04 11:38:52 UTC (rev 456) +++ pkg/CHNOSZ/DESCRIPTION 2019-05-05 02:49:37 UTC (rev 457) @@ -1,6 +1,6 @@ -Date: 2019-05-04 +Date: 2019-05-05 Package: CHNOSZ -Version: 1.3.2-4 +Version: 1.3.2-5 Title: Thermodynamic Calculations and Diagrams for Geochemistry Authors at R: c( person("Jeffrey", "Dick", , "j3ffdick at gmail.com", role = c("aut", "cre"), Modified: pkg/CHNOSZ/R/mosaic.R =================================================================== --- pkg/CHNOSZ/R/mosaic.R 2019-05-04 11:38:52 UTC (rev 456) +++ pkg/CHNOSZ/R/mosaic.R 2019-05-05 02:49:37 UTC (rev 457) @@ -3,6 +3,7 @@ # 20141220 jmd initial version # 20190129 complete rewrite to use any number of groups of changing basis species # and improve speed by pre-calculating subcrt values (sout) +# 20190505 bug fix: adjust affinities of species formation reactions for mole fractions of basis species ## if this file is interactively sourced, the following are also needed to provide unexported functions: #source("basis.R") @@ -10,7 +11,7 @@ #source("util.args.R") # function to calculate affinities with mosaic of basis species -mosaic <- function(bases, bases2 = NULL, blend = TRUE, mixing = TRUE, ...) { +mosaic <- function(bases, bases2 = NULL, blend = TRUE, ...) { # argument recall 20190120 # if the first argument is the result from a previous mosaic() calculation, @@ -41,7 +42,7 @@ hasbases2 <- TRUE } otherargs <- list(...) - allargs <- c(list(bases = bases, blend = blend, mixing = mixing), otherargs) + allargs <- c(list(bases = bases, blend = blend), otherargs) out <- do.call(mosaic, allargs) # replace A.bases (affinity calculations for all groups of basis species) with backwards-compatbile A.bases and A.bases2 if(hasbases2) A.bases2 <- out$A.bases[[2]] @@ -103,7 +104,7 @@ # calculate equilibrium mole fractions for each group of basis species group.fraction <- list() if(blend) { - e.out <- list() + e.bases <- list() for(i in 1:length(A.bases)) { # this isn't needed (and doesn't work) if all the affinities are NA 20180925 if(any(!sapply(A.bases[[1]]$values, is.na))) { @@ -113,7 +114,7 @@ a.tot <- Reduce("+", a.equil) group.fraction[[i]] <- lapply(a.equil, function(x) x / a.tot) # include the equilibrium activities in the output of this function 20190504 - e.out[[1]] <- e + e.bases[[1]] <- e } else { group.fraction[[i]] <- A.bases[[i]]$values } @@ -139,17 +140,28 @@ for(i in 1:length(ispecies)) ind.mat[[i]] <- 1:length(ispecies[[i]]) ind.mat <- as.matrix(expand.grid(ind.mat)) - # calculate mole fractions for each combination of basis species - for(i in 1:nrow(ind.mat)) { - # multiply fractions from each group - for(j in 1:ncol(ind.mat)) { - if(j==1) x <- group.fraction[[j]][[ind.mat[i, j]]] - else x <- x * group.fraction[[j]][[ind.mat[i, j]]] + # loop over combinations of basis species + for(icomb in 1:nrow(ind.mat)) { + # loop over groups of changing basis species + for(igroup in 1:ncol(ind.mat)) { + # get mole fractions for this particular basis species + basisx <- group.fraction[[igroup]][[ind.mat[icomb, igroup]]] + # loop over species + for(jspecies in 1:length(aff.species[[icomb]]$values)) { + # get coefficient of this basis species in the formation reaction for this species + nbasis <- aff.species[[icomb]]$species[jspecies, ibasis0[igroup]] + # adjust affinity of species for mole fractions (i.e. lower activity) of basis species 20190505 + aff.adjust <- nbasis * log10(basisx) + # avoid infinite values (from log10(0)) + isfin <- is.finite(aff.adjust) + aff.species[[icomb]]$values[[jspecies]][isfin] <- aff.species[[icomb]]$values[[jspecies]][isfin] + aff.adjust[isfin] + } + # multiply fractions of basis species from each group to get overall fraction + if(igroup==1) groupx <- basisx + else groupx <- groupx * basisx } # multiply affinities by the mole fractions of basis species - # include mixing term (-x*log10(x)) 20190121 - if(blend & mixing) aff.species[[i]]$values <- lapply(aff.species[[i]]$values, function(values) values * x - x * log10(x)) - else aff.species[[i]]$values <- lapply(aff.species[[i]]$values, function(values) values * x) + aff.species[[icomb]]$values <- lapply(aff.species[[icomb]]$values, function(values) values * groupx) } # get total affinities for the species @@ -162,8 +174,8 @@ } # for argument recall, include all arguments in output 20190120 - allargs <- c(list(bases = bases, blend = blend, mixing = mixing), list(...)) + allargs <- c(list(bases = bases, blend = blend), list(...)) # return the affinities for the species and basis species - if(blend) return(list(fun = "mosaic", args = allargs, A.species = A.species, A.bases = A.bases, e.out = e.out)) + if(blend) return(list(fun = "mosaic", args = allargs, A.species = A.species, A.bases = A.bases, e.bases = e.bases)) else return(list(fun = "mosaic", args = allargs, A.species = A.species, A.bases = A.bases)) } Modified: pkg/CHNOSZ/inst/NEWS =================================================================== --- pkg/CHNOSZ/inst/NEWS 2019-05-04 11:38:52 UTC (rev 456) +++ pkg/CHNOSZ/inst/NEWS 2019-05-05 02:49:37 UTC (rev 457) @@ -1,14 +1,41 @@ -CHANGES IN CHNOSZ 1.3.2-4 (2019-05-04) +CHANGES IN CHNOSZ 1.3.2-5 (2019-05-05) -------------------------------------- -- demo/aluminum.R: add calculations using Si(OH)4 from Akinfiev-Diamond - model (SiO2 in these reactions is replaced by Si(OH)4 - 2 H2O). +BUG FIXES +- In mosaic(), affinities of formation of species should not only be + weighted by the mole fraction of the changing basis species, but they + should be calculated using activities of basis species that are + adjusted (i.e. lowered) according to their mole fractions. Previously, + constant activities were used for each changing basies species, + leading to an artificial inflation of affinities of species, + especially near the transitions where the changing basis species are + nearly equal in abundance. + +- The 'mixing' argument of mosaic() has been removed, as it no longer + provides correct results and is not needed with the improved handling + of activities of basis species. + +OTHER CHANGES + +- Tests have been added to test-mosaic.R to check that activitives + produced by mosaic() - equilibrate() and mosaic() - solubility() + really are equilibrium activities, i.e. that the affinities of + reactions between species are equivalent to zero, especially near the + transitions of basis species. + - In mosaic(), equilibrate groups of changing basis species using total activity taken from the corresponding basis species in the incoming - basis() definition, and return the result of equilibrate() in the - output. + basis() definition. This is not directly related to the bug above, but + provides a means to constrain the amount of an element in the basis + species. +- In mosaic(), include the result of equilibrate() for each group of + basis species in the output ('e.bases'). + +- demo/aluminum.R: add calculations using Si(OH)4 from Akinfiev-Diamond + model (SiO2 in these reactions is replaced by Si(OH)4 - 2 H2O). + CHANGES IN CHNOSZ 1.3.2 (2019-04-20) ------------------------------------ Modified: pkg/CHNOSZ/man/mosaic.Rd =================================================================== --- pkg/CHNOSZ/man/mosaic.Rd 2019-05-04 11:38:52 UTC (rev 456) +++ pkg/CHNOSZ/man/mosaic.Rd 2019-05-05 02:49:37 UTC (rev 457) @@ -7,7 +7,7 @@ } \usage{ - mosaic(bases, bases2 = NULL, blend = TRUE, mixing = TRUE, ...) + mosaic(bases, bases2 = NULL, blend = TRUE, ...) } \arguments{ @@ -14,7 +14,6 @@ \item{bases}{character, basis species to be changed in the calculation, or list, containing vectors for each group of changing basis species} \item{bases2}{character, second set of changing basis species} \item{blend}{logical, use relative abundances of basis species?} - \item{mixing}{logical, include a term for the Gibbs energy of mixing?} \item{...}{additional arguments to be passed to \code{\link{affinity}}} } @@ -32,9 +31,7 @@ If \code{blend} is TRUE (the default), the relative abundances of the basis species in each group are calculated using \code{\link{equilibrate}}, with the total activity taken from the corresponding basis species in the incoming \code{\link{basis}} definition. Then, the function calculates overall affinities of the formation reactions of each species by combining reactions written using individual basis species in proportion to the relative abundances of the basis species. -Additionally, if \code{mixing} is TRUE (the default), a term is included to account for the Gibbs energy of ideal mixing of the basis species. -See the second example in \code{\link{solubility}} for a numerical test of the calculations using \code{blend} and \code{mixing}. -If \code{blend} is FALSE, the function returns the affinities calculated using the single predominant basis species in \code{bases} at each condition (in this case, the \code{mixing} argument has no effect). +If \code{blend} is FALSE, the function returns the affinities calculated using the single predominant basis species in \code{bases} at each condition. A more flexible method of specifying multiple sets of basis species is now available. Instead of using \code{bases} and \code{bases2}, supply a list for just the \code{bases} argument. @@ -46,12 +43,13 @@ \value{ A list containing \code{A.species} (affinities of formation of the species with changing basis species) and \code{A.bases} (affinities of formation of the basis species in terms of the first basis species), each having same structure as the list returned by \code{\link{affinity}}. -If \code{blend} is TRUE, the output also contains \code{e.out} (the output of \code{\link{equilibrate}} for each group of basis species) +If \code{blend} is TRUE, the output also contains \code{e.bases} (the output of \code{\link{equilibrate}} for each group of basis species) If \code{bases2} is provided, the list also contains \code{A.bases2} (affinities of formation of the second group of basis species). } \seealso{ \code{demo("mosaic")}, extending the example below by addition of carbonate species in \code{bases2}, and using thermodynamic data from Garrels and Christ, 1965. +The help page of \code{\link{solubility}} has an example combining \code{mosaic} with solubility calculations. } \examples{ Modified: pkg/CHNOSZ/tests/testthat/test-mosaic.R =================================================================== --- pkg/CHNOSZ/tests/testthat/test-mosaic.R 2019-05-04 11:38:52 UTC (rev 456) +++ pkg/CHNOSZ/tests/testthat/test-mosaic.R 2019-05-05 02:49:37 UTC (rev 457) @@ -35,13 +35,10 @@ # calculate affinities using the predominant basis species pH <- c(0, 14, 29) m1 <- mosaic(bases, pH = pH, blend = FALSE) - # calculate affinities with smooth transitions between basis species, including a mixing energy + # calculate affinities with smooth transitions between basis species m2 <- mosaic(bases, pH = pH) # these species have no S so the results should be similar, - # 20190121 except for a negative free energy of mixing (positive affinity) - expect_true(all(m2$A.species$values[[1]] - m1$A.species$values[[1]] > 0)) - # the differences increase, then decrease - expect_equal(unique(sign(diff(as.numeric(m2$A.species$values[[1]] - m1$A.species$values[[1]])))), c(1, -1)) + expect_equivalent(m2$A.species$values[[1]], m1$A.species$values[[1]]) # now with S-bearing species ... species(c("pyrrhotite", "pyrite")) m3 <- mosaic(bases, pH = pH, blend = FALSE) @@ -49,8 +46,71 @@ # the results are different ... expect_equal(sapply(m3$A.species$values, "[", 13), sapply(m4$A.species$values, "[", 13), tol=1e-1) # but more similar at extreme pH values - expect_equal(sapply(m3$A.species$values, "[", 1), sapply(m4$A.species$values, "[", 1), tol=1e-6) - expect_equal(sapply(m3$A.species$values, "[", 29), sapply(m4$A.species$values, "[", 29), tol=1e-10) + expect_equal(sapply(m3$A.species$values, "[", 1), sapply(m4$A.species$values, "[", 1), tol=1e-7) + expect_equal(sapply(m3$A.species$values, "[", 29), sapply(m4$A.species$values, "[", 29), tol=1e-13) }) +test_that("mosaic() - equilibrate() produces equilibrium activities", { + # test added 20190505, based on an calculation sent by Kirt Robinson + basis(c("CO2", "NH3", "O2", "H2O", "H+")) + species(c("acetamide", "acetic acid", "acetate")) + m <- mosaic(c("NH3", "NH4+"), pH = c(0, 14)) + e <- equilibrate(m$A.species) + # calculate logK for form acetamide from predominant species at low pH + s1 <- subcrt(c("acetic acid", "NH4+", "acetamide", "water", "H+"), c(-1, -1, 1, 1, 1), T = 25) + logK1 <- s1$out$logK + # values of activities + loga_acetic <- e$loga.equil[[2]] + loga_NH4 <- m$e.bases[[1]]$loga.equil[[2]] + loga_acetamide <- e$loga.equil[[1]] + loga_H2O <- m$e.bases[[1]]$basis$logact[[4]] + loga_Hplus <- - m$e.bases[[1]]$vals$pH + logQ1 <- - loga_acetic - loga_NH4 + loga_acetamide + loga_H2O + loga_Hplus + A1 <- logQ1 - logK1 + ## in CHNOSZ versions before 1.3.2-5 (20190505), the affinity was zero at the pH extremes, + ## but peaked with a value of 0.3 (log10(2)) at pH 9.2 (equal activities of NH3 and NH4+) + #plot(m$e.bases[[1]]$vals$pH, A1, type = "l") + #title(main = describe.reaction(s1$reaction)) + expect_equivalent(A1, rep(0, length(A1))) +}) + +test_that("mosaic() - solubility() produces equilibrium activities", { + # test added 20190505, simplified from demo/contour.R with varying pH at constant logfO2 + # define temperature and pressure + T <- 250 + P <- 500 + # set up system + basis(c("Au", "Cl-", "H2S", "H2O", "oxygen", "H+")) + species(c("Au(HS)2-", "AuHS", "AuOH", "AuCl2-")) + # this get us close to total S = 0.01 m + basis("H2S", -2) + # set a low logfO2 to get into H2S - HS- fields + basis("O2", -40) + # calculate solution composition for 1 mol/kg NaCl + NaCl <- NaCl(T = T, P = P, m_tot = 1) + basis("Cl-", log10(NaCl$m_Cl)) + # calculate affinity with changing basis species + bases <- c("H2S", "HS-", "HSO4-", "SO4-2") + m <- mosaic(bases, pH = c(2, 10), T = 250, P = 500, IS = NaCl$IS) + # calculate solubility + s <- solubility(m$A.species) + # calculate logK to form Au(HS)2- in H2S stability region + # include IS here to compute adjusted logK + s1 <- subcrt(c("Au", "H2S", "oxygen", "Au(HS)2-", "H2O", "H+"), c(-1, -2, -0.25, 1, 0.5, 1), T = T, P = P, IS = NaCl$IS) + logK1 <- s1$out$logK + # calculate logQ with the given or computed activities + loga_Au <- m$A.bases$basis$logact[[1]] + loga_H2S <- m$e.bases[[1]]$loga.equil[[1]] + logf_O2 <- m$A.bases$basis$logact[[5]] + loga_AuHS2minus <- s$loga.equil[[1]] + loga_H2O <- m$A.bases$basis$logact[[4]] + loga_Hplus <- - m$A.bases$vals$pH + logQ1 <- - 1 * loga_Au - 2 * loga_H2S - 0.25 * logf_O2 + 1 * loga_AuHS2minus + 0.5 * loga_H2O + 1 * loga_Hplus + # calculate affinity - should be zero! + A1 <- logQ1 - logK1 + #plot(m$A.bases$vals$pH, A1, type = "l") + #title(main = describe.reaction(s1$reaction)) + expect_equivalent(A1, rep(0, length(A1))) +}) + # TODO: test that basis specifications can be exchanged between bases and bases2 without altering output From noreply at r-forge.r-project.org Sun May 5 07:34:42 2019 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Sun, 5 May 2019 07:34:42 +0200 (CEST) Subject: [CHNOSZ-commits] r458 - in pkg/CHNOSZ: . R demo inst man tests/testthat Message-ID: <20190505053442.87115188463@r-forge.r-project.org> Author: jedick Date: 2019-05-05 07:34:41 +0200 (Sun, 05 May 2019) New Revision: 458 Modified: pkg/CHNOSZ/DESCRIPTION pkg/CHNOSZ/R/mosaic.R pkg/CHNOSZ/demo/mosaic.R pkg/CHNOSZ/inst/NEWS pkg/CHNOSZ/man/mosaic.Rd pkg/CHNOSZ/tests/testthat/test-mosaic.R Log: mosaic(): rename 'e.bases' to 'E.bases' Modified: pkg/CHNOSZ/DESCRIPTION =================================================================== --- pkg/CHNOSZ/DESCRIPTION 2019-05-05 02:49:37 UTC (rev 457) +++ pkg/CHNOSZ/DESCRIPTION 2019-05-05 05:34:41 UTC (rev 458) @@ -1,6 +1,6 @@ Date: 2019-05-05 Package: CHNOSZ -Version: 1.3.2-5 +Version: 1.3.2-6 Title: Thermodynamic Calculations and Diagrams for Geochemistry Authors at R: c( person("Jeffrey", "Dick", , "j3ffdick at gmail.com", role = c("aut", "cre"), Modified: pkg/CHNOSZ/R/mosaic.R =================================================================== --- pkg/CHNOSZ/R/mosaic.R 2019-05-05 02:49:37 UTC (rev 457) +++ pkg/CHNOSZ/R/mosaic.R 2019-05-05 05:34:41 UTC (rev 458) @@ -104,7 +104,7 @@ # calculate equilibrium mole fractions for each group of basis species group.fraction <- list() if(blend) { - e.bases <- list() + E.bases <- list() for(i in 1:length(A.bases)) { # this isn't needed (and doesn't work) if all the affinities are NA 20180925 if(any(!sapply(A.bases[[1]]$values, is.na))) { @@ -114,7 +114,7 @@ a.tot <- Reduce("+", a.equil) group.fraction[[i]] <- lapply(a.equil, function(x) x / a.tot) # include the equilibrium activities in the output of this function 20190504 - e.bases[[1]] <- e + E.bases[[i]] <- e } else { group.fraction[[i]] <- A.bases[[i]]$values } @@ -176,6 +176,6 @@ # for argument recall, include all arguments in output 20190120 allargs <- c(list(bases = bases, blend = blend), list(...)) # return the affinities for the species and basis species - if(blend) return(list(fun = "mosaic", args = allargs, A.species = A.species, A.bases = A.bases, e.bases = e.bases)) + if(blend) return(list(fun = "mosaic", args = allargs, A.species = A.species, A.bases = A.bases, E.bases = E.bases)) else return(list(fun = "mosaic", args = allargs, A.species = A.species, A.bases = A.bases)) } Modified: pkg/CHNOSZ/demo/mosaic.R =================================================================== --- pkg/CHNOSZ/demo/mosaic.R 2019-05-05 02:49:37 UTC (rev 457) +++ pkg/CHNOSZ/demo/mosaic.R 2019-05-05 05:34:41 UTC (rev 458) @@ -33,10 +33,17 @@ species(c("Fe+2", "Fe+3"), -4) m2 <- mosaic(bases, bases2, pH = pH, Eh = Eh, T = T) diagram(m2$A.species, add = TRUE, names = NULL) -title(main=paste("Iron oxides, sulfides and carbonate in water, log(total S) = -6,", - "log(total C)=0, after Garrels and Christ, 1965", sep = "\n")) -# overlay the carbonate basis species predominance fields +# overlay the sulfur and carbonate basis species predominance fields +d <- diagram(m1$A.bases, add = TRUE, col = "red", col.names = "red", lty = 3, limit.water = FALSE) d <- diagram(m1$A.bases2, add = TRUE, col = "blue", names = NULL, lty = 3, limit.water = FALSE) text(d$namesx, -0.8, as.expression(sapply(m1$A.bases2$species$name, expr.species)), col = "blue") +# add legend and title +dP <- describe.property(c("T", "P"), c(25, 1)) +legend("top", dP, bty = "n") +dS <- expression(sum(S)*"(aq)" == 10^-6~italic(m)) +dC <- expression(sum(C)*"(aq)" == 1~italic(m)) +legend("topright", c(dS, dC), bty = "n") +title(main=paste("Iron minerals, sulfur, and carbonate in water,", + "after Garrels and Christ, 1965, Figure 7.21", sep = "\n"), font.main = 1) # reset the database, as it was changed in this example reset() Modified: pkg/CHNOSZ/inst/NEWS =================================================================== --- pkg/CHNOSZ/inst/NEWS 2019-05-05 02:49:37 UTC (rev 457) +++ pkg/CHNOSZ/inst/NEWS 2019-05-05 05:34:41 UTC (rev 458) @@ -7,14 +7,13 @@ weighted by the mole fraction of the changing basis species, but they should be calculated using activities of basis species that are adjusted (i.e. lowered) according to their mole fractions. Previously, - constant activities were used for each changing basies species, + constant activities were used for each changing basis species, leading to an artificial inflation of affinities of species, especially near the transitions where the changing basis species are nearly equal in abundance. -- The 'mixing' argument of mosaic() has been removed, as it no longer - provides correct results and is not needed with the improved handling - of activities of basis species. +- The 'mixing' argument of mosaic() has been removed; it is no longer + needed with the improved handling of activities of basis species. OTHER CHANGES @@ -21,7 +20,7 @@ - Tests have been added to test-mosaic.R to check that activitives produced by mosaic() - equilibrate() and mosaic() - solubility() really are equilibrium activities, i.e. that the affinities of - reactions between species are equivalent to zero, especially near the + reactions between species are zero everywhere, in particular near the transitions of basis species. - In mosaic(), equilibrate groups of changing basis species using total @@ -31,7 +30,7 @@ species. - In mosaic(), include the result of equilibrate() for each group of - basis species in the output ('e.bases'). + basis species in the output ('E.bases'). - demo/aluminum.R: add calculations using Si(OH)4 from Akinfiev-Diamond model (SiO2 in these reactions is replaced by Si(OH)4 - 2 H2O). Modified: pkg/CHNOSZ/man/mosaic.Rd =================================================================== --- pkg/CHNOSZ/man/mosaic.Rd 2019-05-05 02:49:37 UTC (rev 457) +++ pkg/CHNOSZ/man/mosaic.Rd 2019-05-05 05:34:41 UTC (rev 458) @@ -43,7 +43,7 @@ \value{ A list containing \code{A.species} (affinities of formation of the species with changing basis species) and \code{A.bases} (affinities of formation of the basis species in terms of the first basis species), each having same structure as the list returned by \code{\link{affinity}}. -If \code{blend} is TRUE, the output also contains \code{e.bases} (the output of \code{\link{equilibrate}} for each group of basis species) +If \code{blend} is TRUE, the output also contains \code{E.bases} (the output of \code{\link{equilibrate}} for each group of basis species) If \code{bases2} is provided, the list also contains \code{A.bases2} (affinities of formation of the second group of basis species). } Modified: pkg/CHNOSZ/tests/testthat/test-mosaic.R =================================================================== --- pkg/CHNOSZ/tests/testthat/test-mosaic.R 2019-05-05 02:49:37 UTC (rev 457) +++ pkg/CHNOSZ/tests/testthat/test-mosaic.R 2019-05-05 05:34:41 UTC (rev 458) @@ -61,15 +61,15 @@ logK1 <- s1$out$logK # values of activities loga_acetic <- e$loga.equil[[2]] - loga_NH4 <- m$e.bases[[1]]$loga.equil[[2]] + loga_NH4 <- m$E.bases[[1]]$loga.equil[[2]] loga_acetamide <- e$loga.equil[[1]] - loga_H2O <- m$e.bases[[1]]$basis$logact[[4]] - loga_Hplus <- - m$e.bases[[1]]$vals$pH + loga_H2O <- m$E.bases[[1]]$basis$logact[[4]] + loga_Hplus <- - m$E.bases[[1]]$vals$pH logQ1 <- - loga_acetic - loga_NH4 + loga_acetamide + loga_H2O + loga_Hplus A1 <- logQ1 - logK1 ## in CHNOSZ versions before 1.3.2-5 (20190505), the affinity was zero at the pH extremes, ## but peaked with a value of 0.3 (log10(2)) at pH 9.2 (equal activities of NH3 and NH4+) - #plot(m$e.bases[[1]]$vals$pH, A1, type = "l") + #plot(m$E.bases[[1]]$vals$pH, A1, type = "l") #title(main = describe.reaction(s1$reaction)) expect_equivalent(A1, rep(0, length(A1))) }) @@ -100,7 +100,7 @@ logK1 <- s1$out$logK # calculate logQ with the given or computed activities loga_Au <- m$A.bases$basis$logact[[1]] - loga_H2S <- m$e.bases[[1]]$loga.equil[[1]] + loga_H2S <- m$E.bases[[1]]$loga.equil[[1]] logf_O2 <- m$A.bases$basis$logact[[5]] loga_AuHS2minus <- s$loga.equil[[1]] loga_H2O <- m$A.bases$basis$logact[[4]] From noreply at r-forge.r-project.org Sun May 5 08:49:14 2019 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Sun, 5 May 2019 08:49:14 +0200 (CEST) Subject: [CHNOSZ-commits] r459 - in pkg/CHNOSZ: . tests/testthat Message-ID: <20190505064914.EFF10180737@r-forge.r-project.org> Author: jedick Date: 2019-05-05 08:49:13 +0200 (Sun, 05 May 2019) New Revision: 459 Modified: pkg/CHNOSZ/DESCRIPTION pkg/CHNOSZ/tests/testthat/test-mosaic.R Log: test-mosaic.R: add test for affinities of minerals with multiple changing basis species Modified: pkg/CHNOSZ/DESCRIPTION =================================================================== --- pkg/CHNOSZ/DESCRIPTION 2019-05-05 05:34:41 UTC (rev 458) +++ pkg/CHNOSZ/DESCRIPTION 2019-05-05 06:49:13 UTC (rev 459) @@ -1,6 +1,6 @@ Date: 2019-05-05 Package: CHNOSZ -Version: 1.3.2-6 +Version: 1.3.2-7 Title: Thermodynamic Calculations and Diagrams for Geochemistry Authors at R: c( person("Jeffrey", "Dick", , "j3ffdick at gmail.com", role = c("aut", "cre"), Modified: pkg/CHNOSZ/tests/testthat/test-mosaic.R =================================================================== --- pkg/CHNOSZ/tests/testthat/test-mosaic.R 2019-05-05 05:34:41 UTC (rev 458) +++ pkg/CHNOSZ/tests/testthat/test-mosaic.R 2019-05-05 06:49:13 UTC (rev 459) @@ -113,4 +113,45 @@ expect_equivalent(A1, rep(0, length(A1))) }) +test_that("mosaic() - equilibrate() produces equilibrium activities that are consistent with + stability differences of minerals and multiple groups of changing basis species", { + # test added 20190505, adapted from demo/mosaic.R: + # select a constant pH close to equal activities of CO2 - HCO3-, + # and a range of Eh that crosses the upper and lower boundaries + # of pyrite with siderite (including the H2S - SO4-2 transition) + basis(c("FeO", "SO4-2", "H2O", "H+", "e-", "CO3-2")) + basis("SO4-2", -6) + basis("CO3-2", 0) + basis("pH", 6.3) + species(c("pyrrhotite", "pyrite", "hematite", "magnetite", "siderite")) + # two sets of changing basis species: + # speciate SO4-2, HSO4-, HS-, H2S as a function of Eh and pH + # speciate CO3-2, HCO3-, CO2 as a function of pH + bases <- list(c("SO4-2", "HSO4-", "HS-", "H2S"), + c("CO3-2", "HCO3-", "CO2")) + # calculate affinities using the relative abundances of different basis species + m <- mosaic(bases, Eh = c(-0.5, 0)) + # calculate logK for pyrite-siderite reaction using arbitrarily chosen basis species + s1 <- subcrt(c("pyrite", "CO2", "H2O", "H+", "e-", "siderite", "H2S"), c(-1, -1, -1, -2, -2, 1, 2), T = 25) + logK <- s1$out$logK + # get activities of minerals, water, and H+ + loga_pyrite <- loga_siderite <- loga_H2O <- 0 + loga_Hplus <- m$A.bases[[1]]$basis$logact[[4]] + # get activities of basis species + loga_eminus <- - convert(m$A.bases[[1]]$vals$Eh, "pe") + loga_H2S <- m$E.bases[[1]]$loga.equil[[4]] + loga_CO2 <- m$E.bases[[2]]$loga.equil[[3]] + # calculate affinity + logQ <- -1 * loga_pyrite - 1 * loga_CO2 - 1 * loga_H2O - 2 * loga_Hplus - 2 * loga_eminus + 1 * loga_siderite + 2 * loga_H2S + A <- logQ - logK + # the "hand-calculated" value and the affinity calculated by the function should be equal + Adiff <- A - (m$A.species$values[[2]] - m$A.species$values[[5]]) + #par(mfrow = c(2, 1)) + #diagram(m$A.species) + #plot(m$A.bases[[1]]$vals$Eh, Adiff, type = "l") + #title(main = "A(single basis species) - A(all basis species)") + #legend("topleft", legend = describe.reaction(s1$reaction)) + expect_equivalent(Adiff, rep(0, length(Adiff))) +}) + # TODO: test that basis specifications can be exchanged between bases and bases2 without altering output From noreply at r-forge.r-project.org Sun May 5 09:45:42 2019 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Sun, 5 May 2019 09:45:42 +0200 (CEST) Subject: [CHNOSZ-commits] r460 - in pkg/CHNOSZ: . R inst man Message-ID: <20190505074543.07D48181913@r-forge.r-project.org> Author: jedick Date: 2019-05-05 09:45:34 +0200 (Sun, 05 May 2019) New Revision: 460 Modified: pkg/CHNOSZ/DESCRIPTION pkg/CHNOSZ/R/equilibrate.R pkg/CHNOSZ/inst/NEWS pkg/CHNOSZ/man/equilibrate.Rd Log: equilibrate(): handle output from mosaic by combining activities of basis species and formed species Modified: pkg/CHNOSZ/DESCRIPTION =================================================================== --- pkg/CHNOSZ/DESCRIPTION 2019-05-05 06:49:13 UTC (rev 459) +++ pkg/CHNOSZ/DESCRIPTION 2019-05-05 07:45:34 UTC (rev 460) @@ -1,6 +1,6 @@ Date: 2019-05-05 Package: CHNOSZ -Version: 1.3.2-7 +Version: 1.3.2-8 Title: Thermodynamic Calculations and Diagrams for Geochemistry Authors at R: c( person("Jeffrey", "Dick", , "j3ffdick at gmail.com", role = c("aut", "cre"), Modified: pkg/CHNOSZ/R/equilibrate.R =================================================================== --- pkg/CHNOSZ/R/equilibrate.R 2019-05-05 06:49:13 UTC (rev 459) +++ pkg/CHNOSZ/R/equilibrate.R 2019-05-05 07:45:34 UTC (rev 460) @@ -9,9 +9,26 @@ equilibrate <- function(aout, balance=NULL, loga.balance=NULL, ispecies=1:length(aout$values), normalize=FALSE, as.residue=FALSE, method=c("boltzmann", "reaction"), tol=.Machine$double.eps^0.25) { - ### set up calculation of equilibrium activities of species from the affinities - ### of their formation reactions from basis species at known activities + ### calculate equilibrium activities of species from the affinities + ### of their formation reactions from basis species at given activities ### split from diagram() 20120925 jmd + ## if aout is the output from mosaic(), combine the equilibrium activities of basis species + ## and formed species into an object that can be plotted with diagram() 20190505 + if(aout$fun == "mosaic") { + # calculate equilibrium activities of species + if(missing(ispecies)) ispecies <- 1:length(aout$A.species$values) + if(missing(method)) eqc <- equilibrate(aout$A.species, balance = balance, loga.balance = loga.balance, + ispecies = ispecies, normalize = normalize, as.residue = as.residue, tol = tol) + else eqc <- equilibrate(aout$A.species, balance = balance, loga.balance = loga.balance, + ispecies = ispecies, normalize = normalize, as.residue = as.residue, method = method, tol = tol) + # make combined object for basis species and species: + # put together the species matrix and logarithms of equilibrium activity + eqc$species <- rbind(aout$E.bases[[1]]$species, eqc$species) + eqc$loga.equil <- c(aout$E.bases[[1]]$loga.equil, eqc$loga.equil) + # we also need to combine 'values' (values of affinity) because diagram() uses this to get the number of species + eqc$values <- c(aout$E.bases[[1]]$values, eqc$values) + return(eqc) + } ## number of possible species nspecies <- length(aout$values) ## get the balancing coefficients Modified: pkg/CHNOSZ/inst/NEWS =================================================================== --- pkg/CHNOSZ/inst/NEWS 2019-05-05 06:49:13 UTC (rev 459) +++ pkg/CHNOSZ/inst/NEWS 2019-05-05 07:45:34 UTC (rev 460) @@ -1,4 +1,4 @@ -CHANGES IN CHNOSZ 1.3.2-5 (2019-05-05) +CHANGES IN CHNOSZ 1.3.2-8 (2019-05-05) -------------------------------------- BUG FIXES @@ -32,6 +32,13 @@ - In mosaic(), include the result of equilibrate() for each group of basis species in the output ('E.bases'). +- equilibrate(): make it possible to process the output of mosaic(). + This combines the equilibrium activities of the formed species with + the changing basis species to make an object that can be plotted with + diagram(). This can be useful for conserving two elements in a system + (one in the basis species, the other in the formed species). Thanks + to Kirt Robinson for the feature request and test system. + - demo/aluminum.R: add calculations using Si(OH)4 from Akinfiev-Diamond model (SiO2 in these reactions is replaced by Si(OH)4 - 2 H2O). Modified: pkg/CHNOSZ/man/equilibrate.Rd =================================================================== --- pkg/CHNOSZ/man/equilibrate.Rd 2019-05-05 06:49:13 UTC (rev 459) +++ pkg/CHNOSZ/man/equilibrate.Rd 2019-05-05 07:45:34 UTC (rev 460) @@ -32,10 +32,11 @@ \details{ \code{equilibrate} calculates the chemical activities of species in metastable equilibrium, for constant temperature, pressure and chemical activities of basis species, using specified balancing constraints on reactions between species. -It takes as input \code{aout}, the output from \code{\link{affinity}}, which may be calculated from a multidimensional grid of conditions. +It takes as input \code{aout}, the output from \code{\link{affinity}}, giving the chemical affinities of formation reaction of each species, which may be calculated on a multidimensional grid of conditions. +Alternatively, \code{aout} can be the output from \code{\link{mosaic}}, in which case the equilibrium activities of the formed species are calculated and combined with those of the changing basis species to make an object that can be plotted with \code{\link{diagram}}. + The equilibrium chemical activities of species are calculated using either the \code{equil.reaction} or \code{equil.boltzmann} functions, the latter only if the balance is on one mole of species. -\code{aout} contains the chemical affinities of formation reactions of each species of interest. \code{equilibrate} needs to be provided constraints on how to balance the reactions representing transformations between the species. \code{balance} indicates the balancing component, according to the following scheme: @@ -125,6 +126,22 @@ logK <- subcrt(c("CO2","H2O","HCO3-","H+"), c(-1, -1, 1, 1), T=25)$out$logK # we could decrease tolerance here by increasing res stopifnot(all.equal(pKa.equil, -logK, tolerance=1e-2)) + +# equilibrate with mosaic: balancing on N and C +loga_N <- -4 +loga_C <- -3 +basis(c("CO2", "NH3", "O2", "H2O", "H+")) +basis("NH3", loga_N) +species(c("acetamide", "acetic acid", "acetate")) +# this calculates equilibrium activities of NH3 and NH4+ for given loga_N +# and calculates the corresponding affinities of the formed species +m <- mosaic(c("NH3", "NH4+"), pH = c(0, 14)) +# this calculated equilibrium activities of the formed species for given loga_C +# and combines them with the activities of the changing basis species (NH3 and NH4+) +eqc <- equilibrate(m, loga.balance = loga_C) +diagram(eqc, ylim = c(-10, -2)) +title(main = paste("log(total N in basis species) =", loga_N, + "\nlog(total C in formed species) =", loga_C), font.main = 1) } \references{ From noreply at r-forge.r-project.org Sun May 5 11:41:58 2019 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Sun, 5 May 2019 11:41:58 +0200 (CEST) Subject: [CHNOSZ-commits] r461 - in pkg/CHNOSZ: . R inst man Message-ID: <20190505094158.4EA18183B80@r-forge.r-project.org> Author: jedick Date: 2019-05-05 11:41:57 +0200 (Sun, 05 May 2019) New Revision: 461 Modified: pkg/CHNOSZ/DESCRIPTION pkg/CHNOSZ/NAMESPACE pkg/CHNOSZ/R/equilibrate.R pkg/CHNOSZ/inst/NEWS pkg/CHNOSZ/man/equilibrate.Rd Log: add new function moles() Modified: pkg/CHNOSZ/DESCRIPTION =================================================================== --- pkg/CHNOSZ/DESCRIPTION 2019-05-05 07:45:34 UTC (rev 460) +++ pkg/CHNOSZ/DESCRIPTION 2019-05-05 09:41:57 UTC (rev 461) @@ -1,6 +1,6 @@ Date: 2019-05-05 Package: CHNOSZ -Version: 1.3.2-8 +Version: 1.3.2-9 Title: Thermodynamic Calculations and Diagrams for Geochemistry Authors at R: c( person("Jeffrey", "Dick", , "j3ffdick at gmail.com", role = c("aut", "cre"), Modified: pkg/CHNOSZ/NAMESPACE =================================================================== --- pkg/CHNOSZ/NAMESPACE 2019-05-05 07:45:34 UTC (rev 460) +++ pkg/CHNOSZ/NAMESPACE 2019-05-05 09:41:57 UTC (rev 461) @@ -58,7 +58,7 @@ # added 20171121 or later "dumpdata", "thermo.axis", "solubility", "NaCl", # added 20190213 or later - "CHNOSZ", "thermo", "reset", "obigt", "retrieve", "AkDi" + "CHNOSZ", "thermo", "reset", "obigt", "retrieve", "AkDi", "moles" ) # Load shared objects Modified: pkg/CHNOSZ/R/equilibrate.R =================================================================== --- pkg/CHNOSZ/R/equilibrate.R 2019-05-05 07:45:34 UTC (rev 460) +++ pkg/CHNOSZ/R/equilibrate.R 2019-05-05 09:41:57 UTC (rev 461) @@ -266,6 +266,39 @@ return(logact) } +# a function to calculate the total moles of the elements in the output from equilibrate 20190505 +moles <- function(eout) { + # exponentiate loga.equil to get activities + act <- lapply(eout$loga.equil, function(x) 10^x) + # initialize list for moles of basis species + nbasis <- rep(list(act[[1]] * 0), nrow(eout$basis)) + # loop over species + for(i in 1:nrow(eout$species)) { + # loop over basis species + for(j in 1:nrow(eout$basis)) { + # the coefficient of this basis species in the formation reaction of this species + n <- eout$species[i, j] + # accumulate the number of moles of basis species + nbasis[[j]] <- nbasis[[j]] + act[[i]] * n + } + } + # initialize list for moles of elements (same as number of basis species) + nelem <- rep(list(act[[1]] * 0), nrow(eout$basis)) + # loop over basis species + for(i in 1:nrow(eout$basis)) { + # loop over elements + for(j in 1:nrow(eout$basis)) { + # the coefficient of this element in the formula of this basis species + n <- eout$basis[i, j] + # accumulate the number of moles of elements + nelem[[j]] <- nelem[[j]] + nbasis[[i]] * n + } + } + # add element names + names(nelem) <- colnames(eout$basis)[1:nrow(eout$basis)] + nelem +} + ### unexported functions ### # return a list containing the balancing coefficients (n.balance) and a textual description (balance) Modified: pkg/CHNOSZ/inst/NEWS =================================================================== --- pkg/CHNOSZ/inst/NEWS 2019-05-05 07:45:34 UTC (rev 460) +++ pkg/CHNOSZ/inst/NEWS 2019-05-05 09:41:57 UTC (rev 461) @@ -1,16 +1,15 @@ -CHANGES IN CHNOSZ 1.3.2-8 (2019-05-05) +CHANGES IN CHNOSZ 1.3.2-9 (2019-05-05) -------------------------------------- BUG FIXES -- In mosaic(), affinities of formation of species should not only be - weighted by the mole fraction of the changing basis species, but they - should be calculated using activities of basis species that are - adjusted (i.e. lowered) according to their mole fractions. Previously, - constant activities were used for each changing basis species, - leading to an artificial inflation of affinities of species, - especially near the transitions where the changing basis species are - nearly equal in abundance. +- In mosaic(), affinities of formation of species were not calculated + using activities of basis species that are adjusted (i.e. lowered) + according to their mole fractions. Previously, constant activities + were used for each changing basis species, leading to an artificial + inflation of the affinities of species, especially near the + transitions where the changing basis species are nearly equal in + abundance. - The 'mixing' argument of mosaic() has been removed; it is no longer needed with the improved handling of activities of basis species. @@ -17,31 +16,37 @@ OTHER CHANGES -- Tests have been added to test-mosaic.R to check that activitives - produced by mosaic() - equilibrate() and mosaic() - solubility() - really are equilibrium activities, i.e. that the affinities of - reactions between species are zero everywhere, in particular near the - transitions of basis species. +- Add tests to test-mosaic.R to check that activitives produced by + mosaic() - equilibrate() and mosaic() - solubility() really are + equilibrium activities, i.e. that the affinities of reactions between + species are zero everywhere, in particular near the transitions of + basis species. -- In mosaic(), equilibrate groups of changing basis species using total - activity taken from the corresponding basis species in the incoming - basis() definition. This is not directly related to the bug above, but - provides a means to constrain the amount of an element in the basis - species. +- In mosaic(), groups of changing basis species are equilibrated using + a total activity given by the activity of the starting basis species + in the incoming basis() definition. This is not directly related to + the bug above, but instead provides a means to constrain the amount of + an element in the basis species. - In mosaic(), include the result of equilibrate() for each group of basis species in the output ('E.bases'). +NEW FEATURES + - equilibrate(): make it possible to process the output of mosaic(). - This combines the equilibrium activities of the formed species with - the changing basis species to make an object that can be plotted with - diagram(). This can be useful for conserving two elements in a system - (one in the basis species, the other in the formed species). Thanks - to Kirt Robinson for the feature request and test system. + This feature combines the equilibrium activities of the formed species + with those of the changing basis species to make an object that can be + plotted with diagram(). This can be useful for conserving two elements + in a system: one in the basis species, the other in the formed + species. Thanks to Kirt Robinson for the feature request and test + system. -- demo/aluminum.R: add calculations using Si(OH)4 from Akinfiev-Diamond - model (SiO2 in these reactions is replaced by Si(OH)4 - 2 H2O). +- Add function moles(), to calculate the total number of moles of + elements in the output from equilibrate(). +- demo/aluminum.R: add calculations using Si(OH)4 from the Akinfiev- + Diamond model (SiO2 in these reactions is replaced by Si(OH)4 - 2 H2O). + CHANGES IN CHNOSZ 1.3.2 (2019-04-20) ------------------------------------ Modified: pkg/CHNOSZ/man/equilibrate.Rd =================================================================== --- pkg/CHNOSZ/man/equilibrate.Rd 2019-05-05 07:45:34 UTC (rev 460) +++ pkg/CHNOSZ/man/equilibrate.Rd 2019-05-05 09:41:57 UTC (rev 461) @@ -3,6 +3,7 @@ \alias{equilibrate} \alias{equil.boltzmann} \alias{equil.reaction} +\alias{moles} \title{Equilibrium Chemical Activities of Species} \description{ Calculate equilibrium chemical activities of species from the affinities of formation of the species at unit activity. @@ -14,10 +15,11 @@ method=c("boltzmann", "reaction"), tol=.Machine$double.eps^0.25) equil.boltzmann(Astar, n.balance, loga.balance) equil.reaction(Astar, n.balance, loga.balance, tol=.Machine$double.eps^0.25) + moles(eout) } \arguments{ - \item{aout}{list, output from \code{\link{affinity}}} + \item{aout}{list, output from \code{\link{affinity}}} or \code{\link{mosaic}} \item{balance}{character or numeric, how to balance the transformations} \item{ispecies}{numeric, which species to include} \item{normalize}{logical, normalize the molar formulas of species by the balancing coefficients?} @@ -27,6 +29,7 @@ \item{loga.balance}{numeric (single value or vector), logarithm of total activity of balanced quantity} \item{method}{character, equilibration method to use} \item{tol}{numeric, convergence tolerance for \code{\link{uniroot}}} + \item{eout}{list, output from \code{\link{equilibrate}}} } \details{ @@ -66,6 +69,8 @@ Using \code{equil.reaction} may be needed for systems with huge (negative or positive) affinities, where \code{equil.boltzmann} produces a NaN result. \code{ispecies} can be supplied to identify a subset of the species to include in the calculation. + +\code{moles} simply calculates the total number of moles of elements corresponding to the activities of formed species in the output from \code{equilibrate}. } \section{Algorithms}{ From noreply at r-forge.r-project.org Mon May 6 07:13:15 2019 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Mon, 6 May 2019 07:13:15 +0200 (CEST) Subject: [CHNOSZ-commits] r462 - in pkg/CHNOSZ: . inst tests/testthat Message-ID: <20190506051315.B9BD818421E@r-forge.r-project.org> Author: jedick Date: 2019-05-06 07:13:15 +0200 (Mon, 06 May 2019) New Revision: 462 Modified: pkg/CHNOSZ/DESCRIPTION pkg/CHNOSZ/inst/NEWS pkg/CHNOSZ/tests/testthat/test-mosaic.R Log: edit NEWS Modified: pkg/CHNOSZ/DESCRIPTION =================================================================== --- pkg/CHNOSZ/DESCRIPTION 2019-05-05 09:41:57 UTC (rev 461) +++ pkg/CHNOSZ/DESCRIPTION 2019-05-06 05:13:15 UTC (rev 462) @@ -1,6 +1,6 @@ -Date: 2019-05-05 +Date: 2019-05-06 Package: CHNOSZ -Version: 1.3.2-9 +Version: 1.3.2-10 Title: Thermodynamic Calculations and Diagrams for Geochemistry Authors at R: c( person("Jeffrey", "Dick", , "j3ffdick at gmail.com", role = c("aut", "cre"), Modified: pkg/CHNOSZ/inst/NEWS =================================================================== --- pkg/CHNOSZ/inst/NEWS 2019-05-05 09:41:57 UTC (rev 461) +++ pkg/CHNOSZ/inst/NEWS 2019-05-06 05:13:15 UTC (rev 462) @@ -1,15 +1,14 @@ -CHANGES IN CHNOSZ 1.3.2-9 (2019-05-05) --------------------------------------- +CHANGES IN CHNOSZ 1.3.2-10 (2019-05-06) +--------------------------------------- BUG FIXES -- In mosaic(), affinities of formation of species were not calculated - using activities of basis species that are adjusted (i.e. lowered) - according to their mole fractions. Previously, constant activities - were used for each changing basis species, leading to an artificial - inflation of the affinities of species, especially near the - transitions where the changing basis species are nearly equal in - abundance. +- In mosaic(), constant activities were used for each changing basis + species, leading to an artificial inflation of the affinities of + species around the transitions where the basis species become equally + abundant. Now, affinities of formation of species are calculated using + activities of basis species that are adjusted (i.e. lowered) according + to their relative abundances. - The 'mixing' argument of mosaic() has been removed; it is no longer needed with the improved handling of activities of basis species. @@ -22,11 +21,10 @@ species are zero everywhere, in particular near the transitions of basis species. -- In mosaic(), groups of changing basis species are equilibrated using - a total activity given by the activity of the starting basis species - in the incoming basis() definition. This is not directly related to - the bug above, but instead provides a means to constrain the amount of - an element in the basis species. +- In mosaic(), groups of changing basis species are equilibrated for a + total activity given by the activity of the starting basis species in + the incoming basis() definition. This provides a means to specify the + the amount of a conserved element in the basis species. - In mosaic(), include the result of equilibrate() for each group of basis species in the output ('E.bases'). @@ -39,7 +37,7 @@ plotted with diagram(). This can be useful for conserving two elements in a system: one in the basis species, the other in the formed species. Thanks to Kirt Robinson for the feature request and test - system. + system for acetamide, which has been added to ?equilibrate. - Add function moles(), to calculate the total number of moles of elements in the output from equilibrate(). Modified: pkg/CHNOSZ/tests/testthat/test-mosaic.R =================================================================== --- pkg/CHNOSZ/tests/testthat/test-mosaic.R 2019-05-05 09:41:57 UTC (rev 461) +++ pkg/CHNOSZ/tests/testthat/test-mosaic.R 2019-05-06 05:13:15 UTC (rev 462) @@ -51,7 +51,7 @@ }) test_that("mosaic() - equilibrate() produces equilibrium activities", { - # test added 20190505, based on an calculation sent by Kirt Robinson + # test added 20190505, based on a calculation sent by Kirt Robinson basis(c("CO2", "NH3", "O2", "H2O", "H+")) species(c("acetamide", "acetic acid", "acetate")) m <- mosaic(c("NH3", "NH4+"), pH = c(0, 14))