From 5c61108b60c0b9335c2d379963afca843504c0ba Mon Sep 17 00:00:00 2001 From: "Charlton, Scott R" Date: Tue, 25 Aug 2020 12:27:15 -0600 Subject: [PATCH] added googletest and fixed some minor bugs --- CMakeLists.txt | 354 +- IPhreeqcConfig.cmake.in | 4 + doc/CMakeLists.txt | 25 + examples/using-cmake/CMakeLists.txt | 20 + examples/using-cmake/README.txt | 18 + examples/using-cmake/ex2 | 26 + examples/using-cmake/main.cpp | 18 + examples/using-cmake/phreeqc.dat | 1837 +++++++ gtest/CMakeLists.txt | 166 + gtest/FileTest.cpp | 153 + gtest/FileTest.h | 33 + gtest/TestCVar.cpp | 9 + gtest/TestIPhreeqc.cpp | 4742 ++++++++++++++++++ gtest/TestIPhreeqcLib.cpp | 4606 +++++++++++++++++ gtest/TestSelectedOutput.cpp | 669 +++ gtest/TestVar.cpp | 10 + gtest/conv_fail.in | 11 + gtest/dump | 42 + gtest/iso.dat | 7231 +++++++++++++++++++++++++++ gtest/kinn20140218 | 349 ++ gtest/missing_e.dat | 1556 ++++++ gtest/multi_punch | 105 + gtest/multi_punch_no_set | 102 + src/CSelectedOutput.hxx | 8 +- src/phreeqcpp/common/PHRQ_io.h | 46 +- tests/main.f90 | 13 +- 26 files changed, 21991 insertions(+), 162 deletions(-) create mode 100644 IPhreeqcConfig.cmake.in create mode 100644 examples/using-cmake/CMakeLists.txt create mode 100644 examples/using-cmake/README.txt create mode 100644 examples/using-cmake/ex2 create mode 100644 examples/using-cmake/main.cpp create mode 100644 examples/using-cmake/phreeqc.dat create mode 100644 gtest/CMakeLists.txt create mode 100644 gtest/FileTest.cpp create mode 100644 gtest/FileTest.h create mode 100644 gtest/TestCVar.cpp create mode 100644 gtest/TestIPhreeqc.cpp create mode 100644 gtest/TestIPhreeqcLib.cpp create mode 100644 gtest/TestSelectedOutput.cpp create mode 100644 gtest/TestVar.cpp create mode 100644 gtest/conv_fail.in create mode 100644 gtest/dump create mode 100644 gtest/iso.dat create mode 100644 gtest/kinn20140218 create mode 100644 gtest/missing_e.dat create mode 100644 gtest/multi_punch create mode 100644 gtest/multi_punch_no_set diff --git a/CMakeLists.txt b/CMakeLists.txt index 49632115..e1dbfbc2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,17 +1,17 @@ -cmake_minimum_required (VERSION 2.8) +# CMAKE_MSVC_RUNTIME_LIBRARY requires 3.15 +cmake_minimum_required(VERSION 3.15) project (IPhreeqc CXX C) # check if this is the root project -if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) +if (CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) set(STANDALONE_BUILD 1) else() set(STANDALONE_BUILD 0) endif() - # overide docdir on windows -if(WIN32 AND NOT CMAKE_INSTALL_DOCDIR) +if (WIN32 AND NOT CMAKE_INSTALL_DOCDIR) set(CMAKE_INSTALL_DOCDIR "" CACHE PATH "documentation root (doc)") set(CMAKE_INSTALL_DOCDIR "doc") endif() @@ -19,33 +19,27 @@ endif() # set standard directory locations include(GNUInstallDirs) - -# Fortran -option (IPHREEQC_ENABLE_MODULE "Enable Fortran module" ON) -if (STANDALONE_BUILD EQUAL 1) - if (NOT IPHREEQC_FORTRAN_TESTING) - if (NOT CMAKE_Fortran_COMPILER OR CMAKE_Fortran_COMPILER STREQUAL "CMAKE_Fortran_COMPILER-NOTFOUND") - option (IPHREEQC_FORTRAN_TESTING "Build Fortran test" OFF) - else() - option (IPHREEQC_FORTRAN_TESTING "Build Fortran test" ON) - endif() - else() - if (IPHREEQC_FORTRAN_TESTING) - enable_language(Fortran) - endif() +if (STANDALONE_BUILD AND MSVC) + option (IPHREEQC_STATIC_RUNTIME "Build with a static runtime" OFF) + if (IPHREEQC_STATIC_RUNTIME) + # compile with static runtime + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") endif() endif() - -# Disable deprecation warnings for standard C and STL functions in VS2005 -# and later -if(MSVC_VERSION EQUAL 1400 OR MSVC_VERSION GREATER 1400) - add_definitions(-D_CRT_SECURE_NO_DEPRECATE) - add_definitions(-D_SCL_SECURE_NO_WARNINGS) -endif(MSVC_VERSION EQUAL 1400 OR MSVC_VERSION GREATER 1400) - -add_definitions(-DSWIG_SHARED_OBJ) -add_definitions(-DUSE_PHRQ_ALLOC) +# Fortran +option (IPHREEQC_ENABLE_MODULE "Enable Fortran module" ON) +if (STANDALONE_BUILD) + if (IPHREEQC_FORTRAN_TESTING) + enable_language(Fortran) + else() + if (CMAKE_Fortran_COMPILER) + option (IPHREEQC_FORTRAN_TESTING "Build Fortran test" ON) + else() + option (IPHREEQC_FORTRAN_TESTING "Build Fortran test" OFF) + endif() + endif() +endif() SET(IPhreeqc_SOURCES src/CSelectedOutput.cpp @@ -202,12 +196,11 @@ src/Version.h ) # compile Var.c as c++ -SET_SOURCE_FILES_PROPERTIES(src/Var.c PROPERTIES LANGUAGE CXX) +set_source_files_properties(src/Var.c PROPERTIES LANGUAGE CXX) # fwrap files if (NOT IPHREEQC_ENABLE_MODULE) - add_definitions(-DIPHREEQC_NO_FORTRAN_MODULE) - SET(IPhreeqc_SOURCES + set(IPhreeqc_SOURCES ${IPhreeqc_SOURCES} src/fimpl.h src/fwrap.cpp @@ -216,39 +209,84 @@ if (NOT IPHREEQC_ENABLE_MODULE) src/fwrap3.cpp src/fwrap4.cpp src/fwrap5.cpp - src/fwrap6.cpp + src/fwrap6.cpp src/fwrap7.cpp - src/fwrap8.cpp + src/fwrap8.cpp ) endif() -# setup include directories -include_directories("${PROJECT_SOURCE_DIR}") -include_directories("${PROJECT_SOURCE_DIR}/src") -include_directories("${PROJECT_SOURCE_DIR}/src/phreeqcpp") -include_directories("${PROJECT_SOURCE_DIR}/src/phreeqcpp/common") -include_directories("${PROJECT_SOURCE_DIR}/src/phreeqcpp/PhreeqcKeywords") - - -if (STANDALONE_BUILD EQUAL 1) +if (STANDALONE_BUILD) option(BUILD_SHARED_LIBS "Build Shared Libraries" OFF) set(LIB_TYPE STATIC) endif() if (BUILD_SHARED_LIBS) set(LIB_TYPE SHARED) - if (STANDALONE_BUILD EQUAL 1) + if (STANDALONE_BUILD) if (MSVC) option(BUILD_CLR_LIBS "Build CLR Libraries" OFF) endif() endif() endif() add_library(IPhreeqc ${LIB_TYPE} ${IPhreeqc_SOURCES}) + +# target_include_directories(IPhreeqc PUBLIC "${PROJECT_SOURCE_DIR}/src") +# target_include_directories(IPhreeqc PUBLIC "${PROJECT_SOURCE_DIR}/src/phreeqcpp") +# target_include_directories(IPhreeqc PUBLIC "${PROJECT_SOURCE_DIR}/src/phreeqcpp/common") +# target_include_directories(IPhreeqc PUBLIC "${PROJECT_SOURCE_DIR}/src/phreeqcpp/PhreeqcKeywords") + +# # target_include_directories(IPhreeqc PUBLIC $) +# # target_include_directories(IPhreeqc PUBLIC $) +# # target_include_directories(IPhreeqc PUBLIC $) +# # target_include_directories(IPhreeqc PUBLIC $) +# # target_include_directories(IPhreeqc PUBLIC $) + +# target_include_directories(IPhreeqc +# PUBLIC +# "${PROJECT_SOURCE_DIR}/src" +# "${PROJECT_SOURCE_DIR}/src/phreeqcpp" +# "${PROJECT_SOURCE_DIR}/src/phreeqcpp/common" +# "${PROJECT_SOURCE_DIR}/src/phreeqcpp/PhreeqcKeywords" +# ) + +target_include_directories(IPhreeqc + PUBLIC + $ + $ + $ + $ + $ +) + +# target_include_directories(IPhreeqc +# PUBLIC +# $ +# $ +# ) + +target_compile_definitions(IPhreeqc PRIVATE "SWIG_SHARED_OBJ") +target_compile_definitions(IPhreeqc PRIVATE "USE_PHRQ_ALLOC") + +if (NOT IPHREEQC_ENABLE_MODULE) + target_compile_definitions(IPhreeqc PUBLIC "IPHREEQC_NO_FORTRAN_MODULE") +endif() + +if (${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC) + target_compile_options(IPhreeqc PRIVATE /wd4251 /wd4275 /wd4793) +endif() + +# Disable deprecation warnings for standard C and STL functions in VS2005 +# and later +if (MSVC_VERSION EQUAL 1400 OR MSVC_VERSION GREATER 1400) + target_compile_definitions(IPhreeqc PUBLIC "_CRT_SECURE_NO_DEPRECATE") + target_compile_definitions(IPhreeqc PUBLIC "_SCL_SECURE_NO_WARNINGS") +endif(MSVC_VERSION EQUAL 1400 OR MSVC_VERSION GREATER 1400) + set_target_properties(IPhreeqc PROPERTIES DEBUG_POSTFIX "d") set_target_properties(IPhreeqc PROPERTIES MINSIZEREL_POSTFIX "msr") -set_target_properties(IPhreeqc PROPERTIES RELWITHDEBINFO_POSTFIX "rwdi") +set_target_properties(IPhreeqc PROPERTIES RELWITHDEBINFO_POSTFIX "rwd") -SET(IPhreeqc_Headers +set(IPhreeqc_Headers ${PROJECT_SOURCE_DIR}/src/IPhreeqc.h ${PROJECT_SOURCE_DIR}/src/IPhreeqc.hpp ${PROJECT_SOURCE_DIR}/src/IPhreeqcCallbacks.h @@ -258,78 +296,104 @@ ${PROJECT_SOURCE_DIR}/src/Var.h ) if (IPHREEQC_ENABLE_MODULE) - SET(IPhreeqc_SRC + set(IPhreeqc_SRC ${PROJECT_SOURCE_DIR}/src/IPhreeqc_interface.F90 ${PROJECT_SOURCE_DIR}/src/README.Fortran ) else() # always install README.Fortran - SET(IPhreeqc_SRC + set(IPhreeqc_SRC ${PROJECT_SOURCE_DIR}/src/README.Fortran ) # install old fortran include files - SET(IPhreeqc_Headers + set(IPhreeqc_Headers ${IPhreeqc_Headers} ${PROJECT_SOURCE_DIR}/src/IPhreeqc.f.inc ${PROJECT_SOURCE_DIR}/src/IPhreeqc.f90.inc ) endif() + # Setup references for /CLR if (MSVC AND BUILD_SHARED_LIBS AND BUILD_CLR_LIBS) - set_target_properties(IPhreeqc PROPERTIES VS_DOTNET_REFERENCES "System;System.Drawing;System.Windows.Forms;${CMAKE_CURRENT_SOURCE_DIR}/src/phreeqcpp/ZedGraph.dll") - # Remove /EHsc from CMAKE_CXX_FLAGS - STRING(REPLACE " /EHsc" " /EHa /clr" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) - # Remove /RTC1 from CMAKE_CXX_FLAGS_DEBUG - STRING(REPLACE " /RTC1" "" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG}) - if (MSVC10) - # turn off warnings on VS2010 - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4793 /wd4945") - endif() if (MSVC_VERSION LESS 1600) message(FATAL_ERROR "CLR options must be set manually for versions prior to Visual Studio 2010") - endif() - ADD_DEFINITIONS(-DMULTICHART) -endif() - - -# install -if (WIN32) - if (BUILD_CLR_LIBS) - if("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) - SET(CMAKE_INSTALL_LIBDIR "clrx64") - else() - SET(CMAKE_INSTALL_LIBDIR "clr") - endif() - else() - if("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) - if (BUILD_SHARED_LIBS) - SET(CMAKE_INSTALL_LIBDIR "dllx64") - else() - SET(CMAKE_INSTALL_LIBDIR "libx64") - endif() - else() - if (BUILD_SHARED_LIBS) - SET(CMAKE_INSTALL_LIBDIR "dll") - else() - SET(CMAKE_INSTALL_LIBDIR "lib") - endif() - endif() endif() + set_target_properties(IPhreeqc PROPERTIES VS_DOTNET_REFERENCES "System;System.Drawing;System.Windows.Forms;${CMAKE_CURRENT_SOURCE_DIR}/src/phreeqcpp/ZedGraph.dll") + set_target_properties(IPhreeqc PROPERTIES COMMON_LANGUAGE_RUNTIME "") + target_compile_definitions(IPhreeqc PRIVATE "MULTICHART") endif() # install -if (STANDALONE_BUILD EQUAL 1) - install(TARGETS IPhreeqc DESTINATION ${CMAKE_INSTALL_LIBDIR}) +# if (WIN32) +# if (BUILD_CLR_LIBS) +# if ("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) +# SET(CMAKE_INSTALL_LIBDIR "clrx64") +# else() +# SET(CMAKE_INSTALL_LIBDIR "clr") +# endif() +# else() +# if ("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) +# if (BUILD_SHARED_LIBS) +# SET(CMAKE_INSTALL_LIBDIR "dllx64") +# else() +# SET(CMAKE_INSTALL_LIBDIR "libx64") +# endif() +# else() +# if (BUILD_SHARED_LIBS) +# SET(CMAKE_INSTALL_LIBDIR "dll") +# else() +# SET(CMAKE_INSTALL_LIBDIR "lib") +# endif() +# endif() +# endif() +# endif() + +# install +if (STANDALONE_BUILD) + # install(TARGETS IPhreeqc DESTINATION ${CMAKE_INSTALL_LIBDIR}) + + #{{ + + include(CMakePackageConfigHelpers) + + configure_package_config_file(IPhreeqcConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/IPhreeqcConfig.cmake + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/IPhreeqc + ) + + write_basic_package_version_file("IPhreeqcConfigVersion.cmake" + VERSION 3.2.0 + COMPATIBILITY SameMajorVersion + ) + + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/IPhreeqcConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/IPhreeqcConfigVersion.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/IPhreeqc + ) + + install(TARGETS IPhreeqc + EXPORT IPhreeqcTargets + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + ) + install(EXPORT IPhreeqcTargets + FILE IPhreeqcTargets.cmake + NAMESPACE IPhreeqc:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/IPhreeqc + ) + ##}} + install(FILES ${IPhreeqc_Headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) - if (WIN32) - install(FILES ${IPhreeqc_SRC} DESTINATION src) - else() - install(FILES ${IPhreeqc_SRC} DESTINATION ${CMAKE_INSTALL_DOCDIR}/src) - endif() - if (BUILD_CLR_LIBS) - install(FILES "${PROJECT_SOURCE_DIR}/src/phreeqcpp/ZedGraph.dll" DESTINATION ${CMAKE_INSTALL_LIBDIR}) - endif() + # if (WIN32) + # install(FILES ${IPhreeqc_SRC} DESTINATION src) + # else() + # install(FILES ${IPhreeqc_SRC} DESTINATION ${CMAKE_INSTALL_DOCDIR}/src) + # endif() + # if (BUILD_CLR_LIBS) + # install(FILES "${PROJECT_SOURCE_DIR}/src/phreeqcpp/ZedGraph.dll" DESTINATION ${CMAKE_INSTALL_LIBDIR}) + # endif() endif() ##IF(MSVC) @@ -350,54 +414,74 @@ endif() ## ) ##ENDIF(MSVC) -if (STANDALONE_BUILD EQUAL 1 AND MSVC) - option (IPHREEQC_STATIC_RUNTIME "Build with a static runtime" OFF) - if (IPHREEQC_STATIC_RUNTIME) - # compile with static runtime - - set(CompilerFlags - CMAKE_CXX_FLAGS - CMAKE_CXX_FLAGS_DEBUG - CMAKE_CXX_FLAGS_RELEASE - CMAKE_CXX_FLAGS_MINSIZEREL - CMAKE_CXX_FLAGS_RELWITHDEBINFO - CMAKE_C_FLAGS - CMAKE_C_FLAGS_DEBUG - CMAKE_C_FLAGS_RELEASE - CMAKE_C_FLAGS_MINSIZEREL - CMAKE_C_FLAGS_RELWITHDEBINFO - ) - - foreach(CompilerFlag ${CompilerFlags}) - if(${CompilerFlag} MATCHES "/MD") - string(REGEX REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}") - endif() - endforeach() - - set(FortranCompilerFlags - CMAKE_Fortran_FLAGS - ) - - foreach(FortranCompilerFlags ${FortranCompilerFlags}) - if(${FortranCompilerFlags} MATCHES "/libs:dll") - string(REGEX REPLACE "/libs:dll" "/libs:static" ${FortranCompilerFlags} "${${FortranCompilerFlags}}") - endif() - endforeach() - endif() +if (BUILD_CLR_LIBS AND IPHREEQC_STATIC_RUNTIME) + message(FATAL_ERROR "BUILD_CLR_LIBS and IPHREEQC_STATIC_RUNTIME are mutually exclusive") endif() -if (STANDALONE_BUILD EQUAL 1) - # tests - enable_testing() +if (EXISTS "${PROJECT_SOURCE_DIR}/CTestConfig.cmake") + # enable dashboard scripting + include (CTest) +endif() + +if (STANDALONE_BUILD) add_subdirectory(database) add_subdirectory(doc) add_subdirectory(examples) - add_subdirectory(tests) - if (EXISTS "${PROJECT_SOURCE_DIR}/CTestConfig.cmake") - # enable dashboard scripting - include (CTest) + if (BUILD_TESTING) + add_subdirectory(tests) + endif() + + + if (BUILD_TESTING) + include(FetchContent) + + FetchContent_Declare( + googletest + URL https://github.com/google/googletest/archive/release-1.8.1.tar.gz + URL_HASH MD5=2e6fbeb6a91310a16efe181886c59596 + ) + + mark_as_advanced( + FETCHCONTENT_BASE_DIR + FETCHCONTENT_FULLY_DISCONNECTED + FETCHCONTENT_QUIET + FETCHCONTENT_SOURCE_DIR_GOOGLETEST + FETCHCONTENT_UPDATES_DISCONNECTED + FETCHCONTENT_UPDATES_DISCONNECTED_GOOGLETEST + ) + + # Prevent GoogleTest from overriding our compiler/linker options + # when building with Visual Studio + set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + + set(BUILD_GTEST ON CACHE BOOL "" FORCE) + set(BUILD_GMOCK OFF CACHE BOOL "" FORCE) + + set(INSTALL_GTEST OFF CACHE BOOL "" FORCE) + set(INSTALL_GMOCK OFF CACHE BOOL "" FORCE) + + mark_as_advanced( + BUILD_GTEST + BUILD_GMOCK + INSTALL_GTEST + INSTALL_GMOCK + gmock_build_tests + gtest_build_tests + gtest_build_samples + gtest_disable_pthreads + gtest_force_shared_crt + gtest_hide_internal_symbols + ) + + FetchContent_GetProperties(googletest) + if (NOT googletest_POPULATED) + FetchContent_Populate(googletest) + add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR}) + endif() + + add_subdirectory(gtest) endif() # enable distribution creation diff --git a/IPhreeqcConfig.cmake.in b/IPhreeqcConfig.cmake.in new file mode 100644 index 00000000..d1b7ad25 --- /dev/null +++ b/IPhreeqcConfig.cmake.in @@ -0,0 +1,4 @@ +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/IPhreeqcTargets.cmake") +check_required_components("IPhreeqc") diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index cd83cafc..0eb83b12 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -1,3 +1,27 @@ +if (EXISTS ${CMAKE_SOURCE_DIR}/.git) + if (NOT EXISTS ${CMAKE_SOURCE_DIR}/doc/html) + file(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/doc/html) + endif() + + if (NOT EXISTS ${CMAKE_SOURCE_DIR}/doc/NOTICE) + file(COPY ${CMAKE_SOURCE_DIR}/phreeqc3-doc/NOTICE.TXT + DESTINATION ${CMAKE_SOURCE_DIR}/doc) + file(RENAME ${CMAKE_SOURCE_DIR}/doc/NOTICE.TXT ${CMAKE_SOURCE_DIR}/doc/NOTICE) + endif() + + if (NOT EXISTS ${CMAKE_SOURCE_DIR}/doc/README) + file(COPY ${CMAKE_SOURCE_DIR}/phreeqc3-doc/README.IPhreeqc.TXT + DESTINATION ${CMAKE_SOURCE_DIR}/doc) + file(RENAME ${CMAKE_SOURCE_DIR}/doc/README.IPhreeqc.TXT ${CMAKE_SOURCE_DIR}/doc/README) + endif() + + if (NOT EXISTS ${CMAKE_SOURCE_DIR}/doc/RELEASE) + file(COPY ${CMAKE_SOURCE_DIR}/phreeqc3-doc/RELEASE.TXT + DESTINATION ${CMAKE_SOURCE_DIR}/doc) + file(RENAME ${CMAKE_SOURCE_DIR}/doc/RELEASE.TXT ${CMAKE_SOURCE_DIR}/doc/RELEASE) + endif() +endif() + SET(IPhreeqc_Docs IPhreeqc.pdf NOTICE @@ -6,5 +30,6 @@ Phreeqc_3_2013_manual.pdf README RELEASE ) + install(FILES ${IPhreeqc_Docs} DESTINATION ${CMAKE_INSTALL_DOCDIR}) install(DIRECTORY html/ DESTINATION ${CMAKE_INSTALL_DOCDIR}/html) diff --git a/examples/using-cmake/CMakeLists.txt b/examples/using-cmake/CMakeLists.txt new file mode 100644 index 00000000..6a6e4759 --- /dev/null +++ b/examples/using-cmake/CMakeLists.txt @@ -0,0 +1,20 @@ +# set minimum cmake version +cmake_minimum_required(VERSION 3.10) + +# set project name along with language +project(cmake-example CXX) + +# copy necessary files into build directory +configure_file(phreeqc.dat phreeqc.dat COPYONLY) +configure_file(ex2 ex2 COPYONLY) + +# find IPhreeqc export package +# set CMAKE_PREFIX_PATH or IPhreeqc_DIR to the +# location of the IPhreeqcConfig.cmake file +find_package(IPhreeqc) + +# add executable target +add_executable(example main.cpp) + +# set link libraries as well as include paths +target_link_libraries(example IPhreeqc::IPhreeqc) diff --git a/examples/using-cmake/README.txt b/examples/using-cmake/README.txt new file mode 100644 index 00000000..e27e8bd3 --- /dev/null +++ b/examples/using-cmake/README.txt @@ -0,0 +1,18 @@ +Example usage + +Configure, build and install IPhreeqc + +1. cd iphreeqc-3.6.2-15100 +2. mkdir _build +3. cd _build +4. cmake -DCMAKE_INSTALL_PREFIX:PATH=c:/Users/charlton/iphreeqc .. +5. cmake --build . --config release +6. ctest . +6. cmake --build . --config release --target install + +Build example: + +1. cd c:\Users\charlton\iphreeqc\examples\using-cmake +2. mkdir _build +3. cmake -DCMAKE_PREFIX_PATH:PATH=c:/Users/charlton/iphreeqc/lib/cmake/IPhreeqc .. +4. cmake --build . --config release \ No newline at end of file diff --git a/examples/using-cmake/ex2 b/examples/using-cmake/ex2 new file mode 100644 index 00000000..b4d44925 --- /dev/null +++ b/examples/using-cmake/ex2 @@ -0,0 +1,26 @@ +TITLE Example 2.--Temperature dependence of solubility + of gypsum and anhydrite +SOLUTION 1 Pure water + pH 7.0 + temp 25.0 +EQUILIBRIUM_PHASES 1 + Gypsum 0.0 1.0 + Anhydrite 0.0 1.0 +REACTION_TEMPERATURE 1 + 25.0 75.0 in 51 steps +SELECTED_OUTPUT + -file ex2.sel + -temperature + -si anhydrite gypsum +USER_GRAPH 1 Example 2 + -headings Temperature Gypsum Anhydrite + -chart_title "Gypsum-Anhydrite Stability" + -axis_scale x_axis 25 75 5 0 + -axis_scale y_axis auto 0.05 0.1 + -axis_titles "Temperature, in degrees celsius" "Saturation index" + -initial_solutions false + -start + 10 graph_x TC + 20 graph_y SI("Gypsum") SI("Anhydrite") + -end +END diff --git a/examples/using-cmake/main.cpp b/examples/using-cmake/main.cpp new file mode 100644 index 00000000..5fe06983 --- /dev/null +++ b/examples/using-cmake/main.cpp @@ -0,0 +1,18 @@ +#include +#include + +int main (void) +{ + IPhreeqc iphreeqc; + if (iphreeqc.LoadDatabase("phreeqc.dat") != 0) + { + std::cout << iphreeqc.GetErrorString(); + return EXIT_FAILURE; + } + if (iphreeqc.RunFile("ex2") != 0) + { + std::cout << iphreeqc.GetErrorString(); + return EXIT_FAILURE; + } + return 0; +} \ No newline at end of file diff --git a/examples/using-cmake/phreeqc.dat b/examples/using-cmake/phreeqc.dat new file mode 100644 index 00000000..0873e31a --- /dev/null +++ b/examples/using-cmake/phreeqc.dat @@ -0,0 +1,1837 @@ +# PHREEQC.DAT for calculating pressure dependence of reactions, with +# molal volumina of aqueous species and of minerals, and +# critical temperatures and pressures of gases used in Peng-Robinson's EOS. +# Details are given at the end of this file. + +SOLUTION_MASTER_SPECIES +# +#element species alk gfw_formula element_gfw +# +H H+ -1.0 H 1.008 +H(0) H2 0 H +H(1) H+ -1.0 0 +E e- 0 0.0 0 +O H2O 0 O 16.0 +O(0) O2 0 O +O(-2) H2O 0 0 +Ca Ca+2 0 Ca 40.08 +Mg Mg+2 0 Mg 24.312 +Na Na+ 0 Na 22.9898 +K K+ 0 K 39.102 +Fe Fe+2 0 Fe 55.847 +Fe(+2) Fe+2 0 Fe +Fe(+3) Fe+3 -2.0 Fe +Mn Mn+2 0 Mn 54.938 +Mn(+2) Mn+2 0 Mn +Mn(+3) Mn+3 0 Mn +Al Al+3 0 Al 26.9815 +Ba Ba+2 0 Ba 137.34 +Sr Sr+2 0 Sr 87.62 +Si H4SiO4 0 SiO2 28.0843 +Cl Cl- 0 Cl 35.453 +C CO3-2 2.0 HCO3 12.0111 +C(+4) CO3-2 2.0 HCO3 +C(-4) CH4 0 CH4 +Alkalinity CO3-2 1.0 Ca0.5(CO3)0.5 50.05 +S SO4-2 0 SO4 32.064 +S(6) SO4-2 0 SO4 +S(-2) HS- 1.0 S +N NO3- 0 N 14.0067 +N(+5) NO3- 0 N +N(+3) NO2- 0 N +N(0) N2 0 N +N(-3) NH4+ 0 N 14.0067 +#Amm AmmH+ 0 AmmH 17.031 +B H3BO3 0 B 10.81 +P PO4-3 2.0 P 30.9738 +F F- 0 F 18.9984 +Li Li+ 0 Li 6.939 +Br Br- 0 Br 79.904 +Zn Zn+2 0 Zn 65.37 +Cd Cd+2 0 Cd 112.4 +Pb Pb+2 0 Pb 207.19 +Cu Cu+2 0 Cu 63.546 +Cu(+2) Cu+2 0 Cu +Cu(+1) Cu+1 0 Cu +# redox-uncoupled gases +Hdg Hdg 0 Hdg 2.016 # H2 gas +Oxg Oxg 0 Oxg 32 # O2 gas +Mtg Mtg 0 Mtg 16.032 # CH4 gas +Sg H2Sg 1.0 H2Sg 34.08 +Ntg Ntg 0 Ntg 28.0134 # N2 gas + +SOLUTION_SPECIES +H+ = H+ + -gamma 9.0 0 + -dw 9.31e-9 1000 0.46 1e-10 # The dw parameters are defined in ref. 3. +# Dw(TK) = 9.31e-9 * exp(1000 / TK - 1000 / 298.15) * TK * 0.89 / (298.15 * viscos) +# Dw(I) = Dw(TK) * exp(-0.46 * DH_A * |z_H+| * I^0.5 / (1 + DH_B * I^0.5 * 1e-10 / (1 + I^0.75))) +e- = e- +H2O = H2O +# H2O + 0.01e- = H2O-0.01; -log_k -9 # aids convergence +Ca+2 = Ca+2 + -gamma 5.0 0.1650 + -dw 0.793e-9 97 3.4 24.6 + -Vm -0.3456 -7.252 6.149 -2.479 1.239 5 1.60 -57.1 -6.12e-3 1 # ref. 1 +Mg+2 = Mg+2 + -gamma 5.5 0.20 + -dw 0.705e-9 111 2.4 13.7 + -Vm -1.410 -8.6 11.13 -2.39 1.332 5.5 1.29 -32.9 -5.86e-3 1 # ref. 1 +Na+ = Na+ + -gamma 4.0 0.075 + -gamma 4.08 0.082 # halite solubility + -dw 1.33e-9 122 1.52 3.70 + -Vm 2.28 -4.38 -4.1 -0.586 0.09 4 0.3 52 -3.33e-3 0.566 # ref. 1 +# for calculating densities (rho) when I > 3... + # -Vm 2.28 -4.38 -4.1 -0.586 0.09 4 0.3 52 -3.33e-3 0.45 +K+ = K+ + -gamma 3.5 0.015 + -dw 1.96e-9 395 2.5 21 + -Vm 3.322 -1.473 6.534 -2.712 9.06e-2 3.5 0 29.7 0 1 # ref. 1 +Fe+2 = Fe+2 + -gamma 6.0 0 + -dw 0.719e-9 + -Vm -0.3255 -9.687 1.536 -2.379 0.3033 6 -4.21e-2 39.7 0 1 # ref. 1 +Mn+2 = Mn+2 + -gamma 6.0 0 + -dw 0.688e-9 + -Vm -1.10 -8.03 4.08 -2.45 1.4 6 8.07 0 -1.51e-2 0.118 # ref. 2 +Al+3 = Al+3 + -gamma 9.0 0 + -dw 0.559e-9 + -Vm -2.28 -17.1 10.9 -2.07 2.87 9 0 0 5.5e-3 1 # ref. 2 and Barta and Hepler, 1986, Can. J.C. 64, 353. +Ba+2 = Ba+2 + -gamma 5.0 0 + -gamma 4.0 0.153 # Barite solubility + -dw 0.848e-9 46 + -Vm 2.063 -10.06 1.9534 -2.36 0.4218 5 1.58 -12.03 -8.35e-3 1 # ref. 1 +Sr+2 = Sr+2 + -gamma 5.260 0.121 + -dw 0.794e-9 161 + -Vm -1.57e-2 -10.15 10.18 -2.36 0.860 5.26 0.859 -27.0 -4.1e-3 1.97 # ref. 1 +H4SiO4 = H4SiO4 + -dw 1.10e-9 + -Vm 10.5 1.7 20 -2.7 0.1291 # supcrt + 2*H2O in a1 +Cl- = Cl- + -gamma 3.5 0.015 + -gamma 3.63 0.017 # cf. pitzer.dat + -dw 2.03e-9 194 1.6 6.9 + -Vm 4.465 4.801 4.325 -2.847 1.748 0 -0.331 20.16 0 1 # ref. 1 +CO3-2 = CO3-2 + -gamma 5.4 0 + -dw 0.955e-9 0 1.12 2.84 + -Vm 5.95 0 0 -5.67 6.85 0 1.37 106 -0.0343 1 # ref. 1 +SO4-2 = SO4-2 + -gamma 5.0 -0.04 + -dw 1.07e-9 34 2.08 13.4 + -Vm 8.0 2.3 -46.04 6.245 3.82 0 0 0 0 1 # ref. 1 +NO3- = NO3- + -gamma 3.0 0 + -dw 1.9e-9 184 1.85 3.85 + -Vm 6.32 6.78 0 -3.06 0.346 0 0.93 0 -0.012 1 # ref. 1 +#AmmH+ = AmmH+ +# -gamma 2.5 0 +# -dw 1.98e-9 312 0.95 4.53 +# -Vm 4.837 2.345 5.522 -2.88 1.096 3 -1.456 75.0 7.17e-3 1 # ref. 1 +H3BO3 = H3BO3 + -dw 1.1e-9 + -Vm 7.0643 8.8547 3.5844 -3.1451 -.2000 # supcrt +PO4-3 = PO4-3 + -gamma 4.0 0 + -dw 0.612e-9 + -Vm 1.24 -9.07 9.31 -2.4 5.61 0 0 0 -1.41e-2 1 # ref. 2 +F- = F- + -gamma 3.5 0 + -dw 1.46e-9 + -Vm 0.928 1.36 6.27 -2.84 1.84 0 0 -0.318 0 1 # ref. 2 +Li+ = Li+ + -gamma 6.0 0 + -dw 1.03e-9 80 + -Vm -0.419 -0.069 13.16 -2.78 0.416 0 0.296 -12.4 -2.74e-3 1.26 # ref. 2 and Ellis, 1968, J. Chem. Soc. A, 1138 +Br- = Br- + -gamma 3.0 0 + -dw 2.01e-9 258 + -Vm 6.72 2.85 4.21 -3.14 1.38 0 -9.56e-2 7.08 -1.56e-3 1 # ref. 2 +Zn+2 = Zn+2 + -gamma 5.0 0 + -dw 0.715e-9 + -Vm -1.96 -10.4 14.3 -2.35 1.46 5 -1.43 24 1.67e-2 1.11 # ref. 2 +Cd+2 = Cd+2 + -dw 0.717e-9 + -Vm 1.63 -10.7 1.01 -2.34 1.47 5 0 0 0 1 # ref. 2 +Pb+2 = Pb+2 + -dw 0.945e-9 + -Vm -.0051 -7.7939 8.8134 -2.4568 1.0788 4.5 # supcrt +Cu+2 = Cu+2 + -gamma 6.0 0 + -dw 0.733e-9 + -Vm -1.13 -10.5 7.29 -2.35 1.61 6 9.78e-2 0 3.42e-3 1 # ref. 2 +# redox-uncoupled gases +Hdg = Hdg # H2 + -dw 5.13e-9 + -Vm 6.52 0.78 0.12 # supcrt +Oxg = Oxg # O2 + -dw 2.35e-9 + -Vm 5.7889 6.3536 3.2528 -3.0417 -0.3943 # supcrt +Mtg = Mtg # CH4 + -dw 1.85e-9 + -Vm 9.01 -1.11 0 -1.85 -1.50 # ref. 1 + Hnedkovsky et al., 1996, JCT 28, 125 +Ntg = Ntg # N2 + -dw 1.96e-9 + -Vm 7 # Pray et al., 1952, IEC 44. 1146 +H2Sg = H2Sg # H2S + -dw 2.1e-9 + -Vm 7.81 2.96 -0.46 # supcrt +# aqueous species +H2O = OH- + H+ + -analytic 293.29227 0.1360833 -10576.913 -123.73158 0 -6.996455e-5 + -gamma 3.5 0 + -dw 5.27e-9 548 0.52 1e-10 + -Vm -9.66 28.5 80.0 -22.9 1.89 0 1.09 0 0 1 # ref. 1 +2 H2O = O2 + 4 H+ + 4 e- + -log_k -86.08 + -delta_h 134.79 kcal + -dw 2.35e-9 + -Vm 5.7889 6.3536 3.2528 -3.0417 -0.3943 # supcrt +2 H+ + 2 e- = H2 + -log_k -3.15 + -delta_h -1.759 kcal + -dw 5.13e-9 + -Vm 6.52 0.78 0.12 # supcrt +CO3-2 + H+ = HCO3- + -log_k 10.329 + -delta_h -3.561 kcal + -analytic 107.8871 0.03252849 -5151.79 -38.92561 563713.9 + -gamma 5.4 0 + -dw 1.18e-9 0 1.43 1e-10 + -Vm 8.472 0 -11.5 0 1.56 0 0 146 3.16e-3 1 # ref. 1 +CO3-2 + 2 H+ = CO2 + H2O + -log_k 16.681 + -delta_h -5.738 kcal + -analytic 464.1965 0.09344813 -26986.16 -165.75951 2248628.9 + -dw 1.92e-9 + -Vm 7.29 0.92 2.07 -1.23 -1.60 # ref. 1 + McBride et al. 2015, JCED 60, 171 +2CO2 = (CO2)2 # activity correction for CO2 solubility at high P, T + -log_k -1.8 + -analytical_expression 8.68 -0.0103 -2190 + -Vm 14.58 1.84 4.14 -2.46 -3.20 +CO3-2 + 10 H+ + 8 e- = CH4 + 3 H2O + -log_k 41.071 + -delta_h -61.039 kcal + -dw 1.85e-9 + -Vm 9.01 -1.11 0 -1.85 -1.50 # ref. 1 + Hnedkovsky et al., 1996, JCT 28, 125 +SO4-2 + H+ = HSO4- + -log_k 1.988 + -delta_h 3.85 kcal + -analytic -56.889 0.006473 2307.9 19.8858 + -dw 1.33e-9 + -Vm 8.2 9.2590 2.1108 -3.1618 1.1748 0 -0.3 15 0 1 # ref. 1 +HS- = S-2 + H+ + -log_k -12.918 + -delta_h 12.1 kcal + -gamma 5.0 0 + -dw 0.731e-9 +SO4-2 + 9 H+ + 8 e- = HS- + 4 H2O + -log_k 33.65 + -delta_h -60.140 kcal + -gamma 3.5 0 + -dw 1.73e-9 + -Vm 5.0119 4.9799 3.4765 -2.9849 1.4410 # supcrt +HS- + H+ = H2S + -log_k 6.994 + -delta_h -5.30 kcal + -analytical -11.17 0.02386 3279.0 + -dw 2.1e-9 + -Vm 7.81 2.96 -0.46 # supcrt +H2Sg = HSg- + H+ + -log_k -6.994 + -delta_h 5.30 kcal + -analytical 11.17 -0.02386 -3279.0 + -dw 1.73e-9 + -Vm 5.0119 4.9799 3.4765 -2.9849 1.4410 # supcrt +NO3- + 2 H+ + 2 e- = NO2- + H2O + -log_k 28.570 + -delta_h -43.760 kcal + -gamma 3.0 0 + -dw 1.91e-9 + -Vm 5.5864 5.8590 3.4472 -3.0212 1.1847 # supcrt +2 NO3- + 12 H+ + 10 e- = N2 + 6 H2O + -log_k 207.08 + -delta_h -312.130 kcal + -dw 1.96e-9 + -Vm 7 # Pray et al., 1952, IEC 44. 1146 +NO3- + 10 H+ + 8 e- = NH4+ + 3 H2O + -log_k 119.077 + -delta_h -187.055 kcal + -gamma 2.5 0 + -dw 1.98e-9 312 0.95 4.53 + -Vm 4.837 2.345 5.522 -2.88 1.096 3 -1.456 75.0 7.17e-3 1 # ref. 1 + +NH4+ = NH3 + H+ + -log_k -9.252 + -delta_h 12.48 kcal + -analytic 0.6322 -0.001225 -2835.76 + -dw 2.28e-9 + -Vm 6.69 2.8 3.58 -2.88 1.43 # ref. 2 +#NO3- + 10 H+ + 8 e- = AmmH+ + 3 H2O +# -log_k 119.077 +# -delta_h -187.055 kcal +# -gamma 2.5 0 +# -Vm 4.837 2.345 5.522 -2.88 1.096 3 -1.456 75.0 7.17e-3 1 # ref. 1 + +#AmmH+ + SO4-2 = AmmHSO4- +NH4+ + SO4-2 = NH4SO4- + -log_k 1.11 + -Vm 14.0 0 -35.2 0 0 0 12.3 0 -0.141 1 # ref. 2 +H3BO3 = H2BO3- + H+ + -log_k -9.24 + -delta_h 3.224 kcal +H3BO3 + F- = BF(OH)3- + -log_k -0.4 + -delta_h 1.850 kcal +H3BO3 + 2 F- + H+ = BF2(OH)2- + H2O + -log_k 7.63 + -delta_h 1.618 kcal +H3BO3 + 2 H+ + 3 F- = BF3OH- + 2 H2O + -log_k 13.67 + -delta_h -1.614 kcal +H3BO3 + 3 H+ + 4 F- = BF4- + 3 H2O + -log_k 20.28 + -delta_h -1.846 kcal +PO4-3 + H+ = HPO4-2 + -log_k 12.346 + -delta_h -3.530 kcal + -gamma 5.0 0 + -dw 0.69e-9 + -Vm 3.52 1.09 8.39 -2.82 3.34 0 0 0 0 1 # ref. 2 +PO4-3 + 2 H+ = H2PO4- + -log_k 19.553 + -delta_h -4.520 kcal + -gamma 5.4 0 + -dw 0.846e-9 + -Vm 5.58 8.06 12.2 -3.11 1.3 0 0 0 1.62e-2 1 # ref. 2 +PO4-3 + 3H+ = H3PO4 + log_k 21.721 # log_k and delta_h from minteq.v4.dat, NIST46.3 + delta_h -10.1 kJ + -Vm 7.47 12.4 6.29 -3.29 0 # ref. 2 +H+ + F- = HF + -log_k 3.18 + -delta_h 3.18 kcal + -analytic -2.033 0.012645 429.01 + -Vm 3.4753 .7042 5.4732 -2.8081 -.0007 # supcrt +H+ + 2 F- = HF2- + -log_k 3.76 + -delta_h 4.550 kcal + -Vm 5.2263 4.9797 3.7928 -2.9849 1.2934 # supcrt +Ca+2 + H2O = CaOH+ + H+ + -log_k -12.78 +Ca+2 + CO3-2 = CaCO3 + -log_k 3.224 + -delta_h 3.545 kcal + -analytic -1228.732 -0.299440 35512.75 485.818 + -dw 4.46e-10 # complexes: calc'd with the Pikal formula + -Vm -.2430 -8.3748 9.0417 -2.4328 -.0300 # supcrt +Ca+2 + CO3-2 + H+ = CaHCO3+ + -log_k 11.435 + -delta_h -0.871 kcal + -analytic 1317.0071 0.34546894 -39916.84 -517.70761 563713.9 + -gamma 6.0 0 + -dw 5.06e-10 + -Vm 3.1911 .0104 5.7459 -2.7794 .3084 5.4 # supcrt +Ca+2 + SO4-2 = CaSO4 + -log_k 2.25 + -delta_h 1.325 kcal + -dw 4.71e-10 + -Vm 2.7910 -.9666 6.1300 -2.7390 -.0010 # supcrt +Ca+2 + HSO4- = CaHSO4+ + -log_k 1.08 +Ca+2 + PO4-3 = CaPO4- + -log_k 6.459 + -delta_h 3.10 kcal + -gamma 5.4 0.0 +Ca+2 + HPO4-2 = CaHPO4 + -log_k 2.739 + -delta_h 3.3 kcal +Ca+2 + H2PO4- = CaH2PO4+ + -log_k 1.408 + -delta_h 3.4 kcal + -gamma 5.4 0.0 +# Ca+2 + F- = CaF+ + # -log_k 0.94 + # -delta_h 4.120 kcal + # -gamma 5.5 0.0 + # -Vm .9846 -5.3773 7.8635 -2.5567 .6911 5.5 # supcrt +Mg+2 + H2O = MgOH+ + H+ + -log_k -11.44 + -delta_h 15.952 kcal + -gamma 6.5 0 +Mg+2 + CO3-2 = MgCO3 + -log_k 2.98 + -delta_h 2.713 kcal + -analytic 0.9910 0.00667 + -dw 4.21e-10 + -Vm -.5837 -9.2067 9.3687 -2.3984 -.0300 # supcrt +Mg+2 + H+ + CO3-2 = MgHCO3+ + -log_k 11.399 + -delta_h -2.771 kcal + -analytic 48.6721 0.03252849 -2614.335 -18.00263 563713.9 + -gamma 4.0 0 + -dw 4.78e-10 + -Vm 2.7171 -1.1469 6.2008 -2.7316 .5985 4 # supcrt +Mg+2 + SO4-2 = MgSO4 + -log_k 2.37 + -delta_h 4.550 kcal + -dw 4.45e-10 + -Vm 2.4 -0.97 6.1 -2.74 # est'd +Mg+2 + PO4-3 = MgPO4- + -log_k 6.589 + -delta_h 3.10 kcal + -gamma 5.4 0 +Mg+2 + HPO4-2 = MgHPO4 + -log_k 2.87 + -delta_h 3.3 kcal +Mg+2 + H2PO4- = MgH2PO4+ + -log_k 1.513 + -delta_h 3.4 kcal + -gamma 5.4 0 +Mg+2 + F- = MgF+ + -log_k 1.82 + -delta_h 3.20 kcal + -gamma 4.5 0 + -Vm .6494 -6.1958 8.1852 -2.5229 .9706 4.5 # supcrt +Na+ + OH- = NaOH + -log_k -10 # remove this complex +Na+ + CO3-2 = NaCO3- + -log_k 1.27 + -delta_h 8.91 kcal + -dw 1.2e-9 0 1e-10 1e-10 + -Vm 3.89 -8.23e-4 20 -9.44 3.02 9.05e-3 3.07 0 0.0233 1 # ref. 1 +Na+ + HCO3- = NaHCO3 + -log_k -0.25 + -delta_h -1 kcal + -dw 6.73e-10 + -Vm 0.431 # ref. 1 +Na+ + SO4-2 = NaSO4- + -log_k 0.7 + -delta_h 1.120 kcal + -gamma 5.4 0 + -dw 1.33e-9 0 0.57 1e-10 + -Vm 1e-5 16.4 -0.0678 -1.05 4.14 0 6.86 0 0.0242 0.53 # ref. 1 +Na+ + HPO4-2 = NaHPO4- + -log_k 0.29 + -gamma 5.4 0 + -Vm 5.2 8.1 13 -3 0.9 0 0 1.62e-2 1 # ref. 2 +Na+ + F- = NaF + -log_k -0.24 + -Vm 2.7483 -1.0708 6.1709 -2.7347 -.030 # supcrt +K+ + SO4-2 = KSO4- + -log_k 0.85 + -delta_h 2.250 kcal + -analytical 3.106 0.0 -673.6 + -gamma 5.4 0 + -dw 1.5e-9 0 1e-10 1e10 + -Vm 6.8 7.06 3.0 -2.07 1.1 0 0 0 0 1 # ref. 1 +K+ + HPO4-2 = KHPO4- + -log_k 0.29 + -gamma 5.4 0 + -Vm 5.4 8.1 19 -3.1 0.7 0 0 0 1.62e-2 1 # ref. 2 +Fe+2 + H2O = FeOH+ + H+ + -log_k -9.5 + -delta_h 13.20 kcal + -gamma 5.0 0 +Fe+2 + 3H2O = Fe(OH)3- + 3H+ + -log_k -31.0 + -delta_h 30.3 kcal + -gamma 5.0 0 +Fe+2 + Cl- = FeCl+ + -log_k 0.14 +Fe+2 + CO3-2 = FeCO3 + -log_k 4.38 +Fe+2 + HCO3- = FeHCO3+ + -log_k 2.0 +Fe+2 + SO4-2 = FeSO4 + -log_k 2.25 + -delta_h 3.230 kcal + -Vm -13 0 123 # ref. 2 +Fe+2 + HSO4- = FeHSO4+ + -log_k 1.08 +Fe+2 + 2HS- = Fe(HS)2 + -log_k 8.95 +Fe+2 + 3HS- = Fe(HS)3- + -log_k 10.987 +Fe+2 + HPO4-2 = FeHPO4 + -log_k 3.6 +Fe+2 + H2PO4- = FeH2PO4+ + -log_k 2.7 + -gamma 5.4 0 +Fe+2 + F- = FeF+ + -log_k 1.0 +Fe+2 = Fe+3 + e- + -log_k -13.02 + -delta_h 9.680 kcal + -gamma 9.0 0 +Fe+3 + H2O = FeOH+2 + H+ + -log_k -2.19 + -delta_h 10.4 kcal + -gamma 5.0 0 +Fe+3 + 2 H2O = Fe(OH)2+ + 2 H+ + -log_k -5.67 + -delta_h 17.1 kcal + -gamma 5.4 0 +Fe+3 + 3 H2O = Fe(OH)3 + 3 H+ + -log_k -12.56 + -delta_h 24.8 kcal +Fe+3 + 4 H2O = Fe(OH)4- + 4 H+ + -log_k -21.6 + -delta_h 31.9 kcal + -gamma 5.4 0 +Fe+2 + 2H2O = Fe(OH)2 + 2H+ + -log_k -20.57 + -delta_h 28.565 kcal +2 Fe+3 + 2 H2O = Fe2(OH)2+4 + 2 H+ + -log_k -2.95 + -delta_h 13.5 kcal +3 Fe+3 + 4 H2O = Fe3(OH)4+5 + 4 H+ + -log_k -6.3 + -delta_h 14.3 kcal +Fe+3 + Cl- = FeCl+2 + -log_k 1.48 + -delta_h 5.6 kcal + -gamma 5.0 0 +Fe+3 + 2 Cl- = FeCl2+ + -log_k 2.13 + -gamma 5.0 0 +Fe+3 + 3 Cl- = FeCl3 + -log_k 1.13 +Fe+3 + SO4-2 = FeSO4+ + -log_k 4.04 + -delta_h 3.91 kcal + -gamma 5.0 0 +Fe+3 + HSO4- = FeHSO4+2 + -log_k 2.48 +Fe+3 + 2 SO4-2 = Fe(SO4)2- + -log_k 5.38 + -delta_h 4.60 kcal +Fe+3 + HPO4-2 = FeHPO4+ + -log_k 5.43 + -delta_h 5.76 kcal + -gamma 5.0 0 +Fe+3 + H2PO4- = FeH2PO4+2 + -log_k 5.43 + -gamma 5.4 0 +Fe+3 + F- = FeF+2 + -log_k 6.2 + -delta_h 2.7 kcal + -gamma 5.0 0 +Fe+3 + 2 F- = FeF2+ + -log_k 10.8 + -delta_h 4.8 kcal + -gamma 5.0 0 +Fe+3 + 3 F- = FeF3 + -log_k 14.0 + -delta_h 5.4 kcal +Mn+2 + H2O = MnOH+ + H+ + -log_k -10.59 + -delta_h 14.40 kcal + -gamma 5.0 0 +Mn+2 + 3H2O = Mn(OH)3- + 3H+ + -log_k -34.8 + -gamma 5.0 0 +Mn+2 + Cl- = MnCl+ + -log_k 0.61 + -gamma 5.0 0 + -Vm 7.25 -1.08 -25.8 -2.73 3.99 5 0 0 0 1 # ref. 2 +Mn+2 + 2 Cl- = MnCl2 + -log_k 0.25 + -Vm 1e-5 0 144 # ref. 2 +Mn+2 + 3 Cl- = MnCl3- + -log_k -0.31 + -gamma 5.0 0 + -Vm 11.8 0 0 0 2.4 0 0 0 3.6e-2 1 # ref. 2 +Mn+2 + CO3-2 = MnCO3 + -log_k 4.9 +Mn+2 + HCO3- = MnHCO3+ + -log_k 1.95 + -gamma 5.0 0 +Mn+2 + SO4-2 = MnSO4 + -log_k 2.25 + -delta_h 3.370 kcal + -Vm -1.31 -1.83 62.3 -2.7 # ref. 2 +Mn+2 + 2 NO3- = Mn(NO3)2 + -log_k 0.6 + -delta_h -0.396 kcal + -Vm 6.16 0 29.4 0 0.9 # ref. 2 +Mn+2 + F- = MnF+ + -log_k 0.84 + -gamma 5.0 0 +Mn+2 = Mn+3 + e- + -log_k -25.51 + -delta_h 25.80 kcal + -gamma 9.0 0 +Al+3 + H2O = AlOH+2 + H+ + -log_k -5.0 + -delta_h 11.49 kcal + -analytic -38.253 0.0 -656.27 14.327 + -gamma 5.4 0 + -Vm -1.46 -11.4 10.2 -2.31 1.67 5.4 0 0 0 1 # ref. 2 and Barta and Hepler, 1986, Can. J. Chem. 64, 353. +Al+3 + 2 H2O = Al(OH)2+ + 2 H+ + -log_k -10.1 + -delta_h 26.90 kcal + -gamma 5.4 0 + -analytic 88.50 0.0 -9391.6 -27.121 +Al+3 + 3 H2O = Al(OH)3 + 3 H+ + -log_k -16.9 + -delta_h 39.89 kcal + -analytic 226.374 0.0 -18247.8 -73.597 +Al+3 + 4 H2O = Al(OH)4- + 4 H+ + -log_k -22.7 + -delta_h 42.30 kcal + -analytic 51.578 0.0 -11168.9 -14.865 + -gamma 4.5 0 +Al+3 + SO4-2 = AlSO4+ + -log_k 3.5 + -delta_h 2.29 kcal + -gamma 4.5 0 +Al+3 + 2SO4-2 = Al(SO4)2- + -log_k 5.0 + -delta_h 3.11 kcal + -gamma 4.5 0 +Al+3 + HSO4- = AlHSO4+2 + -log_k 0.46 +Al+3 + F- = AlF+2 + -log_k 7.0 + -delta_h 1.060 kcal + -gamma 5.4 0 +Al+3 + 2 F- = AlF2+ + -log_k 12.7 + -delta_h 1.980 kcal + -gamma 5.4 0 +Al+3 + 3 F- = AlF3 + -log_k 16.8 + -delta_h 2.160 kcal +Al+3 + 4 F- = AlF4- + -log_k 19.4 + -delta_h 2.20 kcal + -gamma 4.5 0 +# Al+3 + 5 F- = AlF5-2 + # log_k 20.6 + # delta_h 1.840 kcal +# Al+3 + 6 F- = AlF6-3 + # log_k 20.6 + # delta_h -1.670 kcal +H4SiO4 = H3SiO4- + H+ + -log_k -9.83 + -delta_h 6.12 kcal + -analytic -302.3724 -0.050698 15669.69 108.18466 -1119669.0 + -gamma 4 0 + -Vm 7.94 1.0881 5.3224 -2.8240 1.4767 # supcrt + H2O in a1 +H4SiO4 = H2SiO4-2 + 2 H+ + -log_k -23.0 + -delta_h 17.6 kcal + -analytic -294.0184 -0.072650 11204.49 108.18466 -1119669.0 + -gamma 5.4 0 +H4SiO4 + 4 H+ + 6 F- = SiF6-2 + 4 H2O + -log_k 30.18 + -delta_h -16.260 kcal + -gamma 5.0 0 + -Vm 8.5311 13.0492 .6211 -3.3185 2.7716 # supcrt +Ba+2 + H2O = BaOH+ + H+ + -log_k -13.47 + -gamma 5.0 0 +Ba+2 + CO3-2 = BaCO3 + -log_k 2.71 + -delta_h 3.55 kcal + -analytic 0.113 0.008721 + -Vm .2907 -7.0717 8.5295 -2.4867 -.0300 # supcrt +Ba+2 + HCO3- = BaHCO3+ + -log_k 0.982 + -delta_h 5.56 kcal + -analytic -3.0938 0.013669 +Ba+2 + SO4-2 = BaSO4 + -log_k 2.7 +Sr+2 + H2O = SrOH+ + H+ + -log_k -13.29 + -gamma 5.0 0 +Sr+2 + CO3-2 + H+ = SrHCO3+ + -log_k 11.509 + -delta_h 2.489 kcal + -analytic 104.6391 0.04739549 -5151.79 -38.92561 563713.9 + -gamma 5.4 0 +Sr+2 + CO3-2 = SrCO3 + -log_k 2.81 + -delta_h 5.22 kcal + -analytic -1.019 0.012826 + -Vm -.1787 -8.2177 8.9799 -2.4393 -.0300 # supcrt +Sr+2 + SO4-2 = SrSO4 + -log_k 2.29 + -delta_h 2.08 kcal + -Vm 6.7910 -.9666 6.1300 -2.7390 -.0010 # celestite solubility +Li+ + SO4-2 = LiSO4- + -log_k 0.64 + -gamma 5.0 0 +Cu+2 + e- = Cu+ + -log_k 2.72 + -delta_h 1.65 kcal + -gamma 2.5 0 +Cu+ + 2Cl- = CuCl2- + -log_k 5.50 + -delta_h -0.42 kcal + -gamma 4.0 0 +Cu+ + 3Cl- = CuCl3-2 + -log_k 5.70 + -delta_h 0.26 kcal + -gamma 5.0 0.0 +Cu+2 + CO3-2 = CuCO3 + -log_k 6.73 +Cu+2 + 2CO3-2 = Cu(CO3)2-2 + -log_k 9.83 +Cu+2 + HCO3- = CuHCO3+ + -log_k 2.7 +Cu+2 + Cl- = CuCl+ + -log_k 0.43 + -delta_h 8.65 kcal + -gamma 4.0 0 + -Vm -4.19 0 30.4 0 0 4 0 0 1.94e-2 1 # ref. 2 +Cu+2 + 2Cl- = CuCl2 + -log_k 0.16 + -delta_h 10.56 kcal + -Vm 26.8 0 -136 # ref. 2 +Cu+2 + 3Cl- = CuCl3- + -log_k -2.29 + -delta_h 13.69 kcal + -gamma 4.0 0 +Cu+2 + 4Cl- = CuCl4-2 + -log_k -4.59 + -delta_h 17.78 kcal + -gamma 5.0 0 +Cu+2 + F- = CuF+ + -log_k 1.26 + -delta_h 1.62 kcal +Cu+2 + H2O = CuOH+ + H+ + -log_k -8.0 + -gamma 4.0 0 +Cu+2 + 2 H2O = Cu(OH)2 + 2 H+ + -log_k -13.68 +Cu+2 + 3 H2O = Cu(OH)3- + 3 H+ + -log_k -26.9 +Cu+2 + 4 H2O = Cu(OH)4-2 + 4 H+ + -log_k -39.6 +2Cu+2 + 2H2O = Cu2(OH)2+2 + 2H+ + -log_k -10.359 + -delta_h 17.539 kcal + -analytical 2.497 0.0 -3833.0 +Cu+2 + SO4-2 = CuSO4 + -log_k 2.31 + -delta_h 1.220 kcal + -Vm 5.21 0 -14.6 # ref. 2 +Cu+2 + 3HS- = Cu(HS)3- + -log_k 25.9 +Zn+2 + H2O = ZnOH+ + H+ + -log_k -8.96 + -delta_h 13.4 kcal +Zn+2 + 2 H2O = Zn(OH)2 + 2 H+ + -log_k -16.9 +Zn+2 + 3 H2O = Zn(OH)3- + 3 H+ + -log_k -28.4 +Zn+2 + 4 H2O = Zn(OH)4-2 + 4 H+ + -log_k -41.2 +Zn+2 + Cl- = ZnCl+ + -log_k 0.43 + -delta_h 7.79 kcal + -gamma 4.0 0 + -Vm 14.8 -3.91 -105.7 -2.62 0.203 4 0 0 -5.05e-2 1 # ref. 2 +Zn+2 + 2 Cl- = ZnCl2 + -log_k 0.45 + -delta_h 8.5 kcal + -Vm -10.1 4.57 241 -2.97 -1e-3 # ref. 2 +Zn+2 + 3Cl- = ZnCl3- + -log_k 0.5 + -delta_h 9.56 kcal + -gamma 4.0 0 + -Vm 0.772 15.5 -0.349 -3.42 1.25 0 -7.77 0 0 1 # ref. 2 +Zn+2 + 4Cl- = ZnCl4-2 + -log_k 0.2 + -delta_h 10.96 kcal + -gamma 5.0 0 + -Vm 28.42 28 -5.26 -3.94 2.67 0 0 0 4.62e-2 1 # ref. 2 +Zn+2 + H2O + Cl- = ZnOHCl + H+ + -log_k -7.48 +Zn+2 + 2HS- = Zn(HS)2 + -log_k 14.94 +Zn+2 + 3HS- = Zn(HS)3- + -log_k 16.1 +Zn+2 + CO3-2 = ZnCO3 + -log_k 5.3 +Zn+2 + 2CO3-2 = Zn(CO3)2-2 + -log_k 9.63 +Zn+2 + HCO3- = ZnHCO3+ + -log_k 2.1 +Zn+2 + SO4-2 = ZnSO4 + -log_k 2.37 + -delta_h 1.36 kcal + -Vm 2.51 0 18.8 # ref. 2 +Zn+2 + 2SO4-2 = Zn(SO4)2-2 + -log_k 3.28 + -Vm 10.9 0 -98.7 0 0 0 24 0 -0.236 1 # ref. 2 +Zn+2 + Br- = ZnBr+ + -log_k -0.58 +Zn+2 + 2Br- = ZnBr2 + -log_k -0.98 +Zn+2 + F- = ZnF+ + -log_k 1.15 + -delta_h 2.22 kcal +Cd+2 + H2O = CdOH+ + H+ + -log_k -10.08 + -delta_h 13.1 kcal +Cd+2 + 2 H2O = Cd(OH)2 + 2 H+ + -log_k -20.35 +Cd+2 + 3 H2O = Cd(OH)3- + 3 H+ + -log_k -33.3 +Cd+2 + 4 H2O = Cd(OH)4-2 + 4 H+ + -log_k -47.35 +2Cd+2 + H2O = Cd2OH+3 + H+ + -log_k -9.39 + -delta_h 10.9 kcal +Cd+2 + H2O + Cl- = CdOHCl + H+ + -log_k -7.404 + -delta_h 4.355 kcal +Cd+2 + NO3- = CdNO3+ + -log_k 0.4 + -delta_h -5.2 kcal + -Vm 5.95 0 -1.11 0 2.67 7 0 0 1.53e-2 1 # ref. 2 +Cd+2 + Cl- = CdCl+ + -log_k 1.98 + -delta_h 0.59 kcal + -Vm 5.69 0 -30.2 0 0 6 0 0 0.112 1 # ref. 2 +Cd+2 + 2 Cl- = CdCl2 + -log_k 2.6 + -delta_h 1.24 kcal + -Vm 5.53 # ref. 2 +Cd+2 + 3 Cl- = CdCl3- + -log_k 2.4 + -delta_h 3.9 kcal + -Vm 4.6 0 83.9 0 0 0 0 0 0 1 # ref. 2 +Cd+2 + CO3-2 = CdCO3 + -log_k 2.9 +Cd+2 + 2CO3-2 = Cd(CO3)2-2 + -log_k 6.4 +Cd+2 + HCO3- = CdHCO3+ + -log_k 1.5 +Cd+2 + SO4-2 = CdSO4 + -log_k 2.46 + -delta_h 1.08 kcal + -Vm 10.4 0 57.9 # ref. 2 +Cd+2 + 2SO4-2 = Cd(SO4)2-2 + -log_k 3.5 + -Vm -6.29 0 -93 0 9.5 7 0 0 0 1 # ref. 2 +Cd+2 + Br- = CdBr+ + -log_k 2.17 + -delta_h -0.81 kcal +Cd+2 + 2Br- = CdBr2 + -log_k 2.9 +Cd+2 + F- = CdF+ + -log_k 1.1 +Cd+2 + 2F- = CdF2 + -log_k 1.5 +Cd+2 + HS- = CdHS+ + -log_k 10.17 +Cd+2 + 2HS- = Cd(HS)2 + -log_k 16.53 +Cd+2 + 3HS- = Cd(HS)3- + -log_k 18.71 +Cd+2 + 4HS- = Cd(HS)4-2 + -log_k 20.9 +Pb+2 + H2O = PbOH+ + H+ + -log_k -7.71 +Pb+2 + 2 H2O = Pb(OH)2 + 2 H+ + -log_k -17.12 +Pb+2 + 3 H2O = Pb(OH)3- + 3 H+ + -log_k -28.06 +Pb+2 + 4 H2O = Pb(OH)4-2 + 4 H+ + -log_k -39.7 +2 Pb+2 + H2O = Pb2OH+3 + H+ + -log_k -6.36 +Pb+2 + Cl- = PbCl+ + -log_k 1.6 + -delta_h 4.38 kcal + -Vm 2.8934 -.7165 6.0316 -2.7494 .1281 6 # supcrt +Pb+2 + 2 Cl- = PbCl2 + -log_k 1.8 + -delta_h 1.08 kcal + -Vm 6.5402 8.1879 2.5318 -3.1175 -.0300 # supcrt +Pb+2 + 3 Cl- = PbCl3- + -log_k 1.7 + -delta_h 2.17 kcal + -Vm 11.0396 19.1743 -1.7863 -3.5717 .7356 # supcrt +Pb+2 + 4 Cl- = PbCl4-2 + -log_k 1.38 + -delta_h 3.53 kcal + -Vm 16.4150 32.2997 -6.9452 -4.1143 2.3118 # supcrt +Pb+2 + CO3-2 = PbCO3 + -log_k 7.24 +Pb+2 + 2 CO3-2 = Pb(CO3)2-2 + -log_k 10.64 +Pb+2 + HCO3- = PbHCO3+ + -log_k 2.9 +Pb+2 + SO4-2 = PbSO4 + -log_k 2.75 +Pb+2 + 2 SO4-2 = Pb(SO4)2-2 + -log_k 3.47 +Pb+2 + 2HS- = Pb(HS)2 + -log_k 15.27 +Pb+2 + 3HS- = Pb(HS)3- + -log_k 16.57 +3Pb+2 + 4H2O = Pb3(OH)4+2 + 4H+ + -log_k -23.88 + -delta_h 26.5 kcal +Pb+2 + NO3- = PbNO3+ + -log_k 1.17 +Pb+2 + Br- = PbBr+ + -log_k 1.77 + -delta_h 2.88 kcal +Pb+2 + 2Br- = PbBr2 + -log_k 1.44 +Pb+2 + F- = PbF+ + -log_k 1.25 +Pb+2 + 2F- = PbF2 + -log_k 2.56 +Pb+2 + 3F- = PbF3- + -log_k 3.42 +Pb+2 + 4F- = PbF4-2 + -log_k 3.1 + +PHASES +Calcite + CaCO3 = CO3-2 + Ca+2 + -log_k -8.48 + -delta_h -2.297 kcal + -analytic -171.9065 -0.077993 2839.319 71.595 + -Vm 36.9 cm3/mol # MW (100.09 g/mol) / rho (2.71 g/cm3) +Aragonite + CaCO3 = CO3-2 + Ca+2 + -log_k -8.336 + -delta_h -2.589 kcal + -analytic -171.9773 -0.077993 2903.293 71.595 + -Vm 34.04 +Dolomite + CaMg(CO3)2 = Ca+2 + Mg+2 + 2 CO3-2 + -log_k -17.09 + -delta_h -9.436 kcal + -Vm 64.5 +Siderite + FeCO3 = Fe+2 + CO3-2 + -log_k -10.89 + -delta_h -2.480 kcal + -Vm 29.2 +Rhodochrosite + MnCO3 = Mn+2 + CO3-2 + -log_k -11.13 + -delta_h -1.430 kcal + -Vm 31.1 +Strontianite + SrCO3 = Sr+2 + CO3-2 + -log_k -9.271 + -delta_h -0.400 kcal + -analytic 155.0305 0.0 -7239.594 -56.58638 + -Vm 39.69 +Witherite + BaCO3 = Ba+2 + CO3-2 + -log_k -8.562 + -delta_h 0.703 kcal + -analytic 607.642 0.121098 -20011.25 -236.4948 + -Vm 46 +Gypsum + CaSO4:2H2O = Ca+2 + SO4-2 + 2 H2O + -log_k -4.58 + -delta_h -0.109 kcal + -analytic 68.2401 0.0 -3221.51 -25.0627 + -analytical_expression 93.7 5.99E-03 -4e3 -35.019 # better fits the appendix data of Appelo, 2015, AG 55, 62 + -Vm 73.9 # 172.18 / 2.33 (Vm H2O = 13.9 cm3/mol) +Anhydrite + CaSO4 = Ca+2 + SO4-2 + -log_k -4.36 + -delta_h -1.710 kcal + -analytic 84.90 0 -3135.12 -31.79 # 50 - 160oC, 1 - 1e3 atm, anhydrite dissolution, Blount and Dickson, 1973, Am. Mineral. 58, 323. + -Vm 46.1 # 136.14 / 2.95 +Celestite + SrSO4 = Sr+2 + SO4-2 + -log_k -6.63 + -delta_h -4.037 kcal +# -analytic -14805.9622 -2.4660924 756968.533 5436.3588 -40553604.0 + -analytic -7.14 6.11e-3 75 0 0 -1.79e-5 # Howell et al., 1992, JCED 37, 464. + -Vm 46.4 +Barite + BaSO4 = Ba+2 + SO4-2 + -log_k -9.97 + -delta_h 6.35 kcal + -analytical_expression -282.43 -8.972e-2 5822 113.08 # Blount 1977; Templeton, 1960 + -Vm 52.9 +Hydroxyapatite + Ca5(PO4)3OH + 4 H+ = H2O + 3 HPO4-2 + 5 Ca+2 + -log_k -3.421 + -delta_h -36.155 kcal + -Vm 128.9 +Fluorite + CaF2 = Ca+2 + 2 F- + -log_k -10.6 + -delta_h 4.69 kcal + -analytic 66.348 0.0 -4298.2 -25.271 + -Vm 15.7 +SiO2(a) + SiO2 + 2 H2O = H4SiO4 + -log_k -2.71 + -delta_h 3.340 kcal + -analytic -0.26 0.0 -731.0 +Chalcedony + SiO2 + 2 H2O = H4SiO4 + -log_k -3.55 + -delta_h 4.720 kcal + -analytic -0.09 0.0 -1032.0 + -Vm 23.1 +Quartz + SiO2 + 2 H2O = H4SiO4 + -log_k -3.98 + -delta_h 5.990 kcal + -analytic 0.41 0.0 -1309.0 + -Vm 22.67 +Gibbsite + Al(OH)3 + 3 H+ = Al+3 + 3 H2O + -log_k 8.11 + -delta_h -22.800 kcal + -Vm 32.22 +Al(OH)3(a) + Al(OH)3 + 3 H+ = Al+3 + 3 H2O + -log_k 10.8 + -delta_h -26.500 kcal +Kaolinite + Al2Si2O5(OH)4 + 6 H+ = H2O + 2 H4SiO4 + 2 Al+3 + -log_k 7.435 + -delta_h -35.300 kcal + -Vm 99.35 +Albite + NaAlSi3O8 + 8 H2O = Na+ + Al(OH)4- + 3 H4SiO4 + -log_k -18.002 + -delta_h 25.896 kcal + -Vm 101.31 +Anorthite + CaAl2Si2O8 + 8 H2O = Ca+2 + 2 Al(OH)4- + 2 H4SiO4 + -log_k -19.714 + -delta_h 11.580 kcal + -Vm 105.05 +K-feldspar + KAlSi3O8 + 8 H2O = K+ + Al(OH)4- + 3 H4SiO4 + -log_k -20.573 + -delta_h 30.820 kcal + -Vm 108.15 +K-mica + KAl3Si3O10(OH)2 + 10 H+ = K+ + 3 Al+3 + 3 H4SiO4 + -log_k 12.703 + -delta_h -59.376 kcal +Chlorite(14A) + Mg5Al2Si3O10(OH)8 + 16H+ = 5Mg+2 + 2Al+3 + 3H4SiO4 + 6H2O + -log_k 68.38 + -delta_h -151.494 kcal +Ca-Montmorillonite + Ca0.165Al2.33Si3.67O10(OH)2 + 12 H2O = 0.165Ca+2 + 2.33 Al(OH)4- + 3.67 H4SiO4 + 2 H+ + -log_k -45.027 + -delta_h 58.373 kcal + -Vm 156.16 +Talc + Mg3Si4O10(OH)2 + 4 H2O + 6 H+ = 3 Mg+2 + 4 H4SiO4 + -log_k 21.399 + -delta_h -46.352 kcal + -Vm 68.34 +Illite + K0.6Mg0.25Al2.3Si3.5O10(OH)2 + 11.2H2O = 0.6K+ + 0.25Mg+2 + 2.3Al(OH)4- + 3.5H4SiO4 + 1.2H+ + -log_k -40.267 + -delta_h 54.684 kcal + -Vm 141.48 +Chrysotile + Mg3Si2O5(OH)4 + 6 H+ = H2O + 2 H4SiO4 + 3 Mg+2 + -log_k 32.2 + -delta_h -46.800 kcal + -analytic 13.248 0.0 10217.1 -6.1894 + -Vm 106.5808 # 277.11/2.60 +Sepiolite + Mg2Si3O7.5OH:3H2O + 4 H+ + 0.5H2O = 2 Mg+2 + 3 H4SiO4 + -log_k 15.760 + -delta_h -10.700 kcal + -Vm 143.765 +Sepiolite(d) + Mg2Si3O7.5OH:3H2O + 4 H+ + 0.5H2O = 2 Mg+2 + 3 H4SiO4 + -log_k 18.66 +Hematite + Fe2O3 + 6 H+ = 2 Fe+3 + 3 H2O + -log_k -4.008 + -delta_h -30.845 kcal + -Vm 30.39 +Goethite + FeOOH + 3 H+ = Fe+3 + 2 H2O + -log_k -1.0 + -delta_h -14.48 kcal + -Vm 20.84 +Fe(OH)3(a) + Fe(OH)3 + 3 H+ = Fe+3 + 3 H2O + -log_k 4.891 +Pyrite + FeS2 + 2 H+ + 2 e- = Fe+2 + 2 HS- + -log_k -18.479 + -delta_h 11.300 kcal + -Vm 23.48 +FeS(ppt) + FeS + H+ = Fe+2 + HS- + -log_k -3.915 +Mackinawite + FeS + H+ = Fe+2 + HS- + -log_k -4.648 + -Vm 20.45 +Sulfur + S + 2H+ + 2e- = H2S + -log_k 4.882 + -delta_h -9.5 kcal +Vivianite + Fe3(PO4)2:8H2O = 3 Fe+2 + 2 PO4-3 + 8 H2O + -log_k -36.0 +Pyrolusite # H2O added for surface calc's + MnO2:H2O + 4 H+ + 2 e- = Mn+2 + 3 H2O + -log_k 41.38 + -delta_h -65.110 kcal +Hausmannite + Mn3O4 + 8 H+ + 2 e- = 3 Mn+2 + 4 H2O + -log_k 61.03 + -delta_h -100.640 kcal +Manganite + MnOOH + 3 H+ + e- = Mn+2 + 2 H2O + -log_k 25.34 +Pyrochroite + Mn(OH)2 + 2 H+ = Mn+2 + 2 H2O + -log_k 15.2 +Halite + NaCl = Cl- + Na+ + log_k 1.570 + -delta_h 1.37 + #-analytic -713.4616 -.1201241 37302.21 262.4583 -2106915. + -Vm 27.1 +Sylvite + KCl = K+ + Cl- + log_k 0.900 + -delta_h 8.5 + # -analytic 3.984 0.0 -919.55 + Vm 37.5 +CO2(g) + CO2 = CO2 + -log_k -1.468 + -delta_h -4.776 kcal + -analytic 10.5624 -2.3547e-2 -3972.8 0 5.8746e5 1.9194e-5 + -T_c 304.2 # critical T, K + -P_c 72.86 # critical P, atm + -Omega 0.225 # acentric factor +H2O(g) + H2O = H2O + -log_k 1.506; delta_h -44.03 kJ + -T_c 647.3 + -P_c 217.60 + -Omega 0.344 + -analytic -16.5066 -2.0013E-3 2710.7 3.7646 0 2.24E-6 + +# Gases from LLNL... +O2(g) + O2 = O2 + -log_k -2.8983 + -analytic -7.5001 7.8981e-3 0.0 0.0 2.0027e5 + -T_c 154.6; -P_c 49.80; -Omega 0.021 +H2(g) + H2 = H2 + -log_k -3.1050 + -delta_h -4.184 kJ + -analytic -9.3114 4.6473e-3 -49.335 1.4341 1.2815e5 + -T_c 33.2; -P_c 12.80; -Omega -0.225 +N2(g) + N2 = N2 + -log_k -3.1864 + -analytic -58.453 1.818e-3 3199 17.909 -27460 + -T_c 126.2; -P_c 33.50; -Omega 0.039 +H2S(g) + H2S = H+ + HS- + -log_k -7.9759 + -analytic -97.354 -3.1576e-2 1.8285e3 37.44 28.56 + -T_c 373.2; -P_c 88.20; -Omega 0.1 +CH4(g) + CH4 = CH4 + -log_k -2.8 + -analytic 10.44 -7.65e-3 -6669 0 1.014e6 # CH4 solubilities 25 - 100°C + -T_c 190.6 ; -P_c 45.40 ; -Omega 0.008 +#Amm(g) +# Amm = Amm +NH3(g) + NH3 = NH3 + -log_k 1.7966 + -analytic -18.758 3.3670e-4 2.5113e3 4.8619 39.192 + -T_c 405.6; -P_c 111.3; -Omega 0.25 +# redox-uncoupled gases +Oxg(g) + Oxg = Oxg + -analytic -7.5001 7.8981e-3 0.0 0.0 2.0027e5 + -T_c 154.6 ; -P_c 49.80 ; -Omega 0.021 +Hdg(g) + Hdg = Hdg + -analytic -9.3114 4.6473e-3 -49.335 1.4341 1.2815e5 + -T_c 33.2 ; -P_c 12.80 ; -Omega -0.225 +Ntg(g) + Ntg = Ntg + -analytic -58.453 1.81800e-3 3199 17.909 -27460 + T_c 126.2 ; -P_c 33.50 ; -Omega 0.039 +Mtg(g) + Mtg = Mtg + -log_k -2.8 + -analytic 10.44 -7.65e-3 -6669 0 1.014e6 # CH4 solubilities 25 - 100°C + -T_c 190.6 ; -P_c 45.40 ; -Omega 0.008 +H2Sg(g) + H2Sg = H+ + HSg- + -analytic -97.354 -3.1576e-2 1.8285e3 37.44 28.56 + -T_c 373.2 ; -P_c 88.20 ; -Omega 0.1 +Melanterite + FeSO4:7H2O = 7 H2O + Fe+2 + SO4-2 + -log_k -2.209 + -delta_h 4.910 kcal + -analytic 1.447 -0.004153 0.0 0.0 -214949.0 +Alunite + KAl3(SO4)2(OH)6 + 6 H+ = K+ + 3 Al+3 + 2 SO4-2 + 6H2O + -log_k -1.4 + -delta_h -50.250 kcal +Jarosite-K + KFe3(SO4)2(OH)6 + 6 H+ = 3 Fe+3 + 6 H2O + K+ + 2 SO4-2 + -log_k -9.21 + -delta_h -31.280 kcal +Zn(OH)2(e) + Zn(OH)2 + 2 H+ = Zn+2 + 2 H2O + -log_k 11.5 +Smithsonite + ZnCO3 = Zn+2 + CO3-2 + -log_k -10.0 + -delta_h -4.36 kcal +Sphalerite + ZnS + H+ = Zn+2 + HS- + -log_k -11.618 + -delta_h 8.250 kcal +Willemite 289 + Zn2SiO4 + 4H+ = 2Zn+2 + H4SiO4 + -log_k 15.33 + -delta_h -33.37 kcal +Cd(OH)2 + Cd(OH)2 + 2 H+ = Cd+2 + 2 H2O + -log_k 13.65 +Otavite 315 + CdCO3 = Cd+2 + CO3-2 + -log_k -12.1 + -delta_h -0.019 kcal +CdSiO3 328 + CdSiO3 + H2O + 2H+ = Cd+2 + H4SiO4 + -log_k 9.06 + -delta_h -16.63 kcal +CdSO4 329 + CdSO4 = Cd+2 + SO4-2 + -log_k -0.1 + -delta_h -14.74 kcal +Cerussite 365 + PbCO3 = Pb+2 + CO3-2 + -log_k -13.13 + -delta_h 4.86 kcal +Anglesite 384 + PbSO4 = Pb+2 + SO4-2 + -log_k -7.79 + -delta_h 2.15 kcal +Pb(OH)2 389 + Pb(OH)2 + 2H+ = Pb+2 + 2H2O + -log_k 8.15 + -delta_h -13.99 kcal + +EXCHANGE_MASTER_SPECIES + X X- +EXCHANGE_SPECIES + X- = X- + -log_k 0.0 + + Na+ + X- = NaX + -log_k 0.0 + -gamma 4.08 0.082 + + K+ + X- = KX + -log_k 0.7 + -gamma 3.5 0.015 + -delta_h -4.3 # Jardine & Sparks, 1984 + + Li+ + X- = LiX + -log_k -0.08 + -gamma 6.0 0 + -delta_h 1.4 # Merriam & Thomas, 1956 + +# !!!!! +# H+ + X- = HX +# -log_k 1.0 +# -gamma 9.0 0 + +# AmmH+ + X- = AmmHX + NH4+ + X- = NH4X + -log_k 0.6 + -gamma 2.5 0 + -delta_h -2.4 # Laudelout et al., 1968 + + Ca+2 + 2X- = CaX2 + -log_k 0.8 + -gamma 5.0 0.165 + -delta_h 7.2 # Van Bladel & Gheyl, 1980 + + Mg+2 + 2X- = MgX2 + -log_k 0.6 + -gamma 5.5 0.2 + -delta_h 7.4 # Laudelout et al., 1968 + + Sr+2 + 2X- = SrX2 + -log_k 0.91 + -gamma 5.26 0.121 + -delta_h 5.5 # Laudelout et al., 1968 + + Ba+2 + 2X- = BaX2 + -log_k 0.91 + -gamma 4.0 0.153 + -delta_h 4.5 # Laudelout et al., 1968 + + Mn+2 + 2X- = MnX2 + -log_k 0.52 + -gamma 6.0 0 + + Fe+2 + 2X- = FeX2 + -log_k 0.44 + -gamma 6.0 0 + + Cu+2 + 2X- = CuX2 + -log_k 0.6 + -gamma 6.0 0 + + Zn+2 + 2X- = ZnX2 + -log_k 0.8 + -gamma 5.0 0 + + Cd+2 + 2X- = CdX2 + -log_k 0.8 + -gamma 0.0 0 + + Pb+2 + 2X- = PbX2 + -log_k 1.05 + -gamma 0.0 0 + + Al+3 + 3X- = AlX3 + -log_k 0.41 + -gamma 9.0 0 + + AlOH+2 + 2X- = AlOHX2 + -log_k 0.89 + -gamma 0.0 0 + +SURFACE_MASTER_SPECIES + Hfo_s Hfo_sOH + Hfo_w Hfo_wOH +SURFACE_SPECIES +# All surface data from +# Dzombak and Morel, 1990 +# +# +# Acid-base data from table 5.7 +# +# strong binding site--Hfo_s, + + Hfo_sOH = Hfo_sOH + -log_k 0 + + Hfo_sOH + H+ = Hfo_sOH2+ + -log_k 7.29 # = pKa1,int + + Hfo_sOH = Hfo_sO- + H+ + -log_k -8.93 # = -pKa2,int + +# weak binding site--Hfo_w + + Hfo_wOH = Hfo_wOH + -log_k 0 + + Hfo_wOH + H+ = Hfo_wOH2+ + -log_k 7.29 # = pKa1,int + + Hfo_wOH = Hfo_wO- + H+ + -log_k -8.93 # = -pKa2,int +############################################### +# CATIONS # +############################################### +# +# Cations from table 10.1 or 10.5 +# +# Calcium + Hfo_sOH + Ca+2 = Hfo_sOHCa+2 + -log_k 4.97 + + Hfo_wOH + Ca+2 = Hfo_wOCa+ + H+ + -log_k -5.85 +# Strontium + Hfo_sOH + Sr+2 = Hfo_sOHSr+2 + -log_k 5.01 + + Hfo_wOH + Sr+2 = Hfo_wOSr+ + H+ + -log_k -6.58 + + Hfo_wOH + Sr+2 + H2O = Hfo_wOSrOH + 2H+ + -log_k -17.6 +# Barium + Hfo_sOH + Ba+2 = Hfo_sOHBa+2 + -log_k 5.46 + + Hfo_wOH + Ba+2 = Hfo_wOBa+ + H+ + -log_k -7.2 # table 10.5 +# +# Cations from table 10.2 +# +# Cadmium + Hfo_sOH + Cd+2 = Hfo_sOCd+ + H+ + -log_k 0.47 + + Hfo_wOH + Cd+2 = Hfo_wOCd+ + H+ + -log_k -2.91 +# Zinc + Hfo_sOH + Zn+2 = Hfo_sOZn+ + H+ + -log_k 0.99 + + Hfo_wOH + Zn+2 = Hfo_wOZn+ + H+ + -log_k -1.99 +# Copper + Hfo_sOH + Cu+2 = Hfo_sOCu+ + H+ + -log_k 2.89 + + Hfo_wOH + Cu+2 = Hfo_wOCu+ + H+ + -log_k 0.6 # table 10.5 +# Lead + Hfo_sOH + Pb+2 = Hfo_sOPb+ + H+ + -log_k 4.65 + + Hfo_wOH + Pb+2 = Hfo_wOPb+ + H+ + -log_k 0.3 # table 10.5 +# +# Derived constants table 10.5 +# +# Magnesium + Hfo_wOH + Mg+2 = Hfo_wOMg+ + H+ + -log_k -4.6 +# Manganese + Hfo_sOH + Mn+2 = Hfo_sOMn+ + H+ + -log_k -0.4 # table 10.5 + + Hfo_wOH + Mn+2 = Hfo_wOMn+ + H+ + -log_k -3.5 # table 10.5 +# Iron, strong site: Appelo, Van der Weiden, Tournassat & Charlet, EST 36, 3096 + Hfo_sOH + Fe+2 = Hfo_sOFe+ + H+ + -log_k -0.95 +# Iron, weak site: Liger et al., GCA 63, 2939, re-optimized for D&M + Hfo_wOH + Fe+2 = Hfo_wOFe+ + H+ + -log_k -2.98 + + Hfo_wOH + Fe+2 + H2O = Hfo_wOFeOH + 2H+ + -log_k -11.55 +############################################### +# ANIONS # +############################################### +# +# Anions from table 10.6 +# +# Phosphate + Hfo_wOH + PO4-3 + 3H+ = Hfo_wH2PO4 + H2O + -log_k 31.29 + + Hfo_wOH + PO4-3 + 2H+ = Hfo_wHPO4- + H2O + -log_k 25.39 + + Hfo_wOH + PO4-3 + H+ = Hfo_wPO4-2 + H2O + -log_k 17.72 +# +# Anions from table 10.7 +# +# Borate + Hfo_wOH + H3BO3 = Hfo_wH2BO3 + H2O + -log_k 0.62 +# +# Anions from table 10.8 +# +# Sulfate + Hfo_wOH + SO4-2 + H+ = Hfo_wSO4- + H2O + -log_k 7.78 + + Hfo_wOH + SO4-2 = Hfo_wOHSO4-2 + -log_k 0.79 +# +# Derived constants table 10.10 +# + Hfo_wOH + F- + H+ = Hfo_wF + H2O + -log_k 8.7 + + Hfo_wOH + F- = Hfo_wOHF- + -log_k 1.6 +# +# Carbonate: Van Geen et al., 1994 reoptimized for D&M model +# + Hfo_wOH + CO3-2 + H+ = Hfo_wCO3- + H2O + -log_k 12.56 + + Hfo_wOH + CO3-2 + 2H+= Hfo_wHCO3 + H2O + -log_k 20.62 +# +# Silicate: Swedlund, P.J. and Webster, J.G., 1999. Water Research, 33, 3413-3422. +# + Hfo_wOH + H4SiO4 = Hfo_wH3SiO4 + H2O ; log_K 4.28 + Hfo_wOH + H4SiO4 = Hfo_wH2SiO4- + H+ + H2O ; log_K -3.22 + Hfo_wOH + H4SiO4 = Hfo_wHSiO4-2 + 2H+ + H2O ; log_K -11.69 +RATES + +########### +#Quartz +########### +# +####### +# Example of quartz kinetic rates block: +# KINETICS +# Quartz +# -m0 158.8 # 90 % Qu +# -parms 0.146 1.5 +# -step 3.1536e8 in 10 +# -tol 1e-12 + +Quartz + -start +1 REM Specific rate k from Rimstidt and Barnes, 1980, GCA 44,1683 +2 REM k = 10^-13.7 mol/m2/s (25 C), Ea = 90 kJ/mol +3 REM sp. rate * parm(2) due to salts (Dove and Rimstidt, MSA Rev. 29, 259) +4 REM PARM(1) = Specific area of Quartz, m^2/mol Quartz +5 REM PARM(2) = salt correction: (1 + 1.5 * c_Na (mM)), < 35 + +10 dif_temp = 1/TK - 1/298 +20 pk_w = 13.7 + 4700.4 * dif_temp +40 moles = PARM(1) * M0 * PARM(2) * (M/M0)^0.67 * 10^-pk_w * (1 - SR("Quartz")) +# Integrate... +50 SAVE moles * TIME + -end + +########### +#K-feldspar +########### +# +# Sverdrup and Warfvinge, 1995, Estimating field weathering rates +# using laboratory kinetics: Reviews in mineralogy and geochemistry, +# vol. 31, p. 485-541. +# +# As described in: +# Appelo and Postma, 2005, Geochemistry, groundwater +# and pollution, 2nd Edition: A.A. Balkema Publishers, +# p. 162-163 and 395-399. +# +# Assume soil is 10% K-feldspar by mass in 1 mm spheres (radius 0.05 mm) +# Assume density of rock and Kspar is 2600 kg/m^3 = 2.6 kg/L +# GFW Kspar 0.278 kg/mol +# +# Moles of Kspar per liter pore space calculation: +# Mass of rock per liter pore space = 0.7*2.6/0.3 = 6.07 kg rock/L pore space +# Mass of Kspar per liter pore space 6.07x0.1 = 0.607 kg Kspar/L pore space +# Moles of Kspar per liter pore space 0.607/0.278 = 2.18 mol Kspar/L pore space +# +# Specific area calculation: +# Volume of sphere 4/3 x pi x r^3 = 5.24e-13 m^3 Kspar/sphere +# Mass of sphere 2600 x 5.24e-13 = 1.36e-9 kg Kspar/sphere +# Moles of Kspar in sphere 1.36e-9/0.278 = 4.90e-9 mol Kspar/sphere +# Surface area of one sphere 4 x pi x r^2 = 3.14e-8 m^2/sphere +# Specific area of K-feldspar in sphere 3.14e-8/4.90e-9 = 6.41 m^2/mol Kspar +# +# +# Example of KINETICS data block for K-feldspar rate: +# KINETICS 1 +# K-feldspar +# -m0 2.18 # 10% Kspar, 0.1 mm cubes +# -m 2.18 # Moles per L pore space +# -parms 6.41 0.1 # m^2/mol Kspar, fraction adjusts lab rate to field rate +# -time 1.5 year in 40 + +K-feldspar + -start +1 REM Sverdrup and Warfvinge, 1995, mol m^-2 s^-1 +2 REM PARM(1) = Specific area of Kspar m^2/mol Kspar +3 REM PARM(2) = Adjusts lab rate to field rate +4 REM temp corr: from A&P, p. 162. E (kJ/mol) / R / 2.303 = H in H*(1/T-1/281) +5 REM K-Feldspar parameters +10 DATA 11.7, 0.5, 4e-6, 0.4, 500e-6, 0.15, 14.5, 0.14, 0.15, 13.1, 0.3 +20 RESTORE 10 +30 READ pK_H, n_H, lim_Al, x_Al, lim_BC, x_BC, pK_H2O, z_Al, z_BC, pK_OH, o_OH +40 DATA 3500, 2000, 2500, 2000 +50 RESTORE 40 +60 READ e_H, e_H2O, e_OH, e_CO2 +70 pk_CO2 = 13 +80 n_CO2 = 0.6 +100 REM Generic rate follows +110 dif_temp = 1/TK - 1/281 +120 BC = ACT("Na+") + ACT("K+") + ACT("Mg+2") + ACT("Ca+2") +130 REM rate by H+ +140 pk_H = pk_H + e_H * dif_temp +150 rate_H = 10^-pk_H * ACT("H+")^n_H / ((1 + ACT("Al+3") / lim_Al)^x_Al * (1 + BC / lim_BC)^x_BC) +160 REM rate by hydrolysis +170 pk_H2O = pk_H2O + e_H2O * dif_temp +180 rate_H2O = 10^-pk_H2O / ((1 + ACT("Al+3") / lim_Al)^z_Al * (1 + BC / lim_BC)^z_BC) +190 REM rate by OH- +200 pk_OH = pk_OH + e_OH * dif_temp +210 rate_OH = 10^-pk_OH * ACT("OH-")^o_OH +220 REM rate by CO2 +230 pk_CO2 = pk_CO2 + e_CO2 * dif_temp +240 rate_CO2 = 10^-pk_CO2 * (SR("CO2(g)"))^n_CO2 +250 rate = rate_H + rate_H2O + rate_OH + rate_CO2 +260 area = PARM(1) * M0 *(M/M0)^0.67 +270 rate = PARM(2) * area * rate * (1-SR("K-feldspar")) +280 moles = rate * TIME +290 SAVE moles + -end + + +########### +#Albite +########### +# +# Sverdrup and Warfvinge, 1995, Estimating field weathering rates +# using laboratory kinetics: Reviews in mineralogy and geochemistry, +# vol. 31, p. 485-541. +# +# As described in: +# Appelo and Postma, 2005, Geochemistry, groundwater +# and pollution, 2nd Edition: A.A. Balkema Publishers, +# p. 162-163 and 395-399. +# +# Example of KINETICS data block for Albite rate: +# KINETICS 1 +# Albite +# -m0 0.46 # 2% Albite, 0.1 mm cubes +# -m 0.46 # Moles per L pore space +# -parms 6.04 0.1 # m^2/mol Albite, fraction adjusts lab rate to field rate +# -time 1.5 year in 40 +# +# Assume soil is 2% Albite by mass in 1 mm spheres (radius 0.05 mm) +# Assume density of rock and Albite is 2600 kg/m^3 = 2.6 kg/L +# GFW Albite 0.262 kg/mol +# +# Moles of Albite per liter pore space calculation: +# Mass of rock per liter pore space = 0.7*2.6/0.3 = 6.07 kg rock/L pore space +# Mass of Albite per liter pore space 6.07x0.02 = 0.121 kg Albite/L pore space +# Moles of Albite per liter pore space 0.607/0.262 = 0.46 mol Albite/L pore space +# +# Specific area calculation: +# Volume of sphere 4/3 x pi x r^3 = 5.24e-13 m^3 Albite/sphere +# Mass of sphere 2600 x 5.24e-13 = 1.36e-9 kg Albite/sphere +# Moles of Albite in sphere 1.36e-9/0.262 = 5.20e-9 mol Albite/sphere +# Surface area of one sphere 4 x pi x r^2 = 3.14e-8 m^2/sphere +# Specific area of Albite in sphere 3.14e-8/5.20e-9 = 6.04 m^2/mol Albite + +Albite + -start +1 REM Sverdrup and Warfvinge, 1995, mol m^-2 s^-1 +2 REM PARM(1) = Specific area of Albite m^2/mol Albite +3 REM PARM(2) = Adjusts lab rate to field rate +4 REM temp corr: from A&P, p. 162. E (kJ/mol) / R / 2.303 = H in H*(1/T-1/281) +5 REM Albite parameters +10 DATA 11.5, 0.5, 4e-6, 0.4, 500e-6, 0.2, 13.7, 0.14, 0.15, 11.8, 0.3 +20 RESTORE 10 +30 READ pK_H, n_H, lim_Al, x_Al, lim_BC, x_BC, pK_H2O, z_Al, z_BC, pK_OH, o_OH +40 DATA 3500, 2000, 2500, 2000 +50 RESTORE 40 +60 READ e_H, e_H2O, e_OH, e_CO2 +70 pk_CO2 = 13 +80 n_CO2 = 0.6 +100 REM Generic rate follows +110 dif_temp = 1/TK - 1/281 +120 BC = ACT("Na+") + ACT("K+") + ACT("Mg+2") + ACT("Ca+2") +130 REM rate by H+ +140 pk_H = pk_H + e_H * dif_temp +150 rate_H = 10^-pk_H * ACT("H+")^n_H / ((1 + ACT("Al+3") / lim_Al)^x_Al * (1 + BC / lim_BC)^x_BC) +160 REM rate by hydrolysis +170 pk_H2O = pk_H2O + e_H2O * dif_temp +180 rate_H2O = 10^-pk_H2O / ((1 + ACT("Al+3") / lim_Al)^z_Al * (1 + BC / lim_BC)^z_BC) +190 REM rate by OH- +200 pk_OH = pk_OH + e_OH * dif_temp +210 rate_OH = 10^-pk_OH * ACT("OH-")^o_OH +220 REM rate by CO2 +230 pk_CO2 = pk_CO2 + e_CO2 * dif_temp +240 rate_CO2 = 10^-pk_CO2 * (SR("CO2(g)"))^n_CO2 +250 rate = rate_H + rate_H2O + rate_OH + rate_CO2 +260 area = PARM(1) * M0 *(M/M0)^0.67 +270 rate = PARM(2) * area * rate * (1-SR("Albite")) +280 moles = rate * TIME +290 SAVE moles + -end + +######## +#Calcite +######## +# Example of KINETICS data block for calcite rate, +# in mmol/cm2/s, Plummer et al., 1978, AJS 278, 179; Appelo et al., AG 13, 257. +# KINETICS 1 +# Calcite +# -tol 1e-8 +# -m0 3.e-3 +# -m 3.e-3 +# -parms 1.67e5 0.6 # cm^2/mol calcite, exp factor +# -time 1 day + +Calcite + -start +1 REM PARM(1) = specific surface area of calcite, cm^2/mol calcite +2 REM PARM(2) = exponent for M/M0 + +10 si_cc = SI("Calcite") +20 IF (M <= 0 and si_cc < 0) THEN GOTO 200 +30 k1 = 10^(0.198 - 444.0 / TK ) +40 k2 = 10^(2.84 - 2177.0 /TK ) +50 IF TC <= 25 THEN k3 = 10^(-5.86 - 317.0 / TK) +60 IF TC > 25 THEN k3 = 10^(-1.1 - 1737.0 / TK ) +80 IF M0 > 0 THEN area = PARM(1)*M0*(M/M0)^PARM(2) ELSE area = PARM(1)*M +110 rate = area * (k1 * ACT("H+") + k2 * ACT("CO2") + k3 * ACT("H2O")) +120 rate = rate * (1 - 10^(2/3*si_cc)) +130 moles = rate * 0.001 * TIME # convert from mmol to mol +200 SAVE moles + -end + +####### +#Pyrite +####### +# +# Williamson, M.A. and Rimstidt, J.D., 1994, +# Geochimica et Cosmochimica Acta, v. 58, p. 5443-5454, +# rate equation is mol m^-2 s^-1. +# +# Example of KINETICS data block for pyrite rate: +# KINETICS 1 +# Pyrite +# -tol 1e-8 +# -m0 5.e-4 +# -m 5.e-4 +# -parms 0.3 0.67 .5 -0.11 +# -time 1 day in 10 +Pyrite + -start +1 REM Williamson and Rimstidt, 1994 +2 REM PARM(1) = log10(specific area), log10(m^2 per mole pyrite) +3 REM PARM(2) = exp for (M/M0) +4 REM PARM(3) = exp for O2 +5 REM PARM(4) = exp for H+ + +10 REM Dissolution in presence of DO +20 if (M <= 0) THEN GOTO 200 +30 if (SI("Pyrite") >= 0) THEN GOTO 200 +40 log_rate = -8.19 + PARM(3)*LM("O2") + PARM(4)*LM("H+") +50 log_area = PARM(1) + LOG10(M0) + PARM(2)*LOG10(M/M0) +60 moles = 10^(log_area + log_rate) * TIME +200 SAVE moles + -end + +########## +#Organic_C +########## +# +# Example of KINETICS data block for SOC (sediment organic carbon): +# KINETICS 1 +# Organic_C +# -formula C +# -tol 1e-8 +# -m 5e-3 # SOC in mol +# -time 30 year in 15 +Organic_C + -start +1 REM Additive Monod kinetics for SOC (sediment organic carbon) +2 REM Electron acceptors: O2, NO3, and SO4 + +10 if (M <= 0) THEN GOTO 200 +20 mO2 = MOL("O2") +30 mNO3 = TOT("N(5)") +40 mSO4 = TOT("S(6)") +50 k_O2 = 1.57e-9 # 1/sec +60 k_NO3 = 1.67e-11 # 1/sec +70 k_SO4 = 1.e-13 # 1/sec +80 rate = k_O2 * mO2/(2.94e-4 + mO2) +90 rate = rate + k_NO3 * mNO3/(1.55e-4 + mNO3) +100 rate = rate + k_SO4 * mSO4/(1.e-4 + mSO4) +110 moles = rate * M * (M/M0) * TIME +200 SAVE moles + -end + +########### +#Pyrolusite +########### +# +# Postma, D. and Appelo, C.A.J., 2000, GCA, vol. 64, pp. 1237-1247. +# Rate equation given as mol L^-1 s^-1 +# +# Example of KINETICS data block for Pyrolusite +# KINETICS 1-12 +# Pyrolusite +# -tol 1.e-7 +# -m0 0.1 +# -m 0.1 +# -time 0.5 day in 10 +Pyrolusite + -start +10 if (M <= 0) THEN GOTO 200 +20 sr_pl = SR("Pyrolusite") +30 if (sr_pl > 1) THEN GOTO 100 +40 REM sr_pl <= 1, undersaturated +50 Fe_t = TOT("Fe(2)") +60 if Fe_t < 1e-8 then goto 200 +70 moles = 6.98e-5 * Fe_t * (M/M0)^0.67 * TIME * (1 - sr_pl) +80 GOTO 200 +100 REM sr_pl > 1, supersaturated +110 moles = 2e-3 * 6.98e-5 * (1 - sr_pl) * TIME +200 SAVE moles * SOLN_VOL + -end +END + +# For the reaction aA + bB = cC + dD, +# with delta_v = c*Vm(C) + d*Vm(D) - a*Vm(A) - b*Vm(B), +# PHREEQC adds the pressure term to log_k: -= delta_v * (P - 1) / (2.3RT). +# Vm(A) is volume of A, cm3/mol, P is pressure, atm, R is the gas constant, T is Kelvin. +# Gas-pressures and fugacity coefficients are calculated with Peng-Robinson's EOS. +# Binary interaction coefficients from Soreide and Whitson, 1992, FPE 77, 217 are +# hard-coded in calc_PR(): +# kij CH4 CO2 H2S N2 +# H2O 0.49 0.19 0.19 0.49 +# ============================================================================================= +# The molar volumes of solids are entered with +# -Vm vm cm3/mol +# vm is the molar volume, cm3/mol (default), but dm3/mol and m3/mol are permitted. +# Data for minerals' vm (= MW (g/mol) / rho (g/cm3)) are defined using rho from +# Deer, Howie and Zussman, The rock-forming minerals, Longman. +# -------------------- +# Temperature- and pressure-dependent volumina of aqueous species are calculated with a Redlich- +# type equation (cf. Redlich and Meyer, Chem. Rev. 64, 221), from parameters entered with +# -Vm a1 a2 a3 a4 W a0 i1 i2 i3 i4 +# The volume (cm3/mol) is +# Vm(T, pb, I) = 41.84 * (a1 * 0.1 + a2 * 100 / (2600 + pb) + a3 / (T - 228) + +# a4 * 1e4 / (2600 + pb) / (T - 228) - W * QBrn) +# + z^2 / 2 * Av * f(I^0.5) +# + (i1 + i2 / (T - 228) + i3 * (T - 228)) * I^i4 +# Volumina at I = 0 are obtained using supcrt92 formulas (Johnson et al., 1992, CG 18, 899). +# 41.84 transforms cal/bar/mol into cm3/mol. +# pb is pressure in bar. +# W * QBrn is the energy of solvation, calculated from W and the pressure dependence of the Born equation, +# W is fitted on measured solution densities. +# z is charge of the solute species. +# Av is the Debye-Hückel limiting slope (DH_AV in PHREEQC basic). +# a0 is the ion-size parameter in the extended Debye-Hückel equation: +# f(I^0.5) = I^0.5 / (1 + a0 * DH_B * I^0.5), +# a0 = -gamma x for cations, = 0 for anions. +# For details, consult ref. 1. +# +# ref. 1: Appelo, Parkhurst and Post, 2014. Geochim. Cosmochim. Acta 125, 49–67. +# ref. 2: Procedures from ref. 1 using data compiled by Laliberté, 2009, J. Chem. Eng. Data 54, 1725. +# ref. 3: Appelo, 2017, Cem. Concr. Res. 101, 102-113. +# +# ============================================================================================= +# It remains the responsibility of the user to check the calculated results, for example with +# measured solubilities as a function of (P, T). + diff --git a/gtest/CMakeLists.txt b/gtest/CMakeLists.txt new file mode 100644 index 00000000..620b7d00 --- /dev/null +++ b/gtest/CMakeLists.txt @@ -0,0 +1,166 @@ +project(unit) + +add_executable(TestCVar TestCVar.cpp) +target_link_libraries(TestCVar IPhreeqc gtest gtest_main) + +add_executable(TestVar TestVar.cpp) +target_link_libraries(TestVar IPhreeqc gtest gtest_main) + +add_executable(TestIPhreeqcLib TestIPhreeqcLib.cpp FileTest.cpp) +target_link_libraries(TestIPhreeqcLib IPhreeqc gtest gtest_main) + +add_executable(TestIPhreeqc TestIPhreeqc.cpp FileTest.cpp) +target_link_libraries(TestIPhreeqc IPhreeqc gtest gtest_main) + +add_executable(TestSelectedOutput TestSelectedOutput.cpp) +target_link_libraries(TestSelectedOutput IPhreeqc gtest gtest_main) + + +add_test(TestCVar TestCVar) +add_test(TestVar TestVar) +add_test(TestIPhreeqc TestIPhreeqc) +add_test(TestIPhreeqcLib TestIPhreeqcLib) +add_test(TestSelectedOutput TestSelectedOutput) + +if (MSVC AND BUILD_SHARED_LIBS) + # copy dlls + add_custom_command(TARGET TestCVar POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy $ $ + ) + add_custom_command(TARGET TestCVar POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy $ $ + ) + add_custom_command(TARGET TestCVar POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy $ $ + ) +endif() + + +# databases +configure_file( + ../unit/phreeqc.dat.old + phreeqc.dat.old + COPYONLY + ) + +configure_file( + ../database/phreeqc.dat + phreeqc.dat + COPYONLY + ) + +configure_file( + ../database/pitzer.dat + pitzer.dat + COPYONLY + ) + +configure_file( + ../database/wateq4f.dat + wateq4f.dat + COPYONLY + ) + +configure_file( + ../database/Amm.dat + Amm.dat + COPYONLY + ) + +configure_file( + ../database/frezchem.dat + frezchem.dat + COPYONLY + ) + +configure_file( + ../database/iso.dat + iso.dat + COPYONLY + ) + +configure_file( + ../unit/llnl.dat.old + llnl.dat.old + COPYONLY + ) + +configure_file( + ../database/llnl.dat + llnl.dat + COPYONLY + ) + +configure_file( + ../database/minteq.dat + minteq.dat + COPYONLY + ) + +configure_file( + ../database/minteq.v4.dat + minteq.v4.dat + COPYONLY + ) + +configure_file( + ../database/sit.dat + sit.dat + COPYONLY + ) + +configure_file( + ../database/ColdChem.dat + ColdChem.dat + COPYONLY + ) + +configure_file( + ../database/core10.dat + core10.dat + COPYONLY + ) + +configure_file( + ../database/Tipping_Hurley.dat + Tipping_Hurley.dat + COPYONLY + ) + +configure_file( + missing_e.dat + missing_e.dat + COPYONLY + ) + +# misc files + +configure_file( + conv_fail.in + conv_fail.in + COPYONLY + ) + +configure_file( + dump + dump + COPYONLY + ) + +configure_file( + multi_punch + multi_punch + COPYONLY + ) + +configure_file( + multi_punch_no_set + multi_punch_no_set + COPYONLY + ) + +configure_file( + kinn20140218 + kinn20140218 + COPYONLY + ) diff --git a/gtest/FileTest.cpp b/gtest/FileTest.cpp new file mode 100644 index 00000000..db2db8c0 --- /dev/null +++ b/gtest/FileTest.cpp @@ -0,0 +1,153 @@ +#include "FileTest.h" + +#if defined(_WIN32) || defined(__CYGWIN32__) +#include +#else +#include +#endif + +#if defined(_WIN32) || defined(__CYGWIN32__) +bool FileExists(const char *szPathName) +{ + SECURITY_ATTRIBUTES sa; + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor = NULL; + sa.bInheritHandle = TRUE; + HANDLE fileHandle = ::CreateFile(szPathName, GENERIC_READ, 0, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + bool retValue; + if (fileHandle == INVALID_HANDLE_VALUE) + { + char buffer[100]; + sprintf(buffer, "Could not open file (error %d)\n", GetLastError()); + retValue = false; + } + else + { + retValue = true; + ::CloseHandle(fileHandle); + } + return retValue; +} +#else +bool FileExists(const char *szPathName) +{ + FILE* fp; + fp = fopen(szPathName, "r"); + if (fp == NULL) { + return false; + } else { + fclose(fp); + return true; + } +} +#endif + +#if defined(_WIN32) || defined(__CYGWIN32__) +// DeleteFile defined in +#else +int DeleteFile(const char* szPathName) +{ + if (remove(szPathName) == 0) + { + return 1; + } + return 0; // failure +} +#endif + +#if defined(_WIN32) || defined(__CYGWIN32__) +size_t FileSize(const char *szPathName) +{ + HANDLE hFile = ::CreateFile( + szPathName, // file to open + GENERIC_READ, // open for reading + FILE_SHARE_READ, // share for reading + NULL, // default security + OPEN_EXISTING, // existing file only + FILE_ATTRIBUTE_NORMAL, // normal file + NULL); // no attr. template + + if (hFile != INVALID_HANDLE_VALUE) + { + // read file size + LARGE_INTEGER liFileSize; + ::GetFileSizeEx(hFile, &liFileSize); + ::CloseHandle(hFile); + return (size_t) liFileSize.QuadPart; + } + return 0; +} +#else +#include +#include +#include + +size_t FileSize(const char *szPathName) +{ + struct stat s; + stat(szPathName, &s); + return (size_t) s.st_size; +} +#endif + +FileTest::FileTest(std::string fn) : _fn(fn) +{ +} + +FileTest::~FileTest(void) +{ + int max_tries = 100; + while(::FileExists(_fn.c_str()) && --max_tries) + { + ::DeleteFile(_fn.c_str()); + } +} + +std::string FileTest::GetName(void) +{ + return _fn; +} + +bool FileTest::RemoveExisting(void) +{ + int max_tries = 100; + while(::FileExists(_fn.c_str()) && --max_tries) + { + ::DeleteFile(_fn.c_str()); + } + return !::FileExists(_fn.c_str()); +} + +bool FileTest::VerifyMissing(void) +{ + int max_tries = 100; + while(::FileExists(_fn.c_str()) && --max_tries); + return !::FileExists(_fn.c_str()); +} + +bool FileTest::VerifyExists(void) +{ + int max_tries = 100; + while(!::FileExists(_fn.c_str()) && --max_tries); + return ::FileExists(_fn.c_str()); +} + +bool FileTest::Exists(void) +{ + return ::FileExists(_fn.c_str()); +} + +int FileTest::Delete(void) +{ + if (::FileExists(_fn.c_str())) + { + return ::DeleteFile(_fn.c_str()); + } + return 1; +} + +size_t FileTest::Size(void) +{ + return ::FileSize(_fn.c_str()); +} diff --git a/gtest/FileTest.h b/gtest/FileTest.h new file mode 100644 index 00000000..398380d0 --- /dev/null +++ b/gtest/FileTest.h @@ -0,0 +1,33 @@ +#if !defined(FILETEST_H_INCLUDED) +#define FILETEST_H_INCLUDED + +#include + +#if defined(_WIN32) || defined(__CYGWIN32__) +// DeleteFile defined in +#else +int DeleteFile(const char* szPathName); +#endif + +bool FileExists(const char *szPathName); +size_t FileSize(const char *szPathName); + +class FileTest +{ +public: + FileTest(std::string fn); + ~FileTest(void); + + std::string GetName(void); + bool RemoveExisting(void); + bool VerifyMissing(void); + bool VerifyExists(void); + bool Exists(void); + int Delete(void); + size_t Size(void); + +protected: + std::string _fn; +}; + +#endif // FILETEST_H_INCLUDED \ No newline at end of file diff --git a/gtest/TestCVar.cpp b/gtest/TestCVar.cpp new file mode 100644 index 00000000..14676bd2 --- /dev/null +++ b/gtest/TestCVar.cpp @@ -0,0 +1,9 @@ +#include + +#include "../src/CVar.hxx" + +TEST(TestCVar, CVarCtor) +{ + CVar v; + ASSERT_EQ(TT_EMPTY, v.type); +} diff --git a/gtest/TestIPhreeqc.cpp b/gtest/TestIPhreeqc.cpp new file mode 100644 index 00000000..68c237c6 --- /dev/null +++ b/gtest/TestIPhreeqc.cpp @@ -0,0 +1,4742 @@ +#include + +#include +#include +#include +#include "IPhreeqc.hpp" +#include "Phreeqc.h" +#include "FileTest.h" +#undef true +#undef false +#include "CVar.hxx" + +VRESULT SOLUTION(IPhreeqc& obj, double C, double Ca, double Na); +VRESULT EQUILIBRIUM_PHASES(IPhreeqc& obj, const char* phase, double si, double amount); +VRESULT USER_PUNCH(IPhreeqc& obj, const char* element, int max); +VRESULT SELECTED_OUTPUT(IPhreeqc& obj); +VRESULT DUMP(IPhreeqc& obj); + +void TestFileOnOff(const char* FILENAME_FORMAT, bool output_file_on, bool error_file_on, bool log_file_on, bool selected_output_file_on, bool dump_file_on); + +TEST(TestIPhreeqc, TestLoadDatabase) +{ + std::string FILES[] = { "phreeqc.dat", "pitzer.dat", "wateq4f.dat", + "Amm.dat", "frezchem.dat", "iso.dat", + "llnl.dat", "minteq.dat", "minteq.v4.dat", + "sit.dat","ColdChem.dat","core10.dat", + "Tipping_Hurley.dat" + }; + + for (int j = 0; j < sizeof(FILES) / sizeof(std::string); ++j) + { + IPhreeqc obj; + for (int i = 0; i < 10; ++i) + { + ASSERT_EQ(true, ::FileExists(FILES[j].c_str())); + ASSERT_TRUE(::FileSize(FILES[j].c_str()) > 0); + ASSERT_EQ(0, obj.LoadDatabase(FILES[j].c_str())); + } + + // make sure settings are cleared + // + + IPhreeqc obj2; + for (int i = 0; i < 10; ++i) + { + ASSERT_EQ(false, obj2.GetSelectedOutputFileOn()); + + obj2.SetSelectedOutputFileOn(true); + ASSERT_EQ(true, obj2.GetSelectedOutputFileOn()); + + obj2.SetSelectedOutputFileOn(true); + ASSERT_EQ(true, obj2.GetSelectedOutputFileOn()); + + ASSERT_EQ(true, ::FileExists(FILES[j].c_str())); + ASSERT_TRUE(::FileSize(FILES[j].c_str()) > 0); + ASSERT_EQ(0, obj2.LoadDatabase(FILES[j].c_str())); + + // all previous definitions are cleared + ASSERT_EQ(false, obj2.GetSelectedOutputFileOn()); + } + } +} + +TEST(TestIPhreeqc, TestLoadDatabaseString) +{ + const char ex15_dat[] = + "SOLUTION_MASTER_SPECIES\n" + "C CO2 2.0 61.0173 12.0111\n" + "Cl Cl- 0.0 Cl 35.453\n" + "Co Co+2 0.0 58.93 58.93 \n" + "E e- 0.0 0.0 0.0\n" + "H H+ -1. 1.008 1.008\n" + "H(0) H2 0.0 1.008\n" + "H(1) H+ -1. 1.008\n" + "N NH4+ 0.0 14.0067 14.0067\n" + "Na Na+ 0.0 Na 22.9898\n" + "Nta Nta-3 3.0 1. 1.\n" + "O H2O 0.0 16.00 16.00\n" + "O(-2) H2O 0.0 18.016\n" + "O(0) O2 0.0 16.00\n" + "SOLUTION_SPECIES\n" + "2H2O = O2 + 4H+ + 4e- \n" + " log_k -86.08; -gamma 1e7 0.0\n" + "2 H+ + 2 e- = H2\n" + " log_k -3.15; -gamma 1e7 0.0\n" + "H+ = H+\n" + " log_k 0.0; -gamma 1e7 0.0\n" + "e- = e-\n" + " log_k 0.0; -gamma 1e7 0.0\n" + "H2O = H2O\n" + " log_k 0.0; -gamma 1e7 0.0\n" + "CO2 = CO2\n" + " log_k 0.0; -gamma 1e7 0.0\n" + "Na+ = Na+\n" + " log_k 0.0; -gamma 1e7 0.0\n" + "Cl- = Cl-\n" + " log_k 0.0; -gamma 1e7 0.0\n" + "Co+2 = Co+2\n" + " log_k 0.0; -gamma 1e7 0.0\n" + "NH4+ = NH4+\n" + " log_k 0.0; -gamma 1e7 0.0\n" + "Nta-3 = Nta-3\n" + " log_k 0.0; -gamma 1e7 0.0\n" + "Nta-3 + 3H+ = H3Nta\n" + " log_k 14.9; -gamma 1e7 0.0\n" + "Nta-3 + 2H+ = H2Nta-\n" + " log_k 13.3; -gamma 1e7 0.0\n" + "Nta-3 + H+ = HNta-2\n" + " log_k 10.3; -gamma 1e7 0.0\n" + "Nta-3 + Co+2 = CoNta-\n" + " log_k 11.7; -gamma 1e7 0.0\n" + "2 Nta-3 + Co+2 = CoNta2-4\n" + " log_k 14.5; -gamma 1e7 0.0\n" + "Nta-3 + Co+2 + H2O = CoOHNta-2 + H+\n" + " log_k 0.5; -gamma 1e7 0.0\n" + "Co+2 + H2O = CoOH+ + H+\n" + " log_k -9.7; -gamma 1e7 0.0\n" + "Co+2 + 2H2O = Co(OH)2 + 2H+\n" + " log_k -22.9; -gamma 1e7 0.0\n" + "Co+2 + 3H2O = Co(OH)3- + 3H+\n" + " log_k -31.5; -gamma 1e7 0.0\n" + "CO2 + H2O = HCO3- + H+\n" + " log_k -6.35; -gamma 1e7 0.0\n" + "CO2 + H2O = CO3-2 + 2H+\n" + " log_k -16.68; -gamma 1e7 0.0\n" + "NH4+ = NH3 + H+\n" + " log_k -9.3; -gamma 1e7 0.0\n" + "H2O = OH- + H+\n" + " log_k -14.0; -gamma 1e7 0.0\n" + "END\n"; + + IPhreeqc obj; + ASSERT_EQ(0, obj.LoadDatabaseString(ex15_dat)); +} + +TEST(TestIPhreeqc, TestLoadDatabaseStringBadInput) +{ + IPhreeqc obj; + + for (int i = 0; i < 10; ++i) + { + ASSERT_TRUE(0 != obj.LoadDatabaseString("phreeqc.dat.list")); + } +} + +TEST(TestIPhreeqc, TestLoadDatabaseEx14AsDB) +{ + const char ex14[] = + "TITLE Example 14.--Transport with equilibrium_phases, exchange, and surface reactions\n" + "#\n" + "# Use phreeqc.dat\n" + "# Dzombak and Morel (1990) aqueous and surface complexation models for arsenic\n" + "# are defined here\n" + "#\n" + "SURFACE_MASTER_SPECIES\n" + " Surf SurfOH\n" + "SURFACE_SPECIES\n" + " SurfOH = SurfOH\n" + " log_k 0.0\n" + " SurfOH + H+ = SurfOH2+\n" + " log_k 7.29\n" + " SurfOH = SurfO- + H+\n" + " log_k -8.93\n" + " SurfOH + AsO4-3 + 3H+ = SurfH2AsO4 + H2O\n" + " log_k 29.31\n" + " SurfOH + AsO4-3 + 2H+ = SurfHAsO4- + H2O\n" + " log_k 23.51\n" + " SurfOH + AsO4-3 = SurfOHAsO4-3\n" + " log_k 10.58\n" + "SOLUTION_MASTER_SPECIES\n" + " As H3AsO4 -1.0 74.9216 74.9216\n" + "SOLUTION_SPECIES\n" + " H3AsO4 = H3AsO4\n" + " log_k 0.0\n" + " H3AsO4 = AsO4-3 + 3H+\n" + " log_k -20.7\n" + " H+ + AsO4-3 = HAsO4-2\n" + " log_k 11.50\n" + " 2H+ + AsO4-3 = H2AsO4-\n" + " log_k 18.46\n" + "SOLUTION 1 Brine\n" + " pH 5.713\n" + " pe 4.0 O2(g) -0.7\n" + " temp 25.\n" + " units mol/kgw\n" + " Ca .4655\n" + " Mg .1609\n" + " Na 5.402\n" + " Cl 6.642 charge\n" + " C .00396\n" + " S .004725\n" + " As .025 umol/kgw\n" + "END\n" + "USE solution 1\n" + "EQUILIBRIUM_PHASES 1\n" + " Dolomite 0.0 1.6\n" + " Calcite 0.0 0.1\n" + "SAVE solution 1\n" + "# prints initial condition to the selected-output file\n" + "SELECTED_OUTPUT\n" + " -file ex14.sel\n" + " -reset false\n" + " -step\n" + "USER_PUNCH\n" + " -head m_Ca m_Mg m_Na umol_As pH mmol_sorbedAs\n" + " 10 PUNCH TOT(\"Ca\"), TOT(\"Mg\"), TOT(\"Na\"), TOT(\"As\")*1e6, -LA(\"H+\"), SURF(\"As\", \"Surf\")*1000\n" + "END\n" + "PRINT\n" + "# skips print of initial exchange and initial surface to the selected-output file\n" + " -selected_out false\n" + "EXCHANGE 1\n" + " -equil with solution 1\n" + " X 1.0\n" + "SURFACE 1\n" + " -equil solution 1\n" + "# assumes 1/10 of iron is HFO\n" + " SurfOH 0.07 600. 30.\n" + "END\n" + "SOLUTION 0 20 x precipitation\n" + " pH 4.6\n" + " pe 4.0 O2(g) -0.7\n" + " temp 25.\n" + " units mmol/kgw\n" + " Ca .191625\n" + " Mg .035797\n" + " Na .122668\n" + " Cl .133704\n" + " C .01096\n" + " S .235153 charge\n" + "EQUILIBRIUM_PHASES 0\n" + " Dolomite 0.0 1.6\n" + " Calcite 0.0 0.1\n" + " CO2(g) -1.5 10.\n" + "SAVE solution 0\n" + "END\n" + "PRINT\n" + " -selected_out true\n" + " -status false\n" + "ADVECTION\n" + " -cells 1\n" + " -shifts 200\n" + " -print_frequency 200\n" + "USER_GRAPH 1 Example 14\n" + " -headings PV As(ppb) Ca(M) Mg(M) Na(M) pH\n" + " -chart_title \"Chemical Evolution of the Central Oklahoma Aquifer\"\n" + " -axis_titles \"Pore volumes or shift number\" \"Log(Concentration, in ppb or molal)\" \"pH\"\n" + " -axis_scale x_axis 0 200\n" + " -axis_scale y_axis 1e-6 100 auto auto Log\n" + " 10 GRAPH_X STEP_NO\n" + " 20 GRAPH_Y TOT(\"As\") * 74.92e6, TOT(\"Ca\"), TOT(\"Mg\"), TOT(\"Na\")\n" + " 30 GRAPH_SY -LA(\"H+\")\n" + "END\n"; + + IPhreeqc obj; + for (int i = 0; i < 10; ++i) + { + ASSERT_TRUE(0 != obj.LoadDatabaseString(ex14)); + } +} + +TEST(TestIPhreeqc, TestLoadDatabaseMissingFile) +{ + ASSERT_EQ(false, ::FileExists("missing.file")); + + IPhreeqc obj; + + ASSERT_EQ(1, obj.LoadDatabase("missing.file")); + ASSERT_EQ(1, obj.LoadDatabase("missing.file")); + ASSERT_EQ(1, obj.LoadDatabase("missing.file")); + + const char expected[] = + "ERROR: LoadDatabase: Unable to open:\"missing.file\".\n"; + + const char* err = obj.GetErrorString(); + ASSERT_EQ(std::string(expected), std::string(err)); +} + +TEST(TestIPhreeqc, TestSetErrorOn) +{ + ASSERT_EQ(false, ::FileExists("missing.file")); + + IPhreeqc obj; + ASSERT_EQ(true, obj.GetErrorOn()); // intial setting is true + + obj.SetErrorOn(false); + ASSERT_EQ(false, obj.GetErrorOn()); + + ASSERT_EQ(1, obj.LoadDatabase("missing.file")); + ASSERT_EQ(1, obj.LoadDatabase("missing.file")); + ASSERT_EQ(1, obj.LoadDatabase("missing.file")); + + const char expected[] = "GetErrorString: ErrorOn not set.\n"; + const char* err = obj.GetErrorString(); + ASSERT_EQ(std::string(expected), std::string(err)); +} + +TEST(TestIPhreeqc, TestSetErrorOn2) +{ + ASSERT_EQ(false, ::FileExists("missing.file")); + + IPhreeqc obj; + + char ERR_FILENAME[80]; + sprintf(ERR_FILENAME, "error.%06d.out", ::rand()); + if (::FileExists(ERR_FILENAME)) + { + ::DeleteFile(ERR_FILENAME); + } + ASSERT_EQ(false, ::FileExists(ERR_FILENAME)); + + obj.SetErrorFileOn(true); + obj.SetErrorFileName(ERR_FILENAME); + + ASSERT_EQ(true, obj.GetErrorOn()); // intial setting is true + + obj.SetErrorOn(false); + ASSERT_EQ(false, obj.GetErrorOn()); + + ASSERT_EQ(1, obj.LoadDatabase("missing.file")); + ASSERT_EQ(1, obj.LoadDatabase("missing.file")); + ASSERT_EQ(1, obj.LoadDatabase("missing.file")); + + ASSERT_EQ(false, ::FileExists(ERR_FILENAME)); +} + +TEST(TestIPhreeqc, TestSetErrorOnTakesPrecedence) +{ + ASSERT_EQ(false, ::FileExists("missing.file")); + + IPhreeqc obj; + + char ERR_FILENAME[80]; + sprintf(ERR_FILENAME, "error.%06d.out", ::rand()); + if (::FileExists(ERR_FILENAME)) + { + ::DeleteFile(ERR_FILENAME); + } + ASSERT_EQ(false, ::FileExists(ERR_FILENAME)); + + obj.SetErrorFileOn(true); + obj.SetErrorFileName(ERR_FILENAME); + + obj.SetErrorOn(false); + obj.SetErrorStringOn(false); + + ASSERT_EQ(1, obj.LoadDatabase("missing.file")); + ASSERT_EQ(1, obj.LoadDatabase("missing.file")); + ASSERT_EQ(1, obj.LoadDatabase("missing.file")); + + const char expected[] = "GetErrorString: ErrorOn not set.\n"; + const char* err = obj.GetErrorString(); + ASSERT_EQ(std::string(expected), std::string(err)); + + ASSERT_EQ(false, ::FileExists(ERR_FILENAME)); +} + +TEST(TestIPhreeqc, TestLoadDatabaseWithErrors) +{ +#if defined(_WIN32) + int n0 = ::_fcloseall(); + assert(n0 == 0); +#endif + + IPhreeqc obj; + + for (int i = 0; i < 10; ++i) + { + ASSERT_EQ(true, ::FileExists("missing_e.dat")); + ASSERT_TRUE(::FileSize("missing_e.dat") > 0); + ASSERT_EQ(6, obj.LoadDatabase("missing_e.dat")); + + const char* expected = + "ERROR: Could not reduce equation to primary master species, CH4.\n" + "ERROR: Could not reduce equation to primary master species, Cu+.\n" + "ERROR: Could not reduce equation to primary master species, Fe+3.\n" + "ERROR: Could not reduce equation to primary master species, H2.\n" + "ERROR: Could not reduce equation to primary master species, Mn+3.\n" + "ERROR: Could not reduce equation to primary master species, NH4+.\n" + "ERROR: Could not reduce equation to primary master species, N2.\n" + "ERROR: Could not reduce equation to primary master species, NO2-.\n" + "ERROR: Could not reduce equation to primary master species, O2.\n" + "ERROR: Could not reduce equation to primary master species, HS-.\n" + "ERROR: Could not reduce equation to secondary master species, e-.\n" + "ERROR: Non-master species in secondary reaction, e-.\n" + "ERROR: No master species for element e.\n" + "ERROR: Could not find primary master species for e.\n" + "ERROR: No master species for element e.\n" + "ERROR: Could not reduce equation to secondary master species, Hausmannite.\n" + "ERROR: Could not reduce equation to secondary master species, Manganite.\n" + "ERROR: Could not reduce equation to secondary master species, Pyrite.\n" + "ERROR: Could not reduce equation to secondary master species, Pyrolusite.\n" + "ERROR: Could not reduce equation to secondary master species, Sulfur.\n" + "ERROR: e-, primary master species for E-, not defined.\n" + "ERROR: Calculations terminating due to input errors.\n"; + + const char* err = obj.GetErrorString(); + ASSERT_EQ(std::string(expected), std::string(err)); + } +#if defined(_WIN32) + int n = ::_fcloseall(); + assert(n == 0); +#endif +} + +TEST(TestIPhreeqc, TestRunAccumulated) +{ +#if defined(_WIN32) + int n = ::_fcloseall(); + assert(n == 0); +#endif + + bool files_on = false; + IPhreeqc obj; + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("solution 12")); + obj.SetOutputFileOn(files_on); + obj.SetErrorFileOn(files_on); + obj.SetLogFileOn(files_on); + obj.SetSelectedOutputFileOn(files_on); + obj.SetDumpFileOn(files_on); + ASSERT_EQ(0, obj.RunAccumulated()); +} + +TEST(TestIPhreeqc, TestRunAccumulatedWithDBKeyword) +{ + IPhreeqc obj; + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + for (int i = 0; i < 10; ++i) + { + ASSERT_EQ(VR_OK, obj.AccumulateLine("DATABASE wateq4f.dat")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("SOLUTION 1")); + ASSERT_EQ(0, obj.RunAccumulated()); + + const char* warn = obj.GetWarningString(); + const char expected[] = "WARNING: DATABASE keyword is ignored by IPhreeqc.\n"; + + ASSERT_EQ(std::string(expected), std::string(warn)); + } +} + +TEST(TestIPhreeqc, TestDatabaseNotFirstKeyword) +{ + IPhreeqc obj; + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + for (int i = 0; i < 10; ++i) + { + ASSERT_EQ(VR_OK, obj.AccumulateLine("SOLUTION 1")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("DATABASE wateq4f.dat")); + ASSERT_EQ(2, obj.RunAccumulated()); + + const char expected[] = + "ERROR: DATABASE must be the first keyword in the input file.\n" + "ERROR: Calculations terminating due to input errors.\n"; + const char* err = obj.GetErrorString(); + + ASSERT_EQ(std::string(expected), std::string(err)); + } +} + +TEST(TestIPhreeqc, TestRunWithErrors) +{ + const char dump_file[] = "error.inp"; + IPhreeqc obj; + + FileTest dfile(dump_file); + ASSERT_TRUE(dfile.RemoveExisting()); + + bool files_on = false; + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("SOLUTION 1")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" pH 7")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Na 1")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("PHASES")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Fix_H+")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" H+ = H+")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" log_k 0")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("EQUILIBRIUM_PHASES")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Fix_H+ -10 HCl 10")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("END")); + + obj.SetOutputFileOn(files_on); + obj.SetErrorFileOn(files_on); + obj.SetLogFileOn(files_on); + obj.SetSelectedOutputFileOn(files_on); + obj.SetDumpFileOn(files_on); + ASSERT_EQ(1, obj.RunAccumulated()); + + const char expected[] = + "ERROR: Numerical method failed on all combinations of convergence parameters, cell/soln/mix 1\n"; + const char* err = obj.GetErrorString(); + + ASSERT_EQ(std::string(expected), std::string(err)); + + ASSERT_TRUE(dfile.VerifyExists()); + ASSERT_TRUE(dfile.Size() > 0); +} + +TEST(TestIPhreeqc, TestRunFile) +{ + const char dump_file[] = "error.inp"; + + FileTest dfile(dump_file); + ASSERT_TRUE(dfile.RemoveExisting()); + + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + obj.SetOutputFileOn(false); + obj.SetErrorFileOn(false); + obj.SetLogFileOn(false); + obj.SetSelectedOutputFileOn(false); + obj.SetDumpFileOn(false); + ASSERT_EQ(1, obj.RunFile("conv_fail.in")); + + const char expected[] = + "ERROR: Numerical method failed on all combinations of convergence parameters, cell/soln/mix 1\n"; + const char* err = obj.GetErrorString(); + + ASSERT_EQ(std::string(expected), std::string(err)); + + // Note: should this file exist since GetDumpFileOn is false? + ASSERT_TRUE(dfile.VerifyExists()); + ASSERT_TRUE(dfile.Size() > 0); +} + +TEST(TestIPhreeqc, TestRunString) +{ + const char input[] = + "TITLE Example 1.--Add uranium and speciate seawater.\n" + "SOLUTION 1 SEAWATER FROM NORDSTROM ET AL. (1979)\n" + " units ppm\n" + " pH 8.22\n" + " pe 8.451\n" + " density 1.023\n" + " temp 25.0\n" + " redox O(0)/O(-2)\n" + " Ca 412.3\n" + " Mg 1291.8\n" + " Na 10768.0\n" + " K 399.1\n" + " Fe 0.002\n" + " Mn 0.0002 pe\n" + " Si 4.28\n" + " Cl 19353.0\n" + " Alkalinity 141.682 as HCO3\n" + " S(6) 2712.0\n" + " N(5) 0.29 gfw 62.0\n" + " N(-3) 0.03 as NH4\n" + " U 3.3 ppb N(5)/N(-3)\n" + " O(0) 1.0 O2(g) -0.7\n" + "SOLUTION_MASTER_SPECIES\n" + " U U+4 0.0 238.0290 238.0290\n" + " U(4) U+4 0.0 238.0290\n" + " U(5) UO2+ 0.0 238.0290\n" + " U(6) UO2+2 0.0 238.0290\n" + "SOLUTION_SPECIES\n" + " #primary master species for U\n" + " #is also secondary master species for U(4)\n" + " U+4 = U+4\n" + " log_k 0.0\n" + " U+4 + 4 H2O = U(OH)4 + 4 H+\n" + " log_k -8.538\n" + " delta_h 24.760 kcal\n" + " U+4 + 5 H2O = U(OH)5- + 5 H+\n" + " log_k -13.147\n" + " delta_h 27.580 kcal\n" + " #secondary master species for U(5)\n" + " U+4 + 2 H2O = UO2+ + 4 H+ + e-\n" + " log_k -6.432\n" + " delta_h 31.130 kcal\n" + " #secondary master species for U(6)\n" + " U+4 + 2 H2O = UO2+2 + 4 H+ + 2 e-\n" + " log_k -9.217\n" + " delta_h 34.430 kcal\n" + " UO2+2 + H2O = UO2OH+ + H+\n" + " log_k -5.782\n" + " delta_h 11.015 kcal\n" + " 2UO2+2 + 2H2O = (UO2)2(OH)2+2 + 2H+\n" + " log_k -5.626\n" + " delta_h -36.04 kcal\n" + " 3UO2+2 + 5H2O = (UO2)3(OH)5+ + 5H+\n" + " log_k -15.641\n" + " delta_h -44.27 kcal\n" + " UO2+2 + CO3-2 = UO2CO3\n" + " log_k 10.064\n" + " delta_h 0.84 kcal\n" + " UO2+2 + 2CO3-2 = UO2(CO3)2-2\n" + " log_k 16.977\n" + " delta_h 3.48 kcal\n" + " UO2+2 + 3CO3-2 = UO2(CO3)3-4\n" + " log_k 21.397\n" + " delta_h -8.78 kcal\n" + "PHASES\n" + " Uraninite\n" + " UO2 + 4 H+ = U+4 + 2 H2O\n" + " log_k -3.490\n" + " delta_h -18.630 kcal\n" + "END\n" + "\n"; + + IPhreeqc obj; + + char OUTPUT_FILE[80]; + //sprintf(OUTPUT_FILE, "phreeqc.%lu.out", (unsigned long)obj.GetId()); + sprintf(OUTPUT_FILE, "phreeqc.%lu.out", (unsigned long)obj.GetId()); + + FileTest ofile(OUTPUT_FILE); + ASSERT_TRUE(ofile.RemoveExisting()); + + ASSERT_EQ(false, ::FileExists(OUTPUT_FILE)); + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + obj.SetOutputFileOn(1); + obj.SetErrorFileOn(0); + obj.SetLogFileOn(0); + obj.SetSelectedOutputFileOn(0); + obj.SetDumpFileOn(0); + ASSERT_EQ(false, ::FileExists(OUTPUT_FILE)); + ASSERT_EQ(0, obj.RunString(input)); + + ASSERT_TRUE(ofile.VerifyExists()); + ASSERT_TRUE(ofile.Size() > 0); +} + +TEST(TestIPhreeqc, TestGetSelectedOutputRowCount) +{ + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("llnl.dat")); + + int max = 6; + + ASSERT_EQ(VR_OK, SOLUTION(obj, 1.0, 1.0, 1.0)); + ASSERT_EQ(VR_OK, EQUILIBRIUM_PHASES(obj, "calcite", 0.0, 0.010)); + ASSERT_EQ(VR_OK, USER_PUNCH(obj, "Ca", max)); + + obj.SetOutputFileOn(false); + obj.SetErrorFileOn(false); + obj.SetLogFileOn(false); + obj.SetSelectedOutputFileOn(false); + obj.SetDumpFileOn(false); + ASSERT_EQ(0, obj.RunAccumulated()); + + ASSERT_EQ(3, obj.GetSelectedOutputRowCount()); // rows + header +} + +TEST(TestIPhreeqc, TestGetSelectedOutputValue) +{ + int col; + + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("llnl.dat")); + + int max = 6; + + ASSERT_EQ(VR_OK, SOLUTION(obj, 1.0, 1.0, 1.0)); + ASSERT_EQ(VR_OK, EQUILIBRIUM_PHASES(obj, "calcite", 0.0, 0.010)); + ASSERT_EQ(VR_OK, USER_PUNCH(obj, "Ca", max)); + + obj.SetOutputFileOn(0); + obj.SetErrorFileOn(0); + obj.SetLogFileOn(0); + obj.SetSelectedOutputFileOn(0); + obj.SetDumpFileOn(0); + ASSERT_EQ(0, obj.RunAccumulated()); + + /* + EXPECTED selected.out: + sim state soln dist_x time step pH pe C Ca Na m_CO3-2 m_CaOH+ m_NaCO3- la_CO3-2 la_CaOH+ la_NaCO3- Calcite d_Calcite si_CO2(g) si_Siderite pressure total mol volume g_CO2(g) g_N2(g) k_Albite dk_Albite k_Pyrite dk_Pyrite s_CaSO4 s_SrSO4 1.name 1.type 1.moles 2.name 2.type 2.moles 3.name 3.type 3.moles 4.name 4.type 4.moles 5.name 5.type 5.moles 6.name 6.type 6.moles + 1 i_soln 1 -99 -99 -99 7 4 1.0000e-003 1.0000e-003 1.0000e-003 4.2975e-007 1.1819e-009 1.1881e-009 -6.4686e+000 -8.9530e+000 -8.9507e+000 0.0000e+000 0.0000e+000 -2.2870 -999.9990 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 Ca+2 aq 9.9178e-004 CaHCO3+ aq 7.5980e-006 CaCO3 aq 6.2155e-007 CaOH+ aq 1.1819e-009 + 1 react 1 -99 0 1 7.86135 10.18 1.1556e-003 1.1556e-003 1.0000e-003 4.2718e-006 9.7385e-009 1.1620e-008 -5.4781e+000 -8.0388e+000 -7.9621e+000 9.8444e-003 -1.5555e-004 -3.0192 -999.9990 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 calcite equi 9.8444e-003 Ca+2 aq 1.1371e-003 CaHCO3+ aq 1.1598e-005 CaCO3 aq 6.8668e-006 CaOH+ aq 9.7385e-009 + */ + + + CVar v; + + ASSERT_EQ(VR_INVALIDROW, obj.GetSelectedOutputValue(-1, 0, &v)); + ASSERT_EQ(TT_ERROR, v.type); + ASSERT_EQ(VR_INVALIDROW, v.vresult); + + ASSERT_EQ(VR_INVALIDROW, obj.GetSelectedOutputValue(obj.GetSelectedOutputRowCount(), 0, &v)); + ASSERT_EQ(TT_ERROR, v.type); + ASSERT_EQ(VR_INVALIDROW, v.vresult); + + ASSERT_EQ(VR_INVALIDCOL, obj.GetSelectedOutputValue(0, -1, &v)); + ASSERT_EQ(TT_ERROR, v.type); + ASSERT_EQ(VR_INVALIDCOL, v.vresult); + + ASSERT_EQ(VR_INVALIDCOL, obj.GetSelectedOutputValue(0, obj.GetSelectedOutputColumnCount(), &v)); + ASSERT_EQ(TT_ERROR, v.type); + ASSERT_EQ(VR_INVALIDCOL, v.vresult); + + + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, 0, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("sim"), std::string(v.sVal)); + + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, 1, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("state"), std::string(v.sVal)); + + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, 2, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("soln"), std::string(v.sVal)); + + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, 3, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("dist_x"), std::string(v.sVal)); + + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, 4, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("time"), std::string(v.sVal)); + + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, 5, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("step"), std::string(v.sVal)); + + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, 6, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("pH"), std::string(v.sVal)); + + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, 7, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("pe"), std::string(v.sVal)); + + col = 7; + + // -totals C Ca Na + ++col; + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("C(mol/kgw)"), std::string(v.sVal)); + ++col; + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("Ca(mol/kgw)"), std::string(v.sVal)); + ++col; + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("Na(mol/kgw)"), std::string(v.sVal)); + + // -molalities CO3-2 CaOH+ NaCO3- + ++col; + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("m_CO3-2(mol/kgw)"), std::string(v.sVal)); + ++col; + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("m_CaOH+(mol/kgw)"), std::string(v.sVal)); + ++col; + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("m_NaCO3-(mol/kgw)"), std::string(v.sVal)); + + // -activities CO3-2 CaOH+ NaCO3- + ++col; + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("la_CO3-2"), std::string(v.sVal)); + ++col; + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("la_CaOH+"), std::string(v.sVal)); + ++col; + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("la_NaCO3-"), std::string(v.sVal)); + + // -equilibrium_phases Calcite + ++col; + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("Calcite"), std::string(v.sVal)); + ++col; + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("d_Calcite"), std::string(v.sVal)); + + + // -saturation_indices CO2(g) Siderite + ++col; + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("si_CO2(g)"), std::string(v.sVal)); + ++col; + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("si_Siderite"), std::string(v.sVal)); + + // -gases CO2(g) N2(g) + // pressure "total mol" volume g_CO2(g) g_N2(g) + ++col; + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("pressure"), std::string(v.sVal)); + ++col; + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("total mol"), std::string(v.sVal)); + ++col; + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("volume"), std::string(v.sVal)); + ++col; + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("g_CO2(g)"), std::string(v.sVal)); + ++col; + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("g_N2(g)"), std::string(v.sVal)); + + // -kinetic_reactants Albite Pyrite + // k_Albite dk_Albite k_Pyrite dk_Pyrite + ++col; + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("k_Albite"), std::string(v.sVal)); + ++col; + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("dk_Albite"), std::string(v.sVal)); + ++col; + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("k_Pyrite"), std::string(v.sVal)); + ++col; + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("dk_Pyrite"), std::string(v.sVal)); + + // -solid_solutions CaSO4 SrSO4 + // s_CaSO4 s_SrSO4 + ++col; + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("s_CaSO4"), std::string(v.sVal)); + ++col; + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("s_SrSO4"), std::string(v.sVal)); + + for (int i = 0; i < max; ++i) + { + std::ostringstream oss1, oss2, oss3; + + // 1.name + // + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, col + 1 + (i * 3), &v)); + ASSERT_EQ(TT_STRING, v.type); + oss1 << i + 1 << ".name"; + ASSERT_EQ(oss1.str(), std::string(v.sVal)); + + // 1.type + // + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, col + 2 + (i * 3), &v)); + ASSERT_EQ(TT_STRING, v.type); + oss2 << i + 1 << ".type"; + ASSERT_EQ(oss2.str(), std::string(v.sVal)); + + // 1.moles + // + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, col + 3 + (i * 3), &v)); + ASSERT_EQ(TT_STRING, v.type); + oss3 << i + 1 << ".moles"; + ASSERT_EQ(oss3.str(), std::string(v.sVal)); + } + + // sim + // + col = 0; + // i_soln + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, col, &v)); + ASSERT_EQ(TT_LONG, v.type); + ASSERT_EQ(1L, v.lVal); + // react + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, col, &v)); + ASSERT_EQ(TT_LONG, v.type); + ASSERT_EQ(1L, v.lVal); + + // state + // + ++col; + // i_soln + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("i_soln"), std::string(v.sVal)); + // react + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("react"), std::string(v.sVal)); + + // soln + // + ++col; + // i_soln + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, col, &v)); + ASSERT_EQ(TT_LONG, v.type); + ASSERT_EQ(1L, v.lVal); + // react + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, col, &v)); + ASSERT_EQ(TT_LONG, v.type); + ASSERT_EQ(1L, v.lVal); + + // dist_x -- (always as double) + // + ++col; + // i_soln + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_EQ(-99., v.dVal); + // react + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_EQ(-99., v.dVal); + + + // time -- (always as double) + // + ++col; + // i_soln + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_EQ(-99., v.dVal); + // react + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(0.0, v.dVal, ::pow(10., -DBL_DIG)); + + // step + // + ++col; + // i_soln + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, col, &v)); + ASSERT_EQ(TT_LONG, v.type); + ASSERT_EQ(-99L, v.lVal); + // react + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, col, &v)); + ASSERT_EQ(TT_LONG, v.type); + ASSERT_EQ(1L, v.lVal); + + + // pH + // + ++col; + // i_soln + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(7.0, v.dVal, ::pow(10., -DBL_DIG)); + // react + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(7.861354, v.dVal, ::pow(10., -6)); + + // pe + // + ++col; + // i_soln + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(4.0, v.dVal, ::pow(10., -DBL_DIG)); + // react + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + // COMMENT: {8/8/2013 12:26:01 AM} ASSERT_NEAR( 9.90855, v.dVal, ::pow(10., -1) ); + + // + // -totals C Ca Na + // + + // C(mol/kgw) + // + ++col; + // i_soln + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(1.0000e-003, v.dVal, ::pow(10., -DBL_DIG)); + // react + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(1.1556e-003, v.dVal, ::pow(10., -7)); + + + // Ca(mol/kgw) + // + ++col; + // i_soln + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(1.0000e-003, v.dVal, ::pow(10., -DBL_DIG)); + // react + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(1.1556e-003, v.dVal, ::pow(10., -7)); + + + // Na(mol/kgw) + // + ++col; + // i_soln + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(1.0000e-003, v.dVal, ::pow(10., -DBL_DIG)); + // react + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(1.0000e-003, v.dVal, ::pow(10., -7)); + + // -molalities CO3-2 CaOH+ NaCO3- + col += 3; + + // -activities CO3-2 CaOH+ NaCO3- + col += 3; + + // -equilibrium_phases Calcite + col += 2; + + // -saturation_indices CO2(g) Siderite + col += 2; + + // -gases CO2(g) N2(g) + col += 5; + + // -kinetic_reactants Albite Pyrite + // k_Albite dk_Albite k_Pyrite dk_Pyrite + col += 4; + + // -solid_solutions CaSO4 SrSO4 + // s_CaSO4 s_SrSO4 + col += 2; + + + // 1.name + // + ++col; + // i_soln + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("Ca+2"), std::string(v.sVal)); + // react + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("Calcite"), std::string(v.sVal)); + + // 1.type + // + ++col; + // i_soln + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("aq"), std::string(v.sVal)); + // react + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("equi"), std::string(v.sVal)); + + // 1.moles + // + ++col; + // i_soln + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(9.9177923E-04, v.dVal, ::pow(10., -11)); + // react + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(9.8444477E-03, v.dVal, ::pow(10., -10)); + + // 2.name + // + ++col; + // i_soln + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("CaHCO3+"), std::string(v.sVal)); + // react + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("Ca+2"), std::string(v.sVal)); + + // 2.type + // + ++col; + // i_soln + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("aq"), std::string(v.sVal)); + // react + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("aq"), std::string(v.sVal)); + + // 2.moles + // + ++col; + // i_soln + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(7.5980e-006, v.dVal, ::pow(10., -10)); + // react + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(1.1371e-003, v.dVal, ::pow(10., -7)); + + + // 3.name + // + ++col; + // i_soln + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("CaCO3"), std::string(v.sVal)); + // react + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("CaHCO3+"), std::string(v.sVal)); + + // 3.type + // + ++col; + // i_soln + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("aq"), std::string(v.sVal)); + // react + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("aq"), std::string(v.sVal)); + + // 3.moles + // + ++col; + // i_soln + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(6.2155e-007, v.dVal, ::pow(10., -11)); + // react + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(1.1598e-005, v.dVal, ::pow(10., -9)); + + + + // 4.name + // + ++col; + // i_soln + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("CaOH+"), std::string(v.sVal)); + // react + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("CaCO3"), std::string(v.sVal)); + + // 4.type + // + ++col; + // i_soln + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("aq"), std::string(v.sVal)); + // react + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("aq"), std::string(v.sVal)); + + // 4.moles + // + ++col; + // i_soln + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(1.1819e-009, v.dVal, ::pow(10., -13)); + // react + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(6.8668e-006, v.dVal, ::pow(10., -10)); + + + // 5.name + // + ++col; + // i_soln + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, col, &v)); + ASSERT_EQ(TT_EMPTY, v.type); + // react + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("CaOH+"), std::string(v.sVal)); + + // 5.type + // + ++col; + // i_soln + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, col, &v)); + ASSERT_EQ(TT_EMPTY, v.type); + // react + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("aq"), std::string(v.sVal)); + + // 5.moles + // + ++col; + // i_soln + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, col, &v)); + ASSERT_EQ(TT_EMPTY, v.type); + // react + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(9.7385e-009, v.dVal, ::pow(10., -13)); + + + // 6.name + // + ++col; + // i_soln + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, col, &v)); + ASSERT_EQ(TT_EMPTY, v.type); + // react + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, col, &v)); + ASSERT_EQ(TT_EMPTY, v.type); + + // 6.type + // + ++col; + // i_soln + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, col, &v)); + ASSERT_EQ(TT_EMPTY, v.type); + // react + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, col, &v)); + ASSERT_EQ(TT_EMPTY, v.type); + + // 6.moles + // + ++col; + // i_soln + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, col, &v)); + ASSERT_EQ(TT_EMPTY, v.type); + // react + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, col, &v)); + ASSERT_EQ(TT_EMPTY, v.type); +} + +TEST(TestIPhreeqc, TestGetSelectedOutputColumnCount) +{ + IPhreeqc obj; + ASSERT_EQ(0, obj.LoadDatabase("llnl.dat")); + ASSERT_EQ(0, obj.GetSelectedOutputColumnCount()); + ASSERT_EQ(VR_OK, SOLUTION(obj, 1.0, 1.0, 1.0)); + ASSERT_EQ(VR_OK, EQUILIBRIUM_PHASES(obj, "calcite", 1.0, 1.0)); + ASSERT_EQ(VR_OK, USER_PUNCH(obj, "Ca", 10)); + ASSERT_EQ(0, obj.RunAccumulated()); + ASSERT_EQ(62, obj.GetSelectedOutputColumnCount()); +} + +TEST(TestIPhreeqc, TestAddError) +{ + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + // make sure initialized to empty + // + const char* err = obj.GetErrorString(); + ASSERT_EQ(std::string(""), std::string(err)); + + // make sure initialized to empty + // + const char* expected = "TESTING AddError\n"; + ASSERT_EQ((size_t)1, obj.AddError(expected)); + + // check 1 + // + err = obj.GetErrorString(); + ASSERT_EQ(std::string(expected), std::string(err)); + + // check increment + // + const char* expected2 = "XXXXXX\n"; + ASSERT_EQ((size_t)2, obj.AddError(expected2)); + + // check concatenation + // + err = obj.GetErrorString(); + ASSERT_EQ(std::string(expected) + std::string(expected2), std::string(err)); + + + // clear errors + // + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + // make sure back to empty + // + err = obj.GetErrorString(); + ASSERT_EQ(std::string(""), std::string(err)); +} + +TEST(TestIPhreeqc, TestAccumulateLine) +{ + // TODO +} + +TEST(TestIPhreeqc, TestOutputErrorString) +{ + // TODO +} + +TEST(TestIPhreeqc, TestRunWithCallback) +{ + // TODO +} + +TEST(TestIPhreeqc, TestRunNoDatabaseLoaded) +{ + IPhreeqc obj; + +#if FIXME_PROTECTED + obj.UnLoadDatabase(); +#endif + obj.SetOutputFileOn(false); + obj.SetErrorFileOn(false); + obj.SetLogFileOn(false); + obj.SetSelectedOutputFileOn(false); + obj.SetDumpFileOn(false); + ASSERT_EQ(1, obj.RunAccumulated()); + + const char expected[] = + "ERROR: RunAccumulated: No database is loaded\n"; + const char* err = obj.GetErrorString(); + + ASSERT_EQ(std::string(expected), std::string(err)); +} + +TEST(TestIPhreeqc, TestCase1) +{ + // Case 1 (see do_run) + // pr.punch == TRUE + // punch.new_def == FALSE + // output_isopen(OUTPUT_PUNCH) == FALSE + // selected_output_on == TRUE + + IPhreeqc obj; + + char SELECTED_OUT[80]; + sprintf(SELECTED_OUT, "selected_1.%lu.out", (unsigned long)obj.GetId()); + + // remove punch file if it exists + FileTest sofile(SELECTED_OUT); + ASSERT_TRUE(sofile.RemoveExisting()); + + // clear all flags + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); +#if FIXME_PROTECTED + ASSERT_EQ(false, obj.PhreeqcPtr->SelectedOutput_map.size() > 0); + ASSERT_EQ(TRUE, obj.PhreeqcPtr->pr.punch); +#endif + + + ASSERT_EQ(VR_OK, SOLUTION(obj, 1.0, 1.0, 1.0)); + ASSERT_EQ(VR_OK, USER_PUNCH(obj, "Ca", 10)); + obj.SetOutputFileOn(false); + obj.SetErrorFileOn(false); + obj.SetLogFileOn(false); + obj.SetSelectedOutputFileOn(true); + obj.SetDumpFileOn(false); + ASSERT_EQ(0, obj.RunAccumulated()); + + ASSERT_TRUE(sofile.VerifyExists()); + ASSERT_TRUE(sofile.Size() > 0); + ASSERT_EQ(62, obj.GetSelectedOutputColumnCount()); + + ASSERT_EQ(VR_OK, SOLUTION(obj, 1.0, 1.0, 1.0)); + obj.SetOutputFileOn(false); + obj.SetErrorFileOn(false); + obj.SetLogFileOn(false); + obj.SetSelectedOutputFileOn(true); + obj.SetDumpFileOn(false); + ASSERT_EQ(0, obj.RunAccumulated()); + + ASSERT_TRUE(sofile.VerifyExists()); + ASSERT_TRUE(sofile.Size() > 0); + ASSERT_EQ(62, obj.GetSelectedOutputColumnCount()); +} + +TEST(TestIPhreeqc, TestCase2) +{ + // Case 2 (see do_run) + // pr.punch == TRUE + // punch.new_def == TRUE + // output_isopen(OUTPUT_PUNCH) == FALSE + // selected_output_on == TRUE + + IPhreeqc obj; + + // remove punch files if they exists + // + FileTest sofile("selected.out"); + FileTest c2file("case2.punch"); + ASSERT_TRUE(sofile.RemoveExisting()); + ASSERT_TRUE(c2file.RemoveExisting()); + + // clear all flags + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); +#if FIXME_PROTECTED + ASSERT_EQ(false, obj.PhreeqcPtr->SelectedOutput_map.size() > 0); + ASSERT_EQ(TRUE, obj.PhreeqcPtr->pr.punch); +#endif + + ASSERT_EQ(VR_OK, SOLUTION(obj, 1.0, 1.0, 1.0)); + ASSERT_EQ(VR_OK, USER_PUNCH(obj, "Ca", 10)); + ASSERT_EQ(VR_OK, obj.AccumulateLine("-file case2.punch")); // force have_punch_name to TRUE (see read_selected_ouput) + obj.SetOutputFileOn(false); + obj.SetErrorFileOn(false); + obj.SetLogFileOn(false); + obj.SetSelectedOutputFileOn(true); + obj.SetDumpFileOn(false); + ASSERT_EQ(0, obj.RunAccumulated()); + ASSERT_TRUE(sofile.VerifyMissing()); + ASSERT_TRUE(c2file.VerifyExists()); + ASSERT_EQ(62, obj.GetSelectedOutputColumnCount()); + + + // remove punch files if they exist + // + ASSERT_TRUE(sofile.RemoveExisting()); + ASSERT_TRUE(c2file.RemoveExisting()); + + ASSERT_EQ(VR_OK, SOLUTION(obj, 1.0, 1.0, 1.0)); + ASSERT_EQ(VR_OK, USER_PUNCH(obj, "Ca", 10)); + obj.SetOutputFileOn(false); + obj.SetErrorFileOn(false); + obj.SetLogFileOn(false); + obj.SetSelectedOutputFileOn(true); + obj.SetDumpFileOn(false); + ASSERT_EQ(0, obj.RunAccumulated()); + ASSERT_TRUE(sofile.VerifyMissing()); + ASSERT_TRUE(c2file.VerifyExists()); + ASSERT_EQ(62, obj.GetSelectedOutputColumnCount()); +} + +TEST(TestIPhreeqc, TestPrintSelectedOutputFalse) +{ + IPhreeqc obj; + + // remove punch files if they exists + // + if (::FileExists("selected.out")) + { + ::DeleteFile("selected.out"); + } + ASSERT_EQ(false, ::FileExists("selected.out")); + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + // add solution block + ASSERT_EQ(VR_OK, SOLUTION(obj, 1.0, 1.0, 1.0)); + + // add selected output block + ASSERT_EQ(VR_OK, SELECTED_OUTPUT(obj)); + + // turn off selected output + ASSERT_EQ(VR_OK, obj.AccumulateLine("PRINT; -selected_output false \n")); + + // run + obj.SetOutputFileOn(false); + obj.SetErrorFileOn(false); + obj.SetLogFileOn(false); + obj.SetSelectedOutputFileOn(true); + obj.SetDumpFileOn(false); + ASSERT_EQ(0, obj.RunAccumulated()); + + ASSERT_EQ(0, obj.GetSelectedOutputColumnCount()); + ASSERT_EQ(0, obj.GetSelectedOutputRowCount()); + + + // reset pr.punch to TRUE + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + // add solution block + ASSERT_EQ(VR_OK, SOLUTION(obj, 1.0, 1.0, 1.0)); + + // add selected output block + ASSERT_EQ(VR_OK, SELECTED_OUTPUT(obj)); + + // run + obj.SetOutputFileOn(false); + obj.SetErrorFileOn(false); + obj.SetLogFileOn(false); + obj.SetSelectedOutputFileOn(true); + obj.SetDumpFileOn(false); + ASSERT_EQ(0, obj.RunAccumulated()); + + ASSERT_EQ(11, obj.GetSelectedOutputColumnCount()); + ASSERT_EQ(2, obj.GetSelectedOutputRowCount()); +} + +TEST(TestIPhreeqc, TestOutputFileOnOff) +{ +#if defined(_WIN32) + int n = ::_fcloseall(); + ASSERT_EQ(0, n); +#endif + + bool onoff[5]; + onoff[0] = true; // output_file_on + onoff[1] = false; // error_file_on + onoff[2] = false; // log_file_on + onoff[3] = false; // selected_output_file_on + onoff[4] = false; // dump_file_on + TestFileOnOff("phreeqc.%d.out", onoff[0], onoff[1], onoff[2], onoff[3], onoff[4]); +} + +TEST(TestIPhreeqc, TestErrorFileOnOff) +{ + bool onoff[5]; + onoff[0] = false; // output_file_on + onoff[1] = true; // error_file_on + onoff[2] = false; // log_file_on + onoff[3] = false; // selected_output_file_on + onoff[4] = false; // dump_file_on + TestFileOnOff("phreeqc.%d.err", onoff[0], onoff[1], onoff[2], onoff[3], onoff[4]); +} + +TEST(TestIPhreeqc, TestLogFileOnOff) +{ + bool onoff[5]; + onoff[0] = false; // output_file_on + onoff[1] = false; // error_file_on + onoff[2] = true; // log_file_on + onoff[3] = false; // selected_output_file_on + onoff[4] = false; // dump_file_on + TestFileOnOff("phreeqc.%d.log", onoff[0], onoff[1], onoff[2], onoff[3], onoff[4]); +} + +TEST(TestIPhreeqc, TestDumpFileOnOff) +{ + bool onoff[5]; + onoff[0] = false; // output_file_on + onoff[1] = false; // error_file_on + onoff[2] = false; // log_file_on + onoff[3] = false; // selected_output_file_on + onoff[4] = true; // dump_file_on + TestFileOnOff("dump.%d.out", onoff[0], onoff[1], onoff[2], onoff[3], onoff[4]); +} + +TEST(TestIPhreeqc, TestSelOutFileOnOff) +{ + bool onoff[5]; + onoff[0] = false; // output_file_on + onoff[1] = false; // error_file_on + onoff[2] = false; // log_file_on + onoff[3] = true; // selected_output_file_on + onoff[4] = false; // dump_file_on + TestFileOnOff("selected_1.%d.out", onoff[0], onoff[1], onoff[2], onoff[3], onoff[4]); +} + +void TestFileOnOff(const char* FILENAME_FORMAT, bool output_file_on, bool error_file_on, bool log_file_on, bool selected_output_file_on, bool dump_file_on) +{ + IPhreeqc obj; + + char FILENAME[80]; + sprintf(FILENAME, FILENAME_FORMAT, obj.GetId()); + + // remove FILENAME if it exists + // + if (::FileExists(FILENAME)) + { + ::DeleteFile(FILENAME); + } + ASSERT_EQ(false, ::FileExists(FILENAME)); + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + // add solution block + ASSERT_EQ(VR_OK, SOLUTION(obj, 1.0, 1.0, 1.0)); + + // add selected output block + ASSERT_EQ(VR_OK, SELECTED_OUTPUT(obj)); + + // add dump block + ASSERT_EQ(VR_OK, DUMP(obj)); + + // run all off + obj.SetDumpFileOn(false); + obj.SetErrorFileOn(false); + obj.SetLogFileOn(false); + obj.SetOutputFileOn(false); + obj.SetSelectedOutputFileOn(false); + ASSERT_EQ(0, obj.RunAccumulated()); + ASSERT_EQ(false, ::FileExists(FILENAME)); + + + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + // add solution block + ASSERT_EQ(VR_OK, SOLUTION(obj, 1.0, 1.0, 1.0)); + + // add selected output block + ASSERT_EQ(VR_OK, SELECTED_OUTPUT(obj)); + + // add dump block + ASSERT_EQ(VR_OK, DUMP(obj)); + + // run + obj.SetDumpFileOn(dump_file_on); + obj.SetErrorFileOn(error_file_on); + obj.SetLogFileOn(log_file_on); + obj.SetOutputFileOn(output_file_on); + obj.SetSelectedOutputFileOn(selected_output_file_on); + ASSERT_EQ(0, obj.RunAccumulated()); + ASSERT_EQ(true, ::FileExists(FILENAME)); + ASSERT_TRUE(::DeleteFile(FILENAME)); + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + // add solution block + ASSERT_EQ(VR_OK, SOLUTION(obj, 1.0, 1.0, 1.0)); + + // add selected output block + ASSERT_EQ(VR_OK, SELECTED_OUTPUT(obj)); + + // add dump block + ASSERT_EQ(VR_OK, DUMP(obj)); + + // run + obj.SetDumpFileOn(false); + obj.SetErrorFileOn(false); + obj.SetLogFileOn(false); + obj.SetOutputFileOn(false); + obj.SetSelectedOutputFileOn(false); + ASSERT_EQ(0, obj.RunAccumulated()); + ASSERT_EQ(false, ::FileExists(FILENAME)); + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + // add solution block + ASSERT_EQ(VR_OK, SOLUTION(obj, 1.0, 1.0, 1.0)); + + // add selected output block + ASSERT_EQ(VR_OK, SELECTED_OUTPUT(obj)); + + // add dump block + ASSERT_EQ(VR_OK, DUMP(obj)); + + // run + obj.SetDumpFileOn(dump_file_on); + obj.SetErrorFileOn(error_file_on); + obj.SetLogFileOn(log_file_on); + obj.SetOutputFileOn(output_file_on); + obj.SetSelectedOutputFileOn(selected_output_file_on); + ASSERT_EQ(0, obj.RunAccumulated()); + ASSERT_EQ(true, ::FileExists(FILENAME)); + ASSERT_TRUE(::DeleteFile(FILENAME)); +} + +VRESULT +SOLUTION(IPhreeqc& obj, double C, double Ca, double Na) +{ + std::ostringstream oss; + + oss << "SOLUTION 1\n"; + oss << "C " << C << "\n"; + oss << "Ca " << Ca << "\n"; + oss << "Na " << Na << "\n"; + + return obj.AccumulateLine(oss.str().c_str()); +} + +VRESULT +EQUILIBRIUM_PHASES(IPhreeqc& obj, const char* phase, double si, double amount) +{ + std::ostringstream oss; + + oss << "EQUILIBRIUM_PHASES\n"; + oss << phase << " " << si << " " << amount << "\n"; + return obj.AccumulateLine(oss.str().c_str()); +} + +VRESULT +USER_PUNCH(IPhreeqc& obj, const char* element, int max) +{ + std::ostringstream oss; + + oss << "USER_PUNCH\n"; + + oss << "-head "; + for (int i = 1; i <= max; ++i) + { + oss << i << ".name " << i << ".type " << i << ".moles "; + } + oss << "\n"; + oss << "-start" << "\n"; + oss << "10 n = sys(\"" << element << "\"" << ", count, names$, types$, moles)" << "\n"; + oss << "20 n = " << max << "\n"; + oss << "30 if count < " << max << " then n = count" << "\n"; + oss << "40 for i = 1 to n" << "\n"; + oss << "50 PUNCH names$(i), types$(i), moles(i)" << "\n"; + oss << "60 next i" << "\n"; + oss << "70 list" << "\n"; + oss << "-end" << "\n"; + oss << "SELECTED_OUTPUT" << "\n"; + oss << "-totals C Ca Na" << "\n"; + oss << "-molalities CO3-2 CaOH+ NaCO3-" << "\n"; + oss << "-activities CO3-2 CaOH+ NaCO3-" << "\n"; + oss << "-equilibrium_phases Calcite" << "\n"; + oss << "-saturation_indices CO2(g) Siderite" << "\n"; + oss << "-gases CO2(g) N2(g)" << "\n"; + oss << "-kinetic_reactants Albite Pyrite" << "\n"; + oss << "-solid_solutions CaSO4 SrSO4" << "\n"; + + return obj.AccumulateLine(oss.str().c_str()); +} + +VRESULT +USER_PUNCH_NEH(IPhreeqc& obj) +{ + std::ostringstream oss; + + oss << "USER_PUNCH\n"; + + oss << "-head head0 head1 head2\n"; + oss << "-start" << "\n"; + oss << "10 PUNCH \"have0\", \"have1\", \"have2\"" << "\n"; + oss << "20 PUNCH \"missing0\", \"missing1\", \"missing2\"" << "\n"; + oss << "-end" << "\n"; + oss << "SELECTED_OUTPUT" << "\n"; + oss << "-totals C Ca Na" << "\n"; + oss << "-molalities CO3-2 CaOH+ NaCO3-" << "\n"; + oss << "-activities CO3-2 CaOH+ NaCO3-" << "\n"; + oss << "-equilibrium_phases Calcite" << "\n"; + oss << "-saturation_indices CO2(g) Siderite" << "\n"; + oss << "-gases CO2(g) N2(g)" << "\n"; + oss << "-kinetic_reactants Albite Pyrite" << "\n"; + oss << "-solid_solutions CaSO4 SrSO4" << "\n"; + + return obj.AccumulateLine(oss.str().c_str()); +} + +VRESULT +SELECTED_OUTPUT(IPhreeqc& obj) +{ + std::ostringstream oss; + + oss << "SELECTED_OUTPUT" << "\n"; + oss << "-totals C Ca Na" << "\n"; + + return obj.AccumulateLine(oss.str().c_str()); +} + +VRESULT +DUMP(IPhreeqc& obj) +{ + std::ostringstream oss; + oss << "DUMP" << "\n"; + oss << "-solution 1" << "\n"; + return obj.AccumulateLine(oss.str().c_str()); +} + +TEST(TestIPhreeqc, TestLongHeadings) +{ + char long_header[] = "this_is_a_long_header_0123456789012345678901234567890123456789"; + char long_value[] = "this_is_a_long_value_01234567890123456789012345678901234567890"; + + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + std::ostringstream oss; + oss << "SOLUTION" << "\n"; + + oss << "SELECTED_OUTPUT" << "\n"; + oss << "-reset false" << "\n"; + + oss << "USER_PUNCH" << "\n"; + oss << "-head " << long_header << "\n"; + oss << "-start" << "\n"; + oss << "10 PUNCH \"" << long_value << "\"\n"; + oss << "-end" << "\n"; + ASSERT_EQ(VR_OK, obj.AccumulateLine(oss.str().c_str())); + + // COMMENT: {10/30/2013 10:39:40 PM} //{{ + // COMMENT: {10/30/2013 10:39:40 PM} ASSERT_EQ( VR_OK, obj.AccumulateLine("END") ); + // COMMENT: {10/30/2013 10:39:40 PM} oss << "SELECTED_OUTPUT" << "\n"; + // COMMENT: {10/30/2013 10:39:40 PM} oss << "-reset false" << "\n"; + // COMMENT: {10/30/2013 10:39:40 PM} + // COMMENT: {10/30/2013 10:39:40 PM} oss << "USER_PUNCH" << "\n"; + // COMMENT: {10/30/2013 10:39:40 PM} oss << "-head " << long_header << "\n"; + // COMMENT: {10/30/2013 10:39:40 PM} oss << "-start" << "\n"; + // COMMENT: {10/30/2013 10:39:40 PM} oss << "10 PUNCH \"" << long_value << "\"\n"; + // COMMENT: {10/30/2013 10:39:40 PM} oss << "-end" << "\n"; + // COMMENT: {10/30/2013 10:39:40 PM} ASSERT_EQ( VR_OK, obj.AccumulateLine(oss.str().c_str()) ); + // COMMENT: {10/30/2013 10:39:40 PM} //}} + + obj.SetOutputFileOn(0); + obj.SetErrorFileOn(0); + obj.SetLogFileOn(0); + obj.SetSelectedOutputFileOn(0); + obj.SetDumpFileOn(0); + ASSERT_EQ(0, obj.RunAccumulated()); + + ASSERT_EQ(2, obj.GetSelectedOutputRowCount()); + ASSERT_EQ(1, obj.GetSelectedOutputColumnCount()); + + CVar v; + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, 0, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string(long_header), std::string(v.sVal)); + + CVar v1; + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 0, &v1)); + ASSERT_EQ(TT_STRING, v1.type); + ASSERT_EQ(std::string(long_value), std::string(v1.sVal)); + + ASSERT_EQ(VR_INVALIDCOL, obj.GetSelectedOutputValue(1, 1, &v1)); + ASSERT_EQ(VR_INVALIDROW, obj.GetSelectedOutputValue(2, 0, &v1)); +} + +TEST(TestIPhreeqc, TestDatabaseKeyword) +{ + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + obj.SetOutputFileOn(false); + obj.SetErrorFileOn(false); + obj.SetLogFileOn(false); + obj.SetSelectedOutputFileOn(false); + obj.SetDumpFileOn(false); + ASSERT_EQ(1, obj.RunFile("dump")); + + const char* expected = + "ERROR: Gas not found in PHASES database, Amm(g).\n" + "ERROR: Calculations terminating due to input errors.\n"; + + const char* err = obj.GetErrorString(); + ASSERT_EQ(std::string(expected), std::string(err)); + + const char* exp_warn = + "WARNING: DATABASE keyword is ignored by IPhreeqc.\n" + "WARNING: Cell-lengths were read for 1 cells. Last value is used till cell 100.\n" + "WARNING: No dispersivities were read; disp = 0 assumed.\n" + "WARNING: Could not find element in database, Amm.\n" + " Concentration is set to zero.\n"; + + const char* warn = obj.GetWarningString(); + ASSERT_EQ(std::string(exp_warn), std::string(warn)); +} + +TEST(TestIPhreeqc, TestDumpString) +{ + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + // add solution block + ASSERT_EQ(VR_OK, SOLUTION(obj, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(VR_OK, DUMP(obj)); + + // run + obj.SetOutputFileOn(0); + obj.SetErrorFileOn(0); + obj.SetLogFileOn(0); + obj.SetSelectedOutputFileOn(0); + obj.SetDumpFileOn(0); + obj.SetDumpStringOn(1); + ASSERT_EQ(0, obj.RunAccumulated()); + + const char* dump_str = obj.GetDumpString(); + + ASSERT_TRUE(::strstr(dump_str, "SOLUTION_RAW") != NULL); + ASSERT_TRUE(::strstr(dump_str, "-temp") != NULL); + ASSERT_TRUE(::strstr(dump_str, "-total_h") != NULL); + ASSERT_TRUE(::strstr(dump_str, "-total_o") != NULL); + ASSERT_TRUE(::strstr(dump_str, "-cb") != NULL); + ASSERT_TRUE(::strstr(dump_str, "-totals") != NULL); + ASSERT_TRUE(::strstr(dump_str, " C(4) ") != NULL); + ASSERT_TRUE(::strstr(dump_str, " Ca ") != NULL); + ASSERT_TRUE(::strstr(dump_str, " H(0) ") != NULL); + ASSERT_TRUE(::strstr(dump_str, " Na ") != NULL); + ASSERT_TRUE(::strstr(dump_str, "-pH") != NULL); + ASSERT_TRUE(::strstr(dump_str, "-pe") != NULL); + ASSERT_TRUE(::strstr(dump_str, "-mu") != NULL); + ASSERT_TRUE(::strstr(dump_str, "-ah2o") != NULL); + ASSERT_TRUE(::strstr(dump_str, "-mass_water") != NULL); + ASSERT_TRUE(::strstr(dump_str, "-total_alkalinity") != NULL); + ASSERT_TRUE(::strstr(dump_str, "-activities") != NULL); + ASSERT_TRUE(::strstr(dump_str, " C(-4) ") != NULL); + ASSERT_TRUE(::strstr(dump_str, " C(4) ") != NULL); + ASSERT_TRUE(::strstr(dump_str, " Ca ") != NULL); + ASSERT_TRUE(::strstr(dump_str, " E ") != NULL); + ASSERT_TRUE(::strstr(dump_str, " H(0) ") != NULL); + ASSERT_TRUE(::strstr(dump_str, " Na ") != NULL); + ASSERT_TRUE(::strstr(dump_str, " O(0) ") != NULL); + ASSERT_TRUE(::strstr(dump_str, "-gammas") != NULL); + ASSERT_TRUE(::strstr(dump_str, "USE mix none") != NULL); + ASSERT_TRUE(::strstr(dump_str, "USE reaction none") != NULL); + ASSERT_TRUE(::strstr(dump_str, "USE reaction_temperature none") != NULL); + ASSERT_TRUE(::strstr(dump_str, "USE reaction_pressure none") != NULL); +} + +TEST(TestIPhreeqc, TestGetDumpStringLineCount) +{ + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + // add solution block + ASSERT_EQ(VR_OK, ::SOLUTION(obj, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(VR_OK, ::DUMP(obj)); + + // run + ASSERT_EQ(false, obj.GetOutputFileOn()); + ASSERT_EQ(false, obj.GetErrorFileOn()); + ASSERT_EQ(false, obj.GetLogFileOn()); + ASSERT_EQ(false, obj.GetSelectedOutputFileOn()); + ASSERT_EQ(false, obj.GetDumpFileOn()); + ASSERT_EQ(false, obj.GetDumpStringOn()); + obj.SetDumpStringOn(true); + ASSERT_EQ(true, obj.GetDumpStringOn()); + ASSERT_EQ(0, obj.RunAccumulated()); + ASSERT_EQ(33, obj.GetDumpStringLineCount()); +} + +TEST(TestIPhreeqc, TestGetDumpStringLine) +{ + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + // add solution block + ASSERT_EQ(VR_OK, ::SOLUTION(obj, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(VR_OK, ::DUMP(obj)); + + // run + ASSERT_EQ(false, obj.GetOutputFileOn()); + ASSERT_EQ(false, obj.GetErrorFileOn()); + ASSERT_EQ(false, obj.GetLogFileOn()); + ASSERT_EQ(false, obj.GetSelectedOutputFileOn()); + ASSERT_EQ(false, obj.GetDumpFileOn()); + ASSERT_EQ(false, obj.GetDumpStringOn()); + + obj.SetDumpStringOn(true); + ASSERT_EQ(true, obj.GetDumpStringOn()); + ASSERT_EQ(0, obj.RunAccumulated()); + ASSERT_EQ(33, obj.GetDumpStringLineCount()); + + int line = 0; + + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), "SOLUTION_RAW") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), "-temp") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), "-pressure") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), "-potential") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), "-total_h") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), "-total_o") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), "-cb") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), "-density") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), "-totals") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), " C(4) ") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), " Ca ") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), " H(0) ") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), " Na ") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), "-pH") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), "-pe") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), "-mu") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), "-ah2o") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), "-mass_water") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), "-soln_vol") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), "-total_alkalinity") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), "-activities") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), " C(-4) ") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), " C(4) ") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), " Ca ") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), " E ") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), " H(0) ") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), " Na ") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), " O(0) ") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), "-gammas") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), "USE mix none") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), "USE reaction none") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), "USE reaction_temperature none") != NULL); + ASSERT_TRUE(::strstr(obj.GetDumpStringLine(line++), "USE reaction_pressure none") != NULL); + + // remaining lines should be empty + ASSERT_EQ(std::string(""), std::string(obj.GetDumpStringLine(line++))); + ASSERT_EQ(std::string(""), std::string(obj.GetDumpStringLine(line++))); + ASSERT_EQ(std::string(""), std::string(obj.GetDumpStringLine(line++))); + ASSERT_EQ(std::string(""), std::string(obj.GetDumpStringLine(line++))); + + // negative lines should be empty + ASSERT_EQ(std::string(""), std::string(obj.GetDumpStringLine(-1))); + ASSERT_EQ(std::string(""), std::string(obj.GetDumpStringLine(-2))); + ASSERT_EQ(std::string(""), std::string(obj.GetDumpStringLine(-3))); + ASSERT_EQ(std::string(""), std::string(obj.GetDumpStringLine(-4))); +} + +TEST(TestIPhreeqc, TestGetComponentCount) +{ + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + // add solution block + ASSERT_EQ(VR_OK, ::SOLUTION(obj, 1.0, 1.0, 1.0)); + + // run + ASSERT_EQ(false, obj.GetOutputFileOn()); + ASSERT_EQ(false, obj.GetErrorFileOn()); + ASSERT_EQ(false, obj.GetLogFileOn()); + ASSERT_EQ(false, obj.GetSelectedOutputFileOn()); + ASSERT_EQ(false, obj.GetDumpFileOn()); + ASSERT_EQ(false, obj.GetDumpStringOn()); + ASSERT_EQ(0, obj.RunAccumulated()); + ASSERT_EQ((size_t)3, obj.GetComponentCount()); +} + +TEST(TestIPhreeqc, TestGetComponent) +{ + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + // add solution block + ASSERT_EQ(VR_OK, ::SOLUTION(obj, 1.0, 1.0, 1.0)); + + // run + ASSERT_EQ(false, obj.GetOutputFileOn()); + ASSERT_EQ(false, obj.GetErrorFileOn()); + ASSERT_EQ(false, obj.GetLogFileOn()); + ASSERT_EQ(false, obj.GetSelectedOutputFileOn()); + ASSERT_EQ(false, obj.GetDumpFileOn()); + ASSERT_EQ(false, obj.GetDumpStringOn()); + ASSERT_EQ(0, obj.RunAccumulated()); + ASSERT_EQ((size_t)3, obj.GetComponentCount()); + + ASSERT_EQ(std::string(""), std::string(obj.GetComponent(-2))); + ASSERT_EQ(std::string(""), std::string(obj.GetComponent(-1))); + + ASSERT_EQ(std::string("C"), std::string(obj.GetComponent(0))); + ASSERT_EQ(std::string("Ca"), std::string(obj.GetComponent(1))); + ASSERT_EQ(std::string("Na"), std::string(obj.GetComponent(2))); + + ASSERT_EQ(std::string(""), std::string(obj.GetComponent(3))); + ASSERT_EQ(std::string(""), std::string(obj.GetComponent(4))); + ASSERT_EQ(std::string(""), std::string(obj.GetComponent(5))); +} + +TEST(TestIPhreeqc, TestListComponents) +{ + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + // add solution block + ASSERT_EQ(VR_OK, ::SOLUTION(obj, 1.0, 1.0, 1.0)); + + // run + ASSERT_EQ(false, obj.GetOutputFileOn()); + ASSERT_EQ(false, obj.GetErrorFileOn()); + ASSERT_EQ(false, obj.GetLogFileOn()); + ASSERT_EQ(false, obj.GetSelectedOutputFileOn()); + ASSERT_EQ(false, obj.GetDumpFileOn()); + ASSERT_EQ(false, obj.GetDumpStringOn()); + ASSERT_EQ(0, obj.RunAccumulated()); + + std::list< std::string > comps = obj.ListComponents(); + ASSERT_EQ((size_t)3, comps.size()); + + std::list< std::string >::iterator it = comps.begin(); + ASSERT_EQ(std::string("C"), std::string((*it++))); + ASSERT_EQ(std::string("Ca"), std::string((*it++))); + ASSERT_EQ(std::string("Na"), std::string((*it++))); +} + +TEST(TestIPhreeqc, TestSetDumpFileName) +{ + char DUMP_FILENAME[80]; + sprintf(DUMP_FILENAME, "dump.%06d.out", ::rand()); + if (::FileExists(DUMP_FILENAME)) + { + ::DeleteFile(DUMP_FILENAME); + } + + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + // add solution block + ASSERT_EQ(VR_OK, ::SOLUTION(obj, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(VR_OK, ::DUMP(obj)); + + // run + obj.SetOutputFileOn(false); + obj.SetErrorFileOn(false); + obj.SetLogFileOn(false); + obj.SetSelectedOutputFileOn(false); + obj.SetDumpStringOn(false); + obj.SetDumpFileOn(true); + obj.SetDumpFileName(DUMP_FILENAME); + + ASSERT_EQ(0, obj.RunAccumulated()); + + ASSERT_EQ(true, ::FileExists(DUMP_FILENAME)); + + std::string lines[33]; + std::ifstream ifs(DUMP_FILENAME); + + size_t i = 0; + while (i < sizeof(lines) / sizeof(lines[0]) && std::getline(ifs, lines[i])) + { + ++i; + } + + int line = 0; + ASSERT_TRUE(::strstr(lines[line++].c_str(), "SOLUTION_RAW") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-temp") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-pressure") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-potential") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-total_h") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-total_o") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-cb") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-density") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-totals") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " C(4) ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Ca ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " H(0) ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Na ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-pH") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-pe") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-mu") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-ah2o") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-mass_water") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-soln_vol") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-total_alkalinity") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-activities") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " C(-4) ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " C(4) ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Ca ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " E ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " H(0) ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Na ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " O(0) ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-gammas") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "USE mix none") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "USE reaction none") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "USE reaction_temperature none") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "USE reaction_pressure none") != NULL); + + if (::FileExists(DUMP_FILENAME)) + { + ::DeleteFile(DUMP_FILENAME); + } +} + +TEST(TestIPhreeqc, TestSetOutputFileName) +{ + char OUTPUT_FILENAME[80]; + sprintf(OUTPUT_FILENAME, "output.%06d.out", ::rand()); + if (::FileExists(OUTPUT_FILENAME)) + { + ::DeleteFile(OUTPUT_FILENAME); + } + + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat.old")); + + // add solution block + ASSERT_EQ(VR_OK, ::SOLUTION(obj, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(VR_OK, ::DUMP(obj)); + + // run + obj.SetOutputFileOn(true); + obj.SetErrorFileOn(false); + obj.SetLogFileOn(false); + obj.SetSelectedOutputFileOn(false); + obj.SetDumpStringOn(false); + obj.SetDumpFileOn(false); + obj.SetOutputFileName(OUTPUT_FILENAME); + + ASSERT_EQ(0, obj.RunAccumulated()); + + ASSERT_EQ(true, ::FileExists(OUTPUT_FILENAME)); + + std::string lines[200]; + std::ifstream ifs(OUTPUT_FILENAME); + + size_t i = 0; + while (i < sizeof(lines) / sizeof(lines[0]) && std::getline(ifs, lines[i])) + { + ++i; + } + + ASSERT_EQ((size_t)100, i); + + int line = 0; + + ASSERT_TRUE(::strstr(lines[line++].c_str(), "------------------------------------") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "Reading input data for simulation 1.") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "------------------------------------") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " SOLUTION 1") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " C 1") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Ca 1") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Na 1") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " DUMP") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " -solution 1") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-------------------------------------------") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "Beginning of initial solution calculations.") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-------------------------------------------") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "Initial solution 1. ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-----------------------------Solution composition--------") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Elements Molality Moles") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " C ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Ca ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Na ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "----------------------------Description of solution------") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " pH = ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " pe = ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Activity of water = ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Ionic strength (mol/kgw) = ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Mass of water (kg) = ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Total alkalinity (eq/kg) = ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Total CO2 (mol/kg) = ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Temperature (°C) = ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Electrical balance (eq) = ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Percent error, 100*(Cat-|An|)/(Cat+|An|) = ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Iterations = ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Total H = ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Total O = ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "----------------------------Distribution of species----------------------------") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Log Log Log mole V") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Species Molality Activity Molality Activity Gamma cm³/mol") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " OH- ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " H+ ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " H2O ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "C(-4) ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " CH4 ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "C(4) ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " HCO3- ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " CO2 ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " CaHCO3+ ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " CaCO3 ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " CO3-2 ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " NaHCO3 ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " NaCO3- ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "Ca ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Ca+2 ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " CaHCO3+ ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " CaCO3 ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " CaOH+ ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "H(0) ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " H2 ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "Na ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Na+ ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " NaHCO3 ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " NaCO3- ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " NaOH ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "O(0) ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " O2 ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "------------------------------Saturation indices-------------------------------") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Phase SI** log IAP log K(298 K, 1 atm)") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Aragonite") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Calcite") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " CH4(g)") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " CO2(g)") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " H2(g)") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " H2O(g)") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " O2(g)") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "**For a gas, SI = log10(fugacity). Fugacity = pressure * phi / 1 atm.") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " For ideal gases, phi = 1.") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "------------------") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "End of simulation.") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "------------------") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "------------------------------------") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "Reading input data for simulation 2.") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "------------------------------------") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "----------------") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "End of Run after ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "----------------") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + + if (::FileExists(OUTPUT_FILENAME)) + { + ::DeleteFile(OUTPUT_FILENAME); + } +} + +TEST(TestIPhreeqc, TestOutputStringOnOff) +{ + IPhreeqc obj; + ASSERT_EQ(false, obj.GetOutputStringOn()); + + obj.SetOutputStringOn(true); + ASSERT_EQ(true, obj.GetOutputStringOn()); + + obj.SetOutputStringOn(false); + ASSERT_EQ(false, obj.GetOutputStringOn()); +} + +TEST(TestIPhreeqc, TestGetOutputString) +{ + char OUTPUT_FILENAME[80]; + sprintf(OUTPUT_FILENAME, "output.%06d.out", ::rand()); + if (::FileExists(OUTPUT_FILENAME)) + { + ::DeleteFile(OUTPUT_FILENAME); + } + ASSERT_EQ(false, ::FileExists(OUTPUT_FILENAME)); + + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + // add solution block + ASSERT_EQ(VR_OK, ::SOLUTION(obj, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(VR_OK, ::DUMP(obj)); + + // run + obj.SetOutputFileOn(true); + obj.SetOutputStringOn(true); + + obj.SetErrorFileOn(false); + obj.SetLogFileOn(false); + obj.SetSelectedOutputFileOn(false); + obj.SetDumpStringOn(false); + obj.SetDumpFileOn(false); + obj.SetOutputFileName(OUTPUT_FILENAME); + + ASSERT_EQ(0, obj.RunAccumulated()); + + ASSERT_EQ(true, ::FileExists(OUTPUT_FILENAME)); + + { + std::ifstream ifs(OUTPUT_FILENAME); + std::string fline((std::istreambuf_iterator(ifs)), std::istreambuf_iterator()); + + std::string sline(obj.GetOutputString()); + ASSERT_TRUE(sline.size() > 0); + + ASSERT_EQ(fline, sline); + } + + if (::FileExists(OUTPUT_FILENAME)) + { + ::DeleteFile(OUTPUT_FILENAME); + } +} + +TEST(TestIPhreeqc, TestGetOutputStringLineCount) +{ + IPhreeqc obj; + ASSERT_EQ(0, obj.GetOutputStringLineCount()); + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat.old")); + + ASSERT_EQ(0, obj.GetOutputStringLineCount()); + + // add solution block + ASSERT_EQ(VR_OK, ::SOLUTION(obj, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(VR_OK, ::DUMP(obj)); + + // run + obj.SetOutputStringOn(false); + obj.SetOutputFileOn(false); + obj.SetErrorFileOn(false); + obj.SetLogFileOn(false); + obj.SetSelectedOutputFileOn(false); + obj.SetDumpStringOn(false); + obj.SetDumpFileOn(false); + + ASSERT_EQ(0, obj.RunAccumulated()); + ASSERT_EQ(0, obj.GetOutputStringLineCount()); + + // add solution block + ASSERT_EQ(VR_OK, ::SOLUTION(obj, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(VR_OK, ::DUMP(obj)); + + obj.SetOutputStringOn(true); + + ASSERT_EQ(0, obj.RunAccumulated()); + ASSERT_EQ(100, obj.GetOutputStringLineCount()); + + + // add solution block + ASSERT_EQ(VR_OK, ::SOLUTION(obj, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(VR_OK, ::DUMP(obj)); + + obj.SetOutputStringOn(false); + + ASSERT_EQ(0, obj.RunAccumulated()); + ASSERT_EQ(0, obj.GetOutputStringLineCount()); +} + +TEST(TestIPhreeqc, TestGetOutputStringLine) +{ + IPhreeqc obj; + ASSERT_EQ(0, obj.GetOutputStringLineCount()); + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat.old")); + + ASSERT_EQ(0, obj.GetOutputStringLineCount()); + + // add solution block + ASSERT_EQ(VR_OK, ::SOLUTION(obj, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(VR_OK, ::DUMP(obj)); + + // run + obj.SetOutputStringOn(false); + obj.SetOutputFileOn(false); + obj.SetErrorFileOn(false); + obj.SetLogFileOn(false); + obj.SetSelectedOutputFileOn(false); + obj.SetDumpStringOn(false); + obj.SetDumpFileOn(false); + + ASSERT_EQ(0, obj.RunAccumulated()); + ASSERT_EQ(0, obj.GetOutputStringLineCount()); + + int line = 0; + ASSERT_EQ(std::string(""), std::string(obj.GetOutputStringLine(line++))); + ASSERT_EQ(std::string(""), std::string(obj.GetOutputStringLine(line++))); + ASSERT_EQ(std::string(""), std::string(obj.GetOutputStringLine(line++))); + ASSERT_EQ(std::string(""), std::string(obj.GetOutputStringLine(line++))); + + // negative lines should be empty + ASSERT_EQ(std::string(""), std::string(obj.GetOutputStringLine(-1))); + ASSERT_EQ(std::string(""), std::string(obj.GetOutputStringLine(-2))); + ASSERT_EQ(std::string(""), std::string(obj.GetOutputStringLine(-3))); + ASSERT_EQ(std::string(""), std::string(obj.GetOutputStringLine(-4))); + + // add solution block + ASSERT_EQ(VR_OK, ::SOLUTION(obj, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(VR_OK, ::DUMP(obj)); + + obj.SetOutputStringOn(true); + + ASSERT_EQ(0, obj.RunAccumulated()); + ASSERT_EQ(100, obj.GetOutputStringLineCount()); + + ASSERT_EQ(std::string("------------------------------------"), std::string(obj.GetOutputStringLine(0))); + ASSERT_EQ(std::string("Reading input data for simulation 1."), std::string(obj.GetOutputStringLine(1))); + ASSERT_EQ(std::string("------------------------------------"), std::string(obj.GetOutputStringLine(2))); + ASSERT_EQ(std::string("-----------------------------Solution composition------------------------------"), std::string(obj.GetOutputStringLine(16))); + ASSERT_EQ(std::string("----------------------------Description of solution----------------------------"), std::string(obj.GetOutputStringLine(24))); + ASSERT_EQ(std::string("----------------------------Distribution of species----------------------------"), std::string(obj.GetOutputStringLine(40))); + ASSERT_EQ(std::string("------------------------------Saturation indices-------------------------------"), std::string(obj.GetOutputStringLine(73))); + ASSERT_EQ(std::string("End of Run"), std::string(obj.GetOutputStringLine(97)).substr(0, 10)); + ASSERT_EQ(std::string(""), std::string(obj.GetOutputStringLine(100))); + + // add solution block + ASSERT_EQ(VR_OK, ::SOLUTION(obj, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(VR_OK, ::DUMP(obj)); + + obj.SetOutputStringOn(false); + + ASSERT_EQ(0, obj.RunAccumulated()); + ASSERT_EQ(0, obj.GetOutputStringLineCount()); + + line = 0; + ASSERT_EQ(std::string(""), std::string(obj.GetOutputStringLine(line++))); + ASSERT_EQ(std::string(""), std::string(obj.GetOutputStringLine(line++))); + ASSERT_EQ(std::string(""), std::string(obj.GetOutputStringLine(line++))); + ASSERT_EQ(std::string(""), std::string(obj.GetOutputStringLine(line++))); + + // negative lines should be empty + ASSERT_EQ(std::string(""), std::string(obj.GetOutputStringLine(-1))); + ASSERT_EQ(std::string(""), std::string(obj.GetOutputStringLine(-2))); + ASSERT_EQ(std::string(""), std::string(obj.GetOutputStringLine(-3))); + ASSERT_EQ(std::string(""), std::string(obj.GetOutputStringLine(-4))); +} + +TEST(TestIPhreeqc, TestSetLogFileName) +{ + char LOG_FILENAME[80]; + sprintf(LOG_FILENAME, "log.%06d.out", ::rand()); + if (::FileExists(LOG_FILENAME)) + { + ::DeleteFile(LOG_FILENAME); + } + + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + // add solution block + ASSERT_EQ(VR_OK, ::SOLUTION(obj, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(VR_OK, ::DUMP(obj)); + + // add knobs + ASSERT_EQ(VR_OK, obj.AccumulateLine("KNOBS")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("\t-logfile TRUE")); + + // run + obj.SetLogFileOn(true); + obj.SetErrorFileOn(false); + obj.SetOutputFileOn(false); + obj.SetSelectedOutputFileOn(false); + obj.SetDumpStringOn(false); + obj.SetDumpFileOn(false); + obj.SetLogFileName(LOG_FILENAME); + + ASSERT_EQ(0, obj.RunAccumulated()); + + ASSERT_EQ(true, ::FileExists(LOG_FILENAME)); + + std::string lines[33]; + std::ifstream ifs(LOG_FILENAME); + + size_t i = 0; + while (i < sizeof(lines) / sizeof(lines[0]) && std::getline(ifs, lines[i])) + { + ++i; + } + + ASSERT_EQ((size_t)25, i); + + int line = 0; + ASSERT_EQ(std::string("-------------------------------------------"), lines[line++]); + ASSERT_EQ(std::string("Beginning of initial solution calculations."), lines[line++]); + ASSERT_EQ(std::string("-------------------------------------------"), lines[line++]); + ASSERT_EQ(std::string(""), lines[line++]); + ASSERT_EQ(std::string("Initial solution 1. "), lines[line++]); + ASSERT_EQ(std::string(""), lines[line++]); + ASSERT_EQ(std::string("Iterations in revise_guesses: 2"), lines[line++]); + ASSERT_EQ(std::string(""), lines[line++]); + ASSERT_EQ(std::string("Number of infeasible solutions: 0"), lines[line++]); + ASSERT_EQ(std::string("Number of basis changes: 0"), lines[line++]); + ASSERT_EQ(std::string(""), lines[line++]); + ASSERT_EQ(std::string("Number of iterations: 6"), lines[line++]); + ASSERT_EQ(std::string(""), lines[line++]); + ASSERT_EQ(std::string("------------------"), lines[line++]); + ASSERT_EQ(std::string("End of simulation."), lines[line++]); + ASSERT_EQ(std::string("------------------"), lines[line++]); + ASSERT_EQ(std::string(""), lines[line++]); + ASSERT_EQ(std::string("------------------------------------"), lines[line++]); + ASSERT_EQ(std::string("Reading input data for simulation 2."), lines[line++]); + ASSERT_EQ(std::string("------------------------------------"), lines[line++]); + ASSERT_EQ(std::string(""), lines[line++]); + line++; + ASSERT_EQ(std::string("End of Run"), lines[line++].substr(0, 10)); + line++; + ASSERT_EQ(std::string(""), lines[line++]); + + if (::FileExists(LOG_FILENAME)) + { + ::DeleteFile(LOG_FILENAME); + } +} + +TEST(TestIPhreeqc, TestLogStringOnOff) +{ + IPhreeqc obj; + ASSERT_EQ(false, obj.GetLogStringOn()); + + obj.SetLogStringOn(true); + ASSERT_EQ(true, obj.GetLogStringOn()); + + obj.SetLogStringOn(false); + ASSERT_EQ(false, obj.GetLogStringOn()); +} + +TEST(TestIPhreeqc, TestGetLogString) +{ + char LOG_FILENAME[80]; + sprintf(LOG_FILENAME, "log.%06d.out", ::rand()); + if (::FileExists(LOG_FILENAME)) + { + ::DeleteFile(LOG_FILENAME); + } + ASSERT_EQ(false, ::FileExists(LOG_FILENAME)); + + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + // add solution block + ASSERT_EQ(VR_OK, ::SOLUTION(obj, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(VR_OK, ::DUMP(obj)); + + // add knobs + ASSERT_EQ(VR_OK, obj.AccumulateLine("KNOBS")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("\t-logfile TRUE")); + + // run + obj.SetLogFileOn(true); + obj.SetLogStringOn(true); + + obj.SetDumpFileOn(false); + obj.SetDumpStringOn(false); + obj.SetErrorFileOn(false); + obj.SetOutputFileOn(false); + obj.SetOutputStringOn(false); + obj.SetSelectedOutputFileOn(false); + + obj.SetLogFileName(LOG_FILENAME); + + ASSERT_EQ(0, obj.RunAccumulated()); + + ASSERT_EQ(true, ::FileExists(LOG_FILENAME)); + + { + std::ifstream ifs(LOG_FILENAME); + std::string fline((std::istreambuf_iterator(ifs)), std::istreambuf_iterator()); + + std::string sline(obj.GetLogString()); + ASSERT_TRUE(sline.size() > 0); + + ASSERT_EQ(fline, sline); + } + + if (::FileExists(LOG_FILENAME)) + { + ::DeleteFile(LOG_FILENAME); + } +} + +TEST(TestIPhreeqc, TestGetLogStringLineCount) +{ + IPhreeqc obj; + ASSERT_EQ(0, obj.GetLogStringLineCount()); + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + ASSERT_EQ(0, obj.GetLogStringLineCount()); + + // add solution block + ASSERT_EQ(VR_OK, ::SOLUTION(obj, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(VR_OK, ::DUMP(obj)); + + // add knobs + ASSERT_EQ(VR_OK, obj.AccumulateLine("KNOBS")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("\t-logfile TRUE")); + + // run + obj.SetLogStringOn(false); + obj.SetLogFileOn(false); + obj.SetErrorFileOn(false); + obj.SetOutputFileOn(false); + obj.SetSelectedOutputFileOn(false); + obj.SetDumpStringOn(false); + obj.SetDumpFileOn(false); + + ASSERT_EQ(0, obj.RunAccumulated()); + ASSERT_EQ(0, obj.GetLogStringLineCount()); + + // add solution block + ASSERT_EQ(VR_OK, ::SOLUTION(obj, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(VR_OK, ::DUMP(obj)); + + // add knobs + ASSERT_EQ(VR_OK, obj.AccumulateLine("KNOBS")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("\t-logfile TRUE")); + + obj.SetLogStringOn(true); + + ASSERT_EQ(0, obj.RunAccumulated()); + ASSERT_EQ(29, obj.GetLogStringLineCount()); + + // add solution block + ASSERT_EQ(VR_OK, ::SOLUTION(obj, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(VR_OK, ::DUMP(obj)); + + // add knobs + ASSERT_EQ(VR_OK, obj.AccumulateLine("KNOBS")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("\t-logfile TRUE")); + + obj.SetLogStringOn(false); + + ASSERT_EQ(0, obj.RunAccumulated()); + ASSERT_EQ(0, obj.GetLogStringLineCount()); +} + +TEST(TestIPhreeqc, TestGetLogStringLine) +{ + IPhreeqc obj; + ASSERT_EQ(0, obj.GetLogStringLineCount()); + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + ASSERT_EQ(0, obj.GetLogStringLineCount()); + + // add solution block + ASSERT_EQ(VR_OK, ::SOLUTION(obj, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(VR_OK, ::DUMP(obj)); + + // add knobs + ASSERT_EQ(VR_OK, obj.AccumulateLine("KNOBS")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("\t-logfile TRUE")); + + // run + obj.SetOutputStringOn(false); + obj.SetOutputFileOn(false); + obj.SetErrorFileOn(false); + obj.SetLogFileOn(false); + obj.SetSelectedOutputFileOn(false); + obj.SetDumpStringOn(false); + obj.SetDumpFileOn(false); + + ASSERT_EQ(0, obj.RunAccumulated()); + ASSERT_EQ(0, obj.GetLogStringLineCount()); + + int line = 0; + ASSERT_EQ(std::string(""), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string(""), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string(""), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string(""), std::string(obj.GetLogStringLine(line++))); + + // negative lines should be empty + ASSERT_EQ(std::string(""), std::string(obj.GetLogStringLine(-1))); + ASSERT_EQ(std::string(""), std::string(obj.GetLogStringLine(-2))); + ASSERT_EQ(std::string(""), std::string(obj.GetLogStringLine(-3))); + ASSERT_EQ(std::string(""), std::string(obj.GetLogStringLine(-4))); + + // add solution block + ASSERT_EQ(VR_OK, ::SOLUTION(obj, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(VR_OK, ::DUMP(obj)); + + // add knobs + ASSERT_EQ(VR_OK, obj.AccumulateLine("KNOBS")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("\t-logfile TRUE")); + + obj.SetLogStringOn(true); + + ASSERT_EQ(0, obj.RunAccumulated()); + ASSERT_EQ(29, obj.GetLogStringLineCount()); + + line = 0; + ASSERT_EQ(std::string("------------------------------------"), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string("Reading input data for simulation 1."), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string("------------------------------------"), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string(""), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string("-------------------------------------------"), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string("Beginning of initial solution calculations."), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string("-------------------------------------------"), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string(""), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string("Initial solution 1. "), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string(""), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string("Iterations in revise_guesses: 2"), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string(""), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string("Number of infeasible solutions: 0"), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string("Number of basis changes: 0"), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string(""), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string("Number of iterations: 6"), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string(""), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string("------------------"), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string("End of simulation."), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string("------------------"), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string(""), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string("------------------------------------"), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string("Reading input data for simulation 2."), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string("------------------------------------"), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string(""), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string("----------"), std::string(obj.GetLogStringLine(line++)).substr(0, 10)); + ASSERT_EQ(std::string("End of Run"), std::string(obj.GetLogStringLine(line++)).substr(0, 10)); + ASSERT_EQ(std::string("----------"), std::string(obj.GetLogStringLine(line++)).substr(0, 10)); + ASSERT_EQ(std::string(""), std::string(obj.GetLogStringLine(line++))); + + // add solution block + ASSERT_EQ(VR_OK, ::SOLUTION(obj, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(VR_OK, ::DUMP(obj)); + + // add knobs + ASSERT_EQ(VR_OK, obj.AccumulateLine("KNOBS")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("\t-logfile TRUE")); + + obj.SetLogStringOn(false); + + ASSERT_EQ(0, obj.RunAccumulated()); + ASSERT_EQ(0, obj.GetLogStringLineCount()); + + line = 0; + ASSERT_EQ(std::string(""), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string(""), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string(""), std::string(obj.GetLogStringLine(line++))); + ASSERT_EQ(std::string(""), std::string(obj.GetLogStringLine(line++))); + + // negative lines should be empty + ASSERT_EQ(std::string(""), std::string(obj.GetLogStringLine(-1))); + ASSERT_EQ(std::string(""), std::string(obj.GetLogStringLine(-2))); + ASSERT_EQ(std::string(""), std::string(obj.GetLogStringLine(-3))); + ASSERT_EQ(std::string(""), std::string(obj.GetLogStringLine(-4))); +} + +TEST(TestIPhreeqc, TestSetErrorFileName) +{ + char ERR_FILENAME[80]; + sprintf(ERR_FILENAME, "error.%s.out", "TestIPhreeqc-TestSetErrorFileName"); + if (::FileExists(ERR_FILENAME)) + { + ::DeleteFile(ERR_FILENAME); + } + + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + ASSERT_EQ(VR_OK, obj.AccumulateLine("SOLUTION 1")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" pH 7")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Na 1")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("PHASES")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Fix_H+")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" H+ = H+")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" log_k 0")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("EQUILIBRIUM_PHASES")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Fix_H+ -10 HCl 10")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("END")); + + // run + obj.SetErrorFileOn(true); + obj.SetLogFileOn(false); + obj.SetOutputFileOn(false); + obj.SetSelectedOutputFileOn(false); + obj.SetDumpStringOn(false); + obj.SetDumpFileOn(false); + obj.SetErrorFileName(ERR_FILENAME); + + ASSERT_EQ(1, obj.RunAccumulated()); + + ASSERT_EQ(true, ::FileExists(ERR_FILENAME)); + + std::string lines[100]; + { + std::ifstream ifs(ERR_FILENAME); + + size_t i = 0; + while (i < sizeof(lines) / sizeof(lines[0]) && std::getline(ifs, lines[i % 100])) + { + ++i; + } + + ASSERT_EQ((size_t)90, i); + } + + ASSERT_EQ(std::string("WARNING: Maximum iterations exceeded, 100"), lines[0]); + ASSERT_EQ(std::string("WARNING: Numerical method failed with this set of convergence parameters."), lines[2]); + ASSERT_EQ(std::string("ERROR: Numerical method failed on all combinations of convergence parameters, cell/soln/mix 1"), lines[88]); + ASSERT_EQ(std::string("Stopping."), lines[89]); + + if (::FileExists(ERR_FILENAME)) + { + ::DeleteFile(ERR_FILENAME); + } +} + +TEST(TestIPhreeqc, TestErrorStringOnOff) +{ + IPhreeqc obj; + ASSERT_EQ(true, obj.GetErrorStringOn()); + + obj.SetErrorStringOn(false); + ASSERT_EQ(false, obj.GetErrorStringOn()); + + obj.SetErrorStringOn(true); + ASSERT_EQ(true, obj.GetErrorStringOn()); + + obj.SetErrorStringOn(false); + ASSERT_EQ(false, obj.GetErrorStringOn()); +} + +TEST(TestIPhreeqc, TestGetErrorString) +{ + char ERR_FILENAME[80]; + sprintf(ERR_FILENAME, "error.%06d.out", ::rand()); + if (::FileExists(ERR_FILENAME)) + { + ::DeleteFile(ERR_FILENAME); + } + ASSERT_EQ(false, ::FileExists(ERR_FILENAME)); + + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + ASSERT_EQ(VR_OK, obj.AccumulateLine("SOLUTION 1")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" pH 7")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Na 1")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("PHASES")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Fix_H+")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" H+ = H+")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" log_k 0")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("EQUILIBRIUM_PHASES")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Fix_H+ -10 HCl 10")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("END")); + + // run + obj.SetErrorFileOn(true); + obj.SetErrorStringOn(true); + + obj.SetDumpFileOn(false); + obj.SetDumpStringOn(false); + obj.SetLogFileOn(false); + obj.SetOutputFileOn(false); + obj.SetOutputStringOn(false); + obj.SetSelectedOutputFileOn(false); + + obj.SetErrorFileName(ERR_FILENAME); + ASSERT_EQ(std::string(ERR_FILENAME), std::string(obj.GetErrorFileName())); + + ASSERT_EQ(1, obj.RunAccumulated()); + + ASSERT_EQ(std::string(ERR_FILENAME), std::string(obj.GetErrorFileName())); + + ASSERT_EQ(true, ::FileExists(ERR_FILENAME)); + + { + std::string fline("ERROR: Numerical method failed on all combinations of convergence parameters, cell/soln/mix 1\n"); + + std::string sline(obj.GetErrorString()); + ASSERT_TRUE(sline.size() > 0); + + ASSERT_EQ(fline, sline); + } + + if (::FileExists(ERR_FILENAME)) + { + ::DeleteFile(ERR_FILENAME); + } +} + +TEST(TestIPhreeqc, TestGetErrorStringLineCount) +{ + IPhreeqc obj; + + ASSERT_EQ(0, obj.GetErrorStringLineCount()); + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + ASSERT_EQ(0, obj.GetErrorStringLineCount()); + + ASSERT_EQ(VR_OK, obj.AccumulateLine("SOLUTION 1")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" pH 7")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Na 1")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("PHASES")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Fix_H+")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" H+ = H+")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" log_k 0")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("EQUILIBRIUM_PHASES")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Fix_H+ -10 HCl 10")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("END")); + + ASSERT_EQ(true, obj.GetErrorStringOn()); + ASSERT_EQ(1, obj.RunAccumulated()); + ASSERT_EQ(1, obj.GetErrorStringLineCount()); + + ASSERT_EQ(VR_OK, obj.AccumulateLine("SOLUTION 1")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" pH 7")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Na 1")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("PHASES")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Fix_H+")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" H+ = H+")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" log_k 0")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("EQUILIBRIUM_PHASES")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Fix_H+ -10 HCl 10")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("END")); + + obj.SetErrorStringOn(true); + ASSERT_EQ(1, obj.RunAccumulated()); + ASSERT_EQ(1, obj.GetErrorStringLineCount()); + + ASSERT_EQ(VR_OK, obj.AccumulateLine("SOLUTION 1")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" pH 7")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Na 1")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("PHASES")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Fix_H+")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" H+ = H+")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" log_k 0")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("EQUILIBRIUM_PHASES")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Fix_H+ -10 HCl 10")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("END")); + + obj.SetErrorStringOn(false); + ASSERT_EQ(1, obj.RunAccumulated()); + ASSERT_EQ(0, obj.GetErrorStringLineCount()); +} + +TEST(TestIPhreeqc, TestSetSelectedOutputFileName) +{ + char SELOUT_FILENAME[80]; + sprintf(SELOUT_FILENAME, "selected_output.%06d.out", ::rand()); + if (::FileExists(SELOUT_FILENAME)) + { + ::DeleteFile(SELOUT_FILENAME); + } + + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("llnl.dat")); + + int max = 6; + + ASSERT_EQ(VR_OK, ::SOLUTION(obj, 1.0, 1.0, 1.0)); + ASSERT_EQ(VR_OK, ::EQUILIBRIUM_PHASES(obj, "calcite", 0.0, 0.010)); + ASSERT_EQ(VR_OK, ::USER_PUNCH(obj, "Ca", max)); + + ASSERT_EQ(false, obj.GetOutputFileOn()); + ASSERT_EQ(false, obj.GetErrorFileOn()); + ASSERT_EQ(false, obj.GetLogFileOn()); + ASSERT_EQ(false, obj.GetSelectedOutputFileOn()); + ASSERT_EQ(false, obj.GetDumpFileOn()); + ASSERT_EQ(false, obj.GetDumpStringOn()); + + obj.SetSelectedOutputFileOn(1); + obj.SetSelectedOutputFileName(SELOUT_FILENAME); + + ASSERT_EQ(0, obj.RunAccumulated()); + + ASSERT_EQ(true, ::FileExists(SELOUT_FILENAME)); + + /* + EXPECTED selected.out: + sim state soln dist_x time step pH pe C Ca Na m_CO3-2 m_CaOH+ m_NaCO3- la_CO3-2 la_CaOH+ la_NaCO3- Calcite d_Calcite si_CO2(g) si_Siderite pressure total mol volume g_CO2(g) g_N2(g) k_Albite dk_Albite k_Pyrite dk_Pyrite s_CaSO4 s_SrSO4 1.name 1.type 1.moles 2.name 2.type 2.moles 3.name 3.type 3.moles 4.name 4.type 4.moles 5.name 5.type 5.moles 6.name 6.type 6.moles + 1 i_soln 1 -99 -99 -99 7 4 1.0000e-003 1.0000e-003 1.0000e-003 4.2975e-007 1.1819e-009 1.1881e-009 -6.4686e+000 -8.9530e+000 -8.9507e+000 0.0000e+000 0.0000e+000 -2.2870 -999.9990 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 Ca+2 aq 9.9178e-004 CaHCO3+ aq 7.5980e-006 CaCO3 aq 6.2155e-007 CaOH+ aq 1.1819e-009 + 1 react 1 -99 0 1 7.86135 10.18 1.1556e-003 1.1556e-003 1.0000e-003 4.2718e-006 9.7385e-009 1.1620e-008 -5.4781e+000 -8.0388e+000 -7.9621e+000 9.8444e-003 -1.5555e-004 -3.0192 -999.9990 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 calcite equi 9.8444e-003 Ca+2 aq 1.1371e-003 CaHCO3+ aq 1.1598e-005 CaCO3 aq 6.8668e-006 CaOH+ aq 9.7385e-009 + */ + + if (::FileExists(SELOUT_FILENAME)) + { + ::DeleteFile(SELOUT_FILENAME); + } +} + +TEST(TestIPhreeqc, TestSelectedOutputStringOnOff) +{ + IPhreeqc obj; + ASSERT_EQ(false, obj.GetSelectedOutputFileOn()); + + obj.SetSelectedOutputFileOn(true); + ASSERT_EQ(true, obj.GetSelectedOutputFileOn()); + + obj.SetSelectedOutputFileOn(false); + ASSERT_EQ(false, obj.GetSelectedOutputFileOn()); +} + +TEST(TestIPhreeqc, TestGetSelectedOutputString) +{ + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("llnl.dat")); + + int max = 6; + + ASSERT_EQ(VR_OK, ::SOLUTION(obj, 1.0, 1.0, 1.0)); + ASSERT_EQ(VR_OK, ::EQUILIBRIUM_PHASES(obj, "calcite", 0.0, 0.010)); + ASSERT_EQ(VR_OK, ::USER_PUNCH(obj, "Ca", max)); + + ASSERT_EQ(false, obj.GetOutputFileOn()); + ASSERT_EQ(false, obj.GetErrorFileOn()); + ASSERT_EQ(false, obj.GetLogFileOn()); + ASSERT_EQ(false, obj.GetSelectedOutputFileOn()); + ASSERT_EQ(false, obj.GetDumpFileOn()); + ASSERT_EQ(false, obj.GetDumpStringOn()); + + obj.SetSelectedOutputStringOn(true); + + ASSERT_EQ(0, obj.RunAccumulated()); + + std::string sline(obj.GetSelectedOutputString()); + + ASSERT_TRUE(::strstr(sline.c_str(), "sim\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "state\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "soln\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "dist_x\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "time\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "step\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "pH\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "pe\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "C\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "Ca\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "Na\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "m_CO3-2\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "m_CaOH+\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "m_NaCO3-\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "la_CO3-2\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "la_CaOH+\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "la_NaCO3-\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "Calcite\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "d_Calcite\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "si_CO2(g)\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "si_Siderite\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "pressure\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "total mol\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "volume\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "g_CO2(g)\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "g_N2(g)\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "k_Albite\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "dk_Albite\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "k_Pyrite\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "dk_Pyrite\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "s_CaSO4\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "s_SrSO4\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "1.name\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "1.type\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "1.moles\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "2.name\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "2.type\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "2.moles\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "3.name\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "3.type\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "3.moles\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "4.name\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "4.type\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "4.moles\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "5.name\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "5.type\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "5.moles\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "6.name\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "6.type\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "6.moles\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "\n") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "i_soln\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "react\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "Ca+2\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "aq\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "CaHCO3+\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "CaCO3\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "CaOH+\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "Calcite\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "equi\t") != NULL); +} + +TEST(TestIPhreeqc, TestGetSelectedOutputStringLineCount) +{ + IPhreeqc obj; + + ASSERT_EQ(false, obj.GetSelectedOutputFileOn()); + + ASSERT_EQ(0, obj.LoadDatabase("llnl.dat")); + + ASSERT_EQ(false, obj.GetSelectedOutputFileOn()); + + int max = 6; + + ASSERT_EQ(VR_OK, ::SOLUTION(obj, 1.0, 1.0, 1.0)); + ASSERT_EQ(VR_OK, ::EQUILIBRIUM_PHASES(obj, "calcite", 0.0, 0.010)); + ASSERT_EQ(VR_OK, ::USER_PUNCH(obj, "Ca", max)); + + ASSERT_EQ(false, obj.GetOutputFileOn()); + ASSERT_EQ(false, obj.GetErrorFileOn()); + ASSERT_EQ(false, obj.GetLogFileOn()); + ASSERT_EQ(false, obj.GetSelectedOutputFileOn()); + ASSERT_EQ(false, obj.GetDumpFileOn()); + ASSERT_EQ(false, obj.GetDumpStringOn()); + + ASSERT_EQ(false, obj.GetSelectedOutputStringOn() != 0); + obj.SetSelectedOutputStringOn(true); + + ASSERT_EQ(0, obj.RunAccumulated()); + + ASSERT_EQ(3, obj.GetSelectedOutputStringLineCount()); +} + +TEST(TestIPhreeqc, TestGetSelectedOutputStringLine) +{ + IPhreeqc obj; + + ASSERT_EQ(false, obj.GetSelectedOutputFileOn()); + + ASSERT_EQ(0, obj.LoadDatabase("llnl.dat")); + + ASSERT_EQ(false, obj.GetSelectedOutputFileOn()); + + int max = 6; + + ASSERT_EQ(VR_OK, ::SOLUTION(obj, 1.0, 1.0, 1.0)); + ASSERT_EQ(VR_OK, ::EQUILIBRIUM_PHASES(obj, "calcite", 0.0, 0.010)); + ASSERT_EQ(VR_OK, ::USER_PUNCH(obj, "Ca", max)); + + ASSERT_EQ(false, obj.GetOutputFileOn()); + ASSERT_EQ(false, obj.GetErrorFileOn()); + ASSERT_EQ(false, obj.GetLogFileOn()); + ASSERT_EQ(false, obj.GetSelectedOutputFileOn()); + ASSERT_EQ(false, obj.GetDumpFileOn()); + ASSERT_EQ(false, obj.GetDumpStringOn()); + + ASSERT_EQ(false, obj.GetSelectedOutputStringOn()); + + ASSERT_EQ(0, obj.RunAccumulated()); + ASSERT_EQ(0, obj.GetSelectedOutputStringLineCount()); + + int line = 0; + ASSERT_EQ(std::string(""), std::string(obj.GetSelectedOutputStringLine(line++))); + ASSERT_EQ(std::string(""), std::string(obj.GetSelectedOutputStringLine(line++))); + ASSERT_EQ(std::string(""), std::string(obj.GetSelectedOutputStringLine(line++))); + + // negative lines should be empty + ASSERT_EQ(std::string(""), std::string(obj.GetSelectedOutputStringLine(-1))); + ASSERT_EQ(std::string(""), std::string(obj.GetSelectedOutputStringLine(-2))); + ASSERT_EQ(std::string(""), std::string(obj.GetSelectedOutputStringLine(-3))); + + ASSERT_EQ(VR_OK, ::SOLUTION(obj, 1.0, 1.0, 1.0)); + ASSERT_EQ(VR_OK, ::EQUILIBRIUM_PHASES(obj, "calcite", 0.0, 0.010)); + ASSERT_EQ(VR_OK, ::USER_PUNCH(obj, "Ca", max)); + + ASSERT_EQ(false, obj.GetSelectedOutputStringOn() != 0); + obj.SetSelectedOutputStringOn(true); + + ASSERT_EQ(0, obj.RunAccumulated()); + ASSERT_EQ(3, obj.GetSelectedOutputStringLineCount()); + + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "sim\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "state\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "soln\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "dist_x\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "time\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "step\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "pH\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "pe\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "C\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "Ca\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "Na\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "m_CO3-2\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "m_CaOH+\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "m_NaCO3-\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "la_CO3-2\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "la_CaOH+\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "la_NaCO3-\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "Calcite\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "d_Calcite\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "si_CO2(g)\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "si_Siderite\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "pressure\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "total mol\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "volume\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "g_CO2(g)\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "g_N2(g)\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "k_Albite\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "dk_Albite\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "k_Pyrite\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "dk_Pyrite\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "s_CaSO4\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "s_SrSO4\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "1.name\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "1.type\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "1.moles\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "2.name\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "2.type\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "2.moles\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "3.name\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "3.type\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "3.moles\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "4.name\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "4.type\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "4.moles\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "5.name\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "5.type\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "5.moles\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "6.name\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "6.type\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "6.moles\t") != NULL); + + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(1), "i_soln\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(1), "Ca+2\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(1), "aq\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(1), "CaHCO3+\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(1), "CaCO3\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(1), "CaOH+\t") != NULL); + + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(2), "react\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(2), "Calcite\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(2), "equi\t") != NULL); + + // after obj.GetSelectedOutputStringLineCount() should be empty + ASSERT_EQ(std::string(""), std::string(obj.GetSelectedOutputStringLine(obj.GetSelectedOutputStringLineCount()))); + ASSERT_EQ(std::string(""), std::string(obj.GetSelectedOutputStringLine(obj.GetSelectedOutputStringLineCount() + 1))); + ASSERT_EQ(std::string(""), std::string(obj.GetSelectedOutputStringLine(obj.GetSelectedOutputStringLineCount() + 2))); + + // negative lines should be empty + ASSERT_EQ(std::string(""), std::string(obj.GetSelectedOutputStringLine(-1))); + ASSERT_EQ(std::string(""), std::string(obj.GetSelectedOutputStringLine(-2))); + ASSERT_EQ(std::string(""), std::string(obj.GetSelectedOutputStringLine(-3))); +} + +TEST(TestIPhreeqc, TestGetSelectedOutputStringLineNotEnoughHeadings) +{ + IPhreeqc obj; + + ASSERT_EQ(false, obj.GetSelectedOutputFileOn()); + + ASSERT_EQ(0, obj.LoadDatabase("llnl.dat")); + + ASSERT_EQ(false, obj.GetSelectedOutputFileOn()); + + ASSERT_EQ(VR_OK, ::SOLUTION(obj, 1.0, 1.0, 1.0)); + ASSERT_EQ(VR_OK, ::EQUILIBRIUM_PHASES(obj, "calcite", 0.0, 0.010)); + ASSERT_EQ(VR_OK, ::USER_PUNCH_NEH(obj)); + + ASSERT_EQ(false, obj.GetOutputFileOn()); + ASSERT_EQ(false, obj.GetErrorFileOn()); + ASSERT_EQ(false, obj.GetLogFileOn()); + ASSERT_EQ(false, obj.GetSelectedOutputFileOn()); + ASSERT_EQ(false, obj.GetDumpFileOn()); + ASSERT_EQ(false, obj.GetDumpStringOn()); + + ASSERT_EQ(false, obj.GetSelectedOutputStringOn() != 0); + obj.SetSelectedOutputStringOn(true); + + ASSERT_EQ(0, obj.RunAccumulated()); + ASSERT_EQ(3, obj.GetSelectedOutputStringLineCount()); + + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "sim\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "state\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "soln\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "dist_x\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "time\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "step\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "pH\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "pe\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "C\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "Ca\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "Na\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "m_CO3-2\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "m_CaOH+\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "m_NaCO3-\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "la_CO3-2\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "la_CaOH+\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "la_NaCO3-\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "Calcite\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "d_Calcite\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "si_CO2(g)\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "si_Siderite\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "pressure\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "total mol\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "volume\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "g_CO2(g)\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "g_N2(g)\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "k_Albite\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "dk_Albite\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "k_Pyrite\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "dk_Pyrite\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "s_CaSO4\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "s_SrSO4\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "head0\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "head1\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "head2\t") != NULL); + + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(1), "i_soln\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(1), "have0\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(1), "have1\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(1), "have2\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(1), "missing0\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(1), "missing2\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(1), "missing2\t") != NULL); + + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(2), "react\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(2), "have0\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(2), "have1\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(2), "have2\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(2), "missing0\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(2), "missing2\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(2), "missing2\t") != NULL); + + // after obj.GetSelectedOutputStringLineCount() should be empty + ASSERT_EQ(std::string(""), std::string(obj.GetSelectedOutputStringLine(obj.GetSelectedOutputStringLineCount()))); + ASSERT_EQ(std::string(""), std::string(obj.GetSelectedOutputStringLine(obj.GetSelectedOutputStringLineCount() + 1))); + ASSERT_EQ(std::string(""), std::string(obj.GetSelectedOutputStringLine(obj.GetSelectedOutputStringLineCount() + 2))); + + // negative lines should be empty + ASSERT_EQ(std::string(""), std::string(obj.GetSelectedOutputStringLine(-1))); + ASSERT_EQ(std::string(""), std::string(obj.GetSelectedOutputStringLine(-2))); + ASSERT_EQ(std::string(""), std::string(obj.GetSelectedOutputStringLine(-3))); +} + +TEST(TestIPhreeqc, TestLongUser_Punch) +{ + // stream tests + std::ostringstream oss; + PHRQ_io::fpunchf_helper(&oss, "%2046.2046s", "TEST"); + ASSERT_EQ((size_t)2046, oss.str().size()); + std::string s0(oss.str()); + ASSERT_EQ(std::string("TEST"), trim(s0)); + + oss.clear(); oss.seekp(0); + PHRQ_io::fpunchf_helper(&oss, "%2047.2047s", "TEST"); + ASSERT_EQ((size_t)2047, oss.str().size()); + std::string s1(oss.str()); + ASSERT_EQ(std::string("TEST"), trim(s1)); + + oss.clear(); oss.seekp(0); + PHRQ_io::fpunchf_helper(&oss, "%2048.2048s", "TEST"); + ASSERT_EQ((size_t)2048, oss.str().size()); + std::string s2(oss.str()); + ASSERT_EQ(std::string("TEST"), trim(s2)); + + oss.clear(); oss.seekp(0); + PHRQ_io::fpunchf_helper(&oss, "%2049.2049s", "TEST"); + ASSERT_EQ((size_t)2049, oss.str().size()); + std::string s3(oss.str()); + ASSERT_EQ(std::string("TEST"), trim(s3)); + + oss.clear(); oss.seekp(0); + PHRQ_io::fpunchf_helper(&oss, "%2050.2050s", "TEST"); + ASSERT_EQ((size_t)2050, oss.str().size()); + std::string s4(oss.str()); + ASSERT_EQ(std::string("TEST"), trim(s4)); + + + // string tests + std::string str; + PHRQ_io::fpunchf_helper(&str, "%2046.2046s", "TEST"); + ASSERT_EQ((size_t)2046, str.size()); + ASSERT_EQ(std::string("TEST"), trim(str)); + + str.clear(); + PHRQ_io::fpunchf_helper(&str, "%2047.2047s", "TEST"); + ASSERT_EQ((size_t)2047, str.size()); + ASSERT_EQ(std::string("TEST"), trim(str)); + + str.clear(); + PHRQ_io::fpunchf_helper(&str, "%2048.2048s", "TEST"); + ASSERT_EQ((size_t)2048, str.size()); + ASSERT_EQ(std::string("TEST"), trim(str)); + + str.clear(); + PHRQ_io::fpunchf_helper(&str, "%2049.2049s", "TEST"); + ASSERT_EQ((size_t)2049, str.size()); + ASSERT_EQ(std::string("TEST"), trim(str)); + + str.clear(); + PHRQ_io::fpunchf_helper(&str, "%2050.2050s", "TEST"); + ASSERT_EQ((size_t)2050, str.size()); + ASSERT_EQ(std::string("TEST"), trim(str)); + + const char input[] = + "PRINT\n" + " -selected_output t\n" + "SOLUTION\n" + "SELECTED_OUTPUT\n" + " -reset false\n" + "USER_PUNCH\n" + "1 REM 255 CHARACTER STRING\n" + "10 temp$ = \"XXXXX123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345\"\n" + "20 PUNCH temp$\n"; + + IPhreeqc obj; + obj.SetSelectedOutputFileOn(true); + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + ASSERT_EQ(0, obj.RunString(input)); +} + +TEST(TestIPhreeqc, TestBasicSURF) +{ + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + ASSERT_EQ(VR_OK, obj.AccumulateLine("SURFACE_MASTER_SPECIES")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Surfa Surfa")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Surfb Surfb")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("SURFACE_SPECIES")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Surfa = Surfa")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" log_k 0")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Surfb = Surfb")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" log_k 0")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Surfa + Zn+2 = SurfaZn+2")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" log_k 5.")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Surfb + Zn+2 = SurfbZn+2")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" log_k 6.")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Surfa + Cu+2 = SurfaCu+2")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" log_k 4.5")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Surfb + Cu+2 = SurfbCu+2")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" log_k 6.5")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("SOLUTION 1")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" pH 8")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" units mol/kgw")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Fe(3) 1e-2")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Zn 1e-4")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Cu 1e-5")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Na 1e-1")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Cl 1e-1")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("EQUILIBRIUM_PHASES 1")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Fe(OH)3(a) 0 0")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("SELECTED_OUTPUT")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("USER_PUNCH")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" -headings Hfo-Zn Surfa-Zn Surfb-Zn Surfa-Cu Surfb-Cu")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("-start")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("10 PUNCH SURF(\"Zn\",\"Hfo\")")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("20 PUNCH SURF(\"Zn\",\"Surfa\")")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("30 PUNCH SURF(\"Zn\",\"Surfb\")")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("40 PUNCH SURF(\"Cu\",\"Surfa\")")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("50 PUNCH SURF(\"Cu\",\"Surfb\")")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("-end")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("SURFACE 1")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Hfo_sOH Fe(OH)3(a) equilibrium_phase 0.005 53300")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Hfo_wOH Fe(OH)3(a) equilibrium_phase 0.2")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Surfa 0.2 100. 2")); + ASSERT_EQ(VR_OK, obj.AccumulateLine(" Surfb 0.1 100. 1")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("END")); + + obj.SetOutputStringOn(true); + obj.SetOutputFileOn(false); + obj.SetErrorFileOn(false); + obj.SetLogFileOn(false); + obj.SetSelectedOutputFileOn(false); + obj.SetDumpStringOn(false); + obj.SetDumpFileOn(false); + + ASSERT_EQ(0, obj.RunAccumulated()); + + ASSERT_EQ(13, obj.GetSelectedOutputColumnCount()); + ASSERT_EQ(3, obj.GetSelectedOutputRowCount()); + + CVar v; + + const int offset = 8; + + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, offset + 0, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("Hfo-Zn"), std::string(v.sVal)); + + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, offset + 1, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("Surfa-Zn"), std::string(v.sVal)); + + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, offset + 2, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("Surfb-Zn"), std::string(v.sVal)); + + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, offset + 3, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("Surfa-Cu"), std::string(v.sVal)); + + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, offset + 4, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("Surfb-Cu"), std::string(v.sVal)); + + + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, offset + 0, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(0.0, v.dVal, ::pow(10., -FLT_DIG)); + + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, offset + 1, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(0.0, v.dVal, ::pow(10., -FLT_DIG)); + + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, offset + 2, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(0.0, v.dVal, ::pow(10., -FLT_DIG)); + + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, offset + 3, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(0.0, v.dVal, ::pow(10., -FLT_DIG)); + + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, offset + 4, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(0.0, v.dVal, ::pow(10., -FLT_DIG)); + + + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, offset + 0, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(6.3861e-005, v.dVal, ::pow(10., -FLT_DIG)); + + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, offset + 1, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(1.7868e-005, v.dVal, ::pow(10., -FLT_DIG)); + + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, offset + 2, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(1.8248e-005, v.dVal, ::pow(10., -FLT_DIG)); + + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, offset + 3, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(4.6216e-009, v.dVal, ::pow(10., -FLT_DIG)); + + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, offset + 4, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(4.7201e-008, v.dVal, ::pow(10., -FLT_DIG)); +} + +#include +TEST(TestIPhreeqc, TestCErrorReporter) +{ + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("llnl.dat")); + + int max = 6; + + ASSERT_EQ(VR_OK, SOLUTION(obj, 1.0, 1.0, 1.0)); + ASSERT_EQ(VR_OK, EQUILIBRIUM_PHASES(obj, "calcite", 0.0, 0.010)); + ASSERT_EQ(VR_OK, USER_PUNCH(obj, "Ca", max)); + + obj.SetOutputFileOn(0); + obj.SetErrorFileOn(0); + obj.SetLogFileOn(0); + obj.SetSelectedOutputFileOn(0); + obj.SetDumpFileOn(0); + ASSERT_EQ(0, obj.RunAccumulated()); + + //clock_t t0 = clock(); + int nrows = obj.GetSelectedOutputRowCount(); + int ncols = obj.GetSelectedOutputColumnCount(); + CVar var; + for (int c = 0; c < 4000; ++c) + { + for (int row = 0; row < nrows; ++row) + { + for (int col = 0; col < ncols; ++col) + { + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(row, col, &var)); + } + } + } + //clock_t t = clock(); + //printf("\ntime = %g\n", double(t - t0)); +} + +TEST(TestIPhreeqc, TestDelete) +{ + const char input[] = + "SOLUTION 1 # definition of intial condition 1\n" + "COPY cell 1 7405 # copy cell 1 to placeholder cell with index larger than the number of cells in the model domain\n" + "END\n" + "DELETE # delete initial condition 1 to allow for a redefinition of all reactions\n" + "-cell 1\n" + "END\n" + "# define other initial conditions and copy to another placeholder cell\n" + "\n" + "COPY cell 7405 1 # copy back from placeholder cell to domain cell 1\n" + "END\n" + "MIX 1 # mix according to initial moisture content\n" + " 1 0.25\n" + "END\n" + "RUN_CELLS\n" + "-cells 1\n" + "-start_time 0\n" + "-time_step 0\n" + "DELETE # remove mix reaction in subsequent runs\n" + "-mix 1\n" + "END\n" + "RUN_CELLS\n" + "-cells 1\n"; + + IPhreeqc obj; + + char OUTPUT_FILE[80]; + sprintf(OUTPUT_FILE, "phreeqc.%lu.out", (unsigned long)obj.GetId()); + + if (::FileExists(OUTPUT_FILE)) + { + ASSERT_TRUE(::DeleteFile(OUTPUT_FILE)); + } + ASSERT_EQ(false, ::FileExists(OUTPUT_FILE)); + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + obj.SetOutputFileOn(0); + obj.SetErrorFileOn(0); + obj.SetLogFileOn(0); + obj.SetSelectedOutputFileOn(0); + obj.SetDumpFileOn(0); + ASSERT_EQ(false, ::FileExists(OUTPUT_FILE)); + ASSERT_EQ(0, obj.RunString(input)); + ASSERT_EQ(false, ::FileExists(OUTPUT_FILE)); + if (::FileExists(OUTPUT_FILE)) + { + ASSERT_TRUE(::DeleteFile(OUTPUT_FILE)); + } +} + +TEST(TestIPhreeqc, TestRunFileMultiPunchOn) +{ + FileTest set1("multi_punch_1.sel"); + ASSERT_TRUE(set1.RemoveExisting()); + + FileTest set2("multi_punch_2.sel"); + ASSERT_TRUE(set2.RemoveExisting()); + + FileTest set3("multi_punch_3.sel"); + ASSERT_TRUE(set3.RemoveExisting()); + + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + obj.SetCurrentSelectedOutputUserNumber(1); + obj.SetSelectedOutputFileOn(true); + obj.SetCurrentSelectedOutputUserNumber(2); + obj.SetSelectedOutputFileOn(true); + obj.SetCurrentSelectedOutputUserNumber(3); + obj.SetSelectedOutputFileOn(true); + ASSERT_EQ(0, obj.RunFile("multi_punch")); + + ASSERT_TRUE(set1.VerifyExists()); + ASSERT_TRUE(set2.VerifyExists()); + ASSERT_TRUE(set3.VerifyExists()); +} + +TEST(TestIPhreeqc, TestRunFileMultiPunchOff) +{ + FileTest set1("multi_punch_1.sel"); + ASSERT_TRUE(set1.RemoveExisting()); + + FileTest set2("multi_punch_2.sel"); + ASSERT_TRUE(set2.RemoveExisting()); + + FileTest set3("multi_punch_3.sel"); + ASSERT_TRUE(set3.RemoveExisting()); + + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + obj.SetOutputFileOn(false); + obj.SetErrorFileOn(false); + obj.SetLogFileOn(false); + obj.SetSelectedOutputFileOn(false); + obj.SetDumpFileOn(false); + ASSERT_EQ(0, obj.RunFile("multi_punch")); + + ASSERT_TRUE(set1.VerifyMissing()); + ASSERT_TRUE(set2.VerifyMissing()); + ASSERT_TRUE(set3.VerifyMissing()); +} + +TEST(TestIPhreeqc, TestRunFileMultiPunchSet) +{ + FileTest called("XXX.sel"); + ASSERT_TRUE(called.RemoveExisting()); + + FileTest set1("multi_punch_1.sel"); + ASSERT_TRUE(set1.RemoveExisting()); + + FileTest set2("multi_punch_2.sel"); + ASSERT_TRUE(set2.RemoveExisting()); + + FileTest set3("multi_punch_3.sel"); + ASSERT_TRUE(set3.RemoveExisting()); + + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + obj.SetCurrentSelectedOutputUserNumber(1); + obj.SetSelectedOutputFileOn(true); + obj.SetCurrentSelectedOutputUserNumber(2); + obj.SetSelectedOutputFileOn(true); + obj.SetCurrentSelectedOutputUserNumber(3); + obj.SetSelectedOutputFileOn(true); + + obj.SetSelectedOutputFileName(called.GetName().c_str()); + + ASSERT_EQ(0, obj.RunFile("multi_punch")); + + ASSERT_TRUE(called.VerifyMissing()); + + ASSERT_TRUE(set1.VerifyExists()); + ASSERT_TRUE(set2.VerifyExists()); + ASSERT_TRUE(set3.VerifyExists()); +} + +TEST(TestIPhreeqc, TestRunFileMultiPunchNoSet) +{ + IPhreeqc obj; + + FileTest set("XXX.sel"); + ASSERT_TRUE(set.RemoveExisting()); + +#if FIXME_PROTECTED + FileTest unset1(obj.sel_file_name(1)); + ASSERT_TRUE(unset1.RemoveExisting()); + + FileTest unset2(obj.sel_file_name(2)); + ASSERT_TRUE(unset2.RemoveExisting()); + + FileTest unset3(obj.sel_file_name(3)); + ASSERT_TRUE(unset3.RemoveExisting()); +#endif + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + obj.SetCurrentSelectedOutputUserNumber(1); + obj.SetSelectedOutputFileOn(true); + obj.SetCurrentSelectedOutputUserNumber(2); + obj.SetSelectedOutputFileOn(true); + obj.SetCurrentSelectedOutputUserNumber(3); + obj.SetSelectedOutputFileOn(true); + + obj.SetCurrentSelectedOutputUserNumber(1); + obj.SetSelectedOutputFileName(set.GetName().c_str()); + ASSERT_EQ(0, obj.RunFile("multi_punch_no_set")); + + ASSERT_TRUE(set.VerifyExists()); +#if FIXME_PROTECTED + ASSERT_TRUE(!unset1.VerifyExists()); + ASSERT_TRUE(unset2.VerifyExists()); + ASSERT_TRUE(unset3.VerifyExists()); +#endif +} + +TEST(TestIPhreeqc, TestMultiPunchSelectedOutputStringOn) +{ + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + obj.SetSelectedOutputStringOn(true); + ASSERT_EQ(0, obj.RunFile("multi_punch")); + + ASSERT_EQ(6, obj.GetSelectedOutputStringLineCount()); + + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "sim\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "state\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "soln\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "dist_x\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "time\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "step\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "pH\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "pe\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "reaction\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "temp\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "Alk\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "mu\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "mass_H2O\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "charge\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "pct_err\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "Na\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "Ca\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "m_Na+\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "m_HCO3-\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "la_Ca+2\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "la_CO3-2\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "CO2(g)\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "d_CO2(g)\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "dolomite\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "d_dolomite\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "si_Halite\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "pressure\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "total mol\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "volume\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "g_N2(g)\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "k_Calcite\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "dk_Calcite\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "s_Anhydrite\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "s_Barite\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "V_TOTAL_C\t") != NULL); + + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(1), " 8\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(2), " 10\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(3), " 11\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(4), " 12\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(5), " 14\t") != NULL); + + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(1), "react\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(2), "react\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(3), "i_soln\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(4), "i_soln\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(5), "react\t") != NULL); + + obj.SetCurrentSelectedOutputUserNumber(2); + ASSERT_EQ(9, obj.GetSelectedOutputStringLineCount()); + + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "si_Halite\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(0), "si_Calcite\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(2), "Dummy1\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(2), "Dummy2\t") != NULL); + + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(3), "Dummy1\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(3), "Dummy2\t") != NULL); + + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(4), "Dummy1\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(4), "Dummy2\t") != NULL); + + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(5), "Dummy1\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(5), "Dummy2\t") != NULL); + + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(6), "Sum_resid\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(6), "Sum_Delta/U\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(6), "MaxFracErr\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(6), "Soln_2\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(6), "Soln_2_min\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(6), "Soln_2_max\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(6), "Soln_3\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(6), "Soln_3_min\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(6), "Soln_3_max\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(6), "Halite\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(6), "Halite_max\t") != NULL); + + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(8), "Dummy1\t") != NULL); + ASSERT_TRUE(::strstr(obj.GetSelectedOutputStringLine(8), "Dummy2\t") != NULL); +} + +TEST(TestIPhreeqc, TestMultiPunchCSelectedOutput) +{ + CVar var; + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + ASSERT_EQ(0, obj.RunFile("multi_punch")); + + ASSERT_EQ(6, obj.GetSelectedOutputRowCount()); + ASSERT_EQ(35, obj.GetSelectedOutputColumnCount()); + + // headings + int ncol = 0; + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("sim"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("state"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("soln"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("dist_x"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("time"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("step"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("pH"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("pe"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("reaction"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("temp(C)"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("Alk(eq/kgw)"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("mu"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("mass_H2O"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("charge(eq)"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("pct_err"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("Na(mol/kgw)"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("Ca(mol/kgw)"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("m_Na+(mol/kgw)"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("m_HCO3-(mol/kgw)"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("la_Ca+2"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("la_CO3-2"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("CO2(g)"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("d_CO2(g)"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("dolomite"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("d_dolomite"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("si_Halite"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("pressure"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("total mol"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("volume"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("g_N2(g)"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("k_Calcite"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("dk_Calcite"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("s_Anhydrite"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("s_Barite"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("V_TOTAL_C"), std::string(var.sVal)); + + // sim + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 0, &var)); ASSERT_EQ((long)8, var.lVal); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, 0, &var)); ASSERT_EQ((long)10, var.lVal); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(3, 0, &var)); ASSERT_EQ((long)11, var.lVal); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(4, 0, &var)); ASSERT_EQ((long)12, var.lVal); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(5, 0, &var)); ASSERT_EQ((long)14, var.lVal); + + // state + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 1, &var)); ASSERT_EQ(std::string("react"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, 1, &var)); ASSERT_EQ(std::string("react"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(3, 1, &var)); ASSERT_EQ(std::string("i_soln"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(4, 1, &var)); ASSERT_EQ(std::string("i_soln"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(5, 1, &var)); ASSERT_EQ(std::string("react"), std::string(var.sVal)); + + // pH + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 6, &var)); ASSERT_NEAR(7.30475, var.dVal, ::pow(10., -2)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, 6, &var)); ASSERT_NEAR(7.29765, var.dVal, ::pow(10., -2)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(3, 6, &var)); ASSERT_NEAR(6.99738, var.dVal, ::pow(10., -2)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(4, 6, &var)); ASSERT_NEAR(6.99698, var.dVal, ::pow(10., -2)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(5, 6, &var)); ASSERT_NEAR(7.2942, var.dVal, ::pow(10., -2)); + + // V_TOTAL_C +#ifdef SKIP_TEST + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 34, &var)); ASSERT_NEAR(4.3729e-003, var.dVal, ::pow(10., -6)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, 34, &var)); ASSERT_NEAR(4.3090e-003, var.dVal, ::pow(10., -6)); +#endif + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(3, 34, &var)); ASSERT_NEAR(0.0000e+000, var.dVal, ::pow(10., -6)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(4, 34, &var)); ASSERT_NEAR(0.0000e+000, var.dVal, ::pow(10., -6)); +#ifdef SKIP_TEST + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(5, 34, &var)); ASSERT_NEAR(4.2784e-003, var.dVal, ::pow(10., -6)); +#endif + + // edge cases + int r = obj.GetSelectedOutputRowCount(); + int c = obj.GetSelectedOutputColumnCount(); + ASSERT_EQ(VR_INVALIDROW, obj.GetSelectedOutputValue(-1, 0, &var)); ASSERT_EQ(TT_ERROR, var.type); ASSERT_EQ(VR_INVALIDROW, var.vresult); + ASSERT_EQ(VR_INVALIDROW, obj.GetSelectedOutputValue(r, 0, &var)); ASSERT_EQ(TT_ERROR, var.type); ASSERT_EQ(VR_INVALIDROW, var.vresult); + ASSERT_EQ(VR_INVALIDCOL, obj.GetSelectedOutputValue(0, -1, &var)); ASSERT_EQ(TT_ERROR, var.type); ASSERT_EQ(VR_INVALIDCOL, var.vresult); + ASSERT_EQ(VR_INVALIDCOL, obj.GetSelectedOutputValue(0, c, &var)); ASSERT_EQ(TT_ERROR, var.type); ASSERT_EQ(VR_INVALIDCOL, var.vresult); + + + obj.SetCurrentSelectedOutputUserNumber(2); + ASSERT_EQ(7, obj.GetSelectedOutputRowCount()); + ASSERT_EQ(16, obj.GetSelectedOutputColumnCount()); + + // headings + ncol = 0; + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("si_Halite"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("si_Calcite"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("DUMMY_1"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("DUMMY_2"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("Sum_resid"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("Sum_Delta/U"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("MaxFracErr"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("Soln_2"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("Soln_2_min"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("Soln_2_max"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("Soln_3"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("Soln_3_min"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("Soln_3_max"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("Halite"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("Halite_min"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("Halite_max"), std::string(var.sVal)); + + // si_Halite + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 0, &var)); ASSERT_NEAR(-7.70857, var.dVal, ::pow(10., -2)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, 0, &var)); ASSERT_NEAR(-7.67087, var.dVal, ::pow(10., -2)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(3, 0, &var)); ASSERT_NEAR(-7.6362, var.dVal, ::pow(10., -2)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(4, 0, &var)); ASSERT_NEAR(-999.999, var.dVal, ::pow(10., -2)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(5, 0, &var)); ASSERT_NEAR(-7.60092, var.dVal, ::pow(10., -2)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(6, 0, &var)); ASSERT_NEAR(-7.60411, var.dVal, ::pow(10., -2)); + + // si_Calcite + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 1, &var)); ASSERT_NEAR(0.692077, var.dVal, ::pow(10., -2)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, 1, &var)); ASSERT_NEAR(0.678847, var.dVal, ::pow(10., -2)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(3, 1, &var)); ASSERT_NEAR(0.678847, var.dVal, ::pow(10., -2)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(4, 1, &var)); ASSERT_NEAR(-999.999, var.dVal, ::pow(10., -2)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(5, 1, &var)); ASSERT_NEAR(-999.999, var.dVal, ::pow(10., -2)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(6, 1, &var)); ASSERT_NEAR(0.672429, var.dVal, ::pow(10., -2)); + + // DUMMY_1 + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 2, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, 2, &var)); ASSERT_EQ(std::string("Dummy1"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(3, 2, &var)); ASSERT_EQ(std::string("Dummy1"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(4, 2, &var)); ASSERT_EQ(std::string("Dummy1"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(5, 2, &var)); ASSERT_EQ(std::string("Dummy1"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(6, 2, &var)); ASSERT_EQ(std::string("Dummy1"), std::string(var.sVal)); + + // DUMMY_2 + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 3, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, 3, &var)); ASSERT_EQ(std::string("Dummy2"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(3, 3, &var)); ASSERT_EQ(std::string("Dummy2"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(4, 3, &var)); ASSERT_EQ(std::string("Dummy2"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(5, 3, &var)); ASSERT_EQ(std::string("Dummy2"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(6, 3, &var)); ASSERT_EQ(std::string("Dummy2"), std::string(var.sVal)); + + // Sum_resid + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 4, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, 4, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(3, 4, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(4, 4, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(5, 4, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(6, 4, &var)); ASSERT_NEAR(3.69E-13, var.dVal, ::pow(10., log10(3.69E-13) - 2)); + + // Sum_Delta/U + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 5, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, 5, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(3, 5, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(4, 5, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(5, 5, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(6, 5, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + // MaxFracErr + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 6, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, 6, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(3, 6, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(4, 6, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(5, 6, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(6, 6, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + // Soln_2 + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 7, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, 7, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(3, 7, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(4, 7, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(5, 7, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(6, 7, &var)); ASSERT_NEAR(1, var.dVal, ::pow(10., -3)); + + // Soln_2_min + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 8, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, 8, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(3, 8, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(4, 8, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(5, 8, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(6, 8, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + // Soln_2_max + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 9, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, 9, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(3, 9, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(4, 9, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(5, 9, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(6, 9, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + // Soln_3 + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 10, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, 10, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(3, 10, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(4, 10, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(5, 10, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(6, 10, &var)); ASSERT_NEAR(1, var.dVal, ::pow(10., -3)); + + // Soln_3_min + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 11, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, 11, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(3, 11, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(4, 11, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(5, 11, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(6, 11, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + // Soln_3_max + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 12, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, 12, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(3, 12, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(4, 12, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(5, 12, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(6, 12, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + // Halite + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 13, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, 13, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(3, 13, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(4, 13, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(5, 13, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(6, 13, &var)); ASSERT_NEAR(0.001, var.dVal, ::pow(10., -3)); + + // Halite_min + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 14, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, 14, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(3, 14, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(4, 14, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(5, 14, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(6, 14, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + // Halite_max + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 15, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(2, 15, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(3, 15, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(4, 15, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(5, 15, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(6, 15, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + // edge cases + r = obj.GetSelectedOutputRowCount(); + c = obj.GetSelectedOutputColumnCount(); + ASSERT_EQ(VR_INVALIDROW, obj.GetSelectedOutputValue(-1, 0, &var)); ASSERT_EQ(TT_ERROR, var.type); ASSERT_EQ(VR_INVALIDROW, var.vresult); + ASSERT_EQ(VR_INVALIDROW, obj.GetSelectedOutputValue(r, 0, &var)); ASSERT_EQ(TT_ERROR, var.type); ASSERT_EQ(VR_INVALIDROW, var.vresult); + ASSERT_EQ(VR_INVALIDCOL, obj.GetSelectedOutputValue(0, -1, &var)); ASSERT_EQ(TT_ERROR, var.type); ASSERT_EQ(VR_INVALIDCOL, var.vresult); + ASSERT_EQ(VR_INVALIDCOL, obj.GetSelectedOutputValue(0, c, &var)); ASSERT_EQ(TT_ERROR, var.type); ASSERT_EQ(VR_INVALIDCOL, var.vresult); + + obj.SetCurrentSelectedOutputUserNumber(3); + ASSERT_EQ(2, obj.GetSelectedOutputRowCount()); + ASSERT_EQ(12, obj.GetSelectedOutputColumnCount()); + + // headings + ncol = 0; + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("Sum_resid"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("Sum_Delta/U"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("MaxFracErr"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("Soln_2"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("Soln_2_min"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("Soln_2_max"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("Soln_3"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("Soln_3_min"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("Soln_3_max"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("Halite"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("Halite_min"), std::string(var.sVal)); + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(0, ncol++, &var)); ASSERT_EQ(std::string("Halite_max"), std::string(var.sVal)); + + // Sum_resid + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 0, &var)); ASSERT_NEAR(3.69E-13, var.dVal, ::pow(10., log10(3.69E-13) - 2)); + + // Sum_Delta/U + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 1, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + // MaxFracErr + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 2, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + // Soln_2 + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 3, &var)); ASSERT_NEAR(1, var.dVal, ::pow(10., -3)); + + // Soln_2_min + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 4, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + // Soln_2_max + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 5, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + // Soln_3 + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 6, &var)); ASSERT_NEAR(1, var.dVal, ::pow(10., -3)); + + // Soln_3_min + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 7, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + // Soln_3_max + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 8, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + // Halite + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 9, &var)); ASSERT_NEAR(0.001, var.dVal, ::pow(10., -3)); + + // Halite_min + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 10, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + // Halite_max + ASSERT_EQ(VR_OK, obj.GetSelectedOutputValue(1, 11, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + + // edge cases + r = obj.GetSelectedOutputRowCount(); + c = obj.GetSelectedOutputColumnCount(); + ASSERT_EQ(VR_INVALIDROW, obj.GetSelectedOutputValue(-1, 0, &var)); ASSERT_EQ(TT_ERROR, var.type); ASSERT_EQ(VR_INVALIDROW, var.vresult); + ASSERT_EQ(VR_INVALIDROW, obj.GetSelectedOutputValue(r, 0, &var)); ASSERT_EQ(TT_ERROR, var.type); ASSERT_EQ(VR_INVALIDROW, var.vresult); + ASSERT_EQ(VR_INVALIDCOL, obj.GetSelectedOutputValue(0, -1, &var)); ASSERT_EQ(TT_ERROR, var.type); ASSERT_EQ(VR_INVALIDCOL, var.vresult); + ASSERT_EQ(VR_INVALIDCOL, obj.GetSelectedOutputValue(0, c, &var)); ASSERT_EQ(TT_ERROR, var.type); ASSERT_EQ(VR_INVALIDCOL, var.vresult); + + ASSERT_EQ(VR_INVALIDARG, obj.SetCurrentSelectedOutputUserNumber(-1)); + ASSERT_EQ(VR_OK, obj.SetCurrentSelectedOutputUserNumber(0)); +} + +TEST(TestIPhreeqc, TestGetSelectedOutputCount) +{ + CVar var; + IPhreeqc obj; + + ASSERT_EQ(0, obj.GetSelectedOutputCount()); + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + ASSERT_EQ(0, obj.GetSelectedOutputCount()); + ASSERT_EQ(0, obj.RunFile("multi_punch")); + ASSERT_EQ(3, obj.GetSelectedOutputCount()); +} + +TEST(TestIPhreeqc, TestGetNthSelectedOutputUserNumber) +{ + CVar var; + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + ASSERT_EQ(0, obj.RunFile("multi_punch")); + + ASSERT_EQ(3, obj.GetSelectedOutputCount()); + + ASSERT_EQ(1, obj.GetNthSelectedOutputUserNumber(0)); + ASSERT_EQ(2, obj.GetNthSelectedOutputUserNumber(1)); + ASSERT_EQ(3, obj.GetNthSelectedOutputUserNumber(2)); + + // edge cases + ASSERT_EQ((int)VR_INVALIDARG, obj.GetNthSelectedOutputUserNumber(-1)); + ASSERT_EQ((int)VR_INVALIDARG, obj.GetNthSelectedOutputUserNumber(4)); +} + +TEST(TestIPhreeqc, TestGetCurrentSelectedOutputUserNumber) +{ + IPhreeqc obj; + ASSERT_EQ(1, obj.GetCurrentSelectedOutputUserNumber()); + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + ASSERT_EQ(1, obj.GetCurrentSelectedOutputUserNumber()); + ASSERT_EQ(0, obj.RunFile("multi_punch")); + + ASSERT_EQ(1, obj.GetCurrentSelectedOutputUserNumber()); + ASSERT_EQ(6, obj.GetSelectedOutputRowCount()); + ASSERT_EQ(35, obj.GetSelectedOutputColumnCount()); + + obj.SetCurrentSelectedOutputUserNumber(2); + ASSERT_EQ(2, obj.GetCurrentSelectedOutputUserNumber()); + ASSERT_EQ(7, obj.GetSelectedOutputRowCount()); + ASSERT_EQ(16, obj.GetSelectedOutputColumnCount()); + + obj.SetCurrentSelectedOutputUserNumber(3); + ASSERT_EQ(3, obj.GetCurrentSelectedOutputUserNumber()); + ASSERT_EQ(2, obj.GetSelectedOutputRowCount()); + ASSERT_EQ(12, obj.GetSelectedOutputColumnCount()); + + // edge cases + ASSERT_EQ(VR_INVALIDARG, obj.SetCurrentSelectedOutputUserNumber(-1)); + ASSERT_EQ(3, obj.GetCurrentSelectedOutputUserNumber()); + ASSERT_EQ(VR_OK, obj.SetCurrentSelectedOutputUserNumber(0)); + ASSERT_EQ(0, obj.GetCurrentSelectedOutputUserNumber()); + + // unload database + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + ASSERT_EQ(1, obj.GetCurrentSelectedOutputUserNumber()); + ASSERT_EQ(0, obj.GetSelectedOutputCount()); +} + +TEST(TestIPhreeqc, TestMultiSetSelectedOutputFileName) +{ + FileTest set1("state.sel"); + ASSERT_TRUE(set1.RemoveExisting()); + + FileTest set2("si.sel"); + ASSERT_TRUE(set2.RemoveExisting()); + + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + ASSERT_EQ(VR_OK, obj.SetCurrentSelectedOutputUserNumber(1)); + obj.SetSelectedOutputStringOn(true); + obj.SetSelectedOutputFileOn(true); + obj.SetSelectedOutputFileName(set1.GetName().c_str()); + + ASSERT_EQ(VR_OK, obj.SetCurrentSelectedOutputUserNumber(2)); + obj.SetSelectedOutputStringOn(true); + obj.SetSelectedOutputFileOn(true); + obj.SetSelectedOutputFileName(set2.GetName().c_str()); + + obj.AccumulateLine("TITLE Temperature dependence of solubility"); + obj.AccumulateLine(" of gypsum and anhydrite "); + obj.AccumulateLine("SOLUTION 1 Pure water "); + obj.AccumulateLine(" pH 7.0 "); + obj.AccumulateLine(" temp 25.0 "); + obj.AccumulateLine("EQUILIBRIUM_PHASES 1 "); + obj.AccumulateLine(" Gypsum 0.0 1.0 "); + obj.AccumulateLine(" Anhydrite 0.0 1.0 "); + obj.AccumulateLine("REACTION_TEMPERATURE 1 "); + obj.AccumulateLine(" 25.0 75.0 in 51 steps "); + obj.AccumulateLine("SELECTED_OUTPUT 1 "); + obj.AccumulateLine(" -temperature "); + obj.AccumulateLine("SELECTED_OUTPUT 2 "); + obj.AccumulateLine(" -si anhydrite gypsum "); + obj.AccumulateLine("END "); + + ASSERT_EQ(0, obj.RunAccumulated()); + + ASSERT_TRUE(set1.VerifyExists()); + ASSERT_TRUE(set2.VerifyExists()); +} + +TEST(TestIPhreeqc, TestWissmeier20131203) +{ + IPhreeqc obj; + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + obj.AccumulateLine("selected_output 1"); + obj.AccumulateLine("-totals O"); + obj.AccumulateLine(""); + obj.AccumulateLine("END"); + obj.AccumulateLine("selected_output 1"); + obj.AccumulateLine("-totals H"); + obj.AccumulateLine(""); + obj.AccumulateLine("solution"); + obj.AccumulateLine("END"); + obj.AccumulateLine("selected_output"); + + // original asserts here + ASSERT_EQ(0, obj.RunAccumulated()); + + ASSERT_EQ(1, obj.GetSelectedOutputCount()); + + ASSERT_EQ(9, obj.GetSelectedOutputColumnCount()); + ASSERT_EQ(2, obj.GetSelectedOutputRowCount()); +} + +TEST(TestIPhreeqc, TestWissmeier20131203_2) +{ + IPhreeqc obj; + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + obj.AccumulateLine("selected_output 22"); + obj.AccumulateLine("-totals O"); + obj.AccumulateLine(""); + obj.AccumulateLine("END"); + obj.AccumulateLine("selected_output 22"); + obj.AccumulateLine("-totals H"); + obj.AccumulateLine(""); + obj.AccumulateLine("solution"); + obj.AccumulateLine("END"); + obj.AccumulateLine("selected_output 22"); + + // original asserts here + ASSERT_EQ(0, obj.RunAccumulated()); + + ASSERT_EQ(1, obj.GetSelectedOutputCount()); + + ASSERT_EQ(VR_OK, obj.SetCurrentSelectedOutputUserNumber(22)); + ASSERT_EQ(1, obj.GetSelectedOutputColumnCount()); + ASSERT_EQ(2, obj.GetSelectedOutputRowCount()); +} + +TEST(TestIPhreeqc, TestWissmeier20131203_3) +{ + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + obj.AccumulateLine("selected_output 1"); + obj.AccumulateLine("-reset false"); + obj.AccumulateLine("-totals O"); + obj.AccumulateLine(""); + obj.AccumulateLine("END"); + obj.AccumulateLine("selected_output 1"); + obj.AccumulateLine("-reset false"); + obj.AccumulateLine("-totals H"); + obj.AccumulateLine(""); + obj.AccumulateLine("solution"); + obj.AccumulateLine("END"); + obj.AccumulateLine("selected_output"); + obj.AccumulateLine("-reset false"); + + // original asserts here + ASSERT_EQ(0, obj.RunAccumulated()); + + ASSERT_EQ(1, obj.GetSelectedOutputCount()); + + ASSERT_EQ(1, obj.GetSelectedOutputColumnCount()); + ASSERT_EQ(2, obj.GetSelectedOutputRowCount()); +} + +TEST(TestIPhreeqc, TestKinniburgh20140218) +{ + IPhreeqc obj; + ASSERT_EQ(0, obj.LoadDatabase("wateq4f.dat")); + EXPECT_EQ(0, obj.RunFile("kinn20140218")) << obj.GetErrorString(); + std::string sline(obj.GetErrorString()); + std::cerr << sline; +} + +TEST(TestIPhreeqc, TestGetAccumulatedLines) +{ + IPhreeqc obj; + ASSERT_EQ(VR_OK, obj.AccumulateLine("solution 12")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("solution 13")); + + for (int i = 0; i < 10; ++i) + { + ASSERT_EQ(1, obj.RunAccumulated()); + const char expected[] = "solution 12\nsolution 13\n"; + ASSERT_EQ(std::string(expected), obj.GetAccumulatedLines()); + } + + ASSERT_EQ(VR_OK, obj.AccumulateLine("solution 22")); + for (int i = 0; i < 10; ++i) + { + ASSERT_EQ(1, obj.RunAccumulated()); + const char expected[] = "solution 22\n"; + ASSERT_EQ(std::string(expected), obj.GetAccumulatedLines()); + } +} + +TEST(TestIPhreeqc, TestGetAccumulatedLinesAfterRunFile) +{ + IPhreeqc obj; + ASSERT_EQ(0, obj.LoadDatabase("wateq4f.dat")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("solution 12")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("solution 13")); + + for (int i = 0; i < 10; ++i) + { + ASSERT_EQ(0, obj.RunFile("kinn20140218")); + const char expected[] = ""; + ASSERT_EQ(std::string(expected), obj.GetAccumulatedLines()); + } +} + +TEST(TestIPhreeqc, TestGetAccumulatedLinesAfterRunString) +{ + const char input[] = + "TITLE Example 1.--Add uranium and speciate seawater.\n" + "SOLUTION 1 SEAWATER FROM NORDSTROM ET AL. (1979)\n" + " units ppm\n" + " pH 8.22\n" + " pe 8.451\n" + " density 1.023\n" + " temp 25.0\n" + " redox O(0)/O(-2)\n" + " Ca 412.3\n" + " Mg 1291.8\n" + " Na 10768.0\n" + " K 399.1\n" + " Fe 0.002\n" + " Mn 0.0002 pe\n" + " Si 4.28\n" + " Cl 19353.0\n" + " Alkalinity 141.682 as HCO3\n" + " S(6) 2712.0\n" + " N(5) 0.29 gfw 62.0\n" + " N(-3) 0.03 as NH4\n" + " U 3.3 ppb N(5)/N(-3)\n" + " O(0) 1.0 O2(g) -0.7\n" + "SOLUTION_MASTER_SPECIES\n" + " U U+4 0.0 238.0290 238.0290\n" + " U(4) U+4 0.0 238.0290\n" + " U(5) UO2+ 0.0 238.0290\n" + " U(6) UO2+2 0.0 238.0290\n" + "SOLUTION_SPECIES\n" + " #primary master species for U\n" + " #is also secondary master species for U(4)\n" + " U+4 = U+4\n" + " log_k 0.0\n" + " U+4 + 4 H2O = U(OH)4 + 4 H+\n" + " log_k -8.538\n" + " delta_h 24.760 kcal\n" + " U+4 + 5 H2O = U(OH)5- + 5 H+\n" + " log_k -13.147\n" + " delta_h 27.580 kcal\n" + " #secondary master species for U(5)\n" + " U+4 + 2 H2O = UO2+ + 4 H+ + e-\n" + " log_k -6.432\n" + " delta_h 31.130 kcal\n" + " #secondary master species for U(6)\n" + " U+4 + 2 H2O = UO2+2 + 4 H+ + 2 e-\n" + " log_k -9.217\n" + " delta_h 34.430 kcal\n" + " UO2+2 + H2O = UO2OH+ + H+\n" + " log_k -5.782\n" + " delta_h 11.015 kcal\n" + " 2UO2+2 + 2H2O = (UO2)2(OH)2+2 + 2H+\n" + " log_k -5.626\n" + " delta_h -36.04 kcal\n" + " 3UO2+2 + 5H2O = (UO2)3(OH)5+ + 5H+\n" + " log_k -15.641\n" + " delta_h -44.27 kcal\n" + " UO2+2 + CO3-2 = UO2CO3\n" + " log_k 10.064\n" + " delta_h 0.84 kcal\n" + " UO2+2 + 2CO3-2 = UO2(CO3)2-2\n" + " log_k 16.977\n" + " delta_h 3.48 kcal\n" + " UO2+2 + 3CO3-2 = UO2(CO3)3-4\n" + " log_k 21.397\n" + " delta_h -8.78 kcal\n" + "PHASES\n" + " Uraninite\n" + " UO2 + 4 H+ = U+4 + 2 H2O\n" + " log_k -3.490\n" + " delta_h -18.630 kcal\n" + "END\n" + "\n"; + + IPhreeqc obj; + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("solution 12")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("solution 13")); + + for (int i = 0; i < 10; ++i) + { + ASSERT_EQ(0, obj.RunString(input)); + const char expected[] = ""; + ASSERT_EQ(std::string(expected), obj.GetAccumulatedLines()); + } +} + +TEST(TestIPhreeqc, TestPBasicStopThrow) +{ + IPhreeqc obj; + + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + + ASSERT_EQ(VR_OK, obj.AccumulateLine("SOLUTION 1 # Mine water from Bain et al., 2001")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("USER_PRINT")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("10 print -(0.006^0.9)")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("20 print TOTMOL(\"H\"), TOTMOLE(\"H\"), TOTMOLES(\"H\")")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("110 print (-0.2)^3")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("120 print (-0.2)^3.0")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("130 print (-0.2)^-2")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("140 print (-0.2)^-3")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("150 print -0.2^2.2")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("END")); + + obj.SetOutputFileOn(true); + ASSERT_EQ(5, obj.RunAccumulated()); +} + +TEST(TestIPhreeqc, TestEx10) +{ + const char input[] = + "TITLE Example 10.--Solid solution of strontianite and aragonite.\n" + "PHASES\n" + " Strontianite\n" + " SrCO3 = CO3-2 + Sr+2\n" + " log_k -9.271\n" + " Aragonite\n" + " CaCO3 = CO3-2 + Ca+2\n" + " log_k -8.336\n" + "END\n" + "SOLID_SOLUTIONS 1\n" + " Ca(x)Sr(1-x)CO3 \n" + " -comp1 Aragonite 0 \n" + " -comp2 Strontianite 0 \n" + " -Gugg_nondim 3.43 -1.82\n" + "END\n" + "SOLUTION 1\n" + " -units mmol/kgw\n" + " pH 5.93 charge\n" + " Ca 3.932\n" + " C 7.864\n" + "EQUILIBRIUM_PHASES 1\n" + " CO2(g) -0.01265 10\n" + " Aragonite\n" + "SAVE solution 1\n" + "END\n" + "#\n" + "# Total of 0.00001 to 0.005 moles of SrCO3 added\n" + "#\n" + "USE solution 1\n" + "USE solid_solution 1\n" + "REACTION 1\n" + " SrCO3 1.0\n" + " .005 in 500 steps \n" + "PRINT\n" + " -reset false\n" + " -echo true\n" + " -user_print true\n" + "USER_PRINT\n" + "-start\n" + " 10 sum = (S_S(\"Strontianite\") + S_S(\"Aragonite\"))\n" + " 20 if sum = 0 THEN GOTO 110\n" + " 30 xb = S_S(\"Strontianite\")/sum\n" + " 40 xc = S_S(\"Aragonite\")/sum\n" + " 50 PRINT \"Simulation number: \", SIM_NO\n" + " 60 PRINT \"Reaction step number: \", STEP_NO\n" + " 70 PRINT \"SrCO3 added: \", RXN\n" + " 80 PRINT \"Log Sigma pi: \", LOG10 (ACT(\"CO3-2\") * (ACT(\"Ca+2\") + ACT(\"Sr+2\")))\n" + " 90 PRINT \"XAragonite: \", xc\n" + " 100 PRINT \"XStrontianite: \", xb\n" + " 110 PRINT \"XCa: \", TOT(\"Ca\")/(TOT(\"Ca\") + TOT(\"Sr\"))\n" + " 120 PRINT \"XSr: \", TOT(\"Sr\")/(TOT(\"Ca\") + TOT(\"Sr\"))\n" + " 130 PRINT \"Misc 1: \", MISC1(\"Ca(x)Sr(1-x)CO3\")\n" + " 140 PRINT \"Misc 2: \", MISC2(\"Ca(x)Sr(1-x)CO3\")\n" + "-end\n" + "SELECTED_OUTPUT\n" + " -file ex10.sel\n" + " -reset false\n" + " -reaction true\n" + "USER_PUNCH\n" + "-head lg_SigmaPi X_Arag X_Stront X_Ca_aq X_Sr_aq mol_Misc1 mol_Misc2 \\n" + " mol_Arag mol_Stront\n" + "-start\n" + " 10 sum = (S_S(\"Strontianite\") + S_S(\"Aragonite\"))\n" + " 20 if sum = 0 THEN GOTO 60\n" + " 30 xb = S_S(\"Strontianite\")/(S_S(\"Strontianite\") + S_S(\"Aragonite\"))\n" + " 40 xc = S_S(\"Aragonite\")/(S_S(\"Strontianite\") + S_S(\"Aragonite\"))\n" + " 50 REM Sigma Pi\n" + " 60 PUNCH LOG10(ACT(\"CO3-2\") * (ACT(\"Ca+2\") + ACT(\"Sr+2\")))\n" + " 70 PUNCH xc # Mole fraction aragonite\n" + " 80 PUNCH xb # Mole fraction strontianite\n" + " 90 PUNCH TOT(\"Ca\")/(TOT(\"Ca\") + TOT(\"Sr\")) # Mole aqueous calcium\n" + " 100 PUNCH TOT(\"Sr\")/(TOT(\"Ca\") + TOT(\"Sr\")) # Mole aqueous strontium\n" + " 110 x1 = MISC1(\"Ca(x)Sr(1-x)CO3\")\n" + " 120 x2 = MISC2(\"Ca(x)Sr(1-x)CO3\")\n" + " 130 if (xb < x1 OR xb > x2) THEN GOTO 250\n" + " 140 nc = S_S(\"Aragonite\")\n" + " 150 nb = S_S(\"Strontianite\")\n" + " 160 mol2 = ((x1 - 1)/x1)*nb + nc\n" + " 170 mol2 = mol2 / ( ((x1 -1)/x1)*x2 + (1 - x2))\n" + " 180 mol1 = (nb - mol2*x2)/x1\n" + " 190 REM # Moles of misc. end members if in gap\n" + " 200 PUNCH mol1\n" + " 210 PUNCH mol2\n" + " 220 GOTO 300\n" + " 250 REM # Moles of misc. end members if not in gap\n" + " 260 PUNCH 1e-10\n" + " 270 PUNCH 1e-10\n" + " 300 PUNCH S_S(\"Aragonite\") # Moles aragonite\n" + " 310 PUNCH S_S(\"Strontianite\") # Moles Strontianite\n" + "-end\n" + "USER_GRAPH Example 10\n" + " -headings x_Aragonite x_Srontianite\n" + " -chart_title \"Aragonite-Strontianite Solid Solution\"\n" + " -axis_titles \"Log(SrCO3 added, in moles)\" \"Log(Mole fraction of component)\"\n" + " -axis_scale x_axis -5 1 1 1\n" + " -axis_scale y_axis -5 0.1 1 1\n" + " -connect_simulations true\n" + " -start\n" + " 10 sum = (S_S(\"Strontianite\") + S_S(\"Aragonite\"))\n" + " 20 IF sum = 0 THEN GOTO 70\n" + " 30 xb = S_S(\"Strontianite\")/ sum\n" + " 40 xc = S_S(\"Aragonite\")/ sum\n" + " 50 PLOT_XY LOG10(RXN), LOG10(xc), line_w = 2, symbol_size = 0\n" + " 60 PLOT_XY LOG10(RXN), LOG10(xb), line_w = 2, symbol_size = 0\n" + " 70 rem\n" + " -end\n" + "END \n" + "#\n" + "# Total of 0.005 to 0.1 moles of SrCO3 added\n" + "#\n" + "USE solution 1\n" + "USE solid_solution 1\n" + "REACTION 1\n" + " SrCO3 1.0\n" + " .1 in 20 steps \n" + "END \n" + "#\n" + "# Total of 0.1 to 10 moles of SrCO3 added\n" + "#\n" + "USE solution 1\n" + "USE solid_solution 1\n" + "REACTION 1\n" + " SrCO3 1.0\n" + " 10.0 in 100 steps \n" + "END \n"; + + IPhreeqc obj; + ASSERT_EQ(0, obj.LoadDatabase("phreeqc.dat")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("solution 12")); + ASSERT_EQ(VR_OK, obj.AccumulateLine("solution 13")); + + for (int i = 0; i < 10; ++i) + { + ASSERT_EQ(0, obj.RunString(input)); + const char expected[] = ""; + ASSERT_EQ(std::string(expected), obj.GetAccumulatedLines()); + } +} diff --git a/gtest/TestIPhreeqcLib.cpp b/gtest/TestIPhreeqcLib.cpp new file mode 100644 index 00000000..4a8cee44 --- /dev/null +++ b/gtest/TestIPhreeqcLib.cpp @@ -0,0 +1,4606 @@ +#include + +#include "IPhreeqc.h" +#include "CVar.hxx" + +#if defined(_WIN32) +#include +#endif + +#include +#include +#include // strstr +#include +#include +#include + +#include "FileTest.h" + + +IPQ_RESULT SOLUTION(int n, double C, double Ca, double Na); +IPQ_RESULT EQUILIBRIUM_PHASES(int n, const char* phase, double si, double amount); +IPQ_RESULT USER_PUNCH(int n, const char* element, int max); +IPQ_RESULT SELECTED_OUTPUT(int n); +IPQ_RESULT DUMP(int n); + +void TestFileOnOff(const char* FILENAME_FORMAT, int output_file_on, int error_file_on, int log_file_on, int selected_output_file_on, int dump_file_on); + + +const char ex15_dat[] = +"SOLUTION_MASTER_SPECIES\n" +"C CO2 2.0 61.0173 12.0111\n" +"Cl Cl- 0.0 Cl 35.453\n" +"Co Co+2 0.0 58.93 58.93 \n" +"E e- 0.0 0.0 0.0\n" +"H H+ -1. 1.008 1.008\n" +"H(0) H2 0.0 1.008\n" +"H(1) H+ -1. 1.008\n" +"N NH4+ 0.0 14.0067 14.0067\n" +"Na Na+ 0.0 Na 22.9898\n" +"Nta Nta-3 3.0 1. 1.\n" +"O H2O 0.0 16.00 16.00\n" +"O(-2) H2O 0.0 18.016\n" +"O(0) O2 0.0 16.00\n" +"SOLUTION_SPECIES\n" +"2H2O = O2 + 4H+ + 4e- \n" +" log_k -86.08; -gamma 1e7 0.0\n" +"2 H+ + 2 e- = H2\n" +" log_k -3.15; -gamma 1e7 0.0\n" +"H+ = H+\n" +" log_k 0.0; -gamma 1e7 0.0\n" +"e- = e-\n" +" log_k 0.0; -gamma 1e7 0.0\n" +"H2O = H2O\n" +" log_k 0.0; -gamma 1e7 0.0\n" +"CO2 = CO2\n" +" log_k 0.0; -gamma 1e7 0.0\n" +"Na+ = Na+\n" +" log_k 0.0; -gamma 1e7 0.0\n" +"Cl- = Cl-\n" +" log_k 0.0; -gamma 1e7 0.0\n" +"Co+2 = Co+2\n" +" log_k 0.0; -gamma 1e7 0.0\n" +"NH4+ = NH4+\n" +" log_k 0.0; -gamma 1e7 0.0\n" +"Nta-3 = Nta-3\n" +" log_k 0.0; -gamma 1e7 0.0\n" +"Nta-3 + 3H+ = H3Nta\n" +" log_k 14.9; -gamma 1e7 0.0\n" +"Nta-3 + 2H+ = H2Nta-\n" +" log_k 13.3; -gamma 1e7 0.0\n" +"Nta-3 + H+ = HNta-2\n" +" log_k 10.3; -gamma 1e7 0.0\n" +"Nta-3 + Co+2 = CoNta-\n" +" log_k 11.7; -gamma 1e7 0.0\n" +"2 Nta-3 + Co+2 = CoNta2-4\n" +" log_k 14.5; -gamma 1e7 0.0\n" +"Nta-3 + Co+2 + H2O = CoOHNta-2 + H+\n" +" log_k 0.5; -gamma 1e7 0.0\n" +"Co+2 + H2O = CoOH+ + H+\n" +" log_k -9.7; -gamma 1e7 0.0\n" +"Co+2 + 2H2O = Co(OH)2 + 2H+\n" +" log_k -22.9; -gamma 1e7 0.0\n" +"Co+2 + 3H2O = Co(OH)3- + 3H+\n" +" log_k -31.5; -gamma 1e7 0.0\n" +"CO2 + H2O = HCO3- + H+\n" +" log_k -6.35; -gamma 1e7 0.0\n" +"CO2 + H2O = CO3-2 + 2H+\n" +" log_k -16.68; -gamma 1e7 0.0\n" +"NH4+ = NH3 + H+\n" +" log_k -9.3; -gamma 1e7 0.0\n" +"H2O = OH- + H+\n" +" log_k -14.0; -gamma 1e7 0.0\n" +"END\n"; + + +TEST(TestIPhreeqcLib, TestCreateIPhreeqc) +{ + int n = ::CreateIPhreeqc(); + ASSERT_GE(n, 0); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestDestroyIPhreeqc) +{ + for (int i = 0; i < 10; ++i) + { + ASSERT_EQ(IPQ_BADINSTANCE, ::DestroyIPhreeqc(i)); + } + + int n = ::CreateIPhreeqc(); + ASSERT_GE(n, 0); + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); +} + +TEST(TestIPhreeqcLib, TestLoadDatabase) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + std::string FILES[] = { "phreeqc.dat", "pitzer.dat", "wateq4f.dat", + "Amm.dat", "frezchem.dat", "iso.dat", + "llnl.dat", "minteq.dat", "minteq.v4.dat", + "sit.dat","ColdChem.dat","core10.dat", + "Tipping_Hurley.dat" + }; + + for (int j = 0; j < sizeof(FILES) / sizeof(std::string); ++j) + { + for (int i = 0; i < 10; ++i) + { + ASSERT_EQ(true, ::FileExists(FILES[j].c_str())); + ASSERT_TRUE(::FileSize(FILES[j].c_str()) > 0); + ASSERT_EQ(0, ::LoadDatabase(n, FILES[j].c_str())); + } + } + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); +} + +TEST(TestIPhreeqcLib, TestLoadDatabaseString) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + for (int i = 0; i < 10; ++i) + { + ASSERT_EQ(0, ::LoadDatabaseString(n, ex15_dat)); + } + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestLoadDatabaseMissingFile) +{ + ASSERT_EQ(false, ::FileExists("missing.file")); + + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + for (int i = 0; i < 10; ++i) + { + ASSERT_EQ(1, ::LoadDatabase(n, "missing.file")); + } + + const char expected[] = + "ERROR: LoadDatabase: Unable to open:\"missing.file\".\n"; + + const char* err = ::GetErrorString(n); + + ASSERT_EQ(std::string(expected), std::string(err)); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestSetErrorOn) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(1, ::GetErrorOn(n)); // intial setting is true + ASSERT_EQ(IPQ_OK, ::SetErrorOn(n, 0)); + ASSERT_EQ(0, ::GetErrorOn(n)); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestLoadDatabaseWithErrors) +{ + ASSERT_EQ(true, ::FileExists("missing_e.dat")); + + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + for (int i = 0; i < 10; ++i) + { + ASSERT_EQ(true, ::FileExists("missing_e.dat")); + ASSERT_TRUE(::FileSize("missing_e.dat") > 0); + ASSERT_EQ(6, ::LoadDatabase(n, "missing_e.dat")); + + static const char* expected = + "ERROR: Could not reduce equation to primary master species, CH4.\n" + "ERROR: Could not reduce equation to primary master species, Cu+.\n" + "ERROR: Could not reduce equation to primary master species, Fe+3.\n" + "ERROR: Could not reduce equation to primary master species, H2.\n" + "ERROR: Could not reduce equation to primary master species, Mn+3.\n" + "ERROR: Could not reduce equation to primary master species, NH4+.\n" + "ERROR: Could not reduce equation to primary master species, N2.\n" + "ERROR: Could not reduce equation to primary master species, NO2-.\n" + "ERROR: Could not reduce equation to primary master species, O2.\n" + "ERROR: Could not reduce equation to primary master species, HS-.\n" + "ERROR: Could not reduce equation to secondary master species, e-.\n" + "ERROR: Non-master species in secondary reaction, e-.\n" + "ERROR: No master species for element e.\n" + "ERROR: Could not find primary master species for e.\n" + "ERROR: No master species for element e.\n" + "ERROR: Could not reduce equation to secondary master species, Hausmannite.\n" + "ERROR: Could not reduce equation to secondary master species, Manganite.\n" + "ERROR: Could not reduce equation to secondary master species, Pyrite.\n" + "ERROR: Could not reduce equation to secondary master species, Pyrolusite.\n" + "ERROR: Could not reduce equation to secondary master species, Sulfur.\n" + "ERROR: e-, primary master species for E-, not defined.\n" + "ERROR: Calculations terminating due to input errors.\n"; + + const char* err = ::GetErrorString(n); + + ASSERT_EQ(std::string(expected), std::string(err)); + } + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestRunAccumulated) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "solution 12")); + ASSERT_EQ(0, ::GetOutputFileOn(n)); + ASSERT_EQ(0, ::GetErrorFileOn(n)); + ASSERT_EQ(0, ::GetLogFileOn(n)); + ASSERT_EQ(0, ::GetSelectedOutputFileOn(n)); + ASSERT_EQ(0, ::GetDumpFileOn(n)); + ASSERT_EQ(0, ::GetDumpStringOn(n)); + ASSERT_EQ(0, ::RunAccumulated(n)); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestRunWithErrors) +{ + const char dump_file[] = "error.inp"; + + // remove dump file if it exists + // + FileTest dump(dump_file); + ASSERT_TRUE(dump.RemoveExisting()); + + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "SOLUTION 1")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " pH 7")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Na 1")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "PHASES")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Fix_H+")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " H+ = H+")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " log_k 0")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "EQUILIBRIUM_PHASES")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Fix_H+ -10 HCl 10")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "END")); + ASSERT_EQ(0, ::GetOutputFileOn(n)); + ASSERT_EQ(0, ::GetErrorFileOn(n)); + ASSERT_EQ(0, ::GetLogFileOn(n)); + ASSERT_EQ(0, ::GetSelectedOutputFileOn(n)); + ASSERT_EQ(0, ::GetDumpFileOn(n)); + ASSERT_EQ(0, ::GetDumpStringOn(n)); + ASSERT_EQ(1, ::RunAccumulated(n)); + + const char expected[] = + "ERROR: Numerical method failed on all combinations of convergence parameters, cell/soln/mix 1\n"; + const char* err = ::GetErrorString(n); + + ASSERT_EQ(std::string(expected), std::string(err)); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } + ASSERT_TRUE(dump.VerifyExists()); +} + +TEST(TestIPhreeqcLib, TestRunFile) +{ + static const char dump_file[] = "error.inp"; + + // remove dump file if it exists + // + if (::FileExists(dump_file)) + { + ASSERT_TRUE(::DeleteFile(dump_file)); + } + ASSERT_EQ(false, ::FileExists(dump_file)); + + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(true, ::FileExists("phreeqc.dat")); + ASSERT_TRUE(::FileSize("phreeqc.dat") > 0); + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + ASSERT_EQ(0, ::GetOutputFileOn(n)); + ASSERT_EQ(0, ::GetErrorFileOn(n)); + ASSERT_EQ(0, ::GetLogFileOn(n)); + ASSERT_EQ(0, ::GetSelectedOutputFileOn(n)); + ASSERT_EQ(0, ::GetDumpFileOn(n)); + ASSERT_EQ(0, ::GetDumpStringOn(n)); + ASSERT_EQ(true, ::FileExists("conv_fail.in")); + ASSERT_TRUE(::FileSize("conv_fail.in") > 0); + ASSERT_EQ(1, ::RunFile(n, "conv_fail.in")); + + static const char expected[] = + "ERROR: Numerical method failed on all combinations of convergence parameters, cell/soln/mix 1\n"; + const char* err = ::GetErrorString(n); + + ASSERT_EQ(std::string(expected), std::string(err)); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } + + // Note: should this file exist since GetDumpFileOn is false? + ASSERT_EQ(true, ::FileExists(dump_file)); + ASSERT_TRUE(::FileSize(dump_file) > 0); + ASSERT_TRUE(::DeleteFile(dump_file)); +} + +TEST(TestIPhreeqcLib, TestRunString) +{ + const char input[] = + "TITLE Example 1.--Add uranium and speciate seawater.\n" + "SOLUTION 1 SEAWATER FROM NORDSTROM ET AL. (1979)\n" + " units ppm\n" + " pH 8.22\n" + " pe 8.451\n" + " density 1.023\n" + " temp 25.0\n" + " redox O(0)/O(-2)\n" + " Ca 412.3\n" + " Mg 1291.8\n" + " Na 10768.0\n" + " K 399.1\n" + " Fe 0.002\n" + " Mn 0.0002 pe\n" + " Si 4.28\n" + " Cl 19353.0\n" + " Alkalinity 141.682 as HCO3\n" + " S(6) 2712.0\n" + " N(5) 0.29 gfw 62.0\n" + " N(-3) 0.03 as NH4\n" + " U 3.3 ppb N(5)/N(-3)\n" + " O(0) 1.0 O2(g) -0.7\n" + "SOLUTION_MASTER_SPECIES\n" + " U U+4 0.0 238.0290 238.0290\n" + " U(4) U+4 0.0 238.0290\n" + " U(5) UO2+ 0.0 238.0290\n" + " U(6) UO2+2 0.0 238.0290\n" + "SOLUTION_SPECIES\n" + " #primary master species for U\n" + " #is also secondary master species for U(4)\n" + " U+4 = U+4\n" + " log_k 0.0\n" + " U+4 + 4 H2O = U(OH)4 + 4 H+\n" + " log_k -8.538\n" + " delta_h 24.760 kcal\n" + " U+4 + 5 H2O = U(OH)5- + 5 H+\n" + " log_k -13.147\n" + " delta_h 27.580 kcal\n" + " #secondary master species for U(5)\n" + " U+4 + 2 H2O = UO2+ + 4 H+ + e-\n" + " log_k -6.432\n" + " delta_h 31.130 kcal\n" + " #secondary master species for U(6)\n" + " U+4 + 2 H2O = UO2+2 + 4 H+ + 2 e-\n" + " log_k -9.217\n" + " delta_h 34.430 kcal\n" + " UO2+2 + H2O = UO2OH+ + H+\n" + " log_k -5.782\n" + " delta_h 11.015 kcal\n" + " 2UO2+2 + 2H2O = (UO2)2(OH)2+2 + 2H+\n" + " log_k -5.626\n" + " delta_h -36.04 kcal\n" + " 3UO2+2 + 5H2O = (UO2)3(OH)5+ + 5H+\n" + " log_k -15.641\n" + " delta_h -44.27 kcal\n" + " UO2+2 + CO3-2 = UO2CO3\n" + " log_k 10.064\n" + " delta_h 0.84 kcal\n" + " UO2+2 + 2CO3-2 = UO2(CO3)2-2\n" + " log_k 16.977\n" + " delta_h 3.48 kcal\n" + " UO2+2 + 3CO3-2 = UO2(CO3)3-4\n" + " log_k 21.397\n" + " delta_h -8.78 kcal\n" + "PHASES\n" + " Uraninite\n" + " UO2 + 4 H+ = U+4 + 2 H2O\n" + " log_k -3.490\n" + " delta_h -18.630 kcal\n" + "END\n" + "\n"; + + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + char OUTPUT_FILE[80]; + sprintf(OUTPUT_FILE, "phreeqc.%d.out", n); + + if (::FileExists(OUTPUT_FILE)) + { + ASSERT_TRUE(::DeleteFile(OUTPUT_FILE)); + } + ASSERT_EQ(false, ::FileExists(OUTPUT_FILE)); + + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + ::SetOutputFileOn(n, 1); + ::SetErrorFileOn(n, 0); + ::SetLogFileOn(n, 0); + ::SetSelectedOutputFileOn(n, 0); + ::SetDumpFileOn(n, 0); + ASSERT_EQ(false, ::FileExists(OUTPUT_FILE)); + ASSERT_EQ(0, ::RunString(n, input)); + ASSERT_EQ(true, ::FileExists(OUTPUT_FILE)); + ASSERT_TRUE(::FileSize(OUTPUT_FILE) > 0); + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } + if (::FileExists(OUTPUT_FILE)) + { + ASSERT_TRUE(::DeleteFile(OUTPUT_FILE)); + } +} + +TEST(TestIPhreeqcLib, TestGetSelectedOutputRowCount) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(true, ::FileExists("llnl.dat")); + ASSERT_TRUE(::FileSize("llnl.dat") > 0); + ASSERT_EQ(0, ::LoadDatabase(n, "llnl.dat")); + + int max = 6; + + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + ASSERT_EQ(IPQ_OK, ::EQUILIBRIUM_PHASES(n, "calcite", 0.0, 0.010)); + ASSERT_EQ(IPQ_OK, ::USER_PUNCH(n, "Ca", max)); + ASSERT_EQ(0, ::GetOutputFileOn(n)); + ASSERT_EQ(0, ::GetErrorFileOn(n)); + ASSERT_EQ(0, ::GetLogFileOn(n)); + ASSERT_EQ(0, ::GetSelectedOutputFileOn(n)); + ASSERT_EQ(0, ::GetDumpFileOn(n)); + ASSERT_EQ(0, ::GetDumpStringOn(n)); + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(3, ::GetSelectedOutputRowCount(n)); // rows + header + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} +#define USE_VAR +TEST(TestIPhreeqcLib, TestGetSelectedOutputValue) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(0, ::LoadDatabase(n, "llnl.dat")); + + int max = 6; + + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + ASSERT_EQ(IPQ_OK, ::EQUILIBRIUM_PHASES(n, "calcite", 0.0, 0.010)); + ASSERT_EQ(IPQ_OK, ::USER_PUNCH(n, "Ca", max)); + ASSERT_EQ(0, ::GetOutputFileOn(n)); + ASSERT_EQ(0, ::GetErrorFileOn(n)); + ASSERT_EQ(0, ::GetLogFileOn(n)); + ASSERT_EQ(0, ::GetSelectedOutputFileOn(n)); + ASSERT_EQ(0, ::GetDumpFileOn(n)); + ASSERT_EQ(0, ::GetDumpStringOn(n)); + ASSERT_EQ(0, ::RunAccumulated(n)); + + /* + EXPECTED selected.out: + sim state soln dist_x time step pH pe C Ca Na m_CO3-2 m_CaOH+ m_NaCO3- la_CO3-2 la_CaOH+ la_NaCO3- Calcite d_Calcite si_CO2(g) si_Siderite pressure total mol volume g_CO2(g) g_N2(g) k_Albite dk_Albite k_Pyrite dk_Pyrite s_CaSO4 s_SrSO4 1.name 1.type 1.moles 2.name 2.type 2.moles 3.name 3.type 3.moles 4.name 4.type 4.moles 5.name 5.type 5.moles 6.name 6.type 6.moles + 1 i_soln 1 -99 -99 -99 7 4 1.0000e-003 1.0000e-003 1.0000e-003 4.2975e-007 1.1819e-009 1.1881e-009 -6.4686e+000 -8.9530e+000 -8.9507e+000 0.0000e+000 0.0000e+000 -2.2870 -999.9990 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 Ca+2 aq 9.9178e-004 CaHCO3+ aq 7.5980e-006 CaCO3 aq 6.2155e-007 CaOH+ aq 1.1819e-009 + 1 react 1 -99 0 1 7.86135 10.18 1.1556e-003 1.1556e-003 1.0000e-003 4.2718e-006 9.7385e-009 1.1620e-008 -5.4781e+000 -8.0388e+000 -7.9621e+000 9.8444e-003 -1.5555e-004 -3.0192 -999.9990 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 calcite equi 9.8444e-003 Ca+2 aq 1.1371e-003 CaHCO3+ aq 1.1598e-005 CaCO3 aq 6.8668e-006 CaOH+ aq 9.7385e-009 + */ + +#if defined(USE_VAR) + VAR v; + ::VarInit(&v); +#else + CVar v; +#endif + + ASSERT_EQ(IPQ_INVALIDROW, ::GetSelectedOutputValue(n, -1, 0, &v)); + ASSERT_EQ(TT_ERROR, v.type); + ASSERT_EQ(VR_INVALIDROW, v.vresult); + + ASSERT_EQ(IPQ_INVALIDROW, ::GetSelectedOutputValue(n, ::GetSelectedOutputRowCount(n), 0, &v)); + ASSERT_EQ(TT_ERROR, v.type); + ASSERT_EQ(VR_INVALIDROW, v.vresult); + + ASSERT_EQ(IPQ_INVALIDCOL, ::GetSelectedOutputValue(n, 0, -1, &v)); + ASSERT_EQ(TT_ERROR, v.type); + ASSERT_EQ(VR_INVALIDCOL, v.vresult); + + ASSERT_EQ(IPQ_INVALIDCOL, ::GetSelectedOutputValue(n, 0, ::GetSelectedOutputColumnCount(n), &v)); + ASSERT_EQ(TT_ERROR, v.type); + ASSERT_EQ(VR_INVALIDCOL, v.vresult); + + + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, 0, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("sim"), std::string(v.sVal)); + + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, 1, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("state"), std::string(v.sVal)); + + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, 2, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("soln"), std::string(v.sVal)); + + //{{{{{{ + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, 3, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("dist_x"), std::string(v.sVal)); + + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, 4, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("time"), std::string(v.sVal)); + + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, 5, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("step"), std::string(v.sVal)); + + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, 6, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("pH"), std::string(v.sVal)); + + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, 7, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("pe"), std::string(v.sVal)); + + int col = 7; + + // -totals C Ca Na + ++col; + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("C(mol/kgw)"), std::string(v.sVal)); + ++col; + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("Ca(mol/kgw)"), std::string(v.sVal)); + ++col; + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("Na(mol/kgw)"), std::string(v.sVal)); + + // -molalities CO3-2 CaOH+ NaCO3- + ++col; + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("m_CO3-2(mol/kgw)"), std::string(v.sVal)); + ++col; + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("m_CaOH+(mol/kgw)"), std::string(v.sVal)); + ++col; + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("m_NaCO3-(mol/kgw)"), std::string(v.sVal)); + + // -activities CO3-2 CaOH+ NaCO3- + ++col; + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("la_CO3-2"), std::string(v.sVal)); + ++col; + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("la_CaOH+"), std::string(v.sVal)); + ++col; + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("la_NaCO3-"), std::string(v.sVal)); + + // -equilibrium_phases Calcite + ++col; + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("Calcite"), std::string(v.sVal)); + ++col; + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("d_Calcite"), std::string(v.sVal)); + + + // -saturation_indices CO2(g) Siderite + ++col; + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("si_CO2(g)"), std::string(v.sVal)); + ++col; + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("si_Siderite"), std::string(v.sVal)); + + // -gases CO2(g) N2(g) + // pressure "total mol" volume g_CO2(g) g_N2(g) + ++col; + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("pressure"), std::string(v.sVal)); + ++col; + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("total mol"), std::string(v.sVal)); + ++col; + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("volume"), std::string(v.sVal)); + ++col; + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("g_CO2(g)"), std::string(v.sVal)); + ++col; + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("g_N2(g)"), std::string(v.sVal)); + + // -kinetic_reactants Albite Pyrite + // k_Albite dk_Albite k_Pyrite dk_Pyrite + ++col; + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("k_Albite"), std::string(v.sVal)); + ++col; + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("dk_Albite"), std::string(v.sVal)); + ++col; + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("k_Pyrite"), std::string(v.sVal)); + ++col; + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("dk_Pyrite"), std::string(v.sVal)); + + // -solid_solutions CaSO4 SrSO4 + // s_CaSO4 s_SrSO4 + ++col; + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("s_CaSO4"), std::string(v.sVal)); + ++col; + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("s_SrSO4"), std::string(v.sVal)); + + for (int i = 0; i < max; ++i) + { + std::ostringstream oss1, oss2, oss3; + + // 1.name + // + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, col + 1 + (i * 3), &v)); + ASSERT_EQ(TT_STRING, v.type); + oss1 << i + 1 << ".name"; + ASSERT_EQ(oss1.str(), std::string(v.sVal)); + + // 1.type + // + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, col + 2 + (i * 3), &v)); + ASSERT_EQ(TT_STRING, v.type); + oss2 << i + 1 << ".type"; + ASSERT_EQ(oss2.str(), std::string(v.sVal)); + + // 1.moles + // + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, col + 3 + (i * 3), &v)); + ASSERT_EQ(TT_STRING, v.type); + oss3 << i + 1 << ".moles"; + ASSERT_EQ(oss3.str(), std::string(v.sVal)); + } + + // sim + // + col = 0; + // i_soln + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, col, &v)); + ASSERT_EQ(TT_LONG, v.type); + ASSERT_EQ(1L, v.lVal); + // react + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, col, &v)); + ASSERT_EQ(TT_LONG, v.type); + ASSERT_EQ(1L, v.lVal); + + // state + // + ++col; + // i_soln + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("i_soln"), std::string(v.sVal)); + // react + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("react"), std::string(v.sVal)); + + // soln + // + ++col; + // i_soln + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, col, &v)); + ASSERT_EQ(TT_LONG, v.type); + ASSERT_EQ(1L, v.lVal); + // react + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, col, &v)); + ASSERT_EQ(TT_LONG, v.type); + ASSERT_EQ(1L, v.lVal); + + // dist_x -- sometimes as double sometimes as long (depends on state) + // + ++col; + // i_soln + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_EQ(-99., v.dVal); + // react + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_EQ(-99., v.dVal); + + + // time -- sometimes as double sometimes as long (depends on state) + // + ++col; + // i_soln + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_EQ(-99., v.dVal); + // react + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + //CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, v.dVal, ::pow(10., -DBL_DIG)); + ASSERT_NEAR(0.0, v.dVal, ::pow(10., -DBL_DIG)); + ASSERT_DOUBLE_EQ(0.0, v.dVal); + + // step + // + ++col; + // i_soln + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, col, &v)); + ASSERT_EQ(TT_LONG, v.type); + ASSERT_EQ(-99L, v.lVal); + // react + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, col, &v)); + ASSERT_EQ(TT_LONG, v.type); + ASSERT_EQ(1L, v.lVal); + + + // pH + // + ++col; + // i_soln + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(7.0, v.dVal, ::pow(10., -DBL_DIG)); + // react + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(7.861354, v.dVal, ::pow(10., -6)); + + // pe + // + ++col; + // i_soln + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(4.0, v.dVal, ::pow(10., -DBL_DIG)); + // react + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + // COMMENT: {8/8/2013 3:38:12 PM} ASSERT_NEAR( 9.90852, v.dVal, ::pow(10., -1) ); + + // + // -totals C Ca Na + // + + // C(mol/kgw) + // + ++col; + // i_soln + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(1.0000e-003, v.dVal, ::pow(10., -DBL_DIG)); + // react + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(1.1556e-003, v.dVal, ::pow(10., -7)); + + + // Ca(mol/kgw) + // + ++col; + // i_soln + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(1.0000e-003, v.dVal, ::pow(10., -DBL_DIG)); + // react + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(1.1556e-003, v.dVal, ::pow(10., -7)); + + + // Na(mol/kgw) + // + ++col; + // i_soln + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(1.0000e-003, v.dVal, ::pow(10., -DBL_DIG)); + // react + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(1.0000e-003, v.dVal, ::pow(10., -7)); + + // -molalities CO3-2 CaOH+ NaCO3- + col += 3; + + // -activities CO3-2 CaOH+ NaCO3- + col += 3; + + // -equilibrium_phases Calcite + col += 2; + + // -saturation_indices CO2(g) Siderite + col += 2; + + // -gases CO2(g) N2(g) + col += 5; + + // -kinetic_reactants Albite Pyrite + // k_Albite dk_Albite k_Pyrite dk_Pyrite + col += 4; + + // -solid_solutions CaSO4 SrSO4 + // s_CaSO4 s_SrSO4 + col += 2; + + + // 1.name + // + ++col; + // i_soln + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("Ca+2"), std::string(v.sVal)); + // react + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("Calcite"), std::string(v.sVal)); + + // 1.type + // + ++col; + // i_soln + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("aq"), std::string(v.sVal)); + // react + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("equi"), std::string(v.sVal)); + + // 1.moles + // + ++col; + // i_soln + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(9.9177923E-04, v.dVal, ::pow(10., -11)); + // react + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(9.8444477E-03, v.dVal, ::pow(10., -10)); + + // 2.name + // + ++col; + // i_soln + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("CaHCO3+"), std::string(v.sVal)); + // react + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("Ca+2"), std::string(v.sVal)); + + // 2.type + // + ++col; + // i_soln + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("aq"), std::string(v.sVal)); + // react + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("aq"), std::string(v.sVal)); + + // 2.moles + // + ++col; + // i_soln + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(7.5980e-006, v.dVal, ::pow(10., -10)); + // react + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(1.1371e-003, v.dVal, ::pow(10., -7)); + + + // 3.name + // + ++col; + // i_soln + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("CaCO3"), std::string(v.sVal)); + // react + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("CaHCO3+"), std::string(v.sVal)); + + // 3.type + // + ++col; + // i_soln + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("aq"), std::string(v.sVal)); + // react + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("aq"), std::string(v.sVal)); + + // 3.moles + // + ++col; + // i_soln + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(6.2155e-007, v.dVal, ::pow(10., -11)); + // react + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(1.1598e-005, v.dVal, ::pow(10., -9)); + + + + // 4.name + // + ++col; + // i_soln + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("CaOH+"), std::string(v.sVal)); + // react + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("CaCO3"), std::string(v.sVal)); + + // 4.type + // + ++col; + // i_soln + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("aq"), std::string(v.sVal)); + // react + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("aq"), std::string(v.sVal)); + + // 4.moles + // + ++col; + // i_soln + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(1.1819e-009, v.dVal, ::pow(10., -13)); + // react + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(6.8668e-006, v.dVal, ::pow(10., -10)); + + + // 5.name + // + ++col; + // i_soln + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, col, &v)); + ASSERT_EQ(TT_EMPTY, v.type); + // react + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("CaOH+"), std::string(v.sVal)); + + // 5.type + // + ++col; + // i_soln + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, col, &v)); + ASSERT_EQ(TT_EMPTY, v.type); + // react + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, col, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("aq"), std::string(v.sVal)); + + // 5.moles + // + ++col; + // i_soln + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, col, &v)); + ASSERT_EQ(TT_EMPTY, v.type); + // react + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, col, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(9.7385e-009, v.dVal, ::pow(10., -13)); + + + // 6.name + // + ++col; + // i_soln + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, col, &v)); + ASSERT_EQ(TT_EMPTY, v.type); + // react + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, col, &v)); + ASSERT_EQ(TT_EMPTY, v.type); + + // 6.type + // + ++col; + // i_soln + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, col, &v)); + ASSERT_EQ(TT_EMPTY, v.type); + // react + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, col, &v)); + ASSERT_EQ(TT_EMPTY, v.type); + + // 6.moles + // + ++col; + // i_soln + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, col, &v)); + ASSERT_EQ(TT_EMPTY, v.type); + // react + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, col, &v)); + ASSERT_EQ(TT_EMPTY, v.type); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } + +#if defined(USE_VAR) + ::VarClear(&v); +#endif +} + +IPQ_RESULT +SOLUTION(int n, double C, double Ca, double Na) +{ + std::ostringstream oss; + + oss << "SOLUTION 1\n"; + oss << "C " << C << "\n"; + oss << "Ca " << Ca << "\n"; + oss << "Na " << Na << "\n"; + + return ::AccumulateLine(n, oss.str().c_str()); +} + +IPQ_RESULT +EQUILIBRIUM_PHASES(int n, const char* phase, double si, double amount) +{ + std::ostringstream oss; + + oss << "EQUILIBRIUM_PHASES\n"; + oss << phase << " " << si << " " << amount << "\n"; + return ::AccumulateLine(n, oss.str().c_str()); +} + +IPQ_RESULT +USER_PUNCH(int n, const char* element, int max) +{ + std::ostringstream oss; + + oss << "USER_PUNCH\n"; + + oss << "-head "; + for (int i = 1; i <= max; ++i) + { + oss << i << ".name " << i << ".type " << i << ".moles "; + } + oss << "\n"; + oss << "-start" << "\n"; + oss << "10 n = sys(\"" << element << "\"" << ", count, names$, types$, moles)" << "\n"; + oss << "20 n = " << max << "\n"; + oss << "30 if count < " << max << " then n = count" << "\n"; + oss << "40 for i = 1 to count" << "\n"; + oss << "50 PUNCH names$(i), types$(i), moles(i)" << "\n"; + oss << "60 next i" << "\n"; + oss << "70 list" << "\n"; + oss << "-end" << "\n"; + oss << "SELECTED_OUTPUT" << "\n"; + oss << "-totals C Ca Na" << "\n"; + oss << "-molalities CO3-2 CaOH+ NaCO3-" << "\n"; + oss << "-activities CO3-2 CaOH+ NaCO3-" << "\n"; + oss << "-equilibrium_phases Calcite" << "\n"; + oss << "-saturation_indices CO2(g) Siderite" << "\n"; + oss << "-gases CO2(g) N2(g)" << "\n"; + oss << "-kinetic_reactants Albite Pyrite" << "\n"; + oss << "-solid_solutions CaSO4 SrSO4" << "\n"; + + return ::AccumulateLine(n, oss.str().c_str()); +} + +IPQ_RESULT +USER_PUNCH_NEH(int n) +{ + std::ostringstream oss; + + oss << "USER_PUNCH\n"; + + oss << "-head head0 head1 head2\n"; + oss << "-start" << "\n"; + oss << "10 PUNCH \"have0\", \"have1\", \"have2\"" << "\n"; + oss << "20 PUNCH \"missing0\", \"missing1\", \"missing2\"" << "\n"; + oss << "-end" << "\n"; + oss << "SELECTED_OUTPUT" << "\n"; + oss << "-totals C Ca Na" << "\n"; + oss << "-molalities CO3-2 CaOH+ NaCO3-" << "\n"; + oss << "-activities CO3-2 CaOH+ NaCO3-" << "\n"; + oss << "-equilibrium_phases Calcite" << "\n"; + oss << "-saturation_indices CO2(g) Siderite" << "\n"; + oss << "-gases CO2(g) N2(g)" << "\n"; + oss << "-kinetic_reactants Albite Pyrite" << "\n"; + oss << "-solid_solutions CaSO4 SrSO4" << "\n"; + + return ::AccumulateLine(n, oss.str().c_str()); +} + + +IPQ_RESULT +SELECTED_OUTPUT(int n) +{ + std::ostringstream oss; + + oss << "SELECTED_OUTPUT" << "\n"; + oss << "-totals C Ca Na" << "\n"; + + return ::AccumulateLine(n, oss.str().c_str()); +} + +IPQ_RESULT +DUMP(int n) +{ + std::ostringstream oss; + oss << "DUMP" << "\n"; + oss << "-solution 1" << "\n"; + return ::AccumulateLine(n, oss.str().c_str()); +} + +TEST(TestIPhreeqcLib, TestGetSelectedOutputColumnCount) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(0, ::LoadDatabase(n, "llnl.dat")); + ASSERT_EQ(0, ::GetSelectedOutputColumnCount(n)); + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + ASSERT_EQ(IPQ_OK, ::EQUILIBRIUM_PHASES(n, "calcite", 1.0, 1.0)); + ASSERT_EQ(IPQ_OK, ::USER_PUNCH(n, "Ca", 10)); + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(62, ::GetSelectedOutputColumnCount(n)); + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestAddError) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + + // make sure initialized to empty + // + const char* err = ::GetErrorString(n); + ASSERT_EQ(std::string(""), std::string(err)); + + // make sure initialized to empty + // + const char* expected = "TESTING AddError\n"; + ASSERT_EQ(1, ::AddError(n, expected)); + + // check 1 + // + err = ::GetErrorString(n); + ASSERT_EQ(std::string(expected), std::string(err)); + + // check increment + // + const char* expected2 = "XXXXXX\n"; + ASSERT_EQ(2, ::AddError(n, expected2)); + + // check concatenation + // + err = ::GetErrorString(n); + ASSERT_EQ(std::string(expected) + std::string(expected2), std::string(err)); + + + // clear errors + // + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + + // make sure back to empty + // + err = ::GetErrorString(n); + ASSERT_EQ(std::string(""), std::string(err)); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestAccumulateLine) +{ + // TODO +} + +TEST(TestIPhreeqcLib, TestOutputErrorString) +{ + // TODO +} + +TEST(TestIPhreeqcLib, TestRunWithCallback) +{ + // TODO +} + +TEST(TestIPhreeqcLib, TestRunNoDatabaseLoaded) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(1, ::RunAccumulated(n)); + + const char expected[] = + "ERROR: RunAccumulated: No database is loaded\n"; + const char* err = ::GetErrorString(n); + + ASSERT_EQ(std::string(expected), std::string(err)); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestCase1) +{ + // Case 1 (see do_run) + // pr.punch == TRUE + // punch.new_def == FALSE + // output_isopen(OUTPUT_PUNCH) == FALSE + // selected_output_on == TRUE + + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + char SELECTED_OUT[80]; + sprintf(SELECTED_OUT, "selected_1.%d.out", n); + + // remove punch file if it exists + if (::FileExists(SELECTED_OUT)) + { + ASSERT_TRUE(::DeleteFile(SELECTED_OUT)); + } + ASSERT_EQ(false, ::FileExists(SELECTED_OUT)); + ASSERT_EQ(true, ::FileExists("phreeqc.dat")); + ASSERT_TRUE(::FileSize("phreeqc.dat") > 0); + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + ASSERT_EQ(IPQ_OK, ::USER_PUNCH(n, "Ca", 10)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 1)); + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(true, ::FileExists(SELECTED_OUT)); + ASSERT_TRUE(::FileSize(SELECTED_OUT) > 0); + ASSERT_EQ(62, ::GetSelectedOutputColumnCount(n)); + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 1)); + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(true, ::FileExists(SELECTED_OUT)); + ASSERT_TRUE(::FileSize(SELECTED_OUT) > 0); + ASSERT_EQ(62, ::GetSelectedOutputColumnCount(n)); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestCase2) +{ + // Case 2 (see do_run) + // pr.punch == TRUE + // punch.new_def == TRUE + // output_isopen(OUTPUT_PUNCH) == FALSE + // selected_output_on == TRUE + + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + char SELECTED_OUT[80]; + sprintf(SELECTED_OUT, "selected_1.%d.out", n); + + // remove punch files if they exists + // + if (::FileExists(SELECTED_OUT)) + { + ASSERT_TRUE(::DeleteFile(SELECTED_OUT)); + } + if (::FileExists("case2.punch")) + { + ASSERT_TRUE(::DeleteFile("case2.punch")); + } + ASSERT_EQ(false, ::FileExists(SELECTED_OUT)); + ASSERT_EQ(false, ::FileExists("case2.punch")); + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + ASSERT_EQ(IPQ_OK, ::USER_PUNCH(n, "Ca", 10)); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "-file case2.punch")); // force have_punch_name to TRUE (see read_selected_ouput) + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 1)); + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(false, ::FileExists(SELECTED_OUT)); + ASSERT_EQ(true, ::FileExists("case2.punch")); + ASSERT_TRUE(::FileSize("case2.punch") > 0); + ASSERT_EQ(62, ::GetSelectedOutputColumnCount(n)); + + + // remove punch files if they exists + // + if (::FileExists(SELECTED_OUT)) + { + ASSERT_TRUE(::DeleteFile(SELECTED_OUT)); + } + if (::FileExists("case2.punch")) + { + ASSERT_TRUE(::DeleteFile("case2.punch")); + } + ASSERT_EQ(false, ::FileExists(SELECTED_OUT)); + ASSERT_EQ(false, ::FileExists("case2.punch")); + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + ASSERT_EQ(IPQ_OK, ::USER_PUNCH(n, "Ca", 10)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 1)); + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(false, ::FileExists(SELECTED_OUT)); + ASSERT_EQ(true, ::FileExists("case2.punch")); + ASSERT_TRUE(::FileSize("case2.punch") > 0); + ASSERT_EQ(62, ::GetSelectedOutputColumnCount(n)); + + if (::FileExists("case2.punch")) + { + ASSERT_TRUE(::DeleteFile("case2.punch")); + } + ASSERT_EQ(false, ::FileExists("case2.punch")); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestPrintSelectedOutputFalse) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + // remove punch files if they exists + // + if (::FileExists("selected.out")) + { + ::DeleteFile("selected.out"); + } + ASSERT_EQ(false, ::FileExists("selected.out")); + + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + + // add selected output block + ASSERT_EQ(IPQ_OK, ::SELECTED_OUTPUT(n)); + + // turn off selected output + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "PRINT; -selected_output false \n")); + + // run + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 1)); + ASSERT_EQ(0, ::RunAccumulated(n)); + + ASSERT_EQ(0, ::GetSelectedOutputColumnCount(n)); + ASSERT_EQ(0, ::GetSelectedOutputRowCount(n)); + + + // reset pr.punch to TRUE + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + + // add selected output block + ASSERT_EQ(IPQ_OK, ::SELECTED_OUTPUT(n)); + + // run + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 1)); + ASSERT_EQ(0, ::RunAccumulated(n)); + + ASSERT_EQ(11, ::GetSelectedOutputColumnCount(n)); + ASSERT_EQ(2, ::GetSelectedOutputRowCount(n)); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestOutputFileOnOff) +{ + int onoff[5]; + onoff[0] = 1; // output_file_on + onoff[1] = 0; // error_file_on + onoff[2] = 0; // log_file_on + onoff[3] = 0; // selected_output_file_on + onoff[4] = 0; // dump_file_on + TestFileOnOff("phreeqc.%d.out", onoff[0], onoff[1], onoff[2], onoff[3], onoff[4]); +} + +TEST(TestIPhreeqcLib, TestErrorFileOnOff) +{ + int onoff[5]; + onoff[0] = 0; // output_file_on + onoff[1] = 1; // error_file_on + onoff[2] = 0; // log_file_on + onoff[3] = 0; // selected_output_file_on + onoff[4] = 0; // dump_file_on + TestFileOnOff("phreeqc.%d.err", onoff[0], onoff[1], onoff[2], onoff[3], onoff[4]); +} + +TEST(TestIPhreeqcLib, TestLogFileOnOff) +{ + int onoff[5]; + onoff[0] = 0; // output_file_on + onoff[1] = 0; // error_file_on + onoff[2] = 1; // log_file_on + onoff[3] = 0; // selected_output_file_on + onoff[4] = 0; // dump_file_on + TestFileOnOff("phreeqc.%d.log", onoff[0], onoff[1], onoff[2], onoff[3], onoff[4]); +} + +TEST(TestIPhreeqcLib, TestDumpFileOnOff) +{ + int onoff[5]; + onoff[0] = 0; // output_file_on + onoff[1] = 0; // error_file_on + onoff[2] = 0; // log_file_on + onoff[3] = 0; // selected_output_file_on + onoff[4] = 1; // dump_file_on + TestFileOnOff("dump.%d.out", onoff[0], onoff[1], onoff[2], onoff[3], onoff[4]); +} + +TEST(TestIPhreeqcLib, TestSelOutFileOnOff) +{ + int onoff[5]; + onoff[0] = 0; // output_file_on + onoff[1] = 0; // error_file_on + onoff[2] = 0; // log_file_on + onoff[3] = 1; // selected_output_file_on + onoff[4] = 0; // dump_file_on + TestFileOnOff("selected_1.%d.out", onoff[0], onoff[1], onoff[2], onoff[3], onoff[4]); +} + +//void TestIPhreeqcLib::TestFileOnOff(const char* FILENAME_FORMAT, int output_file_on, int error_file_on, int log_file_on, int selected_output_file_on, int dump_file_on) +void TestFileOnOff(const char* FILENAME_FORMAT, int output_file_on, int error_file_on, int log_file_on, int selected_output_file_on, int dump_file_on) +{ + int dump_string_on = 0; + + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + char FILENAME[80]; + sprintf(FILENAME, FILENAME_FORMAT, n); + + // remove FILENAME if it exists + // + if (::FileExists(FILENAME)) + { + ::DeleteFile(FILENAME); + } + ASSERT_EQ(false, ::FileExists(FILENAME)); + + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + + // add selected output block + ASSERT_EQ(IPQ_OK, ::SELECTED_OUTPUT(n)); + + // add dump block + ASSERT_EQ(IPQ_OK, ::DUMP(n)); + + // run all off + ASSERT_EQ(IPQ_OK, ::SetDumpFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetErrorFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetLogFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpStringOn(n, 0)); + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(false, ::FileExists(FILENAME)); + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + + // add selected output block + ASSERT_EQ(IPQ_OK, ::SELECTED_OUTPUT(n)); + + // add dump block + ASSERT_EQ(IPQ_OK, ::DUMP(n)); + + // run + ASSERT_EQ(IPQ_OK, ::SetDumpFileOn(n, dump_file_on)); + ASSERT_EQ(IPQ_OK, ::SetErrorFileOn(n, error_file_on)); + ASSERT_EQ(IPQ_OK, ::SetLogFileOn(n, log_file_on)); + ASSERT_EQ(IPQ_OK, ::SetOutputFileOn(n, output_file_on)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, selected_output_file_on)); + ASSERT_EQ(IPQ_OK, ::SetDumpStringOn(n, dump_string_on)); + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(true, ::FileExists(FILENAME)); + ASSERT_TRUE(::DeleteFile(FILENAME)); + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + + // add selected output block + ASSERT_EQ(IPQ_OK, ::SELECTED_OUTPUT(n)); + + // add dump block + ASSERT_EQ(IPQ_OK, ::DUMP(n)); + + // run + ASSERT_EQ(IPQ_OK, ::SetDumpFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetErrorFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetLogFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpStringOn(n, 0)); + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(false, ::FileExists(FILENAME)); + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + + // add selected output block + ASSERT_EQ(IPQ_OK, ::SELECTED_OUTPUT(n)); + + // add dump block + ASSERT_EQ(IPQ_OK, ::DUMP(n)); + + // run + ASSERT_EQ(IPQ_OK, ::SetDumpFileOn(n, dump_file_on)); + ASSERT_EQ(IPQ_OK, ::SetErrorFileOn(n, error_file_on)); + ASSERT_EQ(IPQ_OK, ::SetLogFileOn(n, log_file_on)); + ASSERT_EQ(IPQ_OK, ::SetOutputFileOn(n, output_file_on)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, selected_output_file_on)); + ASSERT_EQ(IPQ_OK, ::SetDumpStringOn(n, dump_string_on)); + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(true, ::FileExists(FILENAME)); + ASSERT_TRUE(::DeleteFile(FILENAME)); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + + +TEST(TestIPhreeqcLib, TestLongHeadings) +{ + char long_header[] = "this_is_a_long_header_0123456789012345678901234567890123456789"; + char long_value[] = "this_is_a_long_value_01234567890123456789012345678901234567890"; + + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + + std::ostringstream oss; + oss << "SOLUTION" << "\n"; + + oss << "SELECTED_OUTPUT" << "\n"; + oss << "-reset false" << "\n"; + + oss << "USER_PUNCH" << "\n"; + oss << "-head " << long_header << "\n"; + oss << "-start" << "\n"; + oss << "10 PUNCH \"" << long_value << "\"\n"; + oss << "-end" << "\n"; + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, oss.str().c_str())); + + ASSERT_EQ(IPQ_OK, ::SetOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetErrorFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetLogFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpFileOn(n, 0)); + ASSERT_EQ(0, ::RunAccumulated(n)); + + ASSERT_EQ(2, ::GetSelectedOutputRowCount(n)); + ASSERT_EQ(1, ::GetSelectedOutputColumnCount(n)); + + CVar v; + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, 0, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string(long_header), std::string(v.sVal)); + + CVar v1; + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, 0, &v1)); + ASSERT_EQ(TT_STRING, v1.type); + ASSERT_EQ(std::string(long_value), std::string(v1.sVal)); + + ASSERT_EQ(IPQ_INVALIDCOL, ::GetSelectedOutputValue(n, 1, 1, &v1)); + ASSERT_EQ(IPQ_INVALIDROW, ::GetSelectedOutputValue(n, 2, 0, &v1)); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestDatabaseKeyword) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + ASSERT_EQ(IPQ_OK, ::SetOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetErrorFileOn(n, 1)); + ASSERT_EQ(IPQ_OK, ::SetLogFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpFileOn(n, 0)); + ASSERT_EQ(1, ::RunFile(n, "dump")); + + const char* exp_errs = + "ERROR: Gas not found in PHASES database, Amm(g).\n" + "ERROR: Calculations terminating due to input errors.\n"; + + const char* err = ::GetErrorString(n); + ASSERT_EQ(std::string(exp_errs), std::string(err)); + + const char* exp_warn = + "WARNING: DATABASE keyword is ignored by IPhreeqc.\n" + "WARNING: Cell-lengths were read for 1 cells. Last value is used till cell 100.\n" + "WARNING: No dispersivities were read; disp = 0 assumed.\n" + "WARNING: Could not find element in database, Amm.\n" + " Concentration is set to zero.\n"; + + const char* warn = ::GetWarningString(n); + ASSERT_EQ(std::string(exp_warn), std::string(warn)); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestDumpString) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(IPQ_OK, ::DUMP(n)); + + // run + ASSERT_EQ(IPQ_OK, ::SetOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetErrorFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetLogFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpStringOn(n, 1)); + ASSERT_EQ(0, ::RunAccumulated(n)); + + const char* dump_str = ::GetDumpString(n); + + ASSERT_TRUE(::strstr(dump_str, "SOLUTION_RAW") != NULL); + ASSERT_TRUE(::strstr(dump_str, "-temp") != NULL); + ASSERT_TRUE(::strstr(dump_str, "-total_h") != NULL); + ASSERT_TRUE(::strstr(dump_str, "-total_o") != NULL); + ASSERT_TRUE(::strstr(dump_str, "-cb") != NULL); + ASSERT_TRUE(::strstr(dump_str, "-totals") != NULL); + ASSERT_TRUE(::strstr(dump_str, " C(4) ") != NULL); + ASSERT_TRUE(::strstr(dump_str, " Ca ") != NULL); + ASSERT_TRUE(::strstr(dump_str, " H(0) ") != NULL); + ASSERT_TRUE(::strstr(dump_str, " Na ") != NULL); + ASSERT_TRUE(::strstr(dump_str, "-pH") != NULL); + ASSERT_TRUE(::strstr(dump_str, "-pe") != NULL); + ASSERT_TRUE(::strstr(dump_str, "-mu") != NULL); + ASSERT_TRUE(::strstr(dump_str, "-ah2o") != NULL); + ASSERT_TRUE(::strstr(dump_str, "-mass_water") != NULL); + ASSERT_TRUE(::strstr(dump_str, "-total_alkalinity") != NULL); + ASSERT_TRUE(::strstr(dump_str, "-activities") != NULL); + ASSERT_TRUE(::strstr(dump_str, " C(-4) ") != NULL); + ASSERT_TRUE(::strstr(dump_str, " C(4) ") != NULL); + ASSERT_TRUE(::strstr(dump_str, " Ca ") != NULL); + ASSERT_TRUE(::strstr(dump_str, " E ") != NULL); + ASSERT_TRUE(::strstr(dump_str, " H(0) ") != NULL); + ASSERT_TRUE(::strstr(dump_str, " Na ") != NULL); + ASSERT_TRUE(::strstr(dump_str, " O(0) ") != NULL); + ASSERT_TRUE(::strstr(dump_str, "-gammas") != NULL); + ASSERT_TRUE(::strstr(dump_str, "USE mix none") != NULL); + ASSERT_TRUE(::strstr(dump_str, "USE reaction none") != NULL); + ASSERT_TRUE(::strstr(dump_str, "USE reaction_temperature none") != NULL); + ASSERT_TRUE(::strstr(dump_str, "USE reaction_pressure none") != NULL); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestGetDumpStringLineCount) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(IPQ_OK, ::DUMP(n)); + + // run + ASSERT_EQ(IPQ_OK, ::SetOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetErrorFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetLogFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpStringOn(n, 1)); + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(33, ::GetDumpStringLineCount(n)); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestGetDumpStringLine) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(IPQ_OK, ::DUMP(n)); + + // run + ASSERT_EQ(IPQ_OK, ::SetOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetErrorFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetLogFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpStringOn(n, 1)); + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(33, ::GetDumpStringLineCount(n)); + + int line = 0; + + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), "SOLUTION_RAW") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), "-temp") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), "-pressure") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), "-potential") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), "-total_h") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), "-total_o") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), "-cb") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), "-density") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), "-totals") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), " C(4) ") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), " Ca ") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), " H(0) ") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), " Na ") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), "-pH") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), "-pe") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), "-mu") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), "-ah2o") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), "-mass_water") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), "-soln_vol") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), "-total_alkalinity") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), "-activities") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), " C(-4) ") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), " C(4) ") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), " Ca ") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), " E ") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), " H(0) ") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), " Na ") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), " O(0) ") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), "-gammas") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), "USE mix none") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), "USE reaction none") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), "USE reaction_temperature none") != NULL); + ASSERT_TRUE(::strstr(::GetDumpStringLine(n, line++), "USE reaction_pressure none") != NULL); + + // remaining lines should be empty + ASSERT_EQ(std::string(""), std::string(::GetDumpStringLine(n, line++))); + ASSERT_EQ(std::string(""), std::string(::GetDumpStringLine(n, line++))); + ASSERT_EQ(std::string(""), std::string(::GetDumpStringLine(n, line++))); + ASSERT_EQ(std::string(""), std::string(::GetDumpStringLine(n, line++))); + + // negative lines should be empty + ASSERT_EQ(std::string(""), std::string(::GetDumpStringLine(n, -1))); + ASSERT_EQ(std::string(""), std::string(::GetDumpStringLine(n, -2))); + ASSERT_EQ(std::string(""), std::string(::GetDumpStringLine(n, -3))); + ASSERT_EQ(std::string(""), std::string(::GetDumpStringLine(n, -4))); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestGetComponentCount) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + + // run + ASSERT_EQ(IPQ_OK, ::SetOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetErrorFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetLogFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpStringOn(n, 0)); + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(3, ::GetComponentCount(n)); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestGetComponent) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + + // run + ASSERT_EQ(IPQ_OK, ::SetOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetErrorFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetLogFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpStringOn(n, 0)); + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(3, ::GetComponentCount(n)); + + ASSERT_EQ(std::string(""), std::string(::GetComponent(n, -2))); + ASSERT_EQ(std::string(""), std::string(::GetComponent(n, -1))); + + ASSERT_EQ(std::string("C"), std::string(::GetComponent(n, 0))); + ASSERT_EQ(std::string("Ca"), std::string(::GetComponent(n, 1))); + ASSERT_EQ(std::string("Na"), std::string(::GetComponent(n, 2))); + + ASSERT_EQ(std::string(""), std::string(::GetComponent(n, 3))); + ASSERT_EQ(std::string(""), std::string(::GetComponent(n, 4))); + ASSERT_EQ(std::string(""), std::string(::GetComponent(n, 5))); + + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + + // run + ASSERT_EQ(IPQ_OK, ::SetOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetErrorFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetLogFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpStringOn(n, 0)); + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(3, ::GetComponentCount(n)); + + ASSERT_EQ(std::string(""), std::string(::GetComponent(n, -2))); + ASSERT_EQ(std::string(""), std::string(::GetComponent(n, -1))); + + ASSERT_EQ(std::string("C"), std::string(::GetComponent(n, 0))); + ASSERT_EQ(std::string("Ca"), std::string(::GetComponent(n, 1))); + ASSERT_EQ(std::string("Na"), std::string(::GetComponent(n, 2))); + + ASSERT_EQ(std::string(""), std::string(::GetComponent(n, 3))); + ASSERT_EQ(std::string(""), std::string(::GetComponent(n, 4))); + ASSERT_EQ(std::string(""), std::string(::GetComponent(n, 5))); + + // clear using LoadDatabase + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + ASSERT_EQ(0, ::GetComponentCount(n)); + + ASSERT_EQ(std::string(""), std::string(::GetComponent(n, -2))); + ASSERT_EQ(std::string(""), std::string(::GetComponent(n, -1))); + + ASSERT_EQ(std::string(""), std::string(::GetComponent(n, 0))); + ASSERT_EQ(std::string(""), std::string(::GetComponent(n, 1))); + + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(3, ::GetComponentCount(n)); + + ASSERT_EQ(std::string(""), std::string(::GetComponent(n, -2))); + ASSERT_EQ(std::string(""), std::string(::GetComponent(n, -1))); + + ASSERT_EQ(std::string("C"), std::string(::GetComponent(n, 0))); + ASSERT_EQ(std::string("Ca"), std::string(::GetComponent(n, 1))); + ASSERT_EQ(std::string("Na"), std::string(::GetComponent(n, 2))); + + ASSERT_EQ(std::string(""), std::string(::GetComponent(n, 3))); + ASSERT_EQ(std::string(""), std::string(::GetComponent(n, 4))); + ASSERT_EQ(std::string(""), std::string(::GetComponent(n, 5))); + + + // clear using LoadDatabaseString + ASSERT_EQ(0, ::LoadDatabaseString(n, ex15_dat)); + ASSERT_EQ(0, ::GetComponentCount(n)); + + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + ASSERT_EQ(0, ::RunAccumulated(n)); + + // ex15.dat doesn't have Ca + ASSERT_EQ(2, ::GetWarningStringLineCount(n)); + ASSERT_EQ(std::string("WARNING: Could not find element in database, Ca."), std::string(::GetWarningStringLine(n, 0))); + ASSERT_EQ(std::string("\tConcentration is set to zero."), std::string(::GetWarningStringLine(n, 1))); + + ASSERT_EQ(2, ::GetComponentCount(n)); + + ASSERT_EQ(std::string(""), std::string(::GetComponent(n, -2))); + ASSERT_EQ(std::string(""), std::string(::GetComponent(n, -1))); + + ASSERT_EQ(std::string("C"), std::string(::GetComponent(n, 0))); + ASSERT_EQ(std::string("Na"), std::string(::GetComponent(n, 1))); + + ASSERT_EQ(std::string(""), std::string(::GetComponent(n, 2))); + ASSERT_EQ(std::string(""), std::string(::GetComponent(n, 3))); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestGetErrorStringLine) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + ASSERT_EQ(IPQ_OK, ::SetOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetErrorFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetLogFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpFileOn(n, 0)); + ASSERT_EQ(1, ::RunFile(n, "dump")); +#if 0 + ASSERT_EQ(8, ::GetErrorStringLineCount(n)); +#else + ASSERT_EQ(2, ::GetErrorStringLineCount(n)); +#endif + + int line = 0; +#if 0 + ASSERT_EQ(std::string("WARNING: DATABASE keyword is ignored by IPhreeqc."), std::string(::GetErrorStringLine(n, line++))); + ASSERT_EQ(std::string("WARNING: Cell-lengths were read for 1 cells. Last value is used till cell 100."), std::string(::GetErrorStringLine(n, line++))); + ASSERT_EQ(std::string("WARNING: No dispersivities were read; disp = 0 assumed."), std::string(::GetErrorStringLine(n, line++))); +#endif + ASSERT_EQ(std::string("ERROR: Gas not found in PHASES database, Amm(g)."), std::string(::GetErrorStringLine(n, line++))); +#if 0 + ASSERT_EQ(std::string("WARNING: Could not find element in database, Amm."), std::string(::GetErrorStringLine(n, line++))); + ASSERT_EQ(std::string("\tConcentration is set to zero."), std::string(::GetErrorStringLine(n, line++))); +#endif + ASSERT_EQ(std::string("ERROR: Calculations terminating due to input errors."), std::string(::GetErrorStringLine(n, line++))); +#if 0 + ASSERT_EQ(std::string("Stopping."), std::string(::GetErrorStringLine(n, line++))); +#endif + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestErrorFileOn) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + char FILENAME[80]; + sprintf(FILENAME, "phreeqc.%d.err", n); + + if (::FileExists(FILENAME)) + { + ::DeleteFile(FILENAME); + } + + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + ASSERT_EQ(IPQ_OK, ::SetOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetErrorFileOn(n, 1)); + ASSERT_EQ(IPQ_OK, ::SetLogFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpFileOn(n, 0)); + ASSERT_EQ(1, ::RunFile(n, "dump")); + ASSERT_EQ(true, ::FileExists(FILENAME)); + + std::string lines[10]; + std::ifstream ifs(FILENAME); + + size_t i = 0; + while (i < sizeof(lines) / sizeof(lines[0]) && std::getline(ifs, lines[i])) + { + ++i; + } + + ASSERT_EQ((size_t)8, i); + + ASSERT_EQ(std::string("WARNING: DATABASE keyword is ignored by IPhreeqc."), lines[0]); + ASSERT_EQ(std::string("WARNING: Cell-lengths were read for 1 cells. Last value is used till cell 100."), lines[1]); + ASSERT_EQ(std::string("WARNING: No dispersivities were read; disp = 0 assumed."), lines[2]); + ASSERT_EQ(std::string("ERROR: Gas not found in PHASES database, Amm(g)."), lines[3]); + ASSERT_EQ(std::string("WARNING: Could not find element in database, Amm."), lines[4]); + ASSERT_EQ(std::string("\tConcentration is set to zero."), lines[5]); + ASSERT_EQ(std::string("ERROR: Calculations terminating due to input errors."), lines[6]); + ASSERT_EQ(std::string("Stopping."), lines[7]); + ASSERT_EQ(std::string(""), lines[8]); + ASSERT_EQ(std::string(""), lines[9]); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestLogFileOn) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + char FILENAME[80]; + sprintf(FILENAME, "phreeqc.%d.log", n); + + if (::FileExists(FILENAME)) + { + ::DeleteFile(FILENAME); + } + + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + ASSERT_EQ(IPQ_OK, ::SetOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetErrorFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetLogFileOn(n, 1)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpFileOn(n, 0)); + + ASSERT_EQ(1, ::RunFile(n, "dump")); + ASSERT_EQ(true, ::FileExists(FILENAME)); + + std::string lines[10]; + std::ifstream ifs(FILENAME); + + size_t i = 0; + while (i < sizeof(lines) / sizeof(lines[0]) && std::getline(ifs, lines[i])) + { + ++i; + } + + ASSERT_EQ((size_t)6, i); + + ASSERT_EQ(std::string("WARNING: Cell-lengths were read for 1 cells. Last value is used till cell 100."), lines[0]); + ASSERT_EQ(std::string("WARNING: No dispersivities were read; disp = 0 assumed."), lines[1]); + ASSERT_EQ(std::string("ERROR: Gas not found in PHASES database, Amm(g)."), lines[2]); + ASSERT_EQ(std::string("WARNING: Could not find element in database, Amm."), lines[3]); + ASSERT_EQ(std::string("\tConcentration is set to zero."), lines[4]); + ASSERT_EQ(std::string("ERROR: Calculations terminating due to input errors."), lines[5]); + ASSERT_EQ(std::string(""), lines[8]); + ASSERT_EQ(std::string(""), lines[9]); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestGetWarningStringLine) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + ASSERT_EQ(IPQ_OK, ::SetOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetErrorFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetLogFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpFileOn(n, 0)); + ASSERT_EQ(1, ::RunFile(n, "dump")); + + ASSERT_EQ(5, ::GetWarningStringLineCount(n)); + ASSERT_EQ(std::string("WARNING: DATABASE keyword is ignored by IPhreeqc."), std::string(::GetWarningStringLine(n, 0))); + ASSERT_EQ(std::string("WARNING: Cell-lengths were read for 1 cells. Last value is used till cell 100."), std::string(::GetWarningStringLine(n, 1))); + ASSERT_EQ(std::string("WARNING: No dispersivities were read; disp = 0 assumed."), std::string(::GetWarningStringLine(n, 2))); + ASSERT_EQ(std::string("WARNING: Could not find element in database, Amm."), std::string(::GetWarningStringLine(n, 3))); + ASSERT_EQ(std::string(" Concentration is set to zero."), std::string(::GetWarningStringLine(n, 4))); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestPitzer) +{ + ASSERT_EQ(true, ::FileExists("pitzer.dat")); + ASSERT_TRUE(::FileSize("pitzer.dat") > 0); + + int id = ::CreateIPhreeqc(); + ASSERT_TRUE(id >= 0); + + ASSERT_EQ(0, ::LoadDatabase(id, "pitzer.dat")); + + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "SOLUTION 1")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "units mol/kgw")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "pH 7")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "temp 25")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "Mg 0.1 charge")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "Cl 0")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "S(6) 1.0612244897959")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "EQUILIBRIUM_PHASES 1")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "Halite 0 10")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "Sylvite 0 10")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "Bischofite 0 0")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "Carnallite 0 0")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "Epsomite 0 0")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "Kieserite 0 0")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "END")); + + // this fails -r4375 + // fixed in -r4380 + ASSERT_EQ(0, ::RunAccumulated(id)); + + if (id >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(id)); + } +} + +TEST(TestIPhreeqcLib, TestClearAccumulatedLines) +{ + ASSERT_EQ(true, ::FileExists("wateq4f.dat")); + ASSERT_TRUE(::FileSize("wateq4f.dat") > 0); + + int id = ::CreateIPhreeqc(); + ASSERT_TRUE(id >= 0); + + ASSERT_EQ(0, ::LoadDatabase(id, "wateq4f.dat")); + + // phreeqc can now handle pH of -2 (-r5885) + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "SOLUTION 1")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, " pH 7")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, " Na 1")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "PHASES")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, " Fix_H+")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, " H+ = H+")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, " log_k 0")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "EQUILIBRIUM_PHASES")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, " Fix_H+ -10 HCl 10")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "END")); + + ASSERT_EQ(1, ::RunAccumulated(id)); + + ASSERT_EQ(1, ::GetErrorStringLineCount(id)); + + const char expected[] = + "ERROR: Numerical method failed on all combinations of convergence parameters, cell/soln/mix 1\n"; + const char* err = ::GetErrorString(id); + + ASSERT_EQ(std::string(expected), std::string(err)); + + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "SOLUTION 1")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "pH 2")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "END")); + + // RunAccumulated clears accumulated lines on next call to AccumulateLine + // + ASSERT_EQ(0, ::RunAccumulated(id)); + ASSERT_EQ(0, ::GetErrorStringLineCount(id)); + + ASSERT_EQ(IPQ_OK, ::ClearAccumulatedLines(id)); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "SOLUTION 1")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "pH 2")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "END")); + + ASSERT_EQ(0, ::RunAccumulated(id)); + + if (id >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(id)); + } +} + +TEST(TestIPhreeqcLib, TestSetDumpFileName) +{ + char DUMP_FILENAME[80]; + sprintf(DUMP_FILENAME, "dump.%06d.out", ::rand()); + if (::FileExists(DUMP_FILENAME)) + { + ::DeleteFile(DUMP_FILENAME); + } + + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(IPQ_OK, ::DUMP(n)); + + // run + ASSERT_EQ(IPQ_OK, ::SetOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetErrorFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetLogFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpStringOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpFileOn(n, 1)); + ASSERT_EQ(IPQ_OK, ::SetDumpFileName(n, DUMP_FILENAME)); + + ASSERT_EQ(std::string(DUMP_FILENAME), std::string(::GetDumpFileName(n))); + + ASSERT_EQ(0, ::RunAccumulated(n)); + + ASSERT_EQ(std::string(DUMP_FILENAME), std::string(::GetDumpFileName(n))); + + ASSERT_EQ(true, ::FileExists(DUMP_FILENAME)); + + std::string lines[33]; + std::ifstream ifs(DUMP_FILENAME); + + size_t i = 0; + while (i < sizeof(lines) / sizeof(lines[0]) && std::getline(ifs, lines[i])) + { + ++i; + } + + int line = 0; + ASSERT_TRUE(::strstr(lines[line++].c_str(), "SOLUTION_RAW") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-temp") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-pressure") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-potential") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-total_h") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-total_o") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-cb") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-density") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-totals") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " C(4) ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Ca ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " H(0) ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Na ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-pH") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-pe") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-mu") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-ah2o") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-mass_water") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-soln_vol") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-total_alkalinity") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-activities") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " C(-4) ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " C(4) ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Ca ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " E ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " H(0) ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Na ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " O(0) ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-gammas") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "USE mix none") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "USE reaction none") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "USE reaction_temperature none") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "USE reaction_pressure none") != NULL); + + if (::FileExists(DUMP_FILENAME)) + { + ::DeleteFile(DUMP_FILENAME); + } + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestSetOutputFileName) +{ + char OUTPUT_FILENAME[80]; + sprintf(OUTPUT_FILENAME, "output.%06d.out", ::rand()); + if (::FileExists(OUTPUT_FILENAME)) + { + ::DeleteFile(OUTPUT_FILENAME); + } + + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat.old")); + + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(IPQ_OK, ::DUMP(n)); + + // run + ASSERT_EQ(IPQ_OK, ::SetOutputFileOn(n, 1)); + ASSERT_EQ(IPQ_OK, ::SetErrorFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetLogFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpStringOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetOutputFileName(n, OUTPUT_FILENAME)); + + ASSERT_EQ(std::string(OUTPUT_FILENAME), std::string(::GetOutputFileName(n))); + + + ASSERT_EQ(0, ::RunAccumulated(n)); + + ASSERT_EQ(true, ::FileExists(OUTPUT_FILENAME)); + + std::string lines[200]; + std::ifstream ifs(OUTPUT_FILENAME); + + size_t i = 0; + while (i < sizeof(lines) / sizeof(lines[0]) && std::getline(ifs, lines[i])) + { + ++i; + } + + ASSERT_EQ((size_t)100, i); + + int line = 0; + + ASSERT_TRUE(::strstr(lines[line++].c_str(), "------------------------------------") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "Reading input data for simulation 1.") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "------------------------------------") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " SOLUTION 1") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " C 1") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Ca 1") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Na 1") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " DUMP") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " -solution 1") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-------------------------------------------") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "Beginning of initial solution calculations.") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-------------------------------------------") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "Initial solution 1. ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "-----------------------------Solution composition--------") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Elements Molality Moles") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " C ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Ca ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Na ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "----------------------------Description of solution------") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " pH = ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " pe = ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Activity of water = ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Ionic strength (mol/kgw) = ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Mass of water (kg) = ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Total alkalinity (eq/kg) = ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Total CO2 (mol/kg) = ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Temperature (°C) = ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Electrical balance (eq) = ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Percent error, 100*(Cat-|An|)/(Cat+|An|) = ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Iterations = ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Total H = ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Total O = ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "----------------------------Distribution of species----------------------------") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Log Log Log mole V") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Species Molality Activity Molality Activity Gamma cm³/mol") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " OH- ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " H+ ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " H2O ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "C(-4) ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " CH4 ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "C(4) ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " HCO3- ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " CO2 ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " CaHCO3+ ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " CaCO3 ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " CO3-2 ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " NaHCO3 ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " NaCO3- ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "Ca ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Ca+2 ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " CaHCO3+ ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " CaCO3 ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " CaOH+ ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "H(0) ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " H2 ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "Na ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Na+ ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " NaHCO3 ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " NaCO3- ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " NaOH ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "O(0) ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " O2 ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "------------------------------Saturation indices-------------------------------") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Phase SI** log IAP log K(298 K, 1 atm)") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Aragonite") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " Calcite") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " CH4(g)") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " CO2(g)") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " H2(g)") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " H2O(g)") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " O2(g)") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "**For a gas, SI = log10(fugacity). Fugacity = pressure * phi / 1 atm.") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), " For ideal gases, phi = 1.") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "------------------") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "End of simulation.") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "------------------") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "------------------------------------") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "Reading input data for simulation 2.") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "------------------------------------") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "----------------") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "End of Run after ") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "----------------") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); + ASSERT_TRUE(::strstr(lines[line++].c_str(), "") != NULL); +///#endif + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } + + if (::FileExists(OUTPUT_FILENAME)) + { + ::DeleteFile(OUTPUT_FILENAME); + } +} + +TEST(TestIPhreeqcLib, TestOutputStringOnOff) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(false, ::GetOutputStringOn(n) != 0); + + ASSERT_EQ(IPQ_OK, ::SetOutputStringOn(n, 1)); + ASSERT_EQ(true, ::GetOutputStringOn(n) != 0); + + ASSERT_EQ(IPQ_OK, ::SetOutputStringOn(n, 0)); + ASSERT_EQ(false, ::GetOutputStringOn(n) != 0); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestGetOutputString) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + char OUTPUT_FILENAME[80]; + sprintf(OUTPUT_FILENAME, "output.%06d.out", ::rand()); + if (::FileExists(OUTPUT_FILENAME)) + { + ::DeleteFile(OUTPUT_FILENAME); + } + ASSERT_EQ(false, ::FileExists(OUTPUT_FILENAME)); + + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(IPQ_OK, ::DUMP(n)); + + // run + ASSERT_EQ(IPQ_OK, ::SetOutputFileOn(n, 1)); + ASSERT_EQ(IPQ_OK, ::SetOutputStringOn(n, 1)); + + ASSERT_EQ(IPQ_OK, ::SetErrorFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetLogFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpStringOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetOutputFileName(n, OUTPUT_FILENAME)); + + ASSERT_EQ(0, ::RunAccumulated(n)); + + ASSERT_EQ(true, ::FileExists(OUTPUT_FILENAME)); + + { + std::ifstream ifs(OUTPUT_FILENAME); + std::string fline((std::istreambuf_iterator(ifs)), std::istreambuf_iterator()); + + std::string sline(::GetOutputString(n)); + ASSERT_TRUE(sline.size() > 0); + + ASSERT_EQ(fline, sline); + } + + if (::FileExists(OUTPUT_FILENAME)) + { + ::DeleteFile(OUTPUT_FILENAME); + } + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestGetOutputStringLineCount) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(0, ::GetOutputStringLineCount(n)); + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat.old")); + ASSERT_EQ(0, ::GetOutputStringLineCount(n)); + + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(IPQ_OK, ::DUMP(n)); + + // run + ASSERT_EQ(IPQ_OK, ::SetOutputStringOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetErrorFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetLogFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpStringOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpFileOn(n, 0)); + + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(0, ::GetOutputStringLineCount(n)); + + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(IPQ_OK, ::DUMP(n)); + + ASSERT_EQ(IPQ_OK, ::SetOutputStringOn(n, 1)); + + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(100, ::GetOutputStringLineCount(n)); + + + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(IPQ_OK, ::DUMP(n)); + + ASSERT_EQ(IPQ_OK, ::SetOutputStringOn(n, 0)); + + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(0, ::GetOutputStringLineCount(n)); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestGetOutputStringLine) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(0, ::GetOutputStringLineCount(n)); + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat.old")); + ASSERT_EQ(0, ::GetOutputStringLineCount(n)); + + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(IPQ_OK, ::DUMP(n)); + + // run + ASSERT_EQ(IPQ_OK, ::SetOutputStringOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetErrorFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetLogFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpStringOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpFileOn(n, 0)); + + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(0, ::GetOutputStringLineCount(n)); + + int line = 0; + ASSERT_EQ(std::string(""), std::string(::GetOutputStringLine(n, line++))); + ASSERT_EQ(std::string(""), std::string(::GetOutputStringLine(n, line++))); + ASSERT_EQ(std::string(""), std::string(::GetOutputStringLine(n, line++))); + ASSERT_EQ(std::string(""), std::string(::GetOutputStringLine(n, line++))); + + // negative lines should be empty + ASSERT_EQ(std::string(""), std::string(::GetOutputStringLine(n, -1))); + ASSERT_EQ(std::string(""), std::string(::GetOutputStringLine(n, -2))); + ASSERT_EQ(std::string(""), std::string(::GetOutputStringLine(n, -3))); + ASSERT_EQ(std::string(""), std::string(::GetOutputStringLine(n, -4))); + + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(IPQ_OK, ::DUMP(n)); + + ASSERT_EQ(IPQ_OK, ::SetOutputStringOn(n, 1)); + + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(100, ::GetOutputStringLineCount(n)); + + ASSERT_EQ(std::string("------------------------------------"), std::string(::GetOutputStringLine(n, 0))); + ASSERT_EQ(std::string("Reading input data for simulation 1."), std::string(::GetOutputStringLine(n, 1))); + ASSERT_EQ(std::string("------------------------------------"), std::string(::GetOutputStringLine(n, 2))); + ASSERT_EQ(std::string("-----------------------------Solution composition------------------------------"), std::string(::GetOutputStringLine(n, 16))); + ASSERT_EQ(std::string("----------------------------Description of solution----------------------------"), std::string(::GetOutputStringLine(n, 24))); + ASSERT_EQ(std::string("----------------------------Distribution of species----------------------------"), std::string(::GetOutputStringLine(n, 40))); + ASSERT_EQ(std::string("------------------------------Saturation indices-------------------------------"), std::string(::GetOutputStringLine(n, 73))); + ASSERT_EQ(std::string(""), std::string(::GetOutputStringLine(n, 100))); + + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(IPQ_OK, ::DUMP(n)); + + ASSERT_EQ(IPQ_OK, ::SetOutputStringOn(n, 0)); + + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(0, ::GetOutputStringLineCount(n)); + + line = 0; + ASSERT_EQ(std::string(""), std::string(::GetOutputStringLine(n, line++))); + ASSERT_EQ(std::string(""), std::string(::GetOutputStringLine(n, line++))); + ASSERT_EQ(std::string(""), std::string(::GetOutputStringLine(n, line++))); + ASSERT_EQ(std::string(""), std::string(::GetOutputStringLine(n, line++))); + + // negative lines should be empty + ASSERT_EQ(std::string(""), std::string(::GetOutputStringLine(n, -1))); + ASSERT_EQ(std::string(""), std::string(::GetOutputStringLine(n, -2))); + ASSERT_EQ(std::string(""), std::string(::GetOutputStringLine(n, -3))); + ASSERT_EQ(std::string(""), std::string(::GetOutputStringLine(n, -4))); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestSetLogFileName) +{ + char LOG_FILENAME[80]; + sprintf(LOG_FILENAME, "log.%06d.out", ::rand()); + if (::FileExists(LOG_FILENAME)) + { + ::DeleteFile(LOG_FILENAME); + } + + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(IPQ_OK, ::DUMP(n)); + + // add knobs + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "KNOBS")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "\t-logfile TRUE")); + + // run + ASSERT_EQ(IPQ_OK, ::SetLogFileOn(n, 1)); + ASSERT_EQ(IPQ_OK, ::SetErrorFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpStringOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetLogFileName(n, LOG_FILENAME)); + + + ASSERT_EQ(0, ::RunAccumulated(n)); + + ASSERT_EQ(true, ::FileExists(LOG_FILENAME)); + + std::string lines[33]; + std::ifstream ifs(LOG_FILENAME); + + size_t i = 0; + while (i < sizeof(lines) / sizeof(lines[0]) && std::getline(ifs, lines[i])) + { + ++i; + } + + ASSERT_EQ((size_t)25, i); + + int line = 0; + ASSERT_EQ(std::string("-------------------------------------------"), lines[line++]); + ASSERT_EQ(std::string("Beginning of initial solution calculations."), lines[line++]); + ASSERT_EQ(std::string("-------------------------------------------"), lines[line++]); + ASSERT_EQ(std::string(""), lines[line++]); + ASSERT_EQ(std::string("Initial solution 1. "), lines[line++]); + ASSERT_EQ(std::string(""), lines[line++]); + ASSERT_EQ(std::string("Iterations in revise_guesses: 2"), lines[line++]); + ASSERT_EQ(std::string(""), lines[line++]); + ASSERT_EQ(std::string("Number of infeasible solutions: 0"), lines[line++]); + ASSERT_EQ(std::string("Number of basis changes: 0"), lines[line++]); + ASSERT_EQ(std::string(""), lines[line++]); + ASSERT_EQ(std::string("Number of iterations: 6"), lines[line++]); + ASSERT_EQ(std::string(""), lines[line++]); + ASSERT_EQ(std::string("------------------"), lines[line++]); + ASSERT_EQ(std::string("End of simulation."), lines[line++]); + ASSERT_EQ(std::string("------------------"), lines[line++]); + ASSERT_EQ(std::string(""), lines[line++]); + ASSERT_EQ(std::string("------------------------------------"), lines[line++]); + ASSERT_EQ(std::string("Reading input data for simulation 2."), lines[line++]); + ASSERT_EQ(std::string("------------------------------------"), lines[line++]); + ASSERT_EQ(std::string(""), lines[line++]); + line++; + line++; + line++; + ASSERT_EQ(std::string(""), lines[line++]); + + if (::FileExists(LOG_FILENAME)) + { + ::DeleteFile(LOG_FILENAME); + } + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestLogStringOnOff) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(false, ::GetLogStringOn(n) != 0); + + ASSERT_EQ(IPQ_OK, ::SetLogStringOn(n, 1)); + ASSERT_EQ(true, ::GetLogStringOn(n) != 0); + + ASSERT_EQ(IPQ_OK, ::SetLogStringOn(n, 0)); + ASSERT_EQ(false, ::GetLogStringOn(n) != 0); + + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); +} + +TEST(TestIPhreeqcLib, TestGetLogString) +{ + char LOG_FILENAME[80]; + sprintf(LOG_FILENAME, "log.%06d.out", ::rand()); + if (::FileExists(LOG_FILENAME)) + { + ::DeleteFile(LOG_FILENAME); + } + ASSERT_EQ(false, ::FileExists(LOG_FILENAME)); + + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(IPQ_OK, ::DUMP(n)); + + // add knobs + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "KNOBS")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "\t-logfile TRUE")); + + + // run + ASSERT_EQ(IPQ_OK, ::SetLogFileOn(n, 1)); + ASSERT_EQ(IPQ_OK, ::SetLogStringOn(n, 1)); + + ASSERT_EQ(IPQ_OK, ::SetDumpFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpStringOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetErrorFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetOutputStringOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 0)); + + ASSERT_EQ(IPQ_OK, ::SetLogFileName(n, LOG_FILENAME)); + ASSERT_EQ(std::string(LOG_FILENAME), std::string(::GetLogFileName(n))); + + ASSERT_EQ(0, ::RunAccumulated(n)); + + ASSERT_EQ(std::string(LOG_FILENAME), std::string(::GetLogFileName(n))); + + ASSERT_EQ(true, ::FileExists(LOG_FILENAME)); + + { + std::ifstream ifs(LOG_FILENAME); + std::string fline((std::istreambuf_iterator(ifs)), std::istreambuf_iterator()); + + std::string sline(::GetLogString(n)); + ASSERT_TRUE(sline.size() > 0); + + ASSERT_EQ(fline, sline); + } + + if (::FileExists(LOG_FILENAME)) + { + ::DeleteFile(LOG_FILENAME); + } + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestGetLogStringLineCount) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(0, ::GetLogStringLineCount(n)); + + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + + ASSERT_EQ(0, ::GetLogStringLineCount(n)); + + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(IPQ_OK, ::DUMP(n)); + + // add knobs + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "KNOBS")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "\t-logfile TRUE")); + + // run + ASSERT_EQ(IPQ_OK, ::SetLogStringOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetLogFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetErrorFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetOutputStringOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpStringOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpFileOn(n, 0)); + + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(0, ::GetLogStringLineCount(n)); + + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(IPQ_OK, ::DUMP(n)); + + // add knobs + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "KNOBS")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "\t-logfile TRUE")); + + ASSERT_EQ(IPQ_OK, ::SetLogStringOn(n, 1)); + + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(29, ::GetLogStringLineCount(n)); + + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(IPQ_OK, ::DUMP(n)); + + // add knobs + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "KNOBS")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "\t-logfile TRUE")); + + ASSERT_EQ(IPQ_OK, ::SetLogStringOn(n, 0)); + + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(0, ::GetLogStringLineCount(n)); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestGetLogStringLine) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + ASSERT_EQ(0, ::GetLogStringLineCount(n)); + + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + + ASSERT_EQ(0, ::GetLogStringLineCount(n)); + + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(IPQ_OK, ::DUMP(n)); + + // add knobs + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "KNOBS")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "\t-logfile TRUE")); + + // run + ASSERT_EQ(IPQ_OK, ::SetOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetOutputStringOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetErrorFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetLogFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpStringOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpFileOn(n, 0)); + + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(0, ::GetLogStringLineCount(n)); + + int line = 0; + ASSERT_EQ(std::string(""), std::string(::GetLogStringLine(n, line++))); + ASSERT_EQ(std::string(""), std::string(::GetLogStringLine(n, line++))); + ASSERT_EQ(std::string(""), std::string(::GetLogStringLine(n, line++))); + ASSERT_EQ(std::string(""), std::string(::GetLogStringLine(n, line++))); + + // negative lines should be empty + ASSERT_EQ(std::string(""), std::string(::GetLogStringLine(n, -1))); + ASSERT_EQ(std::string(""), std::string(::GetLogStringLine(n, -2))); + ASSERT_EQ(std::string(""), std::string(::GetLogStringLine(n, -3))); + ASSERT_EQ(std::string(""), std::string(::GetLogStringLine(n, -4))); + + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(IPQ_OK, ::DUMP(n)); + + // add knobs + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "KNOBS")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "\t-logfile TRUE")); + + ASSERT_EQ(IPQ_OK, ::SetLogStringOn(n, 1)); + + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(29, ::GetLogStringLineCount(n)); + + line = 0; + ASSERT_EQ(std::string("------------------------------------"), std::string(::GetLogStringLine(n, line++))); + ASSERT_EQ(std::string("Reading input data for simulation 1."), std::string(::GetLogStringLine(n, line++))); + ASSERT_EQ(std::string("------------------------------------"), std::string(::GetLogStringLine(n, line++))); + ASSERT_EQ(std::string(""), std::string(::GetLogStringLine(n, line++))); + ASSERT_EQ(std::string("-------------------------------------------"), std::string(::GetLogStringLine(n, line++))); + ASSERT_EQ(std::string("Beginning of initial solution calculations."), std::string(::GetLogStringLine(n, line++))); + ASSERT_EQ(std::string("-------------------------------------------"), std::string(::GetLogStringLine(n, line++))); + ASSERT_EQ(std::string(""), std::string(::GetLogStringLine(n, line++))); + ASSERT_EQ(std::string("Initial solution 1. "), std::string(::GetLogStringLine(n, line++))); + ASSERT_EQ(std::string(""), std::string(::GetLogStringLine(n, line++))); + ASSERT_EQ(std::string("Iterations in revise_guesses: 2"), std::string(::GetLogStringLine(n, line++))); + ASSERT_EQ(std::string(""), std::string(::GetLogStringLine(n, line++))); + ASSERT_EQ(std::string("Number of infeasible solutions: 0"), std::string(::GetLogStringLine(n, line++))); + ASSERT_EQ(std::string("Number of basis changes: 0"), std::string(::GetLogStringLine(n, line++))); + ASSERT_EQ(std::string(""), std::string(::GetLogStringLine(n, line++))); + ASSERT_EQ(std::string("Number of iterations: 6"), std::string(::GetLogStringLine(n, line++))); + ASSERT_EQ(std::string(""), std::string(::GetLogStringLine(n, line++))); + ASSERT_EQ(std::string("------------------"), std::string(::GetLogStringLine(n, line++))); + ASSERT_EQ(std::string("End of simulation."), std::string(::GetLogStringLine(n, line++))); + ASSERT_EQ(std::string("------------------"), std::string(::GetLogStringLine(n, line++))); + ASSERT_EQ(std::string(""), std::string(::GetLogStringLine(n, line++))); + ASSERT_EQ(std::string("------------------------------------"), std::string(::GetLogStringLine(n, line++))); + ASSERT_EQ(std::string("Reading input data for simulation 2."), std::string(::GetLogStringLine(n, line++))); + ASSERT_EQ(std::string("------------------------------------"), std::string(::GetLogStringLine(n, line++))); + ASSERT_EQ(std::string(""), std::string(::GetLogStringLine(n, line++))); + line++; + line++; + line++; + ASSERT_EQ(std::string(""), std::string(::GetLogStringLine(n, line++))); + + // add solution block + // add solution block + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + + // add dump block + ASSERT_EQ(IPQ_OK, ::DUMP(n)); + + // add knobs + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "KNOBS")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "\t-logfile TRUE")); + + ASSERT_EQ(IPQ_OK, ::SetLogStringOn(n, 0)); + + + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(0, ::GetLogStringLineCount(n)); + + line = 0; + ASSERT_EQ(std::string(""), std::string(::GetLogStringLine(n, line++))); + ASSERT_EQ(std::string(""), std::string(::GetLogStringLine(n, line++))); + ASSERT_EQ(std::string(""), std::string(::GetLogStringLine(n, line++))); + ASSERT_EQ(std::string(""), std::string(::GetLogStringLine(n, line++))); + + // negative lines should be empty + ASSERT_EQ(std::string(""), std::string(::GetLogStringLine(n, -1))); + ASSERT_EQ(std::string(""), std::string(::GetLogStringLine(n, -2))); + ASSERT_EQ(std::string(""), std::string(::GetLogStringLine(n, -3))); + ASSERT_EQ(std::string(""), std::string(::GetLogStringLine(n, -4))); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestSetErrorFileName) +{ + char ERR_FILENAME[80]; + sprintf(ERR_FILENAME, "error.%s.out", "TestIPhreeqcLib-TestSetErrorFileName"); + if (::FileExists(ERR_FILENAME)) + { + ::DeleteFile(ERR_FILENAME); + } + + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "SOLUTION 1")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " pH 7")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Na 1")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "PHASES")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Fix_H+")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " H+ = H+")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " log_k 0")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "EQUILIBRIUM_PHASES")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Fix_H+ -10 HCl 10")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "END")); + + // run + ASSERT_EQ(IPQ_OK, ::SetErrorFileOn(n, 1)); + ASSERT_EQ(IPQ_OK, ::SetLogFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetOutputFileOn(n, 1)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpStringOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetErrorFileName(n, ERR_FILENAME)); + + + ASSERT_EQ(1, ::RunAccumulated(n)); + + ASSERT_EQ(true, ::FileExists(ERR_FILENAME)); + + std::string lines[100]; + { + std::ifstream ifs(ERR_FILENAME); + + size_t i = 0; + while (i < sizeof(lines) / sizeof(lines[0]) && std::getline(ifs, lines[i])) + { + ++i; + } + + ASSERT_EQ((size_t)90, i); + } + + ASSERT_EQ(std::string("WARNING: Maximum iterations exceeded, 100"), lines[0]); + ASSERT_EQ(std::string("WARNING: Numerical method failed with this set of convergence parameters."), lines[2]); + ASSERT_EQ(std::string("ERROR: Numerical method failed on all combinations of convergence parameters, cell/soln/mix 1"), lines[88]); + ASSERT_EQ(std::string("Stopping."), lines[89]); + + if (::FileExists(ERR_FILENAME)) + { + ::DeleteFile(ERR_FILENAME); + } + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestErrorStringOnOff) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(true, ::GetErrorStringOn(n) != 0); + + ASSERT_EQ(IPQ_OK, ::SetErrorStringOn(n, 1)); + ASSERT_EQ(true, ::GetErrorStringOn(n) != 0); + + ASSERT_EQ(IPQ_OK, ::SetErrorStringOn(n, 0)); + ASSERT_EQ(false, ::GetErrorStringOn(n) != 0); + + ASSERT_EQ(IPQ_OK, ::SetErrorStringOn(n, 1)); + ASSERT_EQ(true, ::GetErrorStringOn(n) != 0); + + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); +} + +TEST(TestIPhreeqcLib, TestGetErrorString) +{ + char ERR_FILENAME[80]; + sprintf(ERR_FILENAME, "error.%06d.out", ::rand()); + if (::FileExists(ERR_FILENAME)) + { + ::DeleteFile(ERR_FILENAME); + } + ASSERT_EQ(false, ::FileExists(ERR_FILENAME)); + + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "SOLUTION 1")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " pH 7")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Na 1")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "PHASES")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Fix_H+")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " H+ = H+")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " log_k 0")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "EQUILIBRIUM_PHASES")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Fix_H+ -10 HCl 10")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "END")); + + // run + ASSERT_EQ(IPQ_OK, ::SetErrorFileOn(n, 1)); + ASSERT_EQ(IPQ_OK, ::SetErrorStringOn(n, 1)); + + ASSERT_EQ(IPQ_OK, ::SetDumpFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpStringOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetLogFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetOutputStringOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 0)); + + ASSERT_EQ(IPQ_OK, ::SetErrorFileName(n, ERR_FILENAME)); + ASSERT_EQ(std::string(ERR_FILENAME), std::string(::GetErrorFileName(n))); + + ASSERT_EQ(1, ::RunAccumulated(n)); + + ASSERT_EQ(std::string(ERR_FILENAME), std::string(::GetErrorFileName(n))); + + ASSERT_EQ(true, ::FileExists(ERR_FILENAME)); + + { +#if 0 + std::ifstream ifs(ERR_FILENAME); + std::string fline((std::istreambuf_iterator(ifs)), std::istreambuf_iterator()); +#else + std::string fline("ERROR: Numerical method failed on all combinations of convergence parameters, cell/soln/mix 1\n"); +#endif + + std::string sline(::GetErrorString(n)); + ASSERT_TRUE(sline.size() > 0); + + ASSERT_EQ(fline, sline); + } + + if (::FileExists(ERR_FILENAME)) + { + ::DeleteFile(ERR_FILENAME); + } + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestGetErrorStringLineCount) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(0, ::GetErrorStringLineCount(n)); + + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + + ASSERT_EQ(0, ::GetErrorStringLineCount(n)); + + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "SOLUTION 1")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " pH 7")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Na 1")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "PHASES")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Fix_H+")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " H+ = H+")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " log_k 0")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "EQUILIBRIUM_PHASES")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Fix_H+ -10 HCl 10")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "END")); + + ASSERT_EQ(true, ::GetErrorStringOn(n) != 0); + ASSERT_EQ(1, ::RunAccumulated(n)); + ASSERT_EQ(1, ::GetErrorStringLineCount(n)); + + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "SOLUTION 1")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " pH 7")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Na 1")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "PHASES")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Fix_H+")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " H+ = H+")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " log_k 0")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "EQUILIBRIUM_PHASES")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Fix_H+ -10 HCl 10")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "END")); + + ASSERT_EQ(IPQ_OK, ::SetErrorStringOn(n, 1)); + ASSERT_EQ(1, ::RunAccumulated(n)); + ASSERT_EQ(1, ::GetErrorStringLineCount(n)); + + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "SOLUTION 1")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " pH 7")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Na 1")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "PHASES")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Fix_H+")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " H+ = H+")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " log_k 0")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "EQUILIBRIUM_PHASES")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Fix_H+ -10 HCl 10")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "END")); + + ASSERT_EQ(IPQ_OK, ::SetErrorStringOn(n, 0)); + + ASSERT_EQ(1, ::RunAccumulated(n)); + ASSERT_EQ(0, ::GetErrorStringLineCount(n)); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestSetSelectedOutputFileName) +{ + char SELOUT_FILENAME[80]; + sprintf(SELOUT_FILENAME, "selected_output.%06d.out", ::rand()); + if (::FileExists(SELOUT_FILENAME)) + { + ::DeleteFile(SELOUT_FILENAME); + } + + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(0, ::LoadDatabase(n, "llnl.dat")); + + int max = 6; + + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + ASSERT_EQ(IPQ_OK, ::EQUILIBRIUM_PHASES(n, "calcite", 0.0, 0.010)); + ASSERT_EQ(IPQ_OK, ::USER_PUNCH(n, "Ca", max)); + + ASSERT_EQ(0, ::GetOutputFileOn(n)); + ASSERT_EQ(0, ::GetErrorFileOn(n)); + ASSERT_EQ(0, ::GetLogFileOn(n)); + ASSERT_EQ(0, ::GetSelectedOutputFileOn(n)); + ASSERT_EQ(0, ::GetDumpFileOn(n)); + ASSERT_EQ(0, ::GetDumpStringOn(n)); + + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 1)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileName(n, SELOUT_FILENAME)); + + ASSERT_EQ(0, ::RunAccumulated(n)); + + ASSERT_EQ(true, ::FileExists(SELOUT_FILENAME)); + + /* + EXPECTED selected.out: + sim state soln dist_x time step pH pe C Ca Na m_CO3-2 m_CaOH+ m_NaCO3- la_CO3-2 la_CaOH+ la_NaCO3- Calcite d_Calcite si_CO2(g) si_Siderite pressure total mol volume g_CO2(g) g_N2(g) k_Albite dk_Albite k_Pyrite dk_Pyrite s_CaSO4 s_SrSO4 1.name 1.type 1.moles 2.name 2.type 2.moles 3.name 3.type 3.moles 4.name 4.type 4.moles 5.name 5.type 5.moles 6.name 6.type 6.moles + 1 i_soln 1 -99 -99 -99 7 4 1.0000e-003 1.0000e-003 1.0000e-003 4.2975e-007 1.1819e-009 1.1881e-009 -6.4686e+000 -8.9530e+000 -8.9507e+000 0.0000e+000 0.0000e+000 -2.2870 -999.9990 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 Ca+2 aq 9.9178e-004 CaHCO3+ aq 7.5980e-006 CaCO3 aq 6.2155e-007 CaOH+ aq 1.1819e-009 + 1 react 1 -99 0 1 7.86135 10.18 1.1556e-003 1.1556e-003 1.0000e-003 4.2718e-006 9.7385e-009 1.1620e-008 -5.4781e+000 -8.0388e+000 -7.9621e+000 9.8444e-003 -1.5555e-004 -3.0192 -999.9990 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 0.0000e+000 calcite equi 9.8444e-003 Ca+2 aq 1.1371e-003 CaHCO3+ aq 1.1598e-005 CaCO3 aq 6.8668e-006 CaOH+ aq 9.7385e-009 + */ + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } + + if (::FileExists(SELOUT_FILENAME)) + { + ::DeleteFile(SELOUT_FILENAME); + } +} + +TEST(TestIPhreeqcLib, TestSelectedOutputStringOnOff) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(false, ::GetSelectedOutputFileOn(n) != 0); + + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 1)); + ASSERT_EQ(true, ::GetSelectedOutputFileOn(n) != 0); + + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 0)); + ASSERT_EQ(false, ::GetSelectedOutputFileOn(n) != 0); + + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); +} + +TEST(TestIPhreeqcLib, TestGetSelectedOutputString) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(0, ::LoadDatabase(n, "llnl.dat")); + + int max = 6; + + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + ASSERT_EQ(IPQ_OK, ::EQUILIBRIUM_PHASES(n, "calcite", 0.0, 0.010)); + ASSERT_EQ(IPQ_OK, ::USER_PUNCH(n, "Ca", max)); + + ASSERT_EQ(0, ::GetOutputFileOn(n)); + ASSERT_EQ(0, ::GetErrorFileOn(n)); + ASSERT_EQ(0, ::GetLogFileOn(n)); + ASSERT_EQ(0, ::GetSelectedOutputFileOn(n)); + ASSERT_EQ(0, ::GetDumpFileOn(n)); + ASSERT_EQ(0, ::GetDumpStringOn(n)); + + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputStringOn(n, 1)); + + ASSERT_EQ(0, ::RunAccumulated(n)); + + std::string sline(::GetSelectedOutputString(n)); + + ASSERT_TRUE(::strstr(sline.c_str(), "sim\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "state\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "soln\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "dist_x\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "time\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "step\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "pH\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "pe\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "C\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "Ca\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "Na\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "m_CO3-2\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "m_CaOH+\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "m_NaCO3-\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "la_CO3-2\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "la_CaOH+\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "la_NaCO3-\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "Calcite\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "d_Calcite\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "si_CO2(g)\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "si_Siderite\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "pressure\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "total mol\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "volume\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "g_CO2(g)\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "g_N2(g)\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "k_Albite\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "dk_Albite\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "k_Pyrite\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "dk_Pyrite\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "s_CaSO4\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "s_SrSO4\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "1.name\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "1.type\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "1.moles\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "2.name\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "2.type\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "2.moles\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "3.name\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "3.type\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "3.moles\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "4.name\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "4.type\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "4.moles\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "5.name\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "5.type\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "5.moles\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "6.name\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "6.type\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "6.moles\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "\n") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "i_soln\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "react\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "Ca+2\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "aq\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "CaHCO3+\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "CaCO3\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "CaOH+\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "Calcite\t") != NULL); + ASSERT_TRUE(::strstr(sline.c_str(), "equi\t") != NULL); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestGetSelectedOutputStringLineCount) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(0, ::GetSelectedOutputFileOn(n)); + + ASSERT_EQ(0, ::LoadDatabase(n, "llnl.dat")); + + ASSERT_EQ(0, ::GetSelectedOutputFileOn(n)); + + int max = 6; + + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + ASSERT_EQ(IPQ_OK, ::EQUILIBRIUM_PHASES(n, "calcite", 0.0, 0.010)); + ASSERT_EQ(IPQ_OK, ::USER_PUNCH(n, "Ca", max)); + + ASSERT_EQ(0, ::GetOutputFileOn(n)); + ASSERT_EQ(0, ::GetErrorFileOn(n)); + ASSERT_EQ(0, ::GetLogFileOn(n)); + ASSERT_EQ(0, ::GetSelectedOutputFileOn(n)); + ASSERT_EQ(0, ::GetDumpFileOn(n)); + ASSERT_EQ(0, ::GetDumpStringOn(n)); + + ASSERT_EQ(false, ::GetSelectedOutputStringOn(n) != 0); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputStringOn(n, 1)); + + ASSERT_EQ(0, ::RunAccumulated(n)); + + ASSERT_EQ(3, ::GetSelectedOutputStringLineCount(n)); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestGetSelectedOutputStringLine) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(0, ::GetSelectedOutputFileOn(n)); + + ASSERT_EQ(0, ::LoadDatabase(n, "llnl.dat")); + + ASSERT_EQ(0, ::GetSelectedOutputFileOn(n)); + + int max = 6; + + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + ASSERT_EQ(IPQ_OK, ::EQUILIBRIUM_PHASES(n, "calcite", 0.0, 0.010)); + ASSERT_EQ(IPQ_OK, ::USER_PUNCH(n, "Ca", max)); + + ASSERT_EQ(0, ::GetOutputFileOn(n)); + ASSERT_EQ(0, ::GetErrorFileOn(n)); + ASSERT_EQ(0, ::GetLogFileOn(n)); + ASSERT_EQ(0, ::GetSelectedOutputFileOn(n)); + ASSERT_EQ(0, ::GetDumpFileOn(n)); + ASSERT_EQ(0, ::GetDumpStringOn(n)); + + ASSERT_EQ(false, ::GetSelectedOutputStringOn(n) != 0); + + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(0, ::GetSelectedOutputStringLineCount(n)); + + int line = 0; + ASSERT_EQ(std::string(""), std::string(::GetSelectedOutputStringLine(n, line++))); + ASSERT_EQ(std::string(""), std::string(::GetSelectedOutputStringLine(n, line++))); + ASSERT_EQ(std::string(""), std::string(::GetSelectedOutputStringLine(n, line++))); + + // negative lines should be empty + ASSERT_EQ(std::string(""), std::string(::GetSelectedOutputStringLine(n, -1))); + ASSERT_EQ(std::string(""), std::string(::GetSelectedOutputStringLine(n, -2))); + ASSERT_EQ(std::string(""), std::string(::GetSelectedOutputStringLine(n, -3))); + + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + ASSERT_EQ(IPQ_OK, ::EQUILIBRIUM_PHASES(n, "calcite", 0.0, 0.010)); + ASSERT_EQ(IPQ_OK, ::USER_PUNCH(n, "Ca", max)); + + ASSERT_EQ(false, ::GetSelectedOutputStringOn(n) != 0); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputStringOn(n, 1)); + + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(3, ::GetSelectedOutputStringLineCount(n)); + + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "sim\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "state\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "soln\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "dist_x\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "time\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "step\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "pH\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "pe\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "C\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "Ca\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "Na\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "m_CO3-2\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "m_CaOH+\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "m_NaCO3-\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "la_CO3-2\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "la_CaOH+\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "la_NaCO3-\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "Calcite\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "d_Calcite\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "si_CO2(g)\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "si_Siderite\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "pressure\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "total mol\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "volume\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "g_CO2(g)\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "g_N2(g)\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "k_Albite\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "dk_Albite\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "k_Pyrite\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "dk_Pyrite\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "s_CaSO4\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "s_SrSO4\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "1.name\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "1.type\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "1.moles\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "2.name\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "2.type\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "2.moles\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "3.name\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "3.type\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "3.moles\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "4.name\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "4.type\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "4.moles\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "5.name\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "5.type\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "5.moles\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "6.name\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "6.type\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "6.moles\t") != NULL); + + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 1), "i_soln\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 1), "Ca+2\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 1), "aq\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 1), "CaHCO3+\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 1), "CaCO3\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 1), "CaOH+\t") != NULL); + + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 2), "react\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 2), "Calcite\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 2), "equi\t") != NULL); + + // after obj.GetSelectedOutputStringLineCount() should be empty + ASSERT_EQ(std::string(""), std::string(::GetSelectedOutputStringLine(n, ::GetSelectedOutputStringLineCount(n)))); + ASSERT_EQ(std::string(""), std::string(::GetSelectedOutputStringLine(n, ::GetSelectedOutputStringLineCount(n) + 1))); + ASSERT_EQ(std::string(""), std::string(::GetSelectedOutputStringLine(n, ::GetSelectedOutputStringLineCount(n) + 2))); + + // negative lines should be empty + ASSERT_EQ(std::string(""), std::string(::GetSelectedOutputStringLine(n, -1))); + ASSERT_EQ(std::string(""), std::string(::GetSelectedOutputStringLine(n, -2))); + ASSERT_EQ(std::string(""), std::string(::GetSelectedOutputStringLine(n, -3))); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestGetSelectedOutputStringLineNotEnoughHeadings) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(0, ::GetSelectedOutputFileOn(n)); + + ASSERT_EQ(0, ::LoadDatabase(n, "llnl.dat")); + + ASSERT_EQ(0, ::GetSelectedOutputFileOn(n)); + + ASSERT_EQ(IPQ_OK, ::SOLUTION(n, 1.0, 1.0, 1.0)); + ASSERT_EQ(IPQ_OK, ::EQUILIBRIUM_PHASES(n, "calcite", 0.0, 0.010)); + ASSERT_EQ(IPQ_OK, ::USER_PUNCH_NEH(n)); + + ASSERT_EQ(0, ::GetOutputFileOn(n)); + ASSERT_EQ(0, ::GetErrorFileOn(n)); + ASSERT_EQ(0, ::GetLogFileOn(n)); + ASSERT_EQ(0, ::GetSelectedOutputFileOn(n)); + ASSERT_EQ(0, ::GetDumpFileOn(n)); + ASSERT_EQ(0, ::GetDumpStringOn(n)); + + ASSERT_EQ(false, ::GetSelectedOutputStringOn(n) != 0); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputStringOn(n, 1)); + + ASSERT_EQ(0, ::RunAccumulated(n)); + ASSERT_EQ(3, ::GetSelectedOutputStringLineCount(n)); + + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "sim\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "state\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "soln\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "dist_x\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "time\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "step\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "pH\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "pe\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "C\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "Ca\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "Na\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "m_CO3-2\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "m_CaOH+\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "m_NaCO3-\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "la_CO3-2\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "la_CaOH+\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "la_NaCO3-\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "Calcite\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "d_Calcite\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "si_CO2(g)\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "si_Siderite\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "pressure\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "total mol\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "volume\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "g_CO2(g)\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "g_N2(g)\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "k_Albite\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "dk_Albite\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "k_Pyrite\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "dk_Pyrite\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "s_CaSO4\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "s_SrSO4\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "head0\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "head1\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 0), "head2\t") != NULL); + + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 1), "i_soln\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 1), "have0\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 1), "have1\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 1), "have2\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 1), "missing0\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 1), "missing2\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 1), "missing2\t") != NULL); + + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 2), "react\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 2), "have0\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 2), "have1\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 2), "have2\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 2), "missing0\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 2), "missing2\t") != NULL); + ASSERT_TRUE(::strstr(::GetSelectedOutputStringLine(n, 2), "missing2\t") != NULL); + + // after obj.GetSelectedOutputStringLineCount() should be empty + ASSERT_EQ(std::string(""), std::string(::GetSelectedOutputStringLine(n, ::GetSelectedOutputStringLineCount(n)))); + ASSERT_EQ(std::string(""), std::string(::GetSelectedOutputStringLine(n, ::GetSelectedOutputStringLineCount(n) + 1))); + ASSERT_EQ(std::string(""), std::string(::GetSelectedOutputStringLine(n, ::GetSelectedOutputStringLineCount(n) + 2))); + + // negative lines should be empty + ASSERT_EQ(std::string(""), std::string(::GetSelectedOutputStringLine(n, -1))); + ASSERT_EQ(std::string(""), std::string(::GetSelectedOutputStringLine(n, -2))); + ASSERT_EQ(std::string(""), std::string(::GetSelectedOutputStringLine(n, -3))); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestLongUser_Punch) +{ + const char input[] = + "PRINT\n" + " -selected_output t\n" + "SOLUTION\n" + "SELECTED_OUTPUT\n" + " -reset false\n" + "USER_PUNCH\n" + "1 REM 255 CHARACTER STRING\n" + "10 temp$ = \"XXXXX123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345\"\n" + "20 PUNCH temp$\n"; + + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputStringOn(n, 1)); + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + ASSERT_EQ(0, ::RunString(n, input)); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestBasicSURF) +{ + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "SURFACE_MASTER_SPECIES")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Surfa Surfa")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Surfb Surfb")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "SURFACE_SPECIES")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Surfa = Surfa")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " log_k 0")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Surfb = Surfb")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " log_k 0")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Surfa + Zn+2 = SurfaZn+2")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " log_k 5.")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Surfb + Zn+2 = SurfbZn+2")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " log_k 6.")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Surfa + Cu+2 = SurfaCu+2")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " log_k 4.5")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Surfb + Cu+2 = SurfbCu+2")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " log_k 6.5")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "SOLUTION 1")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " pH 8")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " units mol/kgw")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Fe(3) 1e-2")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Zn 1e-4")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Cu 1e-5")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Na 1e-1")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Cl 1e-1")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "EQUILIBRIUM_PHASES 1")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Fe(OH)3(a) 0 0")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "SELECTED_OUTPUT")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "USER_PUNCH")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " -headings Hfo-Zn Surfa-Zn Surfb-Zn Surfa-Cu Surfb-Cu")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "-start")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "10 PUNCH SURF(\"Zn\",\"Hfo\")")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "20 PUNCH SURF(\"Zn\",\"Surfa\")")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "30 PUNCH SURF(\"Zn\",\"Surfb\")")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "40 PUNCH SURF(\"Cu\",\"Surfa\")")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "50 PUNCH SURF(\"Cu\",\"Surfb\")")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "-end")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "SURFACE 1")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Hfo_sOH Fe(OH)3(a) equilibrium_phase 0.005 53300")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Hfo_wOH Fe(OH)3(a) equilibrium_phase 0.2")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Surfa 0.2 100. 2")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, " Surfb 0.1 100. 1")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(n, "END")); + + + ASSERT_EQ(IPQ_OK, ::SetOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetOutputStringOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetErrorFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetLogFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpStringOn(n, 0)); + ASSERT_EQ(IPQ_OK, ::SetDumpFileOn(n, 0)); + + + ASSERT_EQ(0, ::RunAccumulated(n)); + + ASSERT_EQ(13, ::GetSelectedOutputColumnCount(n)); + ASSERT_EQ(3, ::GetSelectedOutputRowCount(n)); + + VAR v; + VarInit(&v); + + const int offset = 8; + + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, offset + 0, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("Hfo-Zn"), std::string(v.sVal)); + + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, offset + 1, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("Surfa-Zn"), std::string(v.sVal)); + + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, offset + 2, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("Surfb-Zn"), std::string(v.sVal)); + + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, offset + 3, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("Surfa-Cu"), std::string(v.sVal)); + + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 0, offset + 4, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("Surfb-Cu"), std::string(v.sVal)); + + + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, offset + 0, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(0.0, v.dVal, ::pow(10., -FLT_DIG)); + + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, offset + 1, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(0.0, v.dVal, ::pow(10., -FLT_DIG)); + + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, offset + 2, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(0.0, v.dVal, ::pow(10., -FLT_DIG)); + + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, offset + 3, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(0.0, v.dVal, ::pow(10., -FLT_DIG)); + + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 1, offset + 4, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(0.0, v.dVal, ::pow(10., -FLT_DIG)); + + + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, offset + 0, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(6.3861e-005, v.dVal, ::pow(10., -FLT_DIG)); + + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, offset + 1, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(1.7868e-005, v.dVal, ::pow(10., -FLT_DIG)); + + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, offset + 2, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(1.8248e-005, v.dVal, ::pow(10., -FLT_DIG)); + + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, offset + 3, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(4.6216e-009, v.dVal, ::pow(10., -FLT_DIG)); + + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(n, 2, offset + 4, &v)); + ASSERT_EQ(TT_DOUBLE, v.type); + ASSERT_NEAR(4.7201e-008, v.dVal, ::pow(10., -FLT_DIG)); + + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } +} + +TEST(TestIPhreeqcLib, TestIEEE) +{ + // COMMENT: {1/18/2013 6:34:57 PM} int n = ::CreateIPhreeqc(); + // COMMENT: {1/18/2013 6:34:57 PM} ASSERT_TRUE(n >= 0); + // COMMENT: {1/18/2013 6:34:57 PM} + // COMMENT: {1/18/2013 6:34:57 PM} ASSERT_EQ( 0, ::LoadDatabase(n, "wateq4f.dat") ); + // COMMENT: {1/18/2013 6:34:57 PM} //ASSERT_EQ( 0, ::LoadDatabase(n, "cdmusic_hiemstra.dat") ); + // COMMENT: {1/18/2013 6:34:57 PM} //::LoadDatabase(n, "cdmusic_hiemstra.dat"); + // COMMENT: {1/18/2013 6:34:57 PM} //const char* errdb = ::GetErrorString(n); + // COMMENT: {1/18/2013 6:34:57 PM} //fprintf(stderr, "%s\n", errdb); + // COMMENT: {1/18/2013 6:34:57 PM} + // COMMENT: {1/18/2013 6:34:57 PM} ASSERT_EQ( IPQ_OK, ::SetOutputFileOn(n, 0) ); + // COMMENT: {1/18/2013 6:34:57 PM} ASSERT_EQ( IPQ_OK, ::SetOutputStringOn(n, 0) ); + // COMMENT: {1/18/2013 6:34:57 PM} ASSERT_EQ( IPQ_OK, ::SetErrorFileOn(n, 0) ); + // COMMENT: {1/18/2013 6:34:57 PM} ASSERT_EQ( IPQ_OK, ::SetLogFileOn(n, 0) ); + // COMMENT: {1/18/2013 6:34:57 PM} ASSERT_EQ( IPQ_OK, ::SetSelectedOutputFileOn(n, 0) ); + // COMMENT: {1/18/2013 6:34:57 PM} ASSERT_EQ( IPQ_OK, ::SetDumpStringOn(n, 0) ); + // COMMENT: {1/18/2013 6:34:57 PM} ASSERT_EQ( IPQ_OK, ::SetDumpFileOn(n, 0) ); + // COMMENT: {1/18/2013 6:34:57 PM} + // COMMENT: {1/18/2013 6:34:57 PM} ::RunFile(n, "IEEE"); + // COMMENT: {1/18/2013 6:34:57 PM} const char* err = ::GetErrorString(n); + // COMMENT: {1/18/2013 6:34:57 PM} fprintf(stderr, "%s\n", err); + // COMMENT: {1/18/2013 6:34:57 PM} + // COMMENT: {1/18/2013 6:34:57 PM} if (n >= 0) + // COMMENT: {1/18/2013 6:34:57 PM} { + // COMMENT: {1/18/2013 6:34:57 PM} ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + // COMMENT: {1/18/2013 6:34:57 PM} } +} + +TEST(TestIPhreeqcLib, TestDelete) +{ + const char input[] = + "SOLUTION 1 # definition of intial condition 1\n" + "COPY cell 1 7405 # copy cell 1 to placeholder cell with index larger than the number of cells in the model domain\n" + "END\n" + "DELETE # delete initial condition 1 to allow for a redefinition of all reactions\n" + "-cell 1\n" + "END\n" + "# define other initial conditions and copy to another placeholder cell\n" + "\n" + "COPY cell 7405 1 # copy back from placeholder cell to domain cell 1\n" + "END\n" + "MIX 1 # mix according to initial moisture content\n" + " 1 0.25\n" + "END\n" + "RUN_CELLS\n" + "-cells 1\n" + "-start_time 0\n" + "-time_step 0\n" + "DELETE # remove mix reaction in subsequent runs\n" + "-mix 1\n" + "END\n" + "RUN_CELLS\n" + "-cells 1\n"; + + int n = ::CreateIPhreeqc(); + ASSERT_TRUE(n >= 0); + + char OUTPUT_FILE[80]; + sprintf(OUTPUT_FILE, "phreeqc.%d.out", n); + + if (::FileExists(OUTPUT_FILE)) + { + ASSERT_TRUE(::DeleteFile(OUTPUT_FILE)); + } + ASSERT_EQ(false, ::FileExists(OUTPUT_FILE)); + + ASSERT_EQ(0, ::LoadDatabase(n, "phreeqc.dat")); + ::SetOutputFileOn(n, 0); + ::SetErrorFileOn(n, 0); + ::SetLogFileOn(n, 0); + ::SetSelectedOutputFileOn(n, 0); + ::SetDumpFileOn(n, 0); + ASSERT_EQ(false, ::FileExists(OUTPUT_FILE)); + ASSERT_EQ(0, ::RunString(n, input)); + ASSERT_EQ(false, ::FileExists(OUTPUT_FILE)); + if (n >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(n)); + } + if (::FileExists(OUTPUT_FILE)) + { + ASSERT_TRUE(::DeleteFile(OUTPUT_FILE)); + } +} + +TEST(TestIPhreeqcLib, TestMultiPunchCSelectedOutput) +{ + VAR var; + ::VarInit(&var); + + int id = ::CreateIPhreeqc(); + ASSERT_TRUE(id >= 0); + + ASSERT_EQ(0, ::LoadDatabase(id, "phreeqc.dat")); + ASSERT_EQ(0, ::RunFile(id, "multi_punch")); + + ASSERT_EQ(6, ::GetSelectedOutputRowCount(id)); + ASSERT_EQ(35, ::GetSelectedOutputColumnCount(id)); + + // headings + int ncol = 0; + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("sim"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("state"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("soln"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("dist_x"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("time"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("step"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("pH"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("pe"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("reaction"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("temp(C)"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("Alk(eq/kgw)"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("mu"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("mass_H2O"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("charge(eq)"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("pct_err"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("Na(mol/kgw)"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("Ca(mol/kgw)"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("m_Na+(mol/kgw)"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("m_HCO3-(mol/kgw)"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("la_Ca+2"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("la_CO3-2"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("CO2(g)"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("d_CO2(g)"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("dolomite"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("d_dolomite"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("si_Halite"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("pressure"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("total mol"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("volume"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("g_N2(g)"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("k_Calcite"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("dk_Calcite"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("s_Anhydrite"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("s_Barite"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("V_TOTAL_C"), std::string(var.sVal)); + + // sim + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 0, &var)); ASSERT_EQ((long)8, var.lVal); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 2, 0, &var)); ASSERT_EQ((long)10, var.lVal); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 3, 0, &var)); ASSERT_EQ((long)11, var.lVal); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 4, 0, &var)); ASSERT_EQ((long)12, var.lVal); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 5, 0, &var)); ASSERT_EQ((long)14, var.lVal); + + // state + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 1, &var)); ASSERT_EQ(std::string("react"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 2, 1, &var)); ASSERT_EQ(std::string("react"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 3, 1, &var)); ASSERT_EQ(std::string("i_soln"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 4, 1, &var)); ASSERT_EQ(std::string("i_soln"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 5, 1, &var)); ASSERT_EQ(std::string("react"), std::string(var.sVal)); + + // pH + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 6, &var)); ASSERT_NEAR(7.30475, var.dVal, ::pow(10., -2)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 2, 6, &var)); ASSERT_NEAR(7.29765, var.dVal, ::pow(10., -2)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 3, 6, &var)); ASSERT_NEAR(6.99738, var.dVal, ::pow(10., -2)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 4, 6, &var)); ASSERT_NEAR(6.99698, var.dVal, ::pow(10., -2)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 5, 6, &var)); ASSERT_NEAR(7.2942, var.dVal, ::pow(10., -2)); + + // V_TOTAL_C +#ifdef SKIP_TEST + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 34, &var)); ASSERT_NEAR(4.3729e-003, var.dVal, ::pow(10., -6)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 2, 34, &var)); ASSERT_NEAR(4.3090e-003, var.dVal, ::pow(10., -6)); +#endif + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 3, 34, &var)); ASSERT_NEAR(0.0000e+000, var.dVal, ::pow(10., -6)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 4, 34, &var)); ASSERT_NEAR(0.0000e+000, var.dVal, ::pow(10., -6)); +#ifdef SKIP_TEST + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 5, 34, &var)); ASSERT_NEAR(4.2784e-003, var.dVal, ::pow(10., -6)); +#endif + + // edge cases + int r = ::GetSelectedOutputRowCount(id); + int c = ::GetSelectedOutputColumnCount(id); + ASSERT_EQ(IPQ_INVALIDROW, ::GetSelectedOutputValue(id, -1, 0, &var)); + ASSERT_EQ(TT_ERROR, var.type); + ASSERT_EQ(VR_INVALIDROW, var.vresult); + + ASSERT_EQ(IPQ_INVALIDROW, ::GetSelectedOutputValue(id, r, 0, &var)); ASSERT_EQ(TT_ERROR, var.type); ASSERT_EQ(VR_INVALIDROW, var.vresult); + ASSERT_EQ(IPQ_INVALIDCOL, ::GetSelectedOutputValue(id, 0, -1, &var)); ASSERT_EQ(TT_ERROR, var.type); ASSERT_EQ(VR_INVALIDCOL, var.vresult); + ASSERT_EQ(IPQ_INVALIDCOL, ::GetSelectedOutputValue(id, 0, c, &var)); ASSERT_EQ(TT_ERROR, var.type); ASSERT_EQ(VR_INVALIDCOL, var.vresult); + + ::SetCurrentSelectedOutputUserNumber(id, 2); + ASSERT_EQ(7, ::GetSelectedOutputRowCount(id)); + ASSERT_EQ(16, ::GetSelectedOutputColumnCount(id)); + + // headings + ncol = 0; + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("si_Halite"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("si_Calcite"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("DUMMY_1"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("DUMMY_2"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("Sum_resid"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("Sum_Delta/U"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("MaxFracErr"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("Soln_2"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("Soln_2_min"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("Soln_2_max"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("Soln_3"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("Soln_3_min"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("Soln_3_max"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("Halite"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("Halite_min"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("Halite_max"), std::string(var.sVal)); + + // si_Halite + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 0, &var)); ASSERT_NEAR(-7.70857, var.dVal, ::pow(10., -2)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 2, 0, &var)); ASSERT_NEAR(-7.67087, var.dVal, ::pow(10., -2)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 3, 0, &var)); ASSERT_NEAR(-7.6362, var.dVal, ::pow(10., -2)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 4, 0, &var)); ASSERT_NEAR(-999.999, var.dVal, ::pow(10., -2)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 5, 0, &var)); ASSERT_NEAR(-7.60092, var.dVal, ::pow(10., -2)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 6, 0, &var)); ASSERT_NEAR(-7.60411, var.dVal, ::pow(10., -2)); + + // si_Calcite + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 1, &var)); ASSERT_NEAR(0.692077, var.dVal, ::pow(10., -2)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 2, 1, &var)); ASSERT_NEAR(0.678847, var.dVal, ::pow(10., -2)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 3, 1, &var)); ASSERT_NEAR(0.678847, var.dVal, ::pow(10., -2)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 4, 1, &var)); ASSERT_NEAR(-999.999, var.dVal, ::pow(10., -2)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 5, 1, &var)); ASSERT_NEAR(-999.999, var.dVal, ::pow(10., -2)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 6, 1, &var)); ASSERT_NEAR(0.672429, var.dVal, ::pow(10., -2)); + + // DUMMY_1 + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 2, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 2, 2, &var)); ASSERT_EQ(std::string("Dummy1"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 3, 2, &var)); ASSERT_EQ(std::string("Dummy1"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 4, 2, &var)); ASSERT_EQ(std::string("Dummy1"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 5, 2, &var)); ASSERT_EQ(std::string("Dummy1"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 6, 2, &var)); ASSERT_EQ(std::string("Dummy1"), std::string(var.sVal)); + + // DUMMY_2 + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 3, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 2, 3, &var)); ASSERT_EQ(std::string("Dummy2"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 3, 3, &var)); ASSERT_EQ(std::string("Dummy2"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 4, 3, &var)); ASSERT_EQ(std::string("Dummy2"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 5, 3, &var)); ASSERT_EQ(std::string("Dummy2"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 6, 3, &var)); ASSERT_EQ(std::string("Dummy2"), std::string(var.sVal)); + + // Sum_resid + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 4, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 2, 4, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 3, 4, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 4, 4, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 5, 4, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 6, 4, &var)); ASSERT_NEAR(3.69E-13, var.dVal, ::pow(10., log10(3.69E-13) - 2)); + + // Sum_Delta/U + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 5, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 2, 5, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 3, 5, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 4, 5, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 5, 5, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 6, 5, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + // MaxFracErr + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 6, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 2, 6, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 3, 6, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 4, 6, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 5, 6, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 6, 6, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + // Soln_2 + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 7, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 2, 7, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 3, 7, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 4, 7, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 5, 7, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 6, 7, &var)); ASSERT_NEAR(1, var.dVal, ::pow(10., -3)); + + // Soln_2_min + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 8, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 2, 8, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 3, 8, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 4, 8, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 5, 8, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 6, 8, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + // Soln_2_max + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 9, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 2, 9, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 3, 9, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 4, 9, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 5, 9, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 6, 9, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + // Soln_3 + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 10, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 2, 10, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 3, 10, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 4, 10, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 5, 10, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 6, 10, &var)); ASSERT_NEAR(1, var.dVal, ::pow(10., -3)); + + // Soln_3_min + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 11, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 2, 11, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 3, 11, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 4, 11, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 5, 11, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 6, 11, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + // Soln_3_max + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 12, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 2, 12, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 3, 12, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 4, 12, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 5, 12, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 6, 12, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + // Halite + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 13, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 2, 13, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 3, 13, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 4, 13, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 5, 13, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 6, 13, &var)); ASSERT_NEAR(0.001, var.dVal, ::pow(10., -3)); + + // Halite_min + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 14, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 2, 14, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 3, 14, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 4, 14, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 5, 14, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 6, 14, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + // Halite_max + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 15, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 2, 15, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 3, 15, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 4, 15, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 5, 15, &var)); ASSERT_EQ(TT_EMPTY, var.type); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 6, 15, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + // edge cases + r = ::GetSelectedOutputRowCount(id); + c = ::GetSelectedOutputColumnCount(id); + ASSERT_EQ(IPQ_INVALIDROW, ::GetSelectedOutputValue(id, -1, 0, &var)); ASSERT_EQ(TT_ERROR, var.type); ASSERT_EQ(VR_INVALIDROW, var.vresult); + ASSERT_EQ(IPQ_INVALIDROW, ::GetSelectedOutputValue(id, r, 0, &var)); ASSERT_EQ(TT_ERROR, var.type); ASSERT_EQ(VR_INVALIDROW, var.vresult); + ASSERT_EQ(IPQ_INVALIDCOL, ::GetSelectedOutputValue(id, 0, -1, &var)); ASSERT_EQ(TT_ERROR, var.type); ASSERT_EQ(VR_INVALIDCOL, var.vresult); + ASSERT_EQ(IPQ_INVALIDCOL, ::GetSelectedOutputValue(id, 0, c, &var)); ASSERT_EQ(TT_ERROR, var.type); ASSERT_EQ(VR_INVALIDCOL, var.vresult); + + ::SetCurrentSelectedOutputUserNumber(id, 3); + ASSERT_EQ(2, ::GetSelectedOutputRowCount(id)); + ASSERT_EQ(12, ::GetSelectedOutputColumnCount(id)); + + // headings + ncol = 0; + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("Sum_resid"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("Sum_Delta/U"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("MaxFracErr"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("Soln_2"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("Soln_2_min"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("Soln_2_max"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("Soln_3"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("Soln_3_min"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("Soln_3_max"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("Halite"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("Halite_min"), std::string(var.sVal)); + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 0, ncol++, &var)); ASSERT_EQ(std::string("Halite_max"), std::string(var.sVal)); + + // Sum_resid + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 0, &var)); ASSERT_NEAR(3.69E-13, var.dVal, ::pow(10., log10(3.69E-13) - 2)); + + // Sum_Delta/U + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 1, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + // MaxFracErr + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 2, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + // Soln_2 + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 3, &var)); ASSERT_NEAR(1, var.dVal, ::pow(10., -3)); + + // Soln_2_min + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 4, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + // Soln_2_max + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 5, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + // Soln_3 + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 6, &var)); ASSERT_NEAR(1, var.dVal, ::pow(10., -3)); + + // Soln_3_min + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 7, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + // Soln_3_max + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 8, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + // Halite + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 9, &var)); ASSERT_NEAR(0.001, var.dVal, ::pow(10., -3)); + + // Halite_min + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 10, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + // Halite_max + ASSERT_EQ(IPQ_OK, ::GetSelectedOutputValue(id, 1, 11, &var)); ASSERT_NEAR(0, var.dVal, ::pow(10., -3)); + + + // edge cases + r = ::GetSelectedOutputRowCount(id); + c = ::GetSelectedOutputColumnCount(id); + ASSERT_EQ(IPQ_INVALIDROW, ::GetSelectedOutputValue(id, -1, 0, &var)); ASSERT_EQ(TT_ERROR, var.type); ASSERT_EQ(VR_INVALIDROW, var.vresult); + ASSERT_EQ(IPQ_INVALIDROW, ::GetSelectedOutputValue(id, r, 0, &var)); ASSERT_EQ(TT_ERROR, var.type); ASSERT_EQ(VR_INVALIDROW, var.vresult); + ASSERT_EQ(IPQ_INVALIDCOL, ::GetSelectedOutputValue(id, 0, -1, &var)); ASSERT_EQ(TT_ERROR, var.type); ASSERT_EQ(VR_INVALIDCOL, var.vresult); + ASSERT_EQ(IPQ_INVALIDCOL, ::GetSelectedOutputValue(id, 0, c, &var)); ASSERT_EQ(TT_ERROR, var.type); ASSERT_EQ(VR_INVALIDCOL, var.vresult); + + ASSERT_EQ(IPQ_INVALIDARG, ::SetCurrentSelectedOutputUserNumber(id, -1)); + ASSERT_EQ(IPQ_OK, ::SetCurrentSelectedOutputUserNumber(id, 0)); + ASSERT_EQ(0, ::GetCurrentSelectedOutputUserNumber(id)); + + if (id >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(id)); + } +} + +TEST(TestIPhreeqcLib, TestGetSelectedOutputCount) +{ + int id = ::CreateIPhreeqc(); + ASSERT_TRUE(id >= 0); + + ASSERT_EQ(0, ::GetSelectedOutputCount(id)); + ASSERT_EQ(0, ::LoadDatabase(id, "phreeqc.dat")); + ASSERT_EQ(0, ::GetSelectedOutputCount(id)); + ASSERT_EQ(0, ::RunFile(id, "multi_punch")); + ASSERT_EQ(3, ::GetSelectedOutputCount(id)); + + if (id >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(id)); + } +} + +TEST(TestIPhreeqcLib, TestGetNthSelectedOutputUserNumber) +{ + int id = ::CreateIPhreeqc(); + ASSERT_TRUE(id >= 0); + + ASSERT_EQ(0, ::LoadDatabase(id, "phreeqc.dat")); + ASSERT_EQ(0, ::RunFile(id, "multi_punch")); + + ASSERT_EQ(3, ::GetSelectedOutputCount(id)); + + ASSERT_EQ(1, ::GetNthSelectedOutputUserNumber(id, 0)); + ASSERT_EQ(2, ::GetNthSelectedOutputUserNumber(id, 1)); + ASSERT_EQ(3, ::GetNthSelectedOutputUserNumber(id, 2)); + + // edge cases + ASSERT_EQ((int)IPQ_INVALIDARG, ::GetNthSelectedOutputUserNumber(id, -1)); + ASSERT_EQ((int)IPQ_INVALIDARG, ::GetNthSelectedOutputUserNumber(id, 4)); + + if (id >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(id)); + } +} + +TEST(TestIPhreeqcLib, TestGetCurrentSelectedOutputUserNumber) +{ + int id = ::CreateIPhreeqc(); + ASSERT_TRUE(id >= 0); + ASSERT_EQ(1, ::GetCurrentSelectedOutputUserNumber(id)); + + ASSERT_EQ(0, ::LoadDatabase(id, "phreeqc.dat")); + ASSERT_EQ(1, ::GetCurrentSelectedOutputUserNumber(id)); + ASSERT_EQ(0, ::RunFile(id, "multi_punch")); + + ASSERT_EQ(1, ::GetCurrentSelectedOutputUserNumber(id)); + ASSERT_EQ(6, ::GetSelectedOutputRowCount(id)); + ASSERT_EQ(35, ::GetSelectedOutputColumnCount(id)); + + ::SetCurrentSelectedOutputUserNumber(id, 2); + ASSERT_EQ(2, ::GetCurrentSelectedOutputUserNumber(id)); + ASSERT_EQ(7, ::GetSelectedOutputRowCount(id)); + ASSERT_EQ(16, ::GetSelectedOutputColumnCount(id)); + + ::SetCurrentSelectedOutputUserNumber(id, 3); + ASSERT_EQ(3, ::GetCurrentSelectedOutputUserNumber(id)); + ASSERT_EQ(2, ::GetSelectedOutputRowCount(id)); + ASSERT_EQ(12, ::GetSelectedOutputColumnCount(id)); + + // edge cases + ASSERT_EQ(IPQ_INVALIDARG, ::SetCurrentSelectedOutputUserNumber(id, -1)); + ASSERT_EQ(3, ::GetCurrentSelectedOutputUserNumber(id)); + ASSERT_EQ(IPQ_OK, ::SetCurrentSelectedOutputUserNumber(id, 0)); + ASSERT_EQ(0, ::GetCurrentSelectedOutputUserNumber(id)); + + // unload database + ASSERT_EQ(0, ::LoadDatabase(id, "phreeqc.dat")); + ASSERT_EQ(1, ::GetCurrentSelectedOutputUserNumber(id)); + + if (id >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(id)); + } +} + +TEST(TestIPhreeqcLib, TestMultiSetSelectedOutputFileName) +{ + FileTest set1("state.sel"); + ASSERT_TRUE(set1.RemoveExisting()); + + FileTest set2("si.sel"); + ASSERT_TRUE(set2.RemoveExisting()); + + int id = ::CreateIPhreeqc(); + ASSERT_TRUE(id >= 0); + + ASSERT_EQ(0, ::LoadDatabase(id, "phreeqc.dat")); + + ASSERT_EQ(IPQ_OK, ::SetCurrentSelectedOutputUserNumber(id, 1)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputStringOn(id, true)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(id, true)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileName(id, set1.GetName().c_str())); + + ASSERT_EQ(IPQ_OK, ::SetCurrentSelectedOutputUserNumber(id, 2)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputStringOn(id, true)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileOn(id, true)); + ASSERT_EQ(IPQ_OK, ::SetSelectedOutputFileName(id, set2.GetName().c_str())); + + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "TITLE Temperature dependence of solubility")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, " of gypsum and anhydrite ")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "SOLUTION 1 Pure water ")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, " pH 7.0 ")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, " temp 25.0 ")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "EQUILIBRIUM_PHASES 1 ")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, " Gypsum 0.0 1.0 ")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, " Anhydrite 0.0 1.0 ")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "REACTION_TEMPERATURE 1 ")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, " 25.0 75.0 in 51 steps ")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "SELECTED_OUTPUT 1 ")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, " -temperature ")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "SELECTED_OUTPUT 2 ")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, " -si anhydrite gypsum ")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "END ")); + + ASSERT_EQ(0, ::RunAccumulated(id)); + + ASSERT_TRUE(set1.VerifyExists()); + ASSERT_TRUE(set2.VerifyExists()); + + if (id >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(id)); + } +} + +TEST(TestIPhreeqcLib, TestWissmeier20131203) +{ + int id = ::CreateIPhreeqc(); + ASSERT_TRUE(id >= 0); + + ASSERT_EQ(0, ::LoadDatabase(id, "phreeqc.dat")); + + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "selected_output 1")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "-totals O")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "END")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "selected_output 1")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "-totals H")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "solution")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "END")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "selected_output")); + + // original asserts here + ASSERT_EQ(0, ::RunAccumulated(id)); + + ASSERT_EQ(1, ::GetSelectedOutputCount(id)); + + ASSERT_EQ(9, ::GetSelectedOutputColumnCount(id)); + ASSERT_EQ(2, ::GetSelectedOutputRowCount(id)); + + if (id >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(id)); + } +} + +TEST(TestIPhreeqcLib, TestWissmeier20131203_2) +{ + int id = ::CreateIPhreeqc(); + ASSERT_TRUE(id >= 0); + + ASSERT_EQ(0, ::LoadDatabase(id, "phreeqc.dat")); + + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "selected_output 22")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "-totals O")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "END")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "selected_output 22")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "-totals H")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "solution")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "END")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "selected_output 22")); + + // original asserts here + ASSERT_EQ(0, ::RunAccumulated(id)); + + ASSERT_EQ(1, ::GetSelectedOutputCount(id)); + + ASSERT_EQ(IPQ_OK, ::SetCurrentSelectedOutputUserNumber(id, 22)); + ASSERT_EQ(1, ::GetSelectedOutputColumnCount(id)); + ASSERT_EQ(2, ::GetSelectedOutputRowCount(id)); + + if (id >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(id)); + } +} + +TEST(TestIPhreeqcLib, TestWissmeier20131203_3) +{ + int id = ::CreateIPhreeqc(); + ASSERT_TRUE(id >= 0); + + ASSERT_EQ(0, ::LoadDatabase(id, "phreeqc.dat")); + + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "selected_output 1")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "-reset false")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "-totals O")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "END")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "selected_output 1")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "-reset false")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "-totals H")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "solution")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "END")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "selected_output")); + ASSERT_EQ(IPQ_OK, ::AccumulateLine(id, "-reset false")); + + // original asserts here + ASSERT_EQ(0, ::RunAccumulated(id)); + + ASSERT_EQ(1, ::GetSelectedOutputCount(id)); + + ASSERT_EQ(1, ::GetSelectedOutputColumnCount(id)); + ASSERT_EQ(2, ::GetSelectedOutputRowCount(id)); + + if (id >= 0) + { + ASSERT_EQ(IPQ_OK, ::DestroyIPhreeqc(id)); + } +} + +TEST(TestIPhreeqcLib, TestIsZeroInitialized) +{ + std::map test_map; + ASSERT_TRUE(test_map.find((void*)0) == test_map.end()); + ASSERT_TRUE(test_map[(void*)0] == (void*)0); + + int i = int(); + long l = long(); + float f = float(); + double d = double(); + + // these would fail + /** + int i; + long l; + float f; + double d; + **/ + + ASSERT_EQ((int)0, i); + ASSERT_EQ((long)0, l); + ASSERT_EQ((float)0, f); + ASSERT_EQ((double)0, d); +} diff --git a/gtest/TestSelectedOutput.cpp b/gtest/TestSelectedOutput.cpp new file mode 100644 index 00000000..bd7d7243 --- /dev/null +++ b/gtest/TestSelectedOutput.cpp @@ -0,0 +1,669 @@ +#include + +#include "../src/CSelectedOutput.hxx" +#include "IPhreeqc.hpp" +#include "Phreeqc.h" + +#if defined(_WIN32) +#define strdup _strdup +#endif + +TEST(TestSelectedOutput, TestEmpty) +{ + CSelectedOutput co; + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + co.Clear(); + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); +} + +TEST(TestSelectedOutput, TestSinglePushBack) +{ + CSelectedOutput co; + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + co.Clear(); + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + + CVar v(7.0); + ASSERT_EQ(0, co.PushBack("pH", v)); + + ASSERT_EQ((size_t)1, co.GetColCount()); + // row count doesn't change until EndRow is called + ASSERT_EQ((size_t)1, co.GetRowCount()); + ASSERT_EQ(0, co.EndRow()); + + ASSERT_EQ((size_t)1, co.GetColCount()); + ASSERT_EQ((size_t)2, co.GetRowCount()); +#if defined(_DEBUG) + co.Dump("TestSinglePushBack"); +#endif +} + +TEST(TestSelectedOutput, TestMultiplePushBack) +{ + CSelectedOutput co; + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + co.Clear(); + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + + CVar v1(7.0); + ASSERT_EQ(0, co.PushBack("pH", v1)); + + ASSERT_EQ((size_t)1, co.GetColCount()); + ASSERT_EQ((size_t)1, co.GetRowCount()); + + ASSERT_EQ(0, co.EndRow()); + ASSERT_EQ((size_t)1, co.GetColCount()); + ASSERT_EQ((size_t)2, co.GetRowCount()); + + CVar v2(8.0); + ASSERT_EQ(0, co.PushBack("pH", v2)); + + ASSERT_EQ((size_t)1, co.GetColCount()); + ASSERT_EQ((size_t)2, co.GetRowCount()); + + ASSERT_EQ(0, co.EndRow()); + ASSERT_EQ((size_t)1, co.GetColCount()); + ASSERT_EQ((size_t)3, co.GetRowCount()); +#if defined(_DEBUG) + co.Dump("TestMultiplePushBack"); +#endif +} + +TEST(TestSelectedOutput, TestNewHeadingsPushBack) +{ + CSelectedOutput co; + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + + co.Clear(); + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + + CVar v1(7.0); + ASSERT_EQ(0, co.PushBack("pH", v1)); + + ASSERT_EQ((size_t)1, co.GetColCount()); + ASSERT_EQ((size_t)1, co.GetRowCount()); + + ASSERT_EQ(0, co.EndRow()); + ASSERT_EQ((size_t)1, co.GetColCount()); + ASSERT_EQ((size_t)2, co.GetRowCount()); + + CVar v2(8.0); + ASSERT_EQ(0, co.PushBack("pH", v2)); + + ASSERT_EQ((size_t)1, co.GetColCount()); + ASSERT_EQ((size_t)2, co.GetRowCount()); + + CVar v3(9.0); + ASSERT_EQ(0, co.PushBack("user_pH", v3)); + + ASSERT_EQ((size_t)2, co.GetColCount()); + ASSERT_EQ((size_t)2, co.GetRowCount()); + + + ASSERT_EQ(0, co.EndRow()); + ASSERT_EQ((size_t)2, co.GetColCount()); + ASSERT_EQ((size_t)3, co.GetRowCount()); +#if defined(_DEBUG) + co.Dump("TestNewHeadingsPushBack"); +#endif +} + +TEST(TestSelectedOutput, TestPushBackDouble) +{ + CSelectedOutput co; + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + + co.Clear(); + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + + + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + + ASSERT_EQ(0, co.PushBackDouble("pH", 7.0)); + + ASSERT_EQ((size_t)1, co.GetColCount()); + ASSERT_EQ((size_t)1, co.GetRowCount()); // heading + + ASSERT_EQ(0, co.EndRow()); + ASSERT_EQ((size_t)1, co.GetColCount()); + ASSERT_EQ((size_t)2, co.GetRowCount()); + + CVar v; + ASSERT_EQ(TT_EMPTY, v.type); + ASSERT_EQ(VR_OK, co.Get(0, 0, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("pH"), std::string(v.sVal)); + + CVar vval; + ASSERT_EQ(TT_EMPTY, vval.type); + ASSERT_EQ(VR_OK, co.Get(1, 0, &vval)); + ASSERT_EQ(TT_DOUBLE, vval.type); + ASSERT_EQ(7.0, vval.dVal); +} + +TEST(TestSelectedOutput, TestPushBackLong) +{ + CSelectedOutput co; + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + + co.Clear(); + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + + ASSERT_EQ(0, co.PushBackLong("Sim", 2)); + + ASSERT_EQ((size_t)1, co.GetColCount()); + ASSERT_EQ((size_t)1, co.GetRowCount()); // heading plus first row + + ASSERT_EQ(0, co.EndRow()); + ASSERT_EQ((size_t)1, co.GetColCount()); + ASSERT_EQ((size_t)2, co.GetRowCount()); + + CVar v; + ASSERT_EQ(TT_EMPTY, v.type); + ASSERT_EQ(VR_OK, co.Get(0, 0, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("Sim"), std::string(v.sVal)); + + CVar vval; + ASSERT_EQ(TT_EMPTY, vval.type); + ASSERT_EQ(VR_OK, co.Get(1, 0, &vval)); + ASSERT_EQ(TT_LONG, vval.type); + ASSERT_EQ(2l, vval.lVal); +} + +TEST(TestSelectedOutput, TestPushBackString) +{ + CSelectedOutput co; + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + + co.Clear(); + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + + ASSERT_EQ(0, co.PushBackString("state", "i_soln")); + + ASSERT_EQ((size_t)1, co.GetColCount()); + ASSERT_EQ((size_t)1, co.GetRowCount()); // heading + + ASSERT_EQ(0, co.EndRow()); + ASSERT_EQ((size_t)1, co.GetColCount()); + ASSERT_EQ((size_t)2, co.GetRowCount()); + + CVar v; + ASSERT_EQ(TT_EMPTY, v.type); + ASSERT_EQ(VR_OK, co.Get(0, 0, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("state"), std::string(v.sVal)); + + CVar vval; + ASSERT_EQ(TT_EMPTY, vval.type); + ASSERT_EQ(VR_OK, co.Get(1, 0, &vval)); + ASSERT_EQ(TT_STRING, vval.type); + ASSERT_EQ(std::string("i_soln"), std::string(vval.sVal)); +} + +TEST(TestSelectedOutput, TestPushBackEmpty) +{ + CSelectedOutput co; + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + + co.Clear(); + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + + ASSERT_EQ(0, co.PushBackEmpty("Empty")); + + ASSERT_EQ((size_t)1, co.GetColCount()); + ASSERT_EQ((size_t)1, co.GetRowCount()); // heading + + ASSERT_EQ(0, co.EndRow()); + ASSERT_EQ((size_t)1, co.GetColCount()); + ASSERT_EQ((size_t)2, co.GetRowCount()); + + CVar v; + ASSERT_EQ(TT_EMPTY, v.type); + ASSERT_EQ(VR_OK, co.Get(0, 0, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("Empty"), std::string(v.sVal)); + + CVar vval; + ASSERT_EQ(TT_EMPTY, vval.type); + ASSERT_EQ(VR_OK, co.Get(1, 0, &vval)); + ASSERT_EQ(TT_EMPTY, vval.type); +} + +TEST(TestSelectedOutput, TestDuplicateHeadings) +{ + CSelectedOutput co; + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + + co.Clear(); + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + + ASSERT_EQ(0, co.PushBackDouble("pH", 7.0)); + + ASSERT_EQ((size_t)1, co.GetColCount()); + ASSERT_EQ((size_t)1, co.GetRowCount()); // heading + + // overwrite pH with 8.0 + // + ASSERT_EQ(0, co.PushBackDouble("pH", 8.0)); + + ASSERT_EQ((size_t)1, co.GetColCount()); + ASSERT_EQ((size_t)1, co.GetRowCount()); // heading + + ASSERT_EQ(0, co.EndRow()); + ASSERT_EQ((size_t)1, co.GetColCount()); + ASSERT_EQ((size_t)2, co.GetRowCount()); + + CVar v; + ASSERT_EQ(TT_EMPTY, v.type); + ASSERT_EQ(VR_OK, co.Get(0, 0, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("pH"), std::string(v.sVal)); + + + CVar vval; + ASSERT_EQ(TT_EMPTY, vval.type); + ASSERT_EQ(VR_OK, co.Get(1, 0, &vval)); + ASSERT_EQ(TT_DOUBLE, vval.type); + ASSERT_EQ(8.0, vval.dVal); +} + +TEST(TestSelectedOutput, TestEndRow) +{ + CSelectedOutput co; + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + + co.Clear(); + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + + ASSERT_EQ(0, co.PushBackDouble("pH", 7.0)); + + ASSERT_EQ((size_t)1, co.GetColCount()); + ASSERT_EQ((size_t)1, co.GetRowCount()); // heading + + ASSERT_EQ(0, co.EndRow()); + ASSERT_EQ((size_t)1, co.GetColCount()); + ASSERT_EQ((size_t)2, co.GetRowCount()); + + CVar v; + ASSERT_EQ(TT_EMPTY, v.type); + ASSERT_EQ(VR_OK, co.Get(0, 0, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("pH"), std::string(v.sVal)); + + CVar vval; + ASSERT_EQ(TT_EMPTY, vval.type); + ASSERT_EQ(VR_OK, co.Get(1, 0, &vval)); + ASSERT_EQ(TT_DOUBLE, vval.type); + ASSERT_EQ(7.0, vval.dVal); + + ASSERT_EQ(0, co.PushBackDouble("pH", 8.0)); + ASSERT_EQ(0, co.EndRow()); + ASSERT_EQ((size_t)1, co.GetColCount()); + ASSERT_EQ((size_t)3, co.GetRowCount()); + + CVar vval3; + ASSERT_EQ(TT_EMPTY, vval3.type); + ASSERT_EQ(VR_OK, co.Get(1, 0, &vval3)); + ASSERT_EQ(TT_DOUBLE, vval3.type); + ASSERT_EQ(7.0, vval3.dVal); + + CVar vval2; + ASSERT_EQ(TT_EMPTY, vval2.type); + ASSERT_EQ(VR_OK, co.Get(2, 0, &vval2)); + ASSERT_EQ(TT_DOUBLE, vval2.type); + ASSERT_EQ(8.0, vval2.dVal); +} + +TEST(TestSelectedOutput, TestEndRow2) +{ + CSelectedOutput co; + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + + co.Clear(); + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + + ASSERT_EQ(0, co.PushBackDouble("pH", 6.0)); + ASSERT_EQ(0, co.PushBackDouble("pH", 7.0)); + ASSERT_EQ(0, co.PushBackDouble("pH", 8.0)); + ASSERT_EQ(0, co.PushBackDouble("pH", 9.0)); + + ASSERT_EQ(0, co.EndRow()); + ASSERT_EQ((size_t)1, co.GetColCount()); + ASSERT_EQ((size_t)2, co.GetRowCount()); + + CVar v; + ASSERT_EQ(TT_EMPTY, v.type); + ASSERT_EQ(VR_OK, co.Get(0, 0, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("pH"), std::string(v.sVal)); + + CVar vval; + ASSERT_EQ(TT_EMPTY, vval.type); + ASSERT_EQ(VR_OK, co.Get(1, 0, &vval)); + ASSERT_EQ(TT_DOUBLE, vval.type); + ASSERT_EQ(9.0, vval.dVal); // dups get overwritten + + ASSERT_EQ(0, co.PushBackDouble("pH", 8.0)); + ASSERT_EQ(0, co.EndRow()); + ASSERT_EQ((size_t)1, co.GetColCount()); + ASSERT_EQ((size_t)3, co.GetRowCount()); + + CVar vval3; + ASSERT_EQ(TT_EMPTY, vval3.type); + ASSERT_EQ(VR_OK, co.Get(1, 0, &vval3)); + ASSERT_EQ(TT_DOUBLE, vval3.type); + ASSERT_EQ(9.0, vval3.dVal); + + CVar vval2; + ASSERT_EQ(TT_EMPTY, vval2.type); + ASSERT_EQ(VR_OK, co.Get(2, 0, &vval2)); + ASSERT_EQ(TT_DOUBLE, vval2.type); + ASSERT_EQ(8.0, vval2.dVal); +} + + +TEST(TestSelectedOutput, TestTooManyHeadings) +{ + // COMMENT: {8/26/2013 4:12:03 PM} IPhreeqc p; + // COMMENT: {8/26/2013 4:12:03 PM} + // COMMENT: {8/26/2013 4:12:03 PM} ASSERT_EQ((size_t)0, p.PtrSelectedOutput->GetColCount()); + // COMMENT: {8/26/2013 4:12:03 PM} ASSERT_EQ((size_t)0, p.PtrSelectedOutput->GetRowCount()); + // COMMENT: {8/26/2013 4:12:03 PM} + // COMMENT: {8/26/2013 4:12:03 PM} p.PtrSelectedOutput->Clear(); + // COMMENT: {8/26/2013 4:12:03 PM} ASSERT_EQ((size_t)0, p.PtrSelectedOutput->GetColCount()); + // COMMENT: {8/26/2013 4:12:03 PM} ASSERT_EQ((size_t)0, p.PtrSelectedOutput->GetRowCount()); + // COMMENT: {8/26/2013 4:12:03 PM} + // COMMENT: {8/26/2013 4:12:03 PM} // USER_PUNCH + // COMMENT: {8/26/2013 4:12:03 PM} // -headings 1.name 1.type 1.moles + // COMMENT: {8/26/2013 4:12:03 PM} + // COMMENT: {8/26/2013 4:12:03 PM} p.PhreeqcPtr->n_user_punch_index = 0; + // COMMENT: {8/26/2013 4:12:03 PM} p.PhreeqcPtr->UserPunch_map[1] = UserPunch(); + // COMMENT: {8/26/2013 4:12:03 PM} p.PhreeqcPtr->current_user_punch = &(p.PhreeqcPtr->UserPunch_map[1]); + // COMMENT: {8/26/2013 4:12:03 PM} + // COMMENT: {8/26/2013 4:12:03 PM} std::vector< std::string > headings; + // COMMENT: {8/26/2013 4:12:03 PM} headings.push_back("1.name"); + // COMMENT: {8/26/2013 4:12:03 PM} headings.push_back("1.type"); + // COMMENT: {8/26/2013 4:12:03 PM} headings.push_back("1.moles"); + // COMMENT: {8/26/2013 4:12:03 PM} p.PhreeqcPtr->UserPunch_map[1].Set_headings(headings); + // COMMENT: {8/26/2013 4:12:03 PM} + // COMMENT: {8/26/2013 4:12:03 PM} ASSERT_EQ(0, p.EndRow()); + // COMMENT: {8/26/2013 4:12:03 PM} ASSERT_EQ((size_t)3, p.PtrSelectedOutput->GetColCount()); + // COMMENT: {8/26/2013 4:12:03 PM} ASSERT_EQ((size_t)2, p.PtrSelectedOutput->GetRowCount()); + // COMMENT: {8/26/2013 4:12:03 PM} + // COMMENT: {8/26/2013 4:12:03 PM} + // COMMENT: {8/26/2013 4:12:03 PM}#if defined(_DEBUG) + // COMMENT: {8/26/2013 4:12:03 PM} p.PtrSelectedOutput->Dump("TestTooManyHeadings"); + // COMMENT: {8/26/2013 4:12:03 PM}#endif + // COMMENT: {8/26/2013 4:12:03 PM} + // COMMENT: {8/26/2013 4:12:03 PM} // clean up headings + // COMMENT: {8/26/2013 4:12:03 PM} p.PhreeqcPtr->UserPunch_map[1].Get_headings().empty(); + // COMMENT: {8/26/2013 4:12:03 PM} + // COMMENT: {8/26/2013 4:12:03 PM} CVar head0, head1, head2; + // COMMENT: {8/26/2013 4:12:03 PM} CVar val0, val1, val2; + // COMMENT: {8/26/2013 4:12:03 PM} + // COMMENT: {8/26/2013 4:12:03 PM} ASSERT_EQ(VR_OK, p.PtrSelectedOutput->Get(0, 0, &head0)); + // COMMENT: {8/26/2013 4:12:03 PM} ASSERT_EQ(VR_OK, p.PtrSelectedOutput->Get(0, 1, &head1)); + // COMMENT: {8/26/2013 4:12:03 PM} ASSERT_EQ(VR_OK, p.PtrSelectedOutput->Get(0, 2, &head2)); + // COMMENT: {8/26/2013 4:12:03 PM} + // COMMENT: {8/26/2013 4:12:03 PM} ASSERT_EQ(VR_OK, p.PtrSelectedOutput->Get(1, 0, &val0)); + // COMMENT: {8/26/2013 4:12:03 PM} ASSERT_EQ(VR_OK, p.PtrSelectedOutput->Get(1, 1, &val1)); + // COMMENT: {8/26/2013 4:12:03 PM} ASSERT_EQ(VR_OK, p.PtrSelectedOutput->Get(1, 2, &val2)); + // COMMENT: {8/26/2013 4:12:03 PM} + // COMMENT: {8/26/2013 4:12:03 PM} ASSERT_EQ(TT_STRING, head0.type); + // COMMENT: {8/26/2013 4:12:03 PM} ASSERT_EQ(TT_STRING, head1.type); + // COMMENT: {8/26/2013 4:12:03 PM} ASSERT_EQ(TT_STRING, head2.type); + // COMMENT: {8/26/2013 4:12:03 PM} + // COMMENT: {8/26/2013 4:12:03 PM} ASSERT_EQ(TT_EMPTY, val0.type); + // COMMENT: {8/26/2013 4:12:03 PM} ASSERT_EQ(TT_EMPTY, val1.type); + // COMMENT: {8/26/2013 4:12:03 PM} ASSERT_EQ(TT_EMPTY, val2.type); + // COMMENT: {8/26/2013 4:12:03 PM} + // COMMENT: {8/26/2013 4:12:03 PM} ASSERT_EQ(std::string("1.name"), std::string(head0.sVal)); + // COMMENT: {8/26/2013 4:12:03 PM} ASSERT_EQ(std::string("1.type"), std::string(head1.sVal)); + // COMMENT: {8/26/2013 4:12:03 PM} ASSERT_EQ(std::string("1.moles"), std::string(head2.sVal)); + // COMMENT: {8/26/2013 4:12:03 PM} + // COMMENT: {8/26/2013 4:12:03 PM} + // COMMENT: {8/26/2013 4:12:03 PM} ASSERT_EQ(0, p.PtrSelectedOutput->PushBackLong("sim", 1)); + // COMMENT: {8/26/2013 4:12:03 PM} ASSERT_EQ(0, p.PtrSelectedOutput->PushBackString("state", "i_soln")); + // COMMENT: {8/26/2013 4:12:03 PM} ASSERT_EQ(0, p.PtrSelectedOutput->PushBackLong("soln", 22)); + // COMMENT: {8/26/2013 4:12:03 PM} + // COMMENT: {8/26/2013 4:12:03 PM} ASSERT_EQ(0, p.PtrSelectedOutput->EndRow()); + // COMMENT: {8/26/2013 4:12:03 PM} ASSERT_EQ((size_t)6, p.PtrSelectedOutput->GetColCount()); + // COMMENT: {8/26/2013 4:12:03 PM} ASSERT_EQ((size_t)3, p.PtrSelectedOutput->GetRowCount()); + // COMMENT: {8/26/2013 4:12:03 PM}#if defined(_DEBUG) + // COMMENT: {8/26/2013 4:12:03 PM} p.PtrSelectedOutput->Dump("TestTooManyHeadings"); + // COMMENT: {8/26/2013 4:12:03 PM}#endif +} + +TEST(TestSelectedOutput, TestNotEnoughHeadings) +{ + CSelectedOutput co; + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + + co.Clear(); + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + + // USER_PUNCH + // -headings 1.name 1.type 1.moles + + ASSERT_EQ(0, co.PushBackLong("sim", 1)); + ASSERT_EQ(0, co.PushBackString("state", "i_soln")); + ASSERT_EQ(0, co.PushBackLong("soln", 22)); + + ASSERT_EQ(0, co.EndRow()); + ASSERT_EQ((size_t)3, co.GetColCount()); + ASSERT_EQ((size_t)2, co.GetRowCount()); +#if defined(_DEBUG) + co.Dump("TestNotEnoughHeadings"); +#endif + + ASSERT_EQ(0, co.PushBackLong("sim", 2)); + ASSERT_EQ(0, co.PushBackString("state", "react")); + ASSERT_EQ(0, co.PushBackLong("soln", 23)); + + ASSERT_EQ(0, co.PushBackEmpty("no_heading_1")); + ASSERT_EQ(0, co.PushBackEmpty("no_heading_2")); + ASSERT_EQ(0, co.PushBackEmpty("no_heading_3")); + +#if defined(_DEBUG) + co.Dump("TestNotEnoughHeadings"); +#endif + + ASSERT_EQ(0, co.EndRow()); + ASSERT_EQ((size_t)6, co.GetColCount()); + ASSERT_EQ((size_t)3, co.GetRowCount()); + + CVar head0, head1, head2, head3, head4, head5; + CVar val0, val1, val2, val3, val4, val5; + + ASSERT_EQ(VR_OK, co.Get(0, 0, &head0)); + ASSERT_EQ(VR_OK, co.Get(0, 1, &head1)); + ASSERT_EQ(VR_OK, co.Get(0, 2, &head2)); + ASSERT_EQ(VR_OK, co.Get(0, 3, &head3)); + ASSERT_EQ(VR_OK, co.Get(0, 4, &head4)); + ASSERT_EQ(VR_OK, co.Get(0, 5, &head5)); + + ASSERT_EQ(VR_OK, co.Get(1, 0, &val0)); + ASSERT_EQ(VR_OK, co.Get(1, 1, &val1)); + ASSERT_EQ(VR_OK, co.Get(1, 2, &val2)); + ASSERT_EQ(VR_OK, co.Get(1, 3, &val3)); + ASSERT_EQ(VR_OK, co.Get(1, 4, &val4)); + ASSERT_EQ(VR_OK, co.Get(1, 5, &val5)); + + ASSERT_EQ(TT_STRING, head0.type); + ASSERT_EQ(TT_STRING, head1.type); + ASSERT_EQ(TT_STRING, head2.type); + ASSERT_EQ(TT_STRING, head3.type); + ASSERT_EQ(TT_STRING, head4.type); + ASSERT_EQ(TT_STRING, head5.type); + + ASSERT_EQ(TT_LONG, val0.type); + ASSERT_EQ(TT_STRING, val1.type); + ASSERT_EQ(TT_LONG, val2.type); + ASSERT_EQ(TT_EMPTY, val3.type); + ASSERT_EQ(TT_EMPTY, val4.type); + ASSERT_EQ(TT_EMPTY, val5.type); + + ASSERT_EQ(std::string("sim"), std::string(head0.sVal)); + ASSERT_EQ(std::string("state"), std::string(head1.sVal)); + ASSERT_EQ(std::string("soln"), std::string(head2.sVal)); + ASSERT_EQ(std::string("no_heading_1"), std::string(head3.sVal)); + ASSERT_EQ(std::string("no_heading_2"), std::string(head4.sVal)); + ASSERT_EQ(std::string("no_heading_3"), std::string(head5.sVal)); + + ASSERT_EQ(1l, val0.lVal); + ASSERT_EQ(std::string("i_soln"), std::string(val1.sVal)); + ASSERT_EQ(22l, val2.lVal); +} + +TEST(TestSelectedOutput, TestInvalidRow) +{ + CSelectedOutput co; + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + + co.Clear(); + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + + CVar v; + ASSERT_EQ(VR_INVALIDROW, co.Get(0, 0, &v)); + ASSERT_EQ(TT_ERROR, v.type); + ASSERT_EQ(VR_INVALIDROW, v.vresult); + + + ASSERT_EQ(VR_INVALIDROW, co.Get(-1, -1, &v)); + ASSERT_EQ(TT_ERROR, v.type); + ASSERT_EQ(VR_INVALIDROW, v.vresult); + + ASSERT_EQ(0, co.PushBackEmpty("heading")); + ASSERT_EQ(0, co.EndRow()); + ASSERT_EQ((size_t)1, co.GetColCount()); + ASSERT_EQ((size_t)2, co.GetRowCount()); + + ASSERT_EQ(VR_OK, co.Get(0, 0, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("heading"), std::string(v.sVal)); + + ASSERT_EQ(VR_OK, co.Get(1, 0, &v)); + ASSERT_EQ(TT_EMPTY, v.type); + + + ASSERT_EQ(VR_INVALIDROW, co.Get(2, 0, &v)); + ASSERT_EQ(TT_ERROR, v.type); + ASSERT_EQ(VR_INVALIDROW, v.vresult); +} + +TEST(TestSelectedOutput, TestInvalidCol) +{ + CSelectedOutput co; + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + + co.Clear(); + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + + CVar v; + ASSERT_EQ(VR_INVALIDROW, co.Get(0, 0, &v)); + ASSERT_EQ(TT_ERROR, v.type); + ASSERT_EQ(VR_INVALIDROW, v.vresult); + + + ASSERT_EQ(VR_INVALIDROW, co.Get(-1, -1, &v)); + ASSERT_EQ(TT_ERROR, v.type); + ASSERT_EQ(VR_INVALIDROW, v.vresult); + + ASSERT_EQ(0, co.PushBackEmpty("heading")); + ASSERT_EQ(0, co.EndRow()); + ASSERT_EQ((size_t)1, co.GetColCount()); + ASSERT_EQ((size_t)2, co.GetRowCount()); + + ASSERT_EQ(VR_OK, co.Get(0, 0, &v)); + ASSERT_EQ(TT_STRING, v.type); + ASSERT_EQ(std::string("heading"), std::string(v.sVal)); + + ASSERT_EQ(VR_OK, co.Get(1, 0, &v)); + ASSERT_EQ(TT_EMPTY, v.type); + + + ASSERT_EQ(VR_INVALIDCOL, co.Get(0, 1, &v)); + ASSERT_EQ(TT_ERROR, v.type); + ASSERT_EQ(VR_INVALIDCOL, v.vresult); + + ASSERT_EQ(VR_INVALIDCOL, co.Get(0, -1, &v)); + ASSERT_EQ(TT_ERROR, v.type); + ASSERT_EQ(VR_INVALIDCOL, v.vresult); +} + +TEST(TestSelectedOutput, TestGet) +{ + CSelectedOutput co; + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + + co.Clear(); + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + + ASSERT_EQ(0, co.PushBackEmpty("heading")); + ASSERT_EQ(0, co.EndRow()); + ASSERT_EQ((size_t)1, co.GetColCount()); + ASSERT_EQ((size_t)2, co.GetRowCount()); + + + CVar v0 = co.Get(0, 0); + ASSERT_EQ(TT_STRING, v0.type); + ASSERT_EQ(std::string("heading"), std::string(v0.sVal)); + + CVar v1 = co.Get(1, 0); + ASSERT_EQ(TT_EMPTY, v1.type); +} + +TEST(TestSelectedOutput, TestLongHeadings) +{ + CSelectedOutput co; + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + + co.Clear(); + ASSERT_EQ((size_t)0, co.GetColCount()); + ASSERT_EQ((size_t)0, co.GetRowCount()); + + ASSERT_EQ(0, co.PushBackEmpty("heading890123456789012345678901234567890123456789")); + ASSERT_EQ(0, co.EndRow()); + ASSERT_EQ((size_t)1, co.GetColCount()); + ASSERT_EQ((size_t)2, co.GetRowCount()); + + CVar v0 = co.Get(0, 0); + ASSERT_EQ(TT_STRING, v0.type); + ASSERT_EQ(std::string("heading890123456789012345678901234567890123456789"), std::string(v0.sVal)); + + CVar v1 = co.Get(1, 0); + ASSERT_EQ(TT_EMPTY, v1.type); +} diff --git a/gtest/TestVar.cpp b/gtest/TestVar.cpp new file mode 100644 index 00000000..ba9b2af1 --- /dev/null +++ b/gtest/TestVar.cpp @@ -0,0 +1,10 @@ +#include + +#include "../src/Var.h" + +TEST(TestVar, VarInit) +{ + VAR v; + ::VarInit(&v); + ASSERT_EQ(TT_EMPTY, v.type); +} diff --git a/gtest/conv_fail.in b/gtest/conv_fail.in new file mode 100644 index 00000000..bd1a403a --- /dev/null +++ b/gtest/conv_fail.in @@ -0,0 +1,11 @@ +SOLUTION 1 + pH 7 + Na 1 +PHASES + Fix_H+ + H+ = H+ + log_k 0 +EQUILIBRIUM_PHASES + Fix_H+ -10 HCl 10 +##SELECTED_OUTPUT +END diff --git a/gtest/dump b/gtest/dump new file mode 100644 index 00000000..1d610fcd --- /dev/null +++ b/gtest/dump @@ -0,0 +1,42 @@ +database ../database/Amm.dat +solution 0 +units mol/kgw +-water 0.4 +pH 7 charge +Na 1 + +solution 101 +units mol/kgw +-water 0.2 +pH 7 charge + +solution 1-100 +units mol/kgw +pH 7 charge +-water 0.2 +Amm 1 + +GAS_PHASE 1-100 + -fixed_volume + -volume 1 + -temperature 30 + Amm(g) 0.1 + N2(g) 0.9 + +#---------------- OUTPUT and TRANSPORT ----------------# +KNOBS + -logfile true + +transport +-cells 100 +-shifts 100 +-lengths 0.1 +-time_step 0.1 +-flow_direction diffusion +-bc 1 1 +-dump dump.phrq +-dump_frequency 10 +-dump_restart 0 +-print_frequency 50 +end + diff --git a/gtest/iso.dat b/gtest/iso.dat new file mode 100644 index 00000000..8558cd69 --- /dev/null +++ b/gtest/iso.dat @@ -0,0 +1,7231 @@ +SOLUTION_MASTER_SPECIES +E e- 0 0 0.0 +H H3O+ -1 H 1.008 +H(0) H2 0 H +H(1) H3O+ -1 H +O H2O 0 O 16.00 +O(0) O2 0 O +O(-2) H2O 0 O +Ca Ca+2 0 Ca 40.08 +Mg Mg+2 0 Mg 24.312 +Na Na+ 0 Na 22.9898 +K K+ 0 K 39.102 +Fe Fe+2 0.0 Fe 55.847 +Fe(+2) Fe+2 0.0 Fe +Fe(+3) Fe+3 -2.0 Fe +Al Al+3 0.0 Al 26.9815 +Si H4SiO4 0.0 SiO2 28.0843 +Cl Cl- 0 Cl 35.453 +C CO2 0 HCO3 12.0111 +C(4) CO2 0 HCO3 +C(-4) CH4 0 CH4 +S SO4-2 0 S 31.972 +S(6) SO4-2 0 SO4 +S(-2) HS- 1 S +N NO3- 0 N 14.0067 +N(+5) NO3- 0 N +N(+3) NO2- 0 N +N(0) N2 0 N +N(-3) NH4+ 0 N +P PO4-3 2.0 P 30.9738 +F F- 0.0 F 18.9984 +Br Br- 0.0 Br 79.904 +Alkalinity CO2 0.0 50.05 50.05 + +SOLUTION_SPECIES +H3O+ = H3O+ + log_k 0.000 + -gamma 9.0000 0.0000 + +e- = e- + log_k 0.000 + +H2O = H2O + log_k 0.000 + +Ca+2 = Ca+2 + log_k 0.000 + -gamma 5.0000 0.1650 + +Mg+2 = Mg+2 + log_k 0.000 + -gamma 5.5000 0.2000 + +Na+ = Na+ + log_k 0.000 + -gamma 4.0000 0.0750 + +K+ = K+ + log_k 0.000 + -gamma 3.5000 0.0150 + +Fe+2 = Fe+2 + log_k 0.000 + -gamma 6.0000 0.0000 + +Al+3 = Al+3 + log_k 0.000 + -gamma 9.0000 0.0000 + +H4SiO4 = H4SiO4 + log_k 0.000 + +Cl- = Cl- + log_k 0.000 + -gamma 3.5000 0.0150 + +SO4-2 = SO4-2 + log_k 0.000 + -gamma 5.0000 -0.0400 + +NO3- = NO3- + log_k 0.000 + -gamma 3.0000 0.0000 + +PO4-3 = PO4-3 + log_k 0.000 + -gamma 4.0000 0.0000 + +F- = F- + log_k 0.000 + -gamma 3.5000 0.0000 + +Br- = Br- + log_k 0.000 + -gamma 3.0000 0.0000 + +2H2O = OH- + H3O+ + log_k -14.000 + delta_h 13.362 kcal + -analytic -283.971 -0.05069842 13323.0 102.24447 -1119669.0 + -gamma 3.5000 0.0000 + +6 H2O = O2 + 4 H3O+ + 4 e- + log_k -86.08 + delta_h 134.79 kcal + +2 H3O+ + 2 e- = H2 + 2H2O + log_k -3.15 + delta_h -1.759 kcal + +CO2 + 2H2O = HCO3- + H3O+ + log_k -6.352 + delta_h 2.177 kcal + -analytic -356.3094 -0.06092 21834.37 126.8339 -1684915 + +CO2 + 3H2O = CO3-2 + 2H3O+ + log_k -16.681 + delta_h 5.738 kcal + -analytic -464.1965 -0.09344813 26986.16 165.75951 -2248628.9 + +CO3-2 + 10 H3O+ + 8 e- = CH4 + 13 H2O + log_k 41.071 + delta_h -61.039 kcal + +SO4-2 + H3O+ = HSO4- + H2O + log_k 1.988 + delta_h 3.85 kcal + -analytic -56.889 0.006473 2307.9 19.8858 0.0 + +SO4-2 + 9 H3O+ + 8 e- = HS- + 13 H2O + log_k 33.65 + delta_h -60.140 kcal + -gamma 3.5000 0.0000 + +HS- + H2O = S-2 + H3O+ + log_k -12.918 + delta_h 12.1 kcal + -gamma 5.0000 0.0000 + +HS- + H3O+ = H2S + H2O + log_k 6.994 + delta_h -5.300 kcal + -analytic -11.17 0.02386 3279.0 + +NO3- + 2 H3O+ + 2 e- = NO2- + 3H2O + log_k 28.570 + delta_h -43.760 kcal + -gamma 3.0000 0.0000 + +2 NO3- + 12 H3O+ + 10e- = N2 + 18 H2O + log_k 207.080 + delta_h -312.130 kcal + +NH4+ + H2O = NH3 + H3O+ + log_k -9.252 + delta_h 12.48 kcal + -analytic 0.6322 -0.001225 -2835.76 + +NO3- + 10 H3O+ + 8 e- = NH4+ + 13 H2O + log_k 119.077 + delta_h -187.055 kcal + -gamma 2.5000 0.0000 + +NH4+ + SO4-2 = NH4SO4- + log_k 1.11 + +PO4-3 + H3O+ = HPO4-2 + H2O + log_k 12.346 + delta_h -3.530 kcal + -gamma 4.0000 0.0000 + +PO4-3 + 2 H3O+ = H2PO4- + 2H2O + log_k 19.553 + delta_h -4.520 kcal + -gamma 4.5000 0.0000 + +H3O+ + F- = HF + H2O + log_k 3.18 + delta_h 3.18 kcal + -analytic -2.033 0.012645 429.01 + +H3O+ + 2 F- = HF2- + H2O + log_k 3.760 + delta_h 4.550 kcal + +Ca+2 + OH- = CaOH+ + log_k -12.780 + +Ca+2 + CO3-2 = CaCO3 + log_k 3.224 + delta_h 3.545 kcal + -analytic -1228.732 -0.299440 35512.75 485.818 + +#Ca+2 + HCO3- = CaHCO3+ +Ca+2 + CO3-2 + H3O+ = CaHCO3+ + H2O + log_k 11.435 + delta_h -0.871 kcal + -analytic 1317.0071 0.34546894 -39916.84 -517.70761 563713.9 + -gamma 5.4000 0.0000 + +Ca+2 + SO4-2 = CaSO4 + log_k 2.300 + delta_h 1.650 kcal + +Ca+2 + HSO4- = CaHSO4+ + log_k 1.08 + +Ca+2 + PO4-3 = CaPO4- + log_k 6.459 + delta_h 3.100 kcal + +Ca+2 + HPO4-2 = CaHPO4 + log_k 2.739 + delta_h 3.3 kcal + +Ca+2 + H2PO4- = CaH2PO4+ + log_k 1.408 + delta_h 3.4 kcal + +Ca+2 + F- = CaF+ + log_k 0.940 + delta_h 4.120 kcal + +Mg+2 + OH- = MgOH+ + log_k -11.440 + delta_h 15.952 kcal + +Mg+2 + CO3-2 = MgCO3 + log_k 2.98 + delta_h 2.713 kcal + -analytic 0.9910 0.00667 + +Mg+2 + H3O+ + CO3-2 = MgHCO3+ + H2O + log_k 11.399 + delta_h -2.771 kcal + -analytic 48.6721 0.03252849 -2614.335 -18.00263 563713.9 + +Mg+2 + SO4-2 = MgSO4 + log_k 2.370 + delta_h 4.550 kcal + +Mg+2 + PO4-3 = MgPO4- + log_k 6.589 + delta_h 3.100 kcal + +Mg+2 + HPO4-2 = MgHPO4 + log_k 2.87 + delta_h 3.3 kcal + +Mg+2 + H2PO4- = MgH2PO4+ + log_k 1.513 + delta_h 3.4 kcal + +Mg+2 + F- = MgF+ + log_k 1.820 + delta_h 3.200 kcal + +Na+ + OH- = NaOH + log_k -14.180 + +Na+ + CO3-2 = NaCO3- + log_k 1.270 + delta_h 8.910 kcal + +Na+ + HCO3- = NaHCO3 + log_k -0.25 + +Na+ + SO4-2 = NaSO4- + log_k 0.700 + delta_h 1.120 kcal + +Na+ + HPO4-2 = NaHPO4- + log_k 0.29 + +Na+ + F- = NaF + log_k -0.240 + +K+ + OH- = KOH + log_k -14.460 + +K+ + SO4-2 = KSO4- + log_k 0.850 + delta_h 2.250 kcal + -analytic 3.106 0.0 -673.6 + +K+ + HPO4-2 = KHPO4- + log_k 0.29 + +Fe+2 + 2H2O = FeOH+ + H3O+ + log_k -9.500 + delta_h 13.200 kcal + +Fe+2 + Cl- = FeCl+ + log_k 0.140 + +Fe+2 + CO3-2 = FeCO3 + log_k 4.380 + +Fe+2 + HCO3- = FeHCO3+ + log_k 2.0 + +Fe+2 + SO4-2 = FeSO4 + log_k 2.250 + delta_h 3.230 kcal + +Fe+2 + HSO4- = FeHSO4+ + log_k 1.08 + +Fe+2 + 2HS- = Fe(HS)2 + log_k 8.95 + +Fe+2 + 3HS- = Fe(HS)3- + log_k 10.987 + +Fe+2 + HPO4-2 = FeHPO4 + log_k 3.6 + +Fe+2 + H2PO4- = FeH2PO4+ + log_k 2.7 + +Fe+2 + F- = FeF+ + log_k 1.000 + +Fe+2 = Fe+3 + e- + log_k -13.020 + delta_h 9.680 kcal + -gamma 9.0000 0.0000 + +Fe+3 + 2H2O = FeOH+2 + H3O+ + log_k -2.19 + delta_h 10.4 kcal + +Fe+3 + 4H2O = Fe(OH)2+ + 2 H3O+ + log_k -5.67 + delta_h 17.1 kcal + +Fe+3 + 6 H2O = Fe(OH)3 + 3 H3O+ + log_k -12.56 + delta_h 24.8 kcal + +Fe+3 + 8 H2O = Fe(OH)4- + 4 H3O+ + log_k -21.6 + delta_h 31.9 kcal + +2 Fe+3 + 4 H2O = Fe2(OH)2+4 + 2 H3O+ + log_k -2.95 + delta_h 13.5 kcal + +3 Fe+3 + 8 H2O = Fe3(OH)4+5 + 4 H3O+ + log_k -6.3 + delta_h 14.3 kcal + +Fe+3 + Cl- = FeCl+2 + log_k 1.48 + delta_h 5.6 kcal + +Fe+3 + 2 Cl- = FeCl2+ + log_k 2.13 + +Fe+3 + 3 Cl- = FeCl3 + log_k 1.13 + +Fe+3 + SO4-2 = FeSO4+ + log_k 4.04 + delta_h 3.91 kcal + +Fe+3 + HSO4- = FeHSO4+2 + log_k 2.48 + +Fe+3 + 2 SO4-2 = Fe(SO4)2- + log_k 5.38 + delta_h 4.60 kcal + +Fe+3 + HPO4-2 = FeHPO4+ + log_k 5.43 + delta_h 5.76 kcal + +Fe+3 + H2PO4- = FeH2PO4+2 + log_k 5.43 + +Fe+3 + F- = FeF+2 + log_k 6.2 + delta_h 2.7 kcal + +Fe+3 + 2 F- = FeF2+ + log_k 10.8 + delta_h 4.8 kcal + +Fe+3 + 3 F- = FeF3 + log_k 14.0 + delta_h 5.4 kcal + +Al+3 + 2H2O = AlOH+2 + H3O+ + log_k -5.00 + delta_h 11.49 kcal + -analytic -38.253 0.0 -656.27 14.327 + +Al+3 + 4 H2O = Al(OH)2+ + 2 H3O+ + log_k -10.1 + delta_h 26.90 kcal + -analytic 88.500 0.0 -9391.6 -27.121 + +Al+3 + 6 H2O = Al(OH)3 + 3 H3O+ + log_k -16.9 + delta_h 39.89 kcal + -analytic 226.374 0.0 -18247.8 -73.597 + +Al+3 + 8 H2O = Al(OH)4- + 4 H3O+ + log_k -22.7 + delta_h 42.30 kcal + -analytic 51.578 0.0 -11168.9 -14.865 + +Al+3 + SO4-2 = AlSO4+ + log_k 3.5 + delta_h 2.29 kcal + +Al+3 + 2SO4-2 = Al(SO4)2- + log_k 5.0 + delta_h 3.11 kcal + +Al+3 + HSO4- = AlHSO4+2 + log_k 0.46 + +Al+3 + F- = AlF+2 + log_k 7.000 + delta_h 1.060 kcal + +Al+3 + 2 F- = AlF2+ + log_k 12.700 + delta_h 1.980 kcal + +Al+3 + 3 F- = AlF3 + log_k 16.800 + delta_h 2.160 kcal + +Al+3 + 4 F- = AlF4- + log_k 19.400 + delta_h 2.200 kcal + +Al+3 + 5 F- = AlF5-2 + log_k 20.600 + delta_h 1.840 kcal + +Al+3 + 6 F- = AlF6-3 + log_k 20.600 + delta_h -1.670 kcal + +H4SiO4 + H2O = H3SiO4- + H3O+ + log_k -9.83 + delta_h 6.12 kcal + -analytic -302.3724 -0.050698 15669.69 108.18466 -1119669.0 + +H4SiO4 + 2H2O= H2SiO4-2 + 2 H3O+ + log_k -23.0 + delta_h 17.6 kcal + -analytic -294.0184 -0.072650 11204.49 108.18466 -1119669.0 + +H4SiO4 + 4 H3O+ + 6 F- = SiF6-2 + 8 H2O + log_k 30.180 + delta_h -16.260 kcal +PHASES +Calcite + CaCO3 = CO3-2 + Ca+2 + log_k -8.480 + delta_h -2.297 kcal + -analytic -171.9065 -0.077993 2839.319 71.595 + +Dolomite + CaMg(CO3)2 = Ca+2 + Mg+2 + 2 CO3-2 + log_k -17.090 + delta_h -9.436 kcal + +Siderite + FeCO3 = Fe+2 + CO3-2 + log_k -10.890 + delta_h -2.480 kcal + +Gypsum + CaSO4:2H2O = Ca+2 + SO4-2 + 2 H2O + log_k -4.580 + delta_h -0.109 kcal + -analytic 68.2401 0.0 -3221.51 -25.0627 + +Anhydrite + CaSO4 = Ca+2 + SO4-2 + log_k -4.360 + delta_h -1.710 kcal + -analytic 197.52 0.0 -8669.8 -69.835 + +Hydroxyapatite + Ca5(PO4)3OH + 4 H3O+ = 5H2O + 3 HPO4-2 + 5 Ca+2 + log_k -3.421 + delta_h -36.155 kcal + +Fluorite + CaF2 = Ca+2 + 2 F- + log_k -10.600 + delta_h 4.690 kcal + -analytic 66.348 0.0 -4298.2 -25.271 + +SiO2(a) + SiO2 + 2 H2O = H4SiO4 + log_k -2.710 + delta_h 3.340 kcal + -analytic -0.26 0.0 -731.0 + +Chalcedony + SiO2 + 2 H2O = H4SiO4 + log_k -3.550 + delta_h 4.720 kcal + -analytic -0.09 0.0 -1032.0 + +Quartz + SiO2 + 2 H2O = H4SiO4 + log_k -3.980 + delta_h 5.990 kcal + -analytic 0.41 0.0 -1309.0 + +Gibbsite + Al(OH)3 + 3 H3O+ = Al+3 + 6 H2O + log_k 8.110 + delta_h -22.800 kcal + +Al(OH)3(a) + Al(OH)3 + 3 H3O+ = Al+3 + 6 H2O + log_k 10.800 + delta_h -26.500 kcal + +Kaolinite + Al2Si2O5(OH)4 + 6 H3O+ = 7H2O + 2 H4SiO4 + 2 Al+3 + log_k 7.435 + delta_h -35.300 kcal + +Albite + NaAlSi3O8 + 8 H2O = Na+ + Al(OH)4- + 3 H4SiO4 + log_k -18.002 + delta_h 25.896 kcal + +Anorthite + CaAl2Si2O8 + 8 H2O = Ca+2 + 2 Al(OH)4- + 2 H4SiO4 + log_k -19.714 + delta_h 11.580 kcal + +K-feldspar + KAlSi3O8 + 8 H2O = K+ + Al(OH)4- + 3 H4SiO4 + log_k -20.573 + delta_h 30.820 kcal + +K-mica + KAl3Si3O10(OH)2 + 10 H3O+ = K+ + 3 Al+3 + 3 H4SiO4 + 10H2O + log_k 12.703 + delta_h -59.376 kcal + +Chlorite(14A) + Mg5Al2Si3O10(OH)8 + 16 H3O+ = 5Mg+2 + 2Al+3 + 3H4SiO4 + 22H2O + log_k 68.38 + delta_h -151.494 kcal + +Ca-Montmorillonite + Ca0.165Al2.33Si3.67O10(OH)2 + 14 H2O = 0.165Ca+2 + 2.33 Al(OH)4- + 3.67 H4SiO4 + 2 H3O+ + log_k -45.027 + delta_h 58.373 kcal + +Talc + Mg3Si4O10(OH)2 + 4 H2O + 6 H3O+ = 3 Mg+2 + 4 H4SiO4 + 6H2O + log_k 21.399 + delta_h -46.352 kcal + +Illite + K0.6Mg0.25Al2.3Si3.5O10(OH)2 + 12.4H2O = 0.6K+ + 0.25Mg+2 + 2.3Al(OH)4- + 3.5H4SiO4 + 1.2H3O+ + log_k -40.267 + delta_h 54.684 kcal + +Chrysotile + Mg3Si2O5(OH)4 + 6 H3O+ = 7H2O + 2 H4SiO4 + 3 Mg+2 + log_k 32.200 + delta_h -46.800 kcal + -analytic 13.248 0.0 10217.1 -6.1894 + +Sepiolite + Mg2Si3O7.5OH:3H2O + 4 H3O+ + 0.5H2O = 2 Mg+2 + 3 H4SiO4 + 4H2O + log_k 15.760 + delta_h -10.700 kcal + +Sepiolite(d) + Mg2Si3O7.5OH:3H2O + 4 H3O+ + 0.5H2O = 2 Mg+2 + 3 H4SiO4 + 4H2O + log_k 18.660 + +Hematite + Fe2O3 + 6 H3O+ = 2 Fe+3 + 9 H2O + log_k -4.008 + delta_h -30.845 kcal + +Goethite + FeOOH + 3 H3O+ = Fe+3 + 5 H2O + log_k -1.000 + delta_h -14.48 kcal + +Fe(OH)3(a) + Fe(OH)3 + 3 H3O+ = Fe+3 + 6 H2O + log_k 4.891 + +Pyrite + FeS2 + 2H3O+ + 2e- = Fe+2 + 2HS- + 2H2O + log_k -18.479 + delta_h 11.300 kcal + +FeS(ppt) + FeS + H3O+ = Fe+2 + HS- + H2O + log_k -3.915 + +Mackinawite + FeS + H3O+ = Fe+2 + HS- + H2O + log_k -4.648 + +Sulfur + S + 2 H3O+ + 2e- = H2S + 2H2O + log_k 4.882 + delta_h -9.5 kcal + +Vivianite + Fe3(PO4)2:8H2O = 3 Fe+2 + 2 PO4-3 + 8 H2O + log_k -36.000 + +Halite + NaCl = Na+ + Cl- + log_k 1.582 + delta_h 0.918 kcal + +CO2(g) + CO2(g) = CO2 + log_k -1.468 + delta_h -4.776 kcal + -analytic 108.3865 0.01985076 -6919.53 -40.45154 669365.0 + +O2(g) + O2 = O2 +# log_k -2.960 +# delta_h -1.844 kcal + # log K from llnl.dat Dec 8, 2010 + log_k -2.8983 + -analytic -7.5001e+000 7.8981e-003 0.0000e+000 0.0000e+000 2.0027e+005 + +H2(g) + H2 = H2 + log_k -3.150 + delta_h -1.759 kcal + +H2O(g) + H2O = H2O + log_k 1.51 + delta_h -44.03 kJ + +N2(g) + N2 = N2 + log_k -3.260 + delta_h -1.358 kcal + +H2S(g) + H2S = H2S + log_k -0.997 + delta_h -4.570 kcal + +CH4(g) + CH4 = CH4 + log_k -2.860 + delta_h -3.373 kcal + +NH3(g) + NH3 = NH3 + log_k 1.770 + delta_h -8.170 kcal + +Melanterite + FeSO4:7H2O = 7 H2O + Fe+2 + SO4-2 + log_k -2.209 + delta_h 4.910 kcal + -analytic 1.447 -0.004153 0.0 0.0 -214949.0 + +Alunite + KAl3(SO4)2(OH)6 + 6 H3O+ = K+ + 3 Al+3 + 2 SO4-2 + 12H2O + log_k -1.400 + delta_h -50.250 kcal + +Jarosite-K + KFe3(SO4)2(OH)6 + 6 H3O+ = 3 Fe+3 + 12 H2O + K+ + 2 SO4-2 + log_k -9.210 + delta_h -31.280 kcal + +EXCHANGE_MASTER_SPECIES + X X- +EXCHANGE_SPECIES + X- = X- + log_k 0.0 + + Na+ + X- = NaX + log_k 0.0 + -gamma 4.0 0.075 + + K+ + X- = KX + log_k 0.7 + -gamma 3.5 0.015 + delta_h -4.3 # Jardine & Sparks, 1984 + + NH4+ + X- = NH4X + log_k 0.6 + -gamma 2.5 0.0 + delta_h -2.4 # Laudelout et al., 1968 + + Ca+2 + 2X- = CaX2 + log_k 0.8 + -gamma 5.0 0.165 + delta_h 7.2 # Van Bladel & Gheyl, 1980 + + Mg+2 + 2X- = MgX2 + log_k 0.6 + -gamma 5.5 0.2 + delta_h 7.4 # Laudelout et al., 1968 + + Fe+2 + 2X- = FeX2 + log_k 0.44 + -gamma 6.0 0.0 + + Al+3 + 3X- = AlX3 + log_k 0.41 + -gamma 9.0 0.0 + + AlOH+2 + 2X- = AlOHX2 + log_k 0.89 + -gamma 0.0 0.0 + +SURFACE_MASTER_SPECIES + Hfo_s Hfo_sOH + Hfo_w Hfo_wOH + +SURFACE_SPECIES +# All surface data from +# Dzombak and Morel, 1990 +# +# +# Acid-base data from table 5.7 +# +# strong binding site--Hfo_s, + + Hfo_sOH = Hfo_sOH + log_k 0.0 + + Hfo_sOH + H3O+ = Hfo_sOH2+ + H2O + log_k 7.29 # = pKa1,int + + Hfo_sOH + H2O = Hfo_sO- + H3O+ + log_k -8.93 # = -pKa2,int + +# weak binding site--Hfo_w + + Hfo_wOH = Hfo_wOH + log_k 0.0 + + Hfo_wOH + H3O+ = Hfo_wOH2+ + H2O + log_k 7.29 # = pKa1,int + + Hfo_wOH + H2O = Hfo_wO- + H3O+ + log_k -8.93 # = -pKa2,int + +############################################### +# CATIONS # +############################################### +# +# Cations from table 10.1 or 10.5 +# +# Calcium + Hfo_sOH + Ca+2 = Hfo_sOHCa+2 + log_k 4.97 + + Hfo_wOH + Ca+2 + H2O = Hfo_wOCa+ + H3O+ + log_k -5.85 +# +# Derived constants table 10.5 +# +# Magnesium + Hfo_wOH + Mg+2 + H2O = Hfo_wOMg+ + H3O+ + log_k -4.6 +# Iron +# Hfo_sOH + Fe+2 + H2O = Hfo_sOFe+ + H3O+ +# log_k 0.7 # LFER using table 10.5 + +# Hfo_wOH + Fe+2 + H2O = Hfo_wOFe+ + H3O+ +# log_k -2.5 # LFER using table 10.5 + +# Iron, strong site: Appelo, Van der Weiden, Tournassat & Charlet, subm. + Hfo_sOH + Fe+2 + H2O = Hfo_sOFe+ + H3O+ + log_k -0.95 +# Iron, weak site: Liger et al., GCA 63, 2939, re-optimized for D&M + Hfo_wOH + Fe+2 + H2O = Hfo_wOFe+ + H3O+ + log_k -2.98 + + Hfo_wOH + Fe+2 + 3H2O = Hfo_wOFeOH + 2H3O+ + log_k -11.55 + +############################################### +# ANIONS # +############################################### +# +# Anions from table 10.6 +# +# Phosphate + Hfo_wOH + PO4-3 + 3 H3O+ = Hfo_wH2PO4 + 4H2O + log_k 31.29 + + Hfo_wOH + PO4-3 + 2 H3O+ = Hfo_wHPO4- + 3H2O + log_k 25.39 + + Hfo_wOH + PO4-3 + H3O+ = Hfo_wPO4-2 + 2H2O + log_k 17.72 +# +# Anions from table 10.7 +# +# Sulfate + Hfo_wOH + SO4-2 + H3O+ = Hfo_wSO4- + 2H2O + log_k 7.78 + + Hfo_wOH + SO4-2 = Hfo_wOHSO4-2 + log_k 0.79 +# +# Derived constants table 10.10 +# + Hfo_wOH + F- + H3O+ = Hfo_wF + 2H2O + log_k 8.7 + + Hfo_wOH + F- = Hfo_wOHF- + log_k 1.6 +# +# Carbonate: Van Geen et al., 1994 reoptimized for HFO +# 0.15 g HFO/L has 0.344 mM sites == 2 g of Van Geen's Goethite/L +# +# Hfo_wOH + CO3-2 + H3O+ = Hfo_wCO3- + 2H2O +# log_k 12.56 +# +# Hfo_wOH + CO3-2 + 2 H3O+= Hfo_wHCO3 + 3 H2O +# log_k 20.62 + +# 9/19/96 +# Added analytical expression for H2S, NH3, KSO4. +# Added species CaHSO4+. +# Added delta H for Goethite. + +# +# Begin Isotope definitions +# +############################################################################################### +SOLUTION_MASTER_SPECIES +############################################################################################### +D D2O 0 D 2 +D(1) D2O 0 D +D(0) HD 0 D +T HTO 0 T 3 +T(1) HTO 0 T +T(0) HT 0 T +[18O] H2[18O] 0 [18O] 18 +[18O](-2) H2[18O] 0 [18O] 18 +[18O](0) O[18O] 0 [18O] 18 +[13C] [13C]O2 0 [13C] 13 +[13C](4) [13C]O2 0 [13C] +[13C](-4) [13C]H4 0 [13C] +[14C] [14C]O2 0 [14C] 14 +[14C](4) [14C]O2 0 [14C] +[14C](-4) [14C]H4 0 [14C] +[34S] [34S]O4-2 0 [34S] 33.967 +[34S](6) [34S]O4-2 0 [34S] +[34S](-2) H[34S]- 0 [34S] +[15N] [15N]O3- 0 [15N] 15.00010897312 +[15N](5) [15N]O3- 0 [15N] +[15N](3) [15N]O2- 0 [15N] +[15N](0) N[15N] 0 [15N] +[15N](-3) [15N]H4+ 0 [15N] +############################################################################################### +ISOTOPES +############################################################################################### +H + -isotope D permil 155.76e-6 # VSMOW (Clark and Fritz, 1997) + -isotope T TU 1e-18 # Solomon and Cook, in eds, Cook and Herczeg, 2000 +H(0) + -isotope D(0) permil 155.76e-6 # VSMOW (Clark and Fritz, 1997) + -isotope T(0) TU 1e-18 # Solomon and Cook, in eds, Cook and Herczeg, 2000 + # 1 THO in 10^18 H2O +# -isotope T pCi/L 3.125e-18 # +#1e-18/3.2 = T/mol H2O +C + -isotope [13C] permil 0.0111802 # VPDB, Vienna Pee Dee Belemnite + # Chang and Li, 1990, Chinese Science Bulletin + -isotope [13C](4) permil 0.0111802 # VPDB, Vienna Pee Dee Belemnite + # Chang and Li, 1990, Chinese Science Bulletin + -isotope [13C](-4) permil 0.0111802 # VPDB, Vienna Pee Dee Belemnite + -isotope [14C] pmc 1.175887709e-12 # Mole fraction of 14C in Modern Carbon + -isotope [14C](4) pmc 1.175887709e-12 # Mole fraction of 14C in Modern Carbon + # 13.56 Modern Carbon dpm (Kalin, in eds, Cook and Herczeg, 2000) + -isotope [14C](-4) pmc 1.175887709e-12 # Mole fraction of 14C in Modern Carbon +C(4) + -isotope [13C](4) permil 0.0111802 # VPDB, Vienna Pee Dee Belemnite + # Chang and Li, 1990, Chinese Science Bulletin + -isotope [14C](4) pmc 1.175887709e-12 # Mole fraction of 14C in Modern Carbon + # 13.56 Modern Carbon dpm (Kalin, in eds, Cook and Herczeg, 2000) + # 13.56 Modern Carbon dpm (Kalin, in eds, Cook and Herczeg, 2000) +C(-4) + -isotope [13C](-4) permil 0.0111802 # VPDB, Vienna Pee Dee Belemnite + -isotope [14C](-4) pmc 1.175887709e-12 # Mole fraction of 14C in Modern Carbon + # 14C calculation + # + # lambda = ln(2)/(5730 yrs * 3.15576e7 sec/yr) + # mole/g carbon = -(dn/dt)/lambda = 0.226 dps / 3.8332476e-12 / 6.022136736e23 + # mole C/g C NBS Oxalic Acid with 13C = -19.3: 0.08325783313 + # mole 14C/mol Modern Carbon mol/g carbon/ (mole C/g C) = 1.175887709e-12 + # +O + -isotope [18O] permil 2005.2e-6 # VSMOW (Clark and Fritz, 1997) + -isotope [18O](0) permil 2005.2e-6 # VSMOW (Clark and Fritz, 1997) +O(0) + -isotope [18O](0) permil 2005.2e-6 # VSMOW (Clark and Fritz, 1997) + +S + # Coplen and others, 2002 + -isotope [34S] permil 0.04416264 # VCDT, Vienna Canyon Diablo Troilite + -isotope [34S](6) permil 0.04416264 # VCDT + -isotope [34S](-2) permil 0.04416264 # VCDT +S(6) + -isotope [34S](6) permil 0.04416264 # VCDT +S(-2) + -isotope [34S](-2) permil 0.04416264 # VCDT +N + # Coplen and others, 2002 + -isotope [15N] permil 0.003676867 # Air + -isotope [15N](5) permil 0.003676867 # Air + -isotope [15N](3) permil 0.003676867 # Air + -isotope [15N](0) permil 0.003676867 # Air + -isotope [15N](-3) permil 0.003676867 # Air +N(5) + -isotope [15N](5) permil 0.003676867 # Air +N(3) + -isotope [15N](3) permil 0.003676867 # Air +N(0) + -isotope [15N](0) permil 0.003676867 # Air +N(-3) + -isotope [15N](-3) permil 0.003676867 # Air +############################################################################################### +ISOTOPE_RATIOS +############################################################################################### +# +# Total aqueous ratios +# + R(D) D + R(T) T + R(18O) [18O] + R(13C) [13C] + R(14C) [14C] + R(15N) [15N] + R(34S) [34S] +# H2O(l) ratios + R(D)_H2O(l) D + R(T)_H2O(l) T + R(18O)_H2O(l) [18O] +# OH- ratios + R(D)_OH- D + R(T)_OH- T + R(18O)_OH- [18O] +# H3O+ ratios + R(D)_H3O+ D + R(T)_H3O+ T + R(18O)_H3O+ [18O] +# O2(aq) ratios + R(18O)_O2(aq) [18O] +# H2(aq) ratios + R(D)_H2(aq) D + R(T)_H2(aq) T +# CO2(aq) ratios + R(13C)_CO2(aq) [13C] + R(14C)_CO2(aq) [14C] + R(18O)_CO2(aq) [18O] +# HCO3- ratios + R(D)_HCO3- D + R(T)_HCO3- T + R(18O)_HCO3- [18O] + R(13C)_HCO3- [13C] + R(14C)_HCO3- [14C] +# CO3-2 ratios + R(18O)_CO3-2 [18O] + R(13C)_CO3-2 [13C] + R(14C)_CO3-2 [14C] +# CH4(aq) ratios + R(D)_CH4(aq) D + R(T)_CH4(aq) T + R(13C)_CH4(aq) [13C] + R(14C)_CH4(aq) [14C] +# SO4-2 ratios + R(34S)_SO4-2 [34S] +# HSO4- ratios + R(D)_HSO4- D + R(T)_HSO4- T + R(34S)_HSO4- [34S] +# S-2 ratios + R(34S)_S-2 [34S] +# HS- ratios + R(D)_HS- D + R(T)_HS- T + R(34S)_HS- [34S] +# H2S ratios + R(D)_H2S(aq) D + R(T)_H2S(aq) T + R(34S)_H2S(aq) [34S] +# NO3- ratios + R(15N)_NO3- [15N] +# NO2- ratios + R(15N)_NO2- [15N] +# N2(aq) ratios + R(15N)_N2(aq) [15N] +# NH3(aq) ratios + R(D)_NH3(aq) D + R(T)_NH3(aq) T + R(15N)_NH3(aq) [15N] +# NH4+ ratios + R(D)_NH4+ D + R(T)_NH4+ T + R(15N)_NH4+ [15N] +# +# Ratios for minerals and gases +# +# H2O(g) ratios + R(D)_H2O(g) D + R(T)_H2O(g) T + R(18O)_H2O(g) [18O] +# O2(g) ratios + R(18O)_O2(g) [18O] +# H2(g) ratios + R(D)_H2(g) D + R(T)_H2(g) T +# CO2(g) ratios + R(18O)_CO2(g) [18O] + R(13C)_CO2(g) [13C] + R(14C)_CO2(g) [14C] +# Calcite ratios + R(18O)_Calcite [18O] + R(13C)_Calcite [13C] + R(14C)_Calcite [14C] +# Pyrite ratios + R(34S)_Pyrite [34S] +# CH4(g) ratios + R(D)_CH4(g) D + R(T)_CH4(g) T + R(13C)_CH4(g) [13C] + R(14C)_CH4(g) [14C] +# H2S(g) ratios + R(D)_H2S(g) D + R(T)_H2S(g) T + R(34S)_H2S(g) [34S] +# Gypsum ratios + R(34S)_Gypsum [34S] +# Anhydrite ratios + R(34S)_Anhydrite [34S] +# N2(g) ratios + R(15N)_N2(g) [15N] +# NH3(g) ratios + R(D)_NH3(g) D + R(T)_NH3(g) T + R(15N)_NH3(g) [15N] + +ISOTOPE_ALPHAS +# OH- + Alpha_D_OH-/H2O(l) Log_alpha_D_OH-/H2O(l) + Alpha_T_OH-/H2O(l) Log_alpha_T_OH-/H2O(l) + Alpha_18O_OH-/H2O(l) Log_alpha_18O_OH-/H2O(l) +# H3O+ + Alpha_D_H3O+/H2O(l) Log_alpha_D_H3O+/H2O(l) + Alpha_T_H3O+/H2O(l) Log_alpha_T_H3O+/H2O(l) + Alpha_18O_H3O+/H2O(l) Log_alpha_18O_H3O+/H2O(l) +# O2(aq) + Alpha_18O_O2(aq)/H2O(l) Log_alpha_18O_O2(aq)/H2O(l) +# H2(aq) + Alpha_D_H2(aq)/H2O(l) Log_alpha_D_H2(aq)/H2O(l) + Alpha_T_H2(aq)/H2O(l) Log_alpha_T_H2(aq)/H2O(l) +# CO2(aq) + Alpha_18O_CO2(aq)/H2O(l) Log_alpha_18O_CO2(aq)/H2O(l) + Alpha_13C_CO2(aq)/CO2(g) Log_alpha_13C_CO2(aq)/CO2(g) + Alpha_14C_CO2(aq)/CO2(g) Log_alpha_14C_CO2(aq)/CO2(g) +# HCO3- + Alpha_D_HCO3-/H2O(l) Log_alpha_D_HCO3-/H2O(l) + Alpha_T_HCO3-/H2O(l) Log_alpha_T_HCO3-/H2O(l) + Alpha_18O_HCO3-/H2O(l) Log_alpha_18O_HCO3-/H2O(l) + Alpha_13C_HCO3-/CO2(aq) Log_alpha_13C_HCO3-/CO2(aq) + Alpha_14C_HCO3-/CO2(aq) Log_alpha_14C_HCO3-/CO2(aq) + Alpha_13C_HCO3-/CO2(g) Log_alpha_13C_HCO3-/CO2(g) + Alpha_14C_HCO3-/CO2(g) Log_alpha_14C_HCO3-/CO2(g) +# CO3-2 + Alpha_18O_CO3-2/H2O(l) Log_alpha_18O_CO3-2/H2O(l) + Alpha_13C_CO3-2/CO2(aq) Log_alpha_13C_CO3-2/CO2(aq) + Alpha_14C_CO3-2/CO2(aq) Log_alpha_14C_CO3-2/CO2(aq) + Alpha_13C_CO3-2/CO2(g) Log_alpha_13C_CO3-2/CO2(g) + Alpha_14C_CO3-2/CO2(g) Log_alpha_14C_CO3-2/CO2(g) +# CH4(aq) + Alpha_D_CH4(aq)/H2O(l) Log_alpha_D_CH4(aq)/H2O(l) + Alpha_T_CH4(aq)/H2O(l) Log_alpha_T_CH4(aq)/H2O(l) + Alpha_13C_CH4(aq)/CO2(aq) Log_alpha_13C_CH4(aq)/CO2(aq) + Alpha_14C_CH4(aq)/CO2(aq) Log_alpha_14C_CH4(aq)/CO2(aq) +# HSO4- + Alpha_D_HSO4-/H2O(l) Log_alpha_D_HSO4-/H2O(l) + Alpha_T_HSO4-/H2O(l) Log_alpha_T_HSO4-/H2O(l) + Alpha_34S_HSO4-/SO4-2 Log_alpha_34S_HSO4-/SO4-2 +# S-2 + Alpha_34S_S-2/HS- Log_alpha_34S_S-2/HS- +# HS- + Alpha_D_HS-/H2O(l) Log_alpha_D_HS-/H2O(l) + Alpha_T_HS-/H2O(l) Log_alpha_T_HS-/H2O(l) + Alpha_34S_HS-/SO4-2 Log_alpha_34S_HS-/SO4-2 +# H2S + Alpha_D_H2S(aq)/H2O(l) Log_alpha_D_H2S(aq)/H2O(l) + Alpha_T_H2S(aq)/H2O(l) Log_alpha_T_H2S(aq)/H2O(l) + Alpha_34S_H2S(aq)/HS- Log_alpha_34S_H2S(aq)/HS- +# NO2- + Alpha_15N_NO2-/NO3- Log_alpha_15N_NO2-/NO3- +# N2(aq) + Alpha_15N_N2(aq)/NO3- Log_alpha_15N_N2(aq)/NO3- +# NH3(aq) + Alpha_D_NH3(aq)/H2O(l) Log_alpha_D_NH3(aq)/H2O(l) + Alpha_T_NH3(aq)/H2O(l) Log_alpha_T_NH3(aq)/H2O(l) + Alpha_15N_NH3(aq)/NO3- Log_alpha_15N_NH3(aq)/NO3- +# NH4+ + Alpha_D_NH4+/H2O(l) Log_alpha_D_NH4+/H2O(l) + Alpha_T_NH4+/H2O(l) Log_alpha_T_NH4+/H2O(l) + Alpha_15N_NH4+/NH3(aq) Log_alpha_15N_NH4+/NH3(aq) +# H2O(g) + Alpha_D_H2O(g)/H2O(l) Log_alpha_D_H2O(g)/H2O(l) + Alpha_T_H2O(g)/H2O(l) Log_alpha_T_H2O(g)/H2O(l) + Alpha_18O_H2O(g)/H2O(l) Log_alpha_18O_H2O(g)/H2O(l) +# O2(g) + Alpha_18O_O2(g)/H2O(l) Log_alpha_18O_O2(g)/H2O(l) #? +# H2(g) + Alpha_D_H2(g)/H2O(l) Log_alpha_D_H2(g)/H2O(l) #? + Alpha_T_H2(g)/H2O(l) Log_alpha_T_H2(g)/H2O(l) #? +# CO2(g) + Alpha_18O_CO2(g)/H2O(l) Log_alpha_18O_CO2(g)/H2O(l) + Alpha_13C_CO2(g)/CO2(aq) Log_alpha_13C_CO2(g)/CO2(aq) + Alpha_14C_CO2(g)/CO2(aq) Log_alpha_14C_CO2(g)/CO2(aq) +# Calcite + Alpha_18O_Calcite/H2O(l) Log_alpha_18O_Calcite/H2O(l) + Alpha_13C_Calcite/CO2(aq) Log_alpha_13C_Calcite/CO2(aq) + Alpha_13C_Calcite/CO2(g) Log_alpha_13C_Calcite/CO2(g) + Alpha_14C_Calcite/CO2(aq) Log_alpha_14C_Calcite/CO2(aq) + Alpha_14C_Calcite/CO2(g) Log_alpha_14C_Calcite/CO2(g) +# Pyrite + Alpha_34S_Pyrite/HS- Log_alpha_34S_Pyrite/HS- +# CH4(g) + Alpha_D_CH4(g)/H2O(l) Log_alpha_D_CH4(g)/H2O(l) + Alpha_T_CH4(g)/H2O(l) Log_alpha_T_CH4(g)/H2O(l) + Alpha_13C_CH4(g)/CO2(aq) Log_alpha_13C_CH4(g)/CO2(aq) #? + Alpha_14C_CH4(g)/CO2(aq) Log_alpha_14C_CH4(g)/CO2(aq) #? +# H2S(g) + Alpha_D_H2S(g)/H2S(aq) Log_alpha_D_H2S(g)/H2S(aq) + Alpha_T_H2S(g)/H2S(aq) Log_alpha_T_H2S(g)/H2S(aq) + Alpha_34S_H2S(g)/H2S(aq) Log_alpha_34S_H2S(g)/H2S(aq) +# Gypsum + Alpha_34S_Gypsum/SO4-2 Log_alpha_34S_Gypsum/SO4-2 +# Anhydrite + Alpha_34S_Anhydrite/SO4-2 Log_alpha_34S_Anhydrite/SO4-2 +# N2(g) + Alpha_15N_N2(g)/N2(aq) Log_alpha_15N_N2(g)/N2(aq) +# NH3(g) + Alpha_D_NH3(g)/H2O(l) Log_alpha_D_NH3(g)/H2O(l) + #Alpha_T_NH3(g)/H2O(l) Log_alpha_T_NH3(g)/H2O(l) + Alpha_15N_NH3(g)/NH3(aq) Log_alpha_15N_NH3(g)/NH3(aq) + +NAMED_EXPRESSIONS +# +# OH- fractionation factors +# +Log_alpha_D_OH-/H2O(l) # 1000ln(alpha(25C)) = -1435 + # 13.5 C + -ln_alpha1000 -1435.0 + +Log_alpha_T_OH-/H2O(l) # 1000ln(alpha(25C)) = -2870 + # 13.5 C + -ln_alpha1000 -2870.0 + +Log_alpha_18O_OH-/H2O(l) # 1000ln(alpha(25C)) = -37.8 + # 25 C + -ln_alpha1000 -37.777 +# +# H3O- fractionation factors +# +Log_alpha_D_H3O+/H2O(l) # 1000ln(alpha(25C)) = 40.8 + # 13.5 C + -ln_alpha1000 40.82 + +Log_alpha_T_H3O+/H2O(l) # 1000ln(alpha(25C)) = 81.6 + # 13.5 C + -ln_alpha1000 81.64 + +Log_alpha_18O_H3O+/H2O(l) # 1000ln(alpha(25C)) = 22.9 + # 25 C + -ln_alpha1000 22.86 +# +# O2(aq) fractionation factors +# +Log_alpha_18O_O2(aq)/H2O(l) + -ln_alpha1000 0.0 +# +# H2(aq) fractionation factors +# +Log_alpha_D_H2(aq)/H2O(l) + -ln_alpha1000 0 + +Log_alpha_T_H2(aq)/H2O(l) + -ln_alpha1000 0 +# +# CO2(aq) fractionation factors +# +Log_alpha_18O_CO2(aq)/H2O(l) # 1000ln(alpha(25C)) = 41.2 + # 0-100 C + -ln_alpha1000 -21.9285 0.0 19.43596e3 0.0 -0.181115e6 + +Log_alpha_13C_CO2(aq)/CO2(g) # 1000ln(alpha(25C)) -0.84 + # Deines and others (1974) + -ln_alpha1000 -0.91 0.0 0.0 0.0 .0063e6 + +Log_alpha_14C_CO2(aq)/CO2(g) # 1000ln(alpha(25C)) -0.84 + -add_logk Log_alpha_13C_CO2(aq)/CO2(g) 2 +# +# HCO3- fractionation factors +# +Log_alpha_18O_HCO3-/H2O(l) + -ln_alpha1000 0.0 #? + +Log_alpha_D_HCO3-/H2O(l) + -ln_alpha1000 0.0 + +Log_alpha_T_HCO3-/H2O(l) + -ln_alpha1000 0.0 + +Log_alpha_13C_HCO3-/CO2(g) # 1000ln(alpha(25C)) = 7.82 + # Deines and others (1974) + -ln_alpha1000 -4.54 0.0 0.0 0.0 1.099e6 + +Log_alpha_13C_HCO3-/CO2(aq) # 1000ln(alpha(25C)) = 8.7 + # 0-100 C +# -ln_alpha1000 -3.63 0.0 0.0 0.0 1.0927e6 + -add_logk Log_alpha_13C_HCO3-/CO2(g) 1 + -add_logk Log_alpha_13C_CO2(aq)/CO2(g) -1 + +Log_alpha_14C_HCO3-/CO2(g) # 1000ln(alpha(25C)) = 7.82 + # Deines and others (1974) + -add_logk Log_alpha_13C_HCO3-/CO2(g) 2 + +Log_alpha_14C_HCO3-/CO2(aq) # 1000ln(alpha(25C)) = 17.3 + # 0-100 C +# -ln_alpha1000 -7.26 0.0 0.0 0.0 2.1854e6 + -add_logk Log_alpha_14C_HCO3-/CO2(g) 1 + -add_logk Log_alpha_14C_CO2(aq)/CO2(g) -1 +# +# CO3-2 fractionation factors +# +Log_alpha_18O_CO3-2/H2O(l) + -ln_alpha1000 0.0 + +Log_alpha_13C_CO3-2/CO2(g) # 1000ln(alpha(25C)) + # Deines and others (1974) + -ln_alpha1000 -3.4 0.0 0.0 0.0 0.870e6 + +Log_alpha_13C_CO3-2/CO2(aq) # 1000ln(alpha(25C)) + # 0-100 C +# -ln_alpha1000 -2.49 0.0 0.0 0.0 0.8637e6 + -add_logk Log_alpha_13C_CO3-2/CO2(g) 1 + -add_logk Log_alpha_13C_CO2(aq)/CO2(g) -1 + +Log_alpha_14C_CO3-2/CO2(g) # 1000ln(alpha(25C)) + # Deines and others (1974) + -add_logk Log_alpha_13C_CO3-2/CO2(g) 2 + +Log_alpha_14C_CO3-2/CO2(aq) # 1000ln(alpha(25C)) + # +# -ln_alpha1000 -2.49 0.0 0.0 0.0 0.8637e6 + -add_logk Log_alpha_14C_CO3-2/CO2(g) 1 + -add_logk Log_alpha_14C_CO2(aq)/CO2(g) -1 +# +# CH4(aq) fractionation factors +# +Log_alpha_D_CH4(aq)/H2O(l) + -ln_alpha1000 0 + +Log_alpha_T_CH4(aq)/H2O(l) + -ln_alpha1000 0 + +Log_alpha_13C_CH4(aq)/CO2(aq) + -ln_alpha1000 0 + +Log_alpha_14C_CH4(aq)/CO2(aq) + -ln_alpha1000 0 +# +# HSO4- fractionation factors +# +Log_alpha_D_HSO4-/H2O(l) + -ln_alpha1000 0 + +Log_alpha_T_HSO4-/H2O(l) + -ln_alpha1000 0 + +Log_alpha_34S_HSO4-/SO4-2 + -ln_alpha1000 0.0 +# +# S-2 fractionation factors +# +Log_alpha_34S_S-2/HS- + -ln_alpha1000 0.0 +# +# HS- fractionation factors +# +Log_alpha_D_HS-/H2O(l) + -ln_alpha1000 0 + +Log_alpha_T_HS-/H2O(l) + -ln_alpha1000 0 + +Log_alpha_34S_HS-/SO4-2 + -ln_alpha1000 0.0 +# +# H2S fractionation factors +# +Log_alpha_D_H2S(aq)/H2O(l) + -ln_alpha1000 0 + +Log_alpha_T_H2S(aq)/H2O(l) + -ln_alpha1000 0 + +Log_alpha_34S_H2S(aq)/HS- + -ln_alpha1000 0.0 +# +# NO2- fractionation factors +# +Log_alpha_15N_NO2-/NO3- + -ln_alpha1000 0.0 +# +# N2(aq) fractionation factors +# +Log_alpha_15N_N2(aq)/NO3- + -ln_alpha1000 0.0 +# +# NH3(aq) fractionation factors +# +Log_alpha_D_NH3(aq)/H2O(l) + -ln_alpha1000 0 + +Log_alpha_T_NH3(aq)/H2O(l) + -ln_alpha1000 0 + +Log_alpha_15N_NH3(aq)/NO3- + -ln_alpha1000 0 +# +# NH4+ fractionation factors +# +Log_alpha_D_NH4+/H2O(l) + -ln_alpha1000 0 + +Log_alpha_T_NH4+/H2O(l) + -ln_alpha1000 0 + +Log_alpha_15N_NH4+/NH3(aq) + -ln_alpha1000 0 +# +# H2O(g) fractionation factors +# +Log_alpha_D_H2O(g)/H2O(l) # 1000ln(alpha(25C)) = -76.4 + # 0-100 C + -ln_alpha1000 -52.612 0.0 76.248e3 0.0 -24.844e6 + +Log_alpha_T_H2O(g)/H2O(l) # 1000ln(alpha(25C)) = -152.7 + # 0-100 C + -ln_alpha1000 -105.224 0.0 152.496e3 0.0 -49.688e6 + +Log_alpha_18O_H2O(g)/H2O(l) # 1000ln(alpha(25C)) = -9.3 + # 0-100 C + -ln_alpha1000 2.0667 0.0 0.4156e3 0.0 -1.137e6 +# +# O2(g) fractionaton factors +# +Log_alpha_18O_O2(g)/H2O(l) + -ln_alpha1000 0.0 +# +# H2(g) fractionaton factors +# +Log_alpha_D_H2(g)/H2O(l) + -ln_alpha1000 0 + +Log_alpha_T_H2(g)/H2O(l) + -ln_alpha1000 0 +# +# CO2(g) fractionaton factors +# +Log_alpha_18O_CO2(g)/H2O(l) # 1000ln(alpha(25C)) = 40.151 + # 0-100 C + -ln_alpha1000 -19.97 0.0 17.9942e3 0.0 -0.0206e6 + # Battinga, written commun. 1973, cited in Friedman and O'Neill + +Log_alpha_13C_CO2(g)/CO2(aq) # 1000ln(alpha(25C)) = 0.84 + # 0-100 C + -ln_alpha1000 0.91 0.0 0.0 0.0 -0.0063e6 + +Log_alpha_14C_CO2(g)/CO2(aq) # 1000ln(alpha(25C)) = 1.7 + # 0-100 C + -ln_alpha1000 1.82 0.0 0.0 0.0 -0.0126e6 +# +# CO2-Calcite fractionation factors +# +#Log_alpha_18O_CO2(aq)/Calcite # 1000ln(alpha(25C)) = 13.6 +# # 0-100 C +# -ln_alpha1000 -4.7383 0.0 12.05276e3 0.0 -1.963915e6 +Log_alpha_18O_Calcite/H2O(l) # 1000ln(alpha(25C)) = 28.38 + # O'Neil, Clayton and Mayeda (1969) + -ln_alpha1000 -2.89 0 0 0 2.78e6 + +Log_alpha_13C_Calcite/CO2(g) # 1000ln(alpha(25C)) + # Deines and others (1974) + -ln_alpha1000 -3.63 0.0 0.0 0.0 1.194e6 + +Log_alpha_13C_Calcite/CO2(aq) # 1000ln(alpha(25C)) + # Deines and others (1974) + -add_logk Log_alpha_13C_Calcite/CO2(g) 1 + -add_logk Log_alpha_13C_CO2(aq)/CO2(g) -1 + +Log_alpha_14C_Calcite/CO2(g) # 1000ln(alpha(25C)) + -add_logk Log_alpha_13C_Calcite/CO2(g) 2 + +Log_alpha_14C_Calcite/CO2(aq) # 1000ln(alpha(25C)) + # Deines and others (1974) + -add_logk Log_alpha_14C_Calcite/CO2(g) 1 + -add_logk Log_alpha_14C_CO2(aq)/CO2(g) -1 +# +# Pyrite fractionation factors +# +Log_alpha_34S_Pyrite/HS- + -ln_alpha1000 0 +# +# CH4(g) fractionation factors +# +Log_alpha_D_CH4(g)/H2O(l) #? + -ln_alpha1000 0.0 + +Log_alpha_T_CH4(g)/H2O(l) #? + -ln_alpha1000 0.0 + +Log_alpha_13C_CH4(g)/CO2(aq) #? + -ln_alpha1000 0.0 + +Log_alpha_14C_CH4(g)/CO2(aq) #? + -ln_alpha1000 0.0 +# +# H2S(g) fractionation factors +# +Log_alpha_D_H2S(g)/H2S(aq) + -ln_alpha1000 0 + +Log_alpha_T_H2S(g)/H2S(aq) + -ln_alpha1000 0 + +Log_alpha_34S_H2S(g)/H2S(aq) + -ln_alpha1000 0 +# +# Gypsum fractionation factors +# +Log_alpha_34S_Gypsum/SO4-2 + -ln_alpha1000 0 +# +# Anhydrite fractionation factors +# +Log_alpha_34S_Anhydrite/SO4-2 + -ln_alpha1000 0 +# +# N2(g) fractionation factors +# +Log_alpha_15N_N2(g)/N2(aq) + -ln_alpha1000 0 +# +# NH3(g) fractionation factors +# +Log_alpha_D_NH3(g)/H2O(l) #? + -ln_alpha1000 0 + +Log_alpha_T_NH3(g)/H2O(l) #? + -ln_alpha1000 0 + +Log_alpha_15N_NH3(g)/NH3(aq) + -ln_alpha1000 0 + +############################################################################################### +CALCULATE_VALUES +############################################################################################### +# +# Ratios +# +R(D) + -start +10 ratio = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 100 +30 total_D = TOT("D") +40 total_H = TOT("H") +50 ratio = total_D/total_H +100 save ratio + -end + +R(T) ?? + -start +10 ratio = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 100 +30 total_T = TOT("T") +40 total_water = MOL("H2O") +50 ratio = total_T/total_water +100 save ratio + -end + +R(18O) + -start +10 ratio = -9999.999 +20 if (TOT("[18O]") <= 0) THEN GOTO 100 +30 total_18O = TOT("[18O]") +40 total_16O = TOT("O") +50 ratio = total_18O/total_16O +100 save ratio + -end + +R(13C) + -start +10 ratio = -9999.999 +20 if (TOT("[13C]") <= 0) THEN GOTO 100 +30 total_13C = TOT("[13C]") +40 total_12C = TOT("C") +50 ratio = total_13C/total_12C +100 save ratio + -end + +R(14C) + -start +10 ratio = -9999.999 +20 if (TOT("[14C]") <= 0) THEN GOTO 100 +30 total_14C = TOT("[14C]") +40 total_C = TOT("C") +50 ratio = total_14C/total_C +100 save ratio + -end + +R(15N) + -start +10 ratio = -9999.999 +20 if (TOT("[15N]") <= 0) THEN GOTO 100 +30 total_15N = TOT("[15N]") +40 total_14N = TOT("N") +50 ratio = total_15N/total_14N +100 save ratio + -end + +R(34S) + -start +10 ratio = -9999.999 +20 if (TOT("[34S]") <= 0) THEN GOTO 100 +30 total_34S = TOT("[34S]") +40 total_32S = TOT("S") +50 ratio = total_34S/total_32S +100 save ratio + -end +# +# H2O(l) ratios +# +R(D)_H2O(l) + -start +10 ratio = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 100 +30 total_D = sum_species("{H,D,T}2{O,[18O]}","D") +40 total_H = sum_species("{H,D,T}2{O,[18O]}","H") +50 if (total_H <= 0) THEN GOTO 100 +60 ratio = total_D/total_H +100 save ratio + -end + +R(T)_H2O(l) + -start +10 ratio = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 100 +30 total_T = sum_species("{H,D,T}2{O,[18O]}","T") +40 total_H = sum_species("{H,D,T}2{O,[18O]}","H") +50 if (total_H <= 0) THEN GOTO 100 +60 ratio = total_T/total_H +100 save ratio + -end + +R(18O)_H2O(l) + -start +10 ratio = -9999.999 +20 if (TOT("[18O]") <= 0) THEN GOTO 100 +30 total_18O = sum_species("{H,D,T}2[18O]","[18O]") +40 total_16O = sum_species("{H,D,T}2O","O") +50 if (total_16O <= 0) THEN GOTO 100 +60 ratio = total_18O/total_16O +100 save ratio + -end +# +# OH- ratios +# +R(D)_OH- + -start +10 ratio = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 100 +30 total_D = sum_species("*{O,[18O]}D*","D") +40 total_H = sum_species("*{O,[18O]}H*","H") +50 if (total_H <= 0) THEN GOTO 100 +60 ratio = total_D/total_H +100 save ratio + -end + +R(T)_OH- + -start +10 ratio = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 100 +30 total_T = sum_species("*{O,[18O]}T*","T") +40 total_H = sum_species("*{O,[18O]}H*","H") +50 if (total_H <= 0) THEN GOTO 100 +60 ratio = total_T/total_H +100 save ratio + -end + +R(18O)_OH- + -start +10 ratio = -9999.999 +20 if (TOT("[18O]") <= 0) THEN GOTO 100 +30 total_18O = sum_species("*[18O]{H,D,T}*","[18O]") +40 total_16O = sum_species("*O{H,D,T}*","O") +50 ratio = total_18O/total_16O +100 save ratio + -end + +# +# H3O+ ratios +# +R(D)_H3O+ + -start +10 ratio = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 100 +30 total_D = sum_species("{H,D,T}3{O,[18O]}+","D") +40 total_H = sum_species("{H,D,T}3{O,[18O]}+","H") +50 ratio = total_D/total_H +100 save ratio + -end + +R(T)_H3O+ + -start +10 ratio = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 100 +30 total_T = sum_species("{H,D,T}3{O,[18O]}+","T") +40 total_H = sum_species("{H,D,T}3{O,[18O]}+","H") +50 ratio = total_T/total_H +100 save ratio + -end + +R(18O)_H3O+ + -start +10 ratio = -9999.999 +20 if (TOT("[18O]") <= 0) THEN GOTO 100 +30 total_18O = sum_species("{H,D,T}3{O,[18O]}+","[18O]") +40 total_16O = sum_species("{H,D,T}3{O,[18O]}+","O") +50 ratio = total_18O/total_16O +100 save ratio + -end + +# +# O2(aq) ratios +# +R(18O)_O2(aq) + -start +10 ratio = -9999.999 +20 if (TOT("[18O]") <= 0) THEN GOTO 100 +30 total_18O = sum_species("{O,[18O]}2","[18O]") +40 total_O = sum_species("{O,[18O]}2","O") +50 if (total_O <= 0) THEN GOTO 100 +60 ratio = total_18O/total_O +100 save ratio + -end +# +# H2(aq) ratios +# +R(D)_H2(aq) + -start +10 ratio = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 100 +30 total_D = sum_species("{H,D,T}2","D") +40 total_H = sum_species("{H,D,T}2","H") +50 if (total_H <= 0) THEN GOTO 100 +60 ratio = total_D/total_H +100 save ratio + -end + +R(T)_H2(aq) + -start +10 ratio = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 100 +30 total_T = sum_species("{H,D,T}2","T") +40 total_H = sum_species("{H,D,T}2","H") +50 if (total_H <= 0) THEN GOTO 100 +60 ratio = total_T/total_H +100 save ratio + -end +# +# CO2(aq) ratios +# +R(13C)_CO2(aq) + -start +10 ratio = -9999.999 +20 if (TOT("[13C]") <= 0) THEN GOTO 100 +30 total_13C = sum_species("[13C]{O,[18O]}2","[13C]") +40 total_12C = sum_species("C{O,[18O]}2","C") +50 if (total_12C <= 0) THEN GOTO 100 +60 ratio = total_13C/total_12C +100 save ratio + -end + +R(14C)_CO2(aq) + -start +10 ratio = -9999.999 +20 if (TOT("[14C]") <= 0) THEN GOTO 100 +30 total_14C = sum_species("[14C]{O,[18O]}2","[14C]") +40 total_12C = sum_species("C{O,[18O]}2","C") +50 if (total_12C <= 0) THEN GOTO 100 +60 ratio = total_14C/total_12C +100 save ratio + -end + +R(18O)_CO2(aq) + -start +10 ratio = -9999.999 +20 if (TOT("[18O]") <= 0) THEN GOTO 100 +30 if (TOT("C") <= 0) THEN GOTO 100 +40 total_18O = sum_species("{C,[13C],[14C]}{O,[18O]}2","[18O]") +50 total_16O = sum_species("{C,[13C],[14C]}{O,[18O]}2","O") +60 if (total_16O <= 0) THEN GOTO 100 +70 ratio = total_18O/total_16O +100 save ratio + -end +# +# HCO3- ratios +# +R(D)_HCO3- + -start +10 ratio = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 100 +30 if (TOT("C") <= 0) THEN GOTO 100 +40 total_D = sum_species("*D{C,[13C],[14C]}{O,[18O]}3*","D") +50 total_H = sum_species("*H{C,[13C],[14C]}{O,[18O]}3*","H") +60 if (total_H <= 0) THEN GOTO 100 +70 ratio = total_D/total_H +100 save ratio + -end + +R(T)_HCO3- + -start +10 ratio = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 100 +30 if (TOT("C") <= 0) THEN GOTO 100 +40 total_T = sum_species("*T{C,[13C],[14C]}{O,[18O]}3*","T") +50 total_H = sum_species("*H{C,[13C],[14C]}{O,[18O]}3*","H") +60 if (total_H <= 0) THEN GOTO 100 +70 ratio = total_T/total_H +100 save ratio + -end + +R(18O)_HCO3- + -start +10 ratio = -9999.999 +20 if (TOT("[18O]") <= 0) THEN GOTO 100 +30 if (TOT("C") <= 0) THEN GOTO 100 +40 total_18O = sum_species("*{H,D,T}{C,[13C],[14C]}{O,[18O]}3*","[18O]") +50 total_16O = sum_species("*{H,D,T}{C,[13C],[14C]}{O,[18O]}3*","O") +60 if (total_16O <= 0) THEN GOTO 100 +70 ratio = total_18O/total_16O +100 save ratio + -end + +R(13C)_HCO3- + -start +10 ratio = -9999.999 +20 if (TOT("[13C]") <= 0) THEN GOTO 100 +30 total_13C = sum_species("*{H,D,T}[13C]{O,[18O]}3*","[13C]") +40 total_12C = sum_species("*{H,D,T}C{O,[18O]}3*","C") +50 if (total_12C <= 0) THEN GOTO 100 +60 ratio = total_13C/total_12C +100 save ratio + -end + +R(14C)_HCO3- + -start +10 ratio = -9999.999 +20 if (TOT("[14C]") <= 0) THEN GOTO 100 +30 total_14C = sum_species("*{H,D,T}[14C]{O,[18O]}3*","[14C]") +40 total_12C = sum_species("*{H,D,T}C{O,[18O]}3*","C") +50 if (total_12C <= 0) THEN GOTO 100 +60 ratio = total_14C/total_12C +100 save ratio + -end +# +# CO3-2 ratios +# +R(18O)_CO3-2 + -start +10 ratio = -9999.999 +20 if (TOT("[18O]") <= 0) THEN GOTO 100 +30 if (TOT("C") <= 0) THEN GOTO 100 +40 total_18O = sum_species("*{C,[13C],[14C]}{O,[18O]}3*","[18O]") - sum_species("*{H,D,T}{C,[13C],[14C]}{O,[18O]}3*","[18O]") +50 total_16O = sum_species("*{C,[13C],[14C]}{O,[18O]}3*","O") - sum_species("*{H,D,T}{C,[13C],[14C]}{O,[18O]}3*","O") +60 if (total_16O <= 0) THEN GOTO 100 +70 ratio = total_18O/total_16O +100 save ratio + -end + +R(13C)_CO3-2 + -start +10 ratio = -9999.999 +20 if (TOT("[13C]") <= 0) THEN GOTO 100 +30 total_13C = sum_species("*[13C]{O,[18O]}3*","[13C]") - sum_species("*{H,D,T}[13C]{O,[18O]}3*","[13C]") +40 total_12C = sum_species("*C{O,[18O]}3*","C") - sum_species("*{H,D,T}C{O,[18O]}3*","C") +50 if (total_12C <= 0) THEN GOTO 100 +60 ratio = total_13C/total_12C +100 save ratio + -end + +R(14C)_CO3-2 + -start +10 ratio = -9999.999 +20 if (TOT("[14C]") <= 0) THEN GOTO 100 +30 total_14C = sum_species("*[14C]{O,[18O]}3*","[14C]") - sum_species("*{H,D,T}[14C]{O,[18O]}3*","[14C]") +40 total_12C = sum_species("*C{O,[18O]}3*","C") - sum_species("*{H,D,T}C{O,[18O]}3*","C") +50 if (total_12C <= 0) THEN GOTO 100 +60 ratio = total_14C/total_12C +100 save ratio + -end +# +# CH4(aq) ratios +# +R(D)_CH4(aq) + -start +10 ratio = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 100 +30 total_D = sum_species("{C,[13C],[14C]}{H,D,T}4","D") +40 total_H = sum_species("{C,[13C],[14C]}{H,D,T}4","H") +50 if (total_H <= 0) THEN GOTO 100 +60 ratio = total_D/total_H +100 save ratio + -end + +R(T)_CH4(aq) + -start +10 ratio = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 100 +30 total_T = sum_species("{C,[13C],[14C]}{H,D,T}4","T") +40 total_H = sum_species("{C,[13C],[14C]}{H,D,T}4","H") +50 if (total_H <= 0) THEN GOTO 100 +60 ratio = total_T/total_H +100 save ratio + -end + +R(13C)_CH4(aq) + -start +10 ratio = -9999.999 +20 if (TOT("[13C]") <= 0) THEN GOTO 100 +30 total_13C = sum_species("[13C]{H,D,T}4","[13C]") +40 total_C = sum_species("C{H,D,T}4","C") +50 if (total_C <= 0) THEN GOTO 100 +60 ratio = total_13C/total_C +100 save ratio + -end + +R(14C)_CH4(aq) + -start +10 ratio = -9999.999 +20 if (TOT("[14C]") <= 0) THEN GOTO 100 +30 total_14C = sum_species("[14C]{H,D,T}4","[14C]") +40 total_C = sum_species("C{H,D,T}4","C") +50 if (total_C <= 0) THEN GOTO 100 +60 ratio = total_14C/total_C +100 save ratio + -end +# +# SO4-2 ratios +# +R(34S)_SO4-2 + -start +10 ratio = -9999.999 +20 if (TOT("[34S]") <= 0) THEN GOTO 100 +30 total_34S = sum_species("*[34S]O4*","[34S]") - sum_species("*{H,D,T}[34S]O4*","[34S]") +40 total_S = sum_species("*SO4*","S") - sum_species("*{H,D,T}SO4*","S") +50 if (total_S <= 0) THEN GOTO 100 +60 ratio = total_34S/total_S +100 save ratio + -end +# +# HSO4- ratios +# +R(D)_HSO4- + -start +10 ratio = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 100 +30 total_D = sum_species("*D{S,[34S]}O4*","D") +40 total_H = sum_species("*H{S,[34S]}O4*","H") +50 if (total_H <= 0) THEN GOTO 100 +60 ratio = total_D/total_H +100 save ratio + -end + +R(T)_HSO4- + -start +10 ratio = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 100 +30 total_T = sum_species("*T{S,[34S]}O4*","T") +40 total_H = sum_species("*H{S,[34S]}O4*","H") +50 if (total_H <= 0) THEN GOTO 100 +60 ratio = total_T/total_H +100 save ratio + -end + +R(34S)_HSO4- + -start +10 ratio = -9999.999 +20 if (TOT("[34S]") <= 0) THEN GOTO 100 +30 total_34S = sum_species("*{H,D,T}[34S]O4*","[34S]") +40 total_S = sum_species("*{H,D,T}SO4*","S") +50 if (total_S <= 0) THEN GOTO 100 +60 ratio = total_34S/total_S +100 save ratio + -end +# +# S-2 ratios +# +R(34S)_S-2 + -start +10 ratio = -9999.999 +20 if (TOT("[34S](-2)") <= 0) THEN GOTO 100 +30 total_34S = MOL("[34S]-2") +40 total_S = MOL("S-2") +50 if (total_S <= 0) THEN GOTO 100 +60 ratio = total_34S/total_S +100 save ratio + -end +# +# HS- ratios +# +R(D)_HS- + -start +10 ratio = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 100 +30 total_D = sum_species("*D{S,[34S]}*","D") - sum_species("*D{S,[34S]}O4*","D") +40 total_H = sum_species("*H{S,[34S]}*","H") - sum_species("*H{S,[34S]}O4*","H") +50 if (total_H <= 0) THEN GOTO 100 +60 ratio = total_D/total_H +100 save ratio + -end + +R(T)_HS- + -start +10 ratio = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 100 +30 total_T = sum_species("*T{S,[34S]}*","T") - sum_species("*T{S,[34S]}O4*","T") +40 total_H = sum_species("*H{S,[34S]}*","H") - sum_species("*H{S,[34S]}O4*","H") +50 if (total_H <= 0) THEN GOTO 100 +60 ratio = total_T/total_H +100 save ratio + -end + +R(34S)_HS- + -start +10 ratio = -9999.999 +20 if (TOT("[34S]") <= 0) THEN GOTO 100 +30 total_34S = sum_species("*{H,D,T}[34S]*","[34S]") - sum_species("*{H,D,T}[34S]O4*","[34S]") +40 total_S = sum_species("*{H,D,T}S*","S") - sum_species("*{H,D,T}SO4*","S") +50 if (total_S <= 0) THEN GOTO 100 +60 ratio = total_34S/total_S +100 save ratio + -end +# +# H2S ratios +# +R(D)_H2S(aq) + -start +10 ratio = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 100 +30 total_D = sum_species("*{H,D,T}2{S,[34S]}*","D") - sum_species("*{H,D,T}2{S,[34S]}O4*","D") +40 total_S = sum_species("*{H,D,T}2{S,[34S]}*","H") - sum_species("*{H,D,T}2{S,[34]}SO4*","H") +50 if (total_H <= 0) THEN GOTO 100 +60 ratio = total_D/total_H +100 save ratio + -end + +R(T)_H2S(aq) + -start +10 ratio = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 100 +30 total_T = sum_species("{H,D,T}2{S,[34S]}","T") +40 total_H = sum_species("{H,D,T}2{S,[34S]}","H") +50 if (total_H <= 0) THEN GOTO 100 +60 ratio = total_T/total_H +100 save ratio + -end + +R(34S)_H2S(aq) + -start +10 ratio = -9999.999 +20 if (TOT("[34S]") <= 0) THEN GOTO 100 +30 total_34S = sum_species("{H,D,T}2[34S]","[34S]") +40 total_S = sum_species("{H,D,T}2S","S") +50 if (total_S <= 0) THEN GOTO 100 +60 ratio = total_34S/total_S +100 save ratio + -end +# +# NO3- ratios +# +R(15N)_NO3- + -start +10 ratio = -9999.999 +20 if (TOT("[15N]") <= 0) THEN GOTO 100 +30 total_15N = TOT("[15N](5)") +40 total_N = TOT("N(5)") +50 if (total_N <= 0) THEN GOTO 100 +60 ratio = total_15N/total_N +100 save ratio + -end +# +# NO2- ratios +# +R(15N)_NO2- + -start +10 ratio = -9999.999 +20 if (TOT("[15N]") <= 0) THEN GOTO 100 +30 total_15N = TOT("[15N](3)") +40 total_N = TOT("N(3)") +50 if (total_N <= 0) THEN GOTO 100 +60 ratio = total_15N/total_N +100 save ratio + -end +# +# N2(aq) ratios +# +R(15N)_N2(aq) + -start +10 ratio = -9999.999 +20 if (TOT("[15N]") <= 0) THEN GOTO 100 +30 total_15N = TOT("[15N](0)") +40 total_N = TOT("N(0)") +50 if (total_N <= 0) THEN GOTO 100 +60 ratio = total_15N/total_N +100 save ratio + -end +# +# NH3(aq) ratios +# +R(D)_NH3(aq) + -start +10 ratio = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 100 +30 total_D = sum_species("{[15N],N}{H,D,T}3","D") +40 total_H = sum_species("{[15N],N}{H,D,T}3","H") +50 if (total_H <= 0) THEN GOTO 100 +60 ratio = total_D/total_H +100 save ratio + -end + +R(T)_NH3(aq) + -start +10 ratio = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 100 +30 total_T = sum_species("{[15N],N}{H,D,T}3","T") +40 total_H = sum_species("{[15N],N}{H,D,T}3","H") +50 if (total_H <= 0) THEN GOTO 100 +60 ratio = total_T/total_H +100 save ratio + -end + +R(15N)_NH3(aq) + -start +10 ratio = -9999.999 +20 if (TOT("[15N]") <= 0) THEN GOTO 100 +30 total_15N = sum_species("[15N]{H,D,T}3","[15N]") +40 total_N = sum_species("N{H,D,T}3","N") +50 if (total_N <= 0) THEN GOTO 100 +60 ratio = total_15N/total_N +100 save ratio + -end +# +# NH4+ ratios +# +R(D)_NH4+ + -start +10 ratio = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 100 +30 total_D = sum_species("*{[15N],N}{H,D,T}4*","D") +40 total_H = sum_species("*{[15N],N}{H,D,T}4*","H") +50 if (total_H <= 0) THEN GOTO 100 +60 ratio = total_D/total_H +100 save ratio + -end + +R(T)_NH4+ + -start +10 ratio = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 100 +30 total_T = sum_species("*{[15N],N}{H,D,T}4*","T") +40 total_H = sum_species("*{[15N],N}{H,D,T}4*","H") +50 if (total_H <= 0) THEN GOTO 100 +60 ratio = total_T/total_H +100 save ratio + -end + +R(15N)_NH4+ + -start +10 ratio = -9999.999 +20 if (TOT("[15N]") <= 0) THEN GOTO 100 +30 total_15N = sum_species("*[15N]{H,D,T}4*","[15N]") +40 total_N = sum_species("*N{H,D,T}4*","N") +50 if (total_N <= 0) THEN GOTO 100 +60 ratio = total_15N/total_N +100 save ratio + -end +# +# Ratios for minerals and gases +# +# +# H2O(g) ratios +# +R(D)_H2O(g) + -start +10 ratio = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 1000 +30 if (GAS("H2O(g)") <= 0) THEN GOTO 1000 +40 total_D = SUM_GAS("{H,D,T}2{O,[18O]}", "D") +50 total_H = SUM_GAS("{H,D,T}2{O,[18O]}", "H") +60 if (total_h <= 0) THEN GOTO 1000 +70 ratio = total_D/total_H +1000 save ratio + -end + +R(T)_H2O(g) + -start +10 ratio = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 1000 +30 if (GAS("H2O(g)") <= 0) THEN GOTO 1000 +40 total_T = SUM_GAS("{H,D,T}2{O,[18O]}", "T") +50 total_H = SUM_GAS("{H,D,T}2{O,[18O]}", "H") +60 if (total_h <= 0) THEN GOTO 1000 +70 ratio = total_T/total_H +1000 save ratio + -end + +R(18O)_H2O(g) + -start +10 ratio = -9999.999 +20 if (TOT("[18O]") <= 0) THEN GOTO 1000 +30 if (GAS("H2O(g)") <= 0) THEN GOTO 1000 +40 total_18O = SUM_GAS("{H,D,T}2[18O]", "[18O]") +50 total_O = SUM_GAS("{H,D,T}2O", "O") +60 if (total_O <= 0) THEN GOTO 1000 +70 ratio = total_18O/total_O +1000 save ratio + -end +# +# O2(g) ratios +# +R(18O)_O2(g) + -start +10 ratio = -9999.999 +20 if (TOT("[18O]") <= 0) THEN GOTO 1000 +30 if (GAS("O2(g)") <= 0) THEN GOTO 1000 +40 total_18O = SUM_GAS("{O,[18O]}2", "[18O]") +50 total_O = SUM_GAS("{O,[18O]}2", "O") +60 if (total_O <= 0) THEN GOTO 1000 +70 ratio = total_18O/total_O +1000 save ratio + -end +# +# H2(g) ratios +# +R(D)_H2(g) + -start +10 ratio = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 1000 +30 if (GAS("H2(g)") <= 0) THEN GOTO 1000 +40 total_D = SUM_GAS("{H,D,T}2", "D") +50 total_H = SUM_GAS("{H,D,T}2", "H") +60 if (total_H <= 0) THEN GOTO 1000 +70 ratio = total_D/total_H +1000 save ratio + -end + +R(T)_H2(g) + -start +10 ratio = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 1000 +30 if (GAS("H2(g)") <= 0) THEN GOTO 1000 +40 total_T = SUM_GAS("{H,D,T}2", "T") +50 total_H = SUM_GAS("{H,D,T}2", "H") +60 if (total_H <= 0) THEN GOTO 1000 +70 ratio = total_T/total_H +1000 save ratio + -end +# +# CO2(g) ratios +# +R(18O)_CO2(g) + -start +10 ratio = -9999.999 +20 if (TOT("[18O]") <= 0) THEN GOTO 1000 +30 if (GAS("CO2(g)") <= 0) THEN GOTO 1000 +40 total_18O = SUM_GAS("{C,[13C],[14C]}{O,[18O]}2", "[18O]") +50 total_O = SUM_GAS("{C,[13C],[14C]}{O,[18O]}2", "O") +60 if (total_O <= 0) THEN GOTO 1000 +70 ratio = total_18O/total_O +1000 save ratio + -end + +R(13C)_CO2(g) + -start +10 ratio = -9999.999 +20 if (TOT("[13C]") <= 0) THEN GOTO 1000 +30 if (GAS("CO2(g)") <= 0) THEN GOTO 1000 +40 if (GAS("[13C]O2(g)") <= 0) THEN GOTO 1000 +50 total_13C = SUM_GAS("[13C]{O,[18O]}2", "[13C]") +60 total_C = SUM_GAS("C{O,[18O]}2", "C") +70 if (total_C <= 0) THEN GOTO 1000 +80 ratio = total_13C/total_C +1000 save ratio + -end + +R(14C)_CO2(g) + -start +10 ratio = -9999.999 +20 if (TOT("[14C]") <= 0) THEN GOTO 1000 +30 if (GAS("CO2(g)") <= 0) THEN GOTO 1000 +40 if (GAS("[14C]O2(g)") <= 0) THEN GOTO 1000 +50 total_14C = SUM_GAS("[14C]{O,[18O]}2", "[14C]") +60 total_C = SUM_GAS("C{O,[18O]}2", "C") +70 if (total_C <= 0) THEN GOTO 1000 +80 ratio = total_14C/total_C +1000 save ratio + -end +# +# Calcite ratios +# +R(18O)_Calcite + -start +10 ratio = -9999.999 +20 if (TOT("[18O]") <= 0) THEN GOTO 1000 +30 if (S_S("Calcite") <= 0) THEN GOTO 1000 +40 total_18O = SUM_S_S("Calcite", "[18O]") +50 total_O = SUM_S_S("Calcite", "O") +60 if (total_O <= 0) THEN GOTO 1000 +70 ratio = total_18O/total_O +1000 save ratio + -end + +R(13C)_Calcite + -start +10 ratio = -9999.999 +20 if (TOT("[13C]") <= 0) THEN GOTO 1000 +30 if (S_S("Calcite") <= 0) THEN GOTO 1000 +40 total_13C = SUM_S_S("Calcite", "[13C]") +50 total_C = SUM_S_S("Calcite", "C") +60 if (total_C <= 0) THEN GOTO 1000 +70 ratio = total_13C/total_C +1000 save ratio + -end + +R(14C)_Calcite + -start +10 ratio = -9999.999 +20 if (TOT("[14C]") <= 0) THEN GOTO 1000 +30 if (S_S("Calcite") <= 0) THEN GOTO 1000 +40 total_14C = SUM_S_S("Calcite", "[14C]") +50 total_C = SUM_S_S("Calcite", "C") +60 if (total_C <= 0) THEN GOTO 1000 +70 ratio = total_14C/total_C +1000 save ratio + -end +# +# Pyrite ratios +# +R(34S)_Pyrite + -start +10 ratio = -9999.999 +20 if (TOT("[34S]") <= 0) THEN GOTO 1000 +30 if (S_S("Pyrite") <= 0) THEN GOTO 1000 +40 total_34S = SUM_S_S("Pyrite", "[34S]") +50 total_S = SUM_S_S("Pyrite", "S") +60 if (total_S <= 0) THEN GOTO 1000 +70 ratio = total_34S/total_S +1000 save ratio + -end +# +# CH4(g) ratios +# +R(D)_CH4(g) + -start +10 ratio = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 1000 +30 if (GAS("CH4(g)") <= 0) THEN GOTO 1000 +40 total_D = SUM_GAS("{C,[13C],[14C]}{H,D,T}4", "D") +50 total_H = SUM_GAS("{C,[13C],[14C]}{H,D,T}4", "H") +60 if (total_H <= 0) THEN GOTO 1000 +70 ratio = total_D/total_H +1000 save ratio + -end + +R(T)_CH4(g) + -start +10 ratio = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 1000 +30 if (GAS("CH4(g)") <= 0) THEN GOTO 1000 +40 total_T = SUM_GAS("{C,[13C],[14C]}{H,D,T}4", "T") +50 total_H = SUM_GAS("{C,[13C],[14C]}{H,D,T}4", "H") +60 if (total_H <= 0) THEN GOTO 1000 +70 ratio = total_T/total_H +1000 save ratio + -end + +R(13C)_CH4(g) + -start +10 ratio = -9999.999 +20 if (TOT("[13C]") <= 0) THEN GOTO 1000 +30 if (GAS("CH4(g)") <= 0) THEN GOTO 1000 +40 total_13C = SUM_GAS("[13C]{H,D,T}4", "[13C]") +50 total_C = SUM_GAS("C{H,D,T}4", "C") +60 if (total_C <= 0) THEN GOTO 1000 +70 ratio = total_13C/total_C +1000 save ratio + -end + +R(14C)_CH4(g) + -start +10 ratio = -9999.999 +20 if (TOT("[14C]") <= 0) THEN GOTO 1000 +30 if (GAS("CH4(g)") <= 0) THEN GOTO 1000 +40 total_14C = SUM_GAS("[14C]{H,D,T}4", "[14C]") +50 total_C = SUM_GAS("C{H,D,T}4", "C") +60 if (total_C <= 0) THEN GOTO 1000 +70 ratio = total_14C/total_C +1000 save ratio + -end +# +# H2S(g) ratios +# +R(D)_H2S(g) + -start +10 ratio = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 1000 +30 if (GAS("H2S(g)") <= 0) THEN GOTO 1000 +40 total_D = SUM_GAS("{H,D,T}2{S,[34S]}", "D") +50 total_H = SUM_GAS("{H,D,T}2{S,[34S]}", "H") +60 if (total_H <= 0) THEN GOTO 1000 +70 ratio = total_D/total_H +1000 save ratio + -end + +R(T)_H2S(g) + -start +10 ratio = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 1000 +30 if (GAS("H2S(g)") <= 0) THEN GOTO 1000 +40 total_T = SUM_GAS("{H,D,T}2{S,[34S]}", "T") +50 total_H = SUM_GAS("{H,D,T}2{S,[34S]}", "H") +60 if (total_H <= 0) THEN GOTO 1000 +70 ratio = total_T/total_H +1000 save ratio + -end + +R(34S)_H2S(g) + -start +10 ratio = -9999.999 +20 if (TOT("[34S]") <= 0) THEN GOTO 1000 +30 if (GAS("H2S(g)") <= 0) THEN GOTO 1000 +40 total_34S = SUM_GAS("{H,D,T}2[34S]", "[34S]") +50 total_S = SUM_GAS("{H,D,T}2S", "S") +60 if (total_S <= 0) THEN GOTO 1000 +70 ratio = total_34S/total_S +1000 save ratio + -end +# +# Gypsum ratios +# +R(34S)_Gypsum + -start +10 ratio = -9999.999 +20 if (TOT("[34S]") <= 0) THEN GOTO 1000 +30 if (S_S("Gypsum") <= 0) THEN GOTO 1000 +40 total_34S = SUM_S_S("Gypsum", "[34S]") +50 total_S = SUM_S_S("Gypsum", "S") +60 if (total_S <= 0) THEN GOTO 1000 +70 ratio = total_34S/total_S +1000 save ratio + -end +# +# Anhydrite ratios +# +R(34S)_Anhydrite + -start +10 ratio = -9999.999 +20 if (TOT("[34S]") <= 0) THEN GOTO 1000 +30 if (S_S("Anhydrite") <= 0) THEN GOTO 1000 +40 total_34S = SUM_S_S("Anhydrite", "[34S]") +50 total_S = SUM_S_S("Anhydrite", "S") +60 if (total_S <= 0) THEN GOTO 1000 +70 ratio = total_34S/total_S +1000 save ratio + -end +# +# N2(g) ratios +# +R(15N)_N2(g) + -start +10 ratio = -9999.999 +20 if (TOT("[15N]") <= 0) THEN GOTO 1000 +30 if (GAS("N2(g)") <= 0) THEN GOTO 1000 +40 total_15N = SUM_GAS("{[15N],N}2", "[15N]") +50 total_N = SUM_GAS("{[15N],N}2", "N") +60 if (total_N <= 0) THEN GOTO 1000 +70 ratio = total_15N/total_N +1000 save ratio + -end +# +# NH3(g) ratios +# +R(D)_NH3(g) + -start +10 ratio = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 1000 +30 if (GAS("NH3(g)") <= 0) THEN GOTO 1000 +40 total_D = SUM_GAS("{[15N],N}{H,D,T}3", "D") +50 total_H = SUM_GAS("{[15N],N}{H,D,T}3", "H") +60 if (total_H <= 0) THEN GOTO 1000 +70 ratio = total_D/total_H +1000 save ratio + -end + +R(T)_NH3(g) + -start +10 ratio = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 1000 +30 if (GAS("NH3(g)") <= 0) THEN GOTO 1000 +40 total_T = SUM_GAS("{[15N],N}{H,D,T}3", "T") +50 total_H = SUM_GAS("{[15N],N}{H,D,T}3", "H") +60 if (total_H <= 0) THEN GOTO 1000 +70 ratio = total_T/total_H +1000 save ratio + -end + +R(15N)_NH3(g) + -start +10 ratio = -9999.999 +20 if (TOT("[15N]") <= 0) THEN GOTO 1000 +30 if (GAS("NH3(g)") <= 0) THEN GOTO 1000 +40 total_15N = SUM_GAS("[15N]{H,D,T}3", "[15N]") +50 total_N = SUM_GAS("N{H,D,T}3", "N") +60 if (total_N <= 0) THEN GOTO 1000 +70 ratio = total_15N/total_N +1000 save ratio + -end +############################################################################################### +CALCULATE_VALUES +############################################################################################### +# +# Alphas +# +# +# H2O(l) ratios +# +# +# OH- ratios +# +Alpha_D_OH-/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 1000 +30 r1 = CALC_VALUE("R(D)_OH-") +40 r2 = CALC_VALUE("R(D)_H2O(l)") +50 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_T_OH-/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 1000 +30 r1 = CALC_VALUE("R(T)_OH-") +40 r2 = CALC_VALUE("R(T)_H2O(l)") +50 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_18O_OH-/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("[18O]") <= 0) THEN GOTO 1000 +30 r1 = CALC_VALUE("R(18O)_OH-") +40 r2 = CALC_VALUE("R(18O)_H2O(l)") +50 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end +# +# H3O+ ratios +# +Alpha_D_H3O+/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 1000 +30 r1 = CALC_VALUE("R(D)_H3O+") +40 r2 = CALC_VALUE("R(D)_H2O(l)") +50 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_T_H3O+/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 1000 +30 r1 = CALC_VALUE("R(T)_H3O+") +40 r2 = CALC_VALUE("R(T)_H2O(l)") +50 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_18O_H3O+/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("[18O]") <= 0) THEN GOTO 1000 +30 r1 = CALC_VALUE("R(18O)_H3O+") +40 r2 = CALC_VALUE("R(18O)_H2O(l)") +50 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end +# +# O2(aq) ratios +# +Alpha_18O_O2(aq)/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("[18O]") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(18O)_O2(aq)") +60 r2 = CALC_VALUE("R(18O)_H2O(l)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end +# +# H2(aq) ratios +# +Alpha_D_H2(aq)/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(D)_H2(aq)") +60 r2 = CALC_VALUE("R(D)_H2O(l)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_T_H2(aq)/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(T)_H2(aq)") +60 r2 = CALC_VALUE("R(T)_H2O(l)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end +# +# CO2(aq) ratios +# +Alpha_18O_CO2(aq)/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("[18O]") <= 0) THEN GOTO 1000 +30 if (TOT("C") <= 0) THEN GOTO 1000 +40 r1 = CALC_VALUE("R(18O)_CO2(aq)") +50 r2 = CALC_VALUE("R(18O)_H2O(l)") +60 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_13C_CO2(aq)/CO2(g) + -start +10 alpha = -9999.999 +20 if (TOT("[13C]") <= 0) THEN GOTO 1000 +30 if (TOT("C") <= 0) THEN GOTO 1000 +40 r1 = CALC_VALUE("R(13C)_CO2(aq)") +50 r2 = CALC_VALUE("R(13C)_CO2(g)") +60 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_14C_CO2(aq)/CO2(g) + -start +10 alpha = -9999.999 +20 if (TOT("[14C]") <= 0) THEN GOTO 1000 +30 if (TOT("C") <= 0) THEN GOTO 1000 +40 r1 = CALC_VALUE("R(14C)_CO2(aq)") +50 r2 = CALC_VALUE("R(14C)_CO2(g)") +60 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end +# +# HCO3- ratios +# +Alpha_D_HCO3-/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 1000 +30 if (TOT("C") <= 0) THEN GOTO 1000 +40 r1 = CALC_VALUE("R(D)_HCO3-") +50 r2 = CALC_VALUE("R(D)_H2O(l)") +60 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_T_HCO3-/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 1000 +30 if (TOT("C") <= 0) THEN GOTO 1000 +40 r1 = CALC_VALUE("R(T)_HCO3-") +50 r2 = CALC_VALUE("R(T)_H2O(l)") +60 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_18O_HCO3-/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("[18O]") <= 0) THEN GOTO 1000 +30 if (TOT("C") <= 0) THEN GOTO 1000 +40 r1 = CALC_VALUE("R(18O)_HCO3-") +50 r2 = CALC_VALUE("R(18O)_H2O(l)") +60 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_18O_HCO3-/CO2(aq) + -start +10 alpha = -9999.999 +20 if (TOT("[18O]") <= 0) THEN GOTO 1000 +30 if (TOT("C") <= 0) THEN GOTO 1000 +40 r1 = CALC_VALUE("R(18O)_HCO3-") +50 r2 = CALC_VALUE("R(18O)_CO2(aq)") +60 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_13C_HCO3-/CO2(g) + -start +10 alpha = -9999.999 +20 if (TOT("[13C]") <= 0) THEN GOTO 1000 +30 if (GAS("CO2(g)") <= 0) THEN GOTO 1000 +40 r1 = CALC_VALUE("R(13C)_HCO3-") +50 r2 = CALC_VALUE("R(13C)_CO2(g)") +60 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_13C_HCO3-/CO2(aq) + -start +10 alpha = -9999.999 +20 if (TOT("[13C]") <= 0) THEN GOTO 1000 +30 if (TOT("C") <= 0) THEN GOTO 1000 +40 r1 = CALC_VALUE("R(13C)_HCO3-") +50 r2 = CALC_VALUE("R(13C)_CO2(aq)") +60 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_14C_HCO3-/CO2(g) + -start +10 alpha = -9999.999 +20 if (TOT("[14C]") <= 0) THEN GOTO 1000 +30 if (GAS("CO2(g)") <= 0) THEN GOTO 1000 +40 r1 = CALC_VALUE("R(14C)_HCO3-") +50 r2 = CALC_VALUE("R(14C)_CO2(g)") +60 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_14C_HCO3-/CO2(aq) + -start +10 alpha = -9999.999 +20 if (TOT("[14C]") <= 0) THEN GOTO 1000 +30 if (TOT("C") <= 0) THEN GOTO 1000 +40 r1 = CALC_VALUE("R(14C)_HCO3-") +50 r2 = CALC_VALUE("R(14C)_CO2(aq)") +60 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end +# +# CO3-2 ratios +# +Alpha_18O_CO3-2/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("[18O]") <= 0) THEN GOTO 1000 +30 if (TOT("C") <= 0) THEN GOTO 1000 +40 r1 = CALC_VALUE("R(18O)_CO3-2") +50 r2 = CALC_VALUE("R(18O)_H2O(l)") +60 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_18O_CO3-2/CO2(aq) + -start +10 alpha = -9999.999 +20 if (TOT("[18O]") <= 0) THEN GOTO 1000 +30 if (TOT("C") <= 0) THEN GOTO 1000 +40 r1 = CALC_VALUE("R(18O)_CO3-2") +50 r2 = CALC_VALUE("R(18O)_CO2(aq)") +60 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_13C_CO3-2/CO2(g) + -start +10 alpha = -9999.999 +20 if (TOT("[13C]") <= 0) THEN GOTO 1000 +30 if (GAS("CO2(g)") <= 0) THEN GOTO 1000 +40 r1 = CALC_VALUE("R(13C)_CO3-2") +50 r2 = CALC_VALUE("R(13C)_CO2(g)") +60 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_13C_CO3-2/CO2(aq) #? + -start +10 alpha = -9999.999 +20 if (TOT("[13C]") <= 0) THEN GOTO 1000 +30 if (TOT("C") <= 0) THEN GOTO 1000 +40 r1 = CALC_VALUE("R(13C)_CO3-2") +50 r2 = CALC_VALUE("R(13C)_CO2(aq)") +60 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_14C_CO3-2/CO2(g) + -start +10 alpha = -9999.999 +20 if (TOT("[14C]") <= 0) THEN GOTO 1000 +30 if (GAS("CO2(g)") <= 0) THEN GOTO 1000 +40 r1 = CALC_VALUE("R(14C)_CO3-2") +50 r2 = CALC_VALUE("R(14C)_CO2(g)") +60 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_14C_CO3-2/CO2(aq) #? + -start +10 alpha = -9999.999 +20 if (TOT("[14C]") <= 0) THEN GOTO 1000 +30 if (TOT("C") <= 0) THEN GOTO 1000 +40 r1 = CALC_VALUE("R(14C)_CO3-2") +50 r2 = CALC_VALUE("R(14C)_CO2(aq)") +60 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end +# +# CH4(aq) ratios +# +Alpha_D_CH4(aq)/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 1000 +30 if (TOT("C") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(D)_CH4(aq)") +60 r2 = CALC_VALUE("R(D)_H2O(l)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_T_CH4(aq)/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 1000 +30 if (TOT("C") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(T)_CH4(aq)") +60 r2 = CALC_VALUE("R(T)_H2O(l)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_13C_CH4(aq)/CO2(aq) + -start +10 alpha = -9999.999 +20 if (TOT("[13C]") <= 0) THEN GOTO 1000 +30 if (TOT("C") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(13C)_CH4(aq)") +60 r2 = CALC_VALUE("R(13C)_CO2(aq)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_14C_CH4(aq)/CO2(aq) + -start +10 alpha = -9999.999 +20 if (TOT("[14C]") <= 0) THEN GOTO 1000 +30 if (TOT("C") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(14C)_CH4(aq)") +60 r2 = CALC_VALUE("R(14C)_CO2(aq)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end +# +# HSO4-2 ratios +# +Alpha_D_HSO4-/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 1000 +30 if (TOT("S(6)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(D)_HSO4-") +60 r2 = CALC_VALUE("R(D)_H2O(l)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_T_HSO4-/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 1000 +30 if (TOT("S(6)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(T)_HSO4-") +60 r2 = CALC_VALUE("R(T)_H2O(l)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_34S_HSO4-/SO4-2 + -start +10 alpha = -9999.999 +20 if (TOT("[34S]") <= 0) THEN GOTO 1000 +30 if (TOT("S(6)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(34S)_HSO4-") +60 r2 = CALC_VALUE("R(34S)_SO4-2") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end +# +# S-2 ratios +# +Alpha_34S_S-2/HS- + -start +10 alpha = -9999.999 +20 if (TOT("[34S]") <= 0) THEN GOTO 1000 +30 if (TOT("S(-2)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(34S)_S-2") +60 r2 = CALC_VALUE("R(34S)_HS-") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +# +# HS- ratios +# +Alpha_D_HS-/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 1000 +30 if (TOT("S(-2)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(D)_HS-") +60 r2 = CALC_VALUE("R(D)_H2O(l)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_T_HS-/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 1000 +30 if (TOT("S(-2)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(T)_HS-") +60 r2 = CALC_VALUE("R(T)_H2O(l)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_34S_HS-/SO4-2 + -start +10 alpha = -9999.999 +20 if (TOT("[34S]") <= 0) THEN GOTO 1000 +30 if (TOT("S(6)") <= 0) THEN GOTO 1000 +40 if (TOT("S(-2)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(34S)_HS-") +60 r2 = CALC_VALUE("R(34S)_SO4-2") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end +# +# H2S ratios +# +Alpha_D_H2S(aq)/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 1000 +30 if (TOT("S(-2)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(D)_H2S(aq)") +60 r2 = CALC_VALUE("R(D)_H2O(l)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_D_H2S(aq)/HS- + -start +10 alpha = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 1000 +30 if (TOT("S(-2)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(D)_H2S(aq)") +60 r2 = CALC_VALUE("R(D)_HS-") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_T_H2S(aq)/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 1000 +30 if (TOT("S(-2)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(T)_H2S(aq)") +60 r2 = CALC_VALUE("R(T)_H2O(l)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_T_H2S(aq)/HS- + -start +10 alpha = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 1000 +30 if (TOT("S(-2)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(T)_H2S(aq)") +60 r2 = CALC_VALUE("R(T)_HS-") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_34S_H2S(aq)/HS- + -start +10 alpha = -9999.999 +20 if (TOT("[34S]") <= 0) THEN GOTO 1000 +30 if (TOT("S(-2)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(34S)_H2S(aq)") +60 r2 = CALC_VALUE("R(34S)_HS-") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end +# +# NO3- ratios +# +Alpha_15N_NO2-/NO3- + -start +10 alpha = -9999.999 +20 if (TOT("[15N]") <= 0) THEN GOTO 1000 +30 if (TOT("N(5)") <= 0) THEN GOTO 1000 +40 if (TOT("N(3)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(15N)_NO2-") +60 r2 = CALC_VALUE("R(15N)_NO3-") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end +# +# N2(aq) ratios +# +Alpha_15N_N2(aq)/NO3- + -start +10 alpha = -9999.999 +20 if (TOT("[15N]") <= 0) THEN GOTO 1000 +30 if (TOT("N(5)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(15N)_N2(aq)") +60 r2 = CALC_VALUE("R(15N)_NO3-") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end +# +# NH3(aq) ratios +# +Alpha_D_NH3(aq)/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 1000 +30 if (TOT("N(-3)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(D)_NH3(aq)") +60 r2 = CALC_VALUE("R(D)_H2O(l)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_T_NH3(aq)/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 1000 +30 if (TOT("N(-3)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(T)_NH3(aq)") +60 r2 = CALC_VALUE("R(T)_H2O(l)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_15N_NH3(aq)/NO3- + -start +10 alpha = -9999.999 +20 if (TOT("[15N]") <= 0) THEN GOTO 1000 +30 if (TOT("N(-3)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(15N)_NH3(aq)") +60 r2 = CALC_VALUE("R(15)_NO3-") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end +# +# NH4+ ratios +# +Alpha_D_NH4+/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 1000 +30 if (TOT("N(-3)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(D)_NH4+") +60 r2 = CALC_VALUE("R(D)_H2O(l)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_T_NH4+/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 1000 +30 if (TOT("N(-3)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(T)_NH4+") +60 r2 = CALC_VALUE("R(T)_H2O(l)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_15N_NH4+/NO3- + -start +10 alpha = -9999.999 +20 if (TOT("[15N]") <= 0) THEN GOTO 1000 +30 if (TOT("N(5)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(15N)_NH4+") +60 r2 = CALC_VALUE("R(15N)_NO3-") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_15N_NH4+/NH3(aq) + -start +10 alpha = -9999.999 +20 if (TOT("[15N]") <= 0) THEN GOTO 1000 +30 if (TOT("N(5)") <= 0) THEN GOTO 1000 +40 if (TOT("N(-3)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(15N)_NH4+") +60 r2 = CALC_VALUE("R(15N)_NH3(aq)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end +# +# Ratios for minerals and gases +# +# +# H2O(g) ratios +# +Alpha_D_H2O(g)/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 1000 +30 if (GAS("H2O(g)") <= 0) THEN GOTO 1000 +40 r1 = CALC_VALUE("R(D)_H2O(g)") +50 r2 = CALC_VALUE("R(D)_H2O(l)") +60 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_T_H2O(g)/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 1000 +30 if (GAS("H2O(g)") <= 0) THEN GOTO 1000 +40 r1 = CALC_VALUE("R(T)_H2O(g)") +50 r2 = CALC_VALUE("R(T)_H2O(l)") +60 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_18O_H2O(g)/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("[18O]") <= 0) THEN GOTO 1000 +30 if (GAS("H2O(g)") <= 0) THEN GOTO 1000 +40 r1 = CALC_VALUE("R(18O)_H2O(g)") +50 r2 = CALC_VALUE("R(18O)_H2O(l)") +60 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end +# +# O2(g) ratios +# +Alpha_18O_O2(aq)/O2(g) + -start +10 alpha = -9999.999 +20 if (TOT("[18O]") <= 0) THEN GOTO 1000 +30 if (GAS("O2(g)") <= 0) THEN GOTO 1000 +40 if (GAS("O[18O](g)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(18O)_O2(aq)") +60 r2 = CALC_VALUE("R(18O)_O2(g)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_18O_O2(g)/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("[18O]") <= 0) THEN GOTO 1000 +30 if (GAS("O2(g)") <= 0) THEN GOTO 1000 +40 if (GAS("O[18O](g)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(18O)_O2(g)") +60 r2 = CALC_VALUE("R(18O)_H2O(l)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +# +# H2(g) ratios +# +Alpha_D_H2(g)/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 1000 +30 if (GAS("H2(g)") <= 0) THEN GOTO 1000 +40 if (GAS("HD(g)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(D)_H2(g)") +60 r2 = CALC_VALUE("R(D)_H2O(l)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_T_H2(g)/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 1000 +30 if (GAS("H2(g)") <= 0) THEN GOTO 1000 +40 if (GAS("HT(g)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(T)_H2(g)") +60 r2 = CALC_VALUE("R(T)_H2O(l)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_D_H2(aq)/H2(g) + -start +10 alpha = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 1000 +30 if (GAS("H2(g)") <= 0) THEN GOTO 1000 +40 if (GAS("HD(g)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(D)_H2(aq)") +60 r2 = CALC_VALUE("R(D)_H2(g)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_T_H2(aq)/H2(g) + -start +10 alpha = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 1000 +30 if (GAS("H2(g)") <= 0) THEN GOTO 1000 +40 if (GAS("HT(g)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(T)_H2(aq)") +60 r2 = CALC_VALUE("R(T)_H2(g)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end +# +# CO2(g) ratios +# +Alpha_18O_CO2(g)/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("[18O]") <= 0) THEN GOTO 1000 +30 if (GAS("CO2(g)") <= 0) THEN GOTO 1000 +40 if (GAS("CO[18O](g)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(18O)_CO2(g)") +60 r2 = CALC_VALUE("R(18O)_H2O(l)") +70 if (r1 <= 0) THEN GOTO 1000 +80 if (r2 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_18O_CO2(g)/CO2(aq) + -start +10 alpha = -9999.999 +20 if (TOT("[18O]") <= 0) THEN GOTO 1000 +30 if (GAS("CO2(g)") <= 0) THEN GOTO 1000 +40 if (GAS("CO[18O](g)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(18O)_CO2(g)") +60 r2 = CALC_VALUE("R(18O)_CO2(aq)") +70 if (r1 <= 0) THEN GOTO 1000 +80 if (r2 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_13C_CO2(g)/CO2(aq) + -start +10 alpha = -9999.999 +20 if (TOT("[13C]") <= 0) THEN GOTO 1000 +30 if (GAS("CO2(g)") <= 0) THEN GOTO 1000 +40 if (GAS("[13C]O2(g)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(13C)_CO2(g)") +60 r2 = CALC_VALUE("R(13C)_CO2(aq)") +70 if (r1 <= 0) THEN GOTO 1000 +80 if (r2 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_14C_CO2(g)/CO2(aq) + -start +10 alpha = -9999.999 +20 if (TOT("[14C]") <= 0) THEN GOTO 1000 +30 if (GAS("CO2(g)") <= 0) THEN GOTO 1000 +40 if (GAS("[134]O2(g)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(14C)_CO2(g)") +60 r2 = CALC_VALUE("R(14C)_CO2(aq)") +70 if (r1 <= 0) THEN GOTO 1000 +80 if (r2 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end +# +# Calcite ratios +# +Alpha_18O_Calcite/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("[18O]") <= 0) THEN GOTO 1000 +30 if (S_S("Calcite") <= 0) THEN GOTO 1000 +40 r1 = CALC_VALUE("R(18O)_Calcite") +50 r2 = CALC_VALUE("R(18O)_H2O(l)") +60 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_18O_Calcite/CO3-2 + -start +10 alpha = -9999.999 +20 if (TOT("[18O]") <= 0) THEN GOTO 1000 +30 if (S_S("Calcite") <= 0) THEN GOTO 1000 +40 r1 = CALC_VALUE("R(18O)_Calcite") +50 r2 = CALC_VALUE("R(18O)_CO3-2") +60 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_13C_Calcite/CO2(g) + -start +10 alpha = -9999.999 +20 if (TOT("[13C]") <= 0) THEN GOTO 1000 +30 if (S_S("Calcite") <= 0) THEN GOTO 1000 +35 if (GAS("CO2(g)") <= 0) THEN GOTO 1000 +40 r1 = CALC_VALUE("R(13C)_Calcite") +50 r2 = CALC_VALUE("R(13C)_CO2(g)") +60 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_13C_Calcite/CO2(aq) + -start +10 alpha = -9999.999 +20 if (TOT("[13C]") <= 0) THEN GOTO 1000 +30 if (S_S("Calcite") <= 0) THEN GOTO 1000 +40 r1 = CALC_VALUE("R(13C)_Calcite") +50 r2 = CALC_VALUE("R(13C)_CO2(aq)") +60 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_13C_Calcite/CO3-2 + -start +10 alpha = -9999.999 +20 if (TOT("[13C]") <= 0) THEN GOTO 1000 +30 if (S_S("Calcite") <= 0) THEN GOTO 1000 +40 r1 = CALC_VALUE("R(13C)_Calcite") +50 r2 = CALC_VALUE("R(13C)_CO3-2") +60 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_14C_Calcite/CO2(g) + -start +10 alpha = -9999.999 +20 if (TOT("[14C]") <= 0) THEN GOTO 1000 +30 if (S_S("Calcite") <= 0) THEN GOTO 1000 +35 if (GAS("CO2(g)") <= 0) THEN GOTO 1000 +40 r1 = CALC_VALUE("R(14C)_Calcite") +50 r2 = CALC_VALUE("R(14C)_CO2(g)") +60 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_14C_Calcite/CO2(aq) + -start +10 alpha = -9999.999 +20 if (TOT("[14C]") <= 0) THEN GOTO 1000 +30 if (S_S("Calcite") <= 0) THEN GOTO 1000 +40 r1 = CALC_VALUE("R(14C)_Calcite") +50 r2 = CALC_VALUE("R(14C)_CO2(aq)") +60 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_14C_Calcite/CO3-2 + -start +10 alpha = -9999.999 +20 if (TOT("[14C]") <= 0) THEN GOTO 1000 +30 if (S_S("Calcite") <= 0) THEN GOTO 1000 +40 r1 = CALC_VALUE("R(14C)_Calcite") +50 r2 = CALC_VALUE("R(14C)_CO3-2") +60 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end +# +# Pyrite ratios +# +Alpha_34S_Pyrite/HS- + -start +10 alpha = -9999.999 +20 if (TOT("[34S]") <= 0) THEN GOTO 1000 +30 if (S_S("Pyrite") <= 0) THEN GOTO 1000 +40 r1 = CALC_VALUE("R(34S)_Pyrite") +50 r2 = CALC_VALUE("R(34S)_HS-") +60 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end +# +# CH4(g) ratios +# +Alpha_D_CH4(aq)/CH4(g) + -start +10 alpha = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 1000 +30 if (GAS("CH4(g)") <= 0) THEN GOTO 1000 +40 if (GAS("CH3D(g)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(D)_CH4(aq)") +60 r2 = CALC_VALUE("R(D)_CH4(g)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_D_CH4(g)/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 1000 +30 if (GAS("CH4(g)") <= 0) THEN GOTO 1000 +40 if (GAS("CH3D(g)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(D)_CH4(g)") +60 r2 = CALC_VALUE("R(D)_H2O(l)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_T_CH4(aq)/CH4(g) + -start +10 alpha = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 1000 +30 if (GAS("CH4(g)") <= 0) THEN GOTO 1000 +40 if (GAS("CH3T(g)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(T)_CH4(aq)") +60 r2 = CALC_VALUE("R(T)_CH4(g)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_T_CH4(g)/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 1000 +30 if (GAS("CH4(g)") <= 0) THEN GOTO 1000 +40 if (GAS("CH3T(g)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(T)_CH4(g)") +60 r2 = CALC_VALUE("R(T)_H2O(l)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_13C_CH4(g)/CO2(aq) + -start +10 alpha = -9999.999 +20 if (TOT("[13C]") <= 0) THEN GOTO 1000 +30 if (GAS("CH4(g)") <= 0) THEN GOTO 1000 +40 if (GAS("[13C]H4(g)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(13C)_CH4(g)") +60 r2 = CALC_VALUE("R(13C)_CO2(aq)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_13C_CH4(aq)/CH4(g) + -start +10 alpha = -9999.999 +20 if (TOT("[13C]") <= 0) THEN GOTO 1000 +30 if (GAS("CH4(g)") <= 0) THEN GOTO 1000 +40 if (GAS("[13C]H4(g)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(13C)_CH4(aq)") +60 r2 = CALC_VALUE("R(13C)_CH4(g)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_14C_CH4(g)/CO2(aq) + -start +10 alpha = -9999.999 +20 if (TOT("[14C]") <= 0) THEN GOTO 1000 +30 if (GAS("CH4(g)") <= 0) THEN GOTO 1000 +40 if (GAS("[14C]H4(g)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(14C)_CH4(g)") +60 r2 = CALC_VALUE("R(14C)_CO2(aq)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_14C_CH4(aq)/CH4(g) + -start +10 alpha = -9999.999 +20 if (TOT("[14C]") <= 0) THEN GOTO 1000 +30 if (GAS("CH4(g)") <= 0) THEN GOTO 1000 +40 if (GAS("[14C]H4(g)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(14C)_CH4(aq)") +60 r2 = CALC_VALUE("R(14C)_CH4(g)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end +# +# H2S(g) ratios +# +Alpha_D_H2S(g)/H2S(aq) + -start +10 alpha = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 1000 +30 if (TOT("S(-2)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(D)_H2S(g)") +60 r2 = CALC_VALUE("R(D)_H2S(aq)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_T_H2S(g)/H2S(aq) + -start +10 alpha = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 1000 +30 if (TOT("S(-2)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(T)_H2S(g)") +60 r2 = CALC_VALUE("R(T)_H2S(aq)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_34S_H2S(g)/H2S(aq) + -start +10 alpha = -9999.999 +20 if (TOT("[34S]") <= 0) THEN GOTO 1000 +30 if (TOT("S(6)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(34S)_H2S(g)") +60 r2 = CALC_VALUE("R(34S)_H2S(aq)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end +# +# Gypsum ratios +# +Alpha_34S_Gypsum/SO4-2 + -start +10 alpha = -9999.999 +20 if (TOT("[34S]") <= 0) THEN GOTO 1000 +30 if (TOT("S(6)") <= 0) THEN GOTO 1000 +40 if (S_S("Gypsum") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(34S)_Gypsum") +60 r2 = CALC_VALUE("R(34S)_SO4-2") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end +# +# Anhydrite ratios +# +Alpha_34S_Anhydrite/SO4-2 + -start +10 alpha = -9999.999 +20 if (TOT("[34S]") <= 0) THEN GOTO 1000 +30 if (TOT("S(6)") <= 0) THEN GOTO 1000 +40 if (S_S("Anhydrite") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(34S)_Anhydrite") +60 r2 = CALC_VALUE("R(34S)_SO4-2") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end +# +# N2(g) ratios +# +Alpha_15N_N2(g)/N2(aq) + -start +10 alpha = -9999.999 +20 if (TOT("[15N]") <= 0) THEN GOTO 1000 +30 if (TOT("N(0)") <= 0) THEN GOTO 1000 +40 if (GAS("N2(g)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(15N)_N2(g)") +60 r2 = CALC_VALUE("R(15N)_N2(aq)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end +# +# NH3(g) ratios +# +Alpha_D_NH3(g)/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("D") <= 0) THEN GOTO 1000 +30 if (TOT("N(-3)") <= 0) THEN GOTO 1000 +40 if (GAS("NH3(g)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(D)_NH3(g)") +60 r2 = CALC_VALUE("R(D)_H2O(l)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_T_NH3(g)/H2O(l) + -start +10 alpha = -9999.999 +20 if (TOT("T") <= 0) THEN GOTO 1000 +30 if (TOT("N(-3)") <= 0) THEN GOTO 1000 +40 if (GAS("NH3(g)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(T)_NH3(g)") +60 r2 = CALC_VALUE("R(T)_H2O(l)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end + +Alpha_15N_NH3(g)/NH3(aq) + -start +10 alpha = -9999.999 +20 if (TOT("[15N]") <= 0) THEN GOTO 1000 +30 if (TOT("N(-3)") <= 0) THEN GOTO 1000 +40 if (GAS("NH3(g)") <= 0) THEN GOTO 1000 +50 r1 = CALC_VALUE("R(15N)_NH3(g)") +60 r2 = CALC_VALUE("R(15N)_NH3(aq)") +70 if (r2 <= 0) THEN GOTO 1000 +80 if (r1 <= -9999) THEN GOTO 1000 +90 alpha = r1/r2 +1000 save alpha + -end +############################################################################################### +SOLUTION_SPECIES +############################################################################################### +D2O = D2O + -activity_water + log_k 0 + +HTO = HTO + -activity_water + log_k 0 + +H2[18O] = H2[18O] + -activity_water + log_k 0 + +CO2 = CO2 + log_k 0 + +[13C]O2 = [13C]O2 + log_k 0 + +[14C]O2 = [14C]O2 + log_k 0 + +[34S]O4-2 = [34S]O4-2 + log_k 0.0 + -gamma 5.0000 -0.0400 + +[15N]O3- = [15N]O3- + log_k 0.0 + -gamma 3.0000 0.0000 + +# +# H2O reactions +# last update July 31, 2006 +# checked September 19, 2006 +# +0.5H2O + 0.5D2O = HDO + log_k 0.301029995663 # log10(2) + -activity_water + +HDO + HTO = DTO + H2O + -mole_balance DTO + log_k -0.301029995663 # log10(1/2) + -activity_water + +2HTO = T2O + H2O + -mole_balance T2O + log_k -0.6020599913279623960 # log10(1/4) + -activity_water + +H2[18O] + HDO = HD[18O] + H2O + -mole_balance HD[18O] + log_k 0.0 + -activity_water + +H2[18O] + HTO = HT[18O] + H2O + -mole_balance HT[18O] + log_k 0.0 + -activity_water + +DTO + H2[18O] = DT[18O] + H2O + -mole_balance DT[18O] + log_k 0.0 + -activity_water + +D2O + H2[18O] = D2[18O] + H2O + -mole_balance D2[18O] + log_k 0.0 + -activity_water + +H2[18O] + T2O = T2[18O] + H2O + -mole_balance T2[18O] + log_k 0.0 + -activity_water +# +# OH- reactions +# last update July 31, 2006 +# checked September 19, 2006 +# +OH- + HDO = OD- + H2O + -mole_balance OD + log_k -0.301029995663 # -log10(2) + -add_logk Log_alpha_D_OH-/H2O(l) 1.0 + -gamma 3.5000 0.0000 + +OH- + HTO = OT- + H2O + -mole_balance OT + log_k -0.301029995663 # -log10(2) + -add_logk Log_alpha_T_OH-/H2O(l) 1.0 + -gamma 3.5000 0.0000 + +OH- + H2[18O] = [18O]H- + H2O + -mole_balance [18O]H + -add_logk Log_alpha_18O_OH-/H2O(l) 1.0 + -gamma 3.5000 0.0000 + +[18O]H- + OD- = [18O]D- + OH- + -mole_balance [18O]D + log_k 0.0 + -gamma 3.5000 0.0000 + +[18O]H- + OT- = [18O]T- + OH- + -mole_balance [18O]T + log_k 0.0 + -gamma 3.5000 0.0000 +# +# H3O+ reactions +# last update July 31, 2006 +# checked September 19, 2006 +# +H3O+ + HDO = H2DO+ + H2O + -mole_balance H2DO + log_k 0.176091259055 # log10(1.5) + -add_logk Log_alpha_D_H3O+/H2O(l) 1.0 + -gamma 9.0000 0.0000 + +2H2DO+ = HD2O+ + H3O+ + -mole_balance HD2O + log_k -0.477121254719662 # log10(1/3) + -gamma 9.0000 0.0000 + +H2DO+ + HD2O+ = D3O+ + H3O+ + -mole_balance D3O + log_k -0.954242509439324 # log10(1/9) + -gamma 9.0000 0.0000 + +H3O+ + HTO = H2TO+ + H2O + -mole_balance H2TO + log_k 0.176091259055 # log10(1.5) + -add_logk Log_alpha_T_H3O+/H2O(l) 1.0 + -gamma 9.0000 0.0000 + +2H2TO+ = HT2O+ + H3O+ + -mole_balance HT2O + log_k -0.477121254719662 # log10(1/3) + -gamma 9.0000 0.0000 + +H2TO+ + HT2O+ = T3O+ + H3O+ + -mole_balance T3O + log_k -0.954242509439324 # log10(1/9) + -gamma 9.0000 0.0000 + +H2TO+ + H2DO+ = HDTO+ + H3O+ + -mole_balance HDTO + log_k -0.477121254719662 # log10(1/3) + -gamma 9.0000 0.0000 + +H2TO+ + HD2O+ = D2TO+ + H3O+ + -mole_balance D2TO + log_k -0.477121254719662 # log10(1/3) + -gamma 9.0000 0.0000 + +H2DO+ + HT2O+ = DT2O+ + H3O+ + -mole_balance DT2O + log_k -0.477121254719662 # log10(1/3) + -gamma 9.0000 0.0000 + +H3O+ + H2[18O] = H3[18O]+ + H2O + -mole_balance H3[18O] + -add_logk Log_alpha_18O_H3O+/H2O(l) 1.0 + -gamma 9.0000 0.0000 + +H3[18O]+ + H2DO+ = H2D[18O]+ + H3O+ + -mole_balance H2D[18O] + log_k 0.0 + -gamma 9.0000 0.0000 + +H3[18O]+ + HD2O+ = HD2[18O]+ + H3O+ + -mole_balance HD2[18O] + log_k 0.0 + -gamma 9.0000 0.0000 + +H3[18O]+ + D3O+ = D3[18O]+ + H3O+ + -mole_balance D3[18O] + log_k 0.0 + -gamma 9.0000 0.0000 + +H3[18O]+ + H2TO+ = H2T[18O]+ + H3O+ + -mole_balance H2T[18O] + log_k 0.0 + -gamma 9.0000 0.0000 + +H3[18O]+ + HT2O+ = HT2[18O]+ + H3O+ + -mole_balance HT2[18O] + log_k 0.0 + -gamma 9.0000 0.0000 + +H3[18O]+ + T3O+ = T3[18O]+ + H3O+ + -mole_balance T3[18O] + log_k 0.0 + -gamma 9.0000 0.0000 + +H3[18O]+ + HDTO+ = HDT[18O]+ + H3O+ + -mole_balance HDT[18O] + log_k 0.0 + -gamma 9.0000 0.0000 + +H3[18O]+ + D2TO+ = D2T[18O]+ + H3O+ + -mole_balance D2T[18O] + log_k 0.0 + -gamma 9.0000 0.0000 + +H3[18O]+ + DT2O+ = DT2[18O]+ + H3O+ + -mole_balance DT2[18O] + log_k 0.0 + -gamma 9.0000 0.0000 + +# +# O2 reactions +# last update July 31, 2006 +# checked September 19, 2006 +# + +O2 + H2[18O] = O[18O] + H2O + log_k 0.301029995663 # log10(2) + -add_logk Log_alpha_18O_O2(aq)/H2O(l) 1.0 + -mole_balance O(0)[18O](0) + +2O[18O] = [18O]2 + O2 + log_k -0.602059991327962396 # -log10(4) + -mole_balance [18O](0)2 +# +# H2 reactions +# last update July 31, 2006 +# checked September 19, 2006 +# +H2 + HDO = HD + H2O + -mole_balance H(0)D(0) + -add_logk Log_alpha_D_H2(aq)/H2O(l) 1.0 + +2HD = D2 + H2 + -mole_balance D(0)2 + log_k -0.602059991327962396 # -log10(4) + +H2 + HTO = HT + H2O + -mole_balance H(0)T(0) + -add_logk Log_alpha_T_H2(aq)/H2O(l) 1.0 + +2HT = T2 + H2 + -mole_balance T(0)2 + log_k -0.602059991327962396 # -log10(4) + +HT + HD = DT + H2 + -mole_balance D(0)T(0) + log_k -0.301029995663 # -log10(2) +# +# CO2 reactions +# last update July 31, 2006 +# Checked September 19, 2006 +# +CO2 + H2[18O] = CO[18O] + H2O + log_k 0.301029995663 # log10(2) + -add_logk Log_alpha_18O_CO2(aq)/H2O(l) 1.0 + +2CO[18O] = C[18O]2 + CO2 + log_k -0.6020599913279623960 # log10(1/4) + +[13C]O2 + CO[18O] = [13C]O[18O] + CO2 + log_k 0 + +[13C]O2 + C[18O]2 = [13C][18O]2 + CO2 + log_k 0 + +[14C]O2 + CO[18O] = [14C]O[18O] + CO2 + log_k 0 + +[14C]O2 + C[18O]2 = [14C][18O]2 + CO2 + log_k 0 +# +# HCO3- reactions +# last update July 31, 2006 +# Checked September 19, 2006 +# +HCO3- + H2[18O] = HCO2[18O]- + H2O + -add_logk Log_alpha_18O_HCO3-/H2O(l) 1.0 + +HCO2[18O]- = HCO[18O]O- +HCO2[18O]- = HC[18O]O2- +2HCO2[18O]- = HCO[18O]2- + HCO3- +HCO[18O]2- = HC[18O]O[18O]- +HCO[18O]2- = HC[18O]2O- +3HCO2[18O]- = HC[18O]3- + 2HCO3- + +HDO + HCO3- = DCO3- + H2O + log_k -0.301029995663 # -log10(2) + -add_logk Log_alpha_D_HCO3-/H2O(l) 1.0 + +DCO3- + HCO2[18O]- = DCO2[18O]- + HCO3- +DCO3- + HCO[18O]O- = DCO[18O]O- + HCO3- +DCO3- + HC[18O]O2- = DC[18O]O2- + HCO3- +DCO3- + HCO[18O]2- = DCO[18O]2- + HCO3- +DCO3- + HC[18O]O[18O]- = DC[18O]O[18O]- + HCO3- +DCO3- + HC[18O]2O- = DC[18O]2O- + HCO3- +DCO3- + HC[18O]3- = DC[18O]3- + HCO3- + +HTO + HCO3- = TCO3- + H2O + log_k -0.301029995663 # -log10(2) + -add_logk Log_alpha_T_HCO3-/H2O(l) 1.0 + +TCO3- + HCO2[18O]- = TCO2[18O]- + HCO3- +TCO3- + HCO[18O]O- = TCO[18O]O- + HCO3- +TCO3- + HC[18O]O2- = TC[18O]O2- + HCO3- +TCO3- + HCO[18O]2- = TCO[18O]2- + HCO3- +TCO3- + HC[18O]O[18O]- = TC[18O]O[18O]- + HCO3- +TCO3- + HC[18O]2O- = TC[18O]2O- + HCO3- +TCO3- + HC[18O]3- = TC[18O]3- + HCO3- + +HCO3- + [13C]O2 = H[13C]O3- + CO2 + -add_logk Log_alpha_13C_HCO3-/CO2(aq) 1.0 + +H[13C]O3- + HCO2[18O]- = H[13C]O2[18O]- + HCO3- +H[13C]O3- + HCO[18O]O- = H[13C]O[18O]O- + HCO3- +H[13C]O3- + HC[18O]O2- = H[13C][18O]O2- + HCO3- +H[13C]O3- + HCO[18O]2- = H[13C]O[18O]2- + HCO3- +H[13C]O3- + HC[18O]O[18O]- = H[13C][18O]O[18O]- + HCO3- +H[13C]O3- + HC[18O]2O- = H[13C][18O]2O- + HCO3- +H[13C]O3- + HC[18O]3- = H[13C][18O]3- + HCO3- +DCO3- + H[13C]O3- = D[13C]O3- + HCO3- +H[13C]O3- + DCO2[18O]- = D[13C]O2[18O]- + HCO3- +H[13C]O3- + DCO[18O]O- = D[13C]O[18O]O- + HCO3- +H[13C]O3- + DC[18O]O2- = D[13C][18O]O2- + HCO3- +H[13C]O3- + DCO[18O]2- = D[13C]O[18O]2- + HCO3- +H[13C]O3- + DC[18O]O[18O]- = D[13C][18O]O[18O]- + HCO3- +H[13C]O3- + DC[18O]2O- = D[13C][18O]2O- + HCO3- +H[13C]O3- + DC[18O]3- = D[13C][18O]3- + HCO3- +TCO3- + H[13C]O3- = T[13C]O3- + HCO3- +H[13C]O3- + TCO2[18O]- = T[13C]O2[18O]- + HCO3- +H[13C]O3- + TCO[18O]O- = T[13C]O[18O]O- + HCO3- +H[13C]O3- + TC[18O]O2- = T[13C][18O]O2- + HCO3- +H[13C]O3- + TCO[18O]2- = T[13C]O[18O]2- + HCO3- +H[13C]O3- + TC[18O]O[18O]- = T[13C][18O]O[18O]- + HCO3- +H[13C]O3- + TC[18O]2O- = T[13C][18O]2O- + HCO3- +H[13C]O3- + TC[18O]3- = T[13C][18O]3- + HCO3- + +HCO3- + [14C]O2 = H[14C]O3- + CO2 + -add_logk Log_alpha_14C_HCO3-/CO2(aq) 1.0 + +H[14C]O3- + HCO2[18O]- = H[14C]O2[18O]- + HCO3- +H[14C]O3- + HCO[18O]O- = H[14C]O[18O]O- + HCO3- +H[14C]O3- + HC[18O]O2- = H[14C][18O]O2- + HCO3- +H[14C]O3- + HCO[18O]2- = H[14C]O[18O]2- + HCO3- +H[14C]O3- + HC[18O]O[18O]- = H[14C][18O]O[18O]- + HCO3- +H[14C]O3- + HC[18O]2O- = H[14C][18O]2O- + HCO3- +H[14C]O3- + HC[18O]3- = H[14C][18O]3- + HCO3- +DCO3- + H[14C]O3- = D[14C]O3- + HCO3- +H[14C]O3- + DCO2[18O]- = D[14C]O2[18O]- + HCO3- +H[14C]O3- + DCO[18O]O- = D[14C]O[18O]O- + HCO3- +H[14C]O3- + DC[18O]O2- = D[14C][18O]O2- + HCO3- +H[14C]O3- + DCO[18O]2- = D[14C]O[18O]2- + HCO3- +H[14C]O3- + DC[18O]O[18O]- = D[14C][18O]O[18O]- + HCO3- +H[14C]O3- + DC[18O]2O- = D[14C][18O]2O- + HCO3- +H[14C]O3- + DC[18O]3- = D[14C][18O]3- + HCO3- +TCO3- + H[14C]O3- = T[14C]O3- + HCO3- +H[14C]O3- + TCO2[18O]- = T[14C]O2[18O]- + HCO3- +H[14C]O3- + TCO[18O]O- = T[14C]O[18O]O- + HCO3- +H[14C]O3- + TC[18O]O2- = T[14C][18O]O2- + HCO3- +H[14C]O3- + TCO[18O]2- = T[14C]O[18O]2- + HCO3- +H[14C]O3- + TC[18O]O[18O]- = T[14C][18O]O[18O]- + HCO3- +H[14C]O3- + TC[18O]2O- = T[14C][18O]2O- + HCO3- +H[14C]O3- + TC[18O]3- = T[14C][18O]3- + HCO3- +# +# CO3-2 reactions +# last update July 31, 2006 +# Checked September 19, 2006 +# +CO3-2 + H2[18O] = CO2[18O]-2 + H2O + log_k 0.477121254719 # log10(3) + -add_logk Log_alpha_18O_CO3-2/H2O(l) 1.0 + +2CO2[18O]-2 = CO[18O]2-2 + CO3-2 + log_k -0.477121254719 # -log10(3) + +CO2[18O]-2 + CO[18O]2-2 = C[18O]3-2 + CO3-2 + log_k -0.954242509439324 # log10(1/9) + +CO3-2 + [13C]O2 = [13C]O3-2 + CO2 + -add_logk Log_alpha_13C_CO3-2/CO2(aq) 1.0 + +[13C]O3-2 + CO2[18O]-2 = [13C]O2[18O]-2 + CO3-2 + log_k 0.0 + +[13C]O3-2 + CO[18O]2-2 = [13C]O[18O]2-2 + CO3-2 + log_k 0.0 + +[13C]O3-2 + C[18O]3-2 = [13C][18O]3-2 + CO3-2 + log_k 0.0 + +CO3-2 + [14C]O2 = [14C]O3-2 + CO2 + -add_logk Log_alpha_14C_CO3-2/CO2(aq) 1.0 + +[14C]O3-2 + CO2[18O]-2 = [14C]O2[18O]-2 + CO3-2 + log_k 0.0 + +[14C]O3-2 + CO[18O]2-2 = [14C]O[18O]2-2 + CO3-2 + log_k 0.0 + +[14C]O3-2 + C[18O]3-2 = [14C][18O]3-2 + CO3-2 + log_k 0.0 +# +# CH4 reactions +# Updated September 19, 2006 +# Checked September 19, 2006 +# +CH4 + HDO = CH3D + H2O + log_k 0.301029995663981198 # log10(2) + -add_logk Log_alpha_D_CH4(aq)/H2O(l) 1.0 + +2CH3D = CH2D2 + CH4 + log_k -0.42596873227228 # log10(3/8) + +3CH3D = CHD3 + 2CH4 + log_k -1.20411998265 # log10(1/16) + +4CH3D = CD4 + 3CH4 + log_k -2.408239965311 # log10(1/256) + +CH4 + HTO = CH3T + H2O + log_k 0.301029995663981198 # log10(2) + -add_logk Log_alpha_T_CH4(aq)/H2O(l) 1.0 + +2CH3T = CH2T2 + CH4 + log_k -0.42596873227228 # log10(3/8) + +3CH3T = CHT3 + 2CH4 + log_k -1.20411998265 # log10(1/16) + +4CH3T = CT4 + 3CH4 + log_k -2.408239965311 # log10(1/256) +# +# Added mixed DT C methane species May 19, 2006 +# +CH3T + CHD3 = CD3T + CH4 + log_k -0.602059991327962396 # -log10(4) + +CH2T2 + CH2D2 = CD2T2 + CH4 + log_k -0.7781512503836 # -log10(6) + +CHT3 + CH3D = CDT3 + CH4 + log_k -0.602059991327962396 # -log10(4) + +[13C]O2 + CH4 = [13C]H4 + CO2 + -add_logk Log_alpha_13C_CH4(aq)/CO2(aq) 1.0 + +[13C]H4 + CH3D = [13C]H3D + CH4 +[13C]H4 + CH2D2 = [13C]H2D2 + CH4 +[13C]H4 + CHD3 = [13C]HD3 + CH4 +[13C]H4 + CD4 = [13C]D4 + CH4 +[13C]H4 + CH3T = [13C]H3T + CH4 +[13C]H4 + CH2T2 = [13C]H2T2 + CH4 +[13C]H4 + CHT3 = [13C]HT3 + CH4 +[13C]H4 + CT4 = [13C]T4 + CH4 +[13C]H4 + CD3T = [13C]D3T + CH4 +[13C]H4 + CD2T2 = [13C]D2T2 + CH4 +[13C]H4 + CDT3 = [13C]DT3 + CH4 + +[14C]O2 + CH4 = [14C]H4 + CO2 + -add_logk Log_alpha_14C_CH4(aq)/CO2(aq) 1.0 +# +# Added mixed DT 14C methane species May 19, 2006 +# +[14C]H4 + CH3D = [14C]H3D + CH4 +[14C]H4 + CH2D2 = [14C]H2D2 + CH4 +[14C]H4 + CHD3 = [14C]HD3 + CH4 +[14C]H4 + CD4 = [14C]D4 + CH4 +[14C]H4 + CH3T = [14C]H3T + CH4 +[14C]H4 + CH2T2 = [14C]H2T2 + CH4 +[14C]H4 + CHT3 = [14C]HT3 + CH4 +[14C]H4 + CT4 = [14C]T4 + CH4 +[14C]H4 + CD3T = [14C]D3T + CH4 +[14C]H4 + CD2T2 = [14C]D2T2 + CH4 +[14C]H4 + CDT3 = [14C]DT3 + CH4 +# +# HSO4- reactions +# Updated September 28, 2006 +# Checked September 28, 2006 +# +HSO4- + HDO = DSO4- + H2O + log_k -0.301029995663 # -log10(2) + -add_logk Log_alpha_D_HSO4-/H2O(l) 1.0 + -mole_balance DS(6)O4- + +HSO4- + HTO = TSO4- + H2O + log_k -0.301029995663 # -log10(2) + -add_logk Log_alpha_T_HSO4-/H2O(l) 1.0 + -mole_balance TS(6)O4- + +[34S]O4-2 + HSO4- = H[34S]O4- + SO4-2 + -add_logk Log_alpha_34S_HSO4-/SO4-2 1.0 + -mole_balance H[34S](6)O4- + +H[34S]O4- + DSO4- = D[34S]O4- + HSO4- + -mole_balance D[34S](6)O4 + +H[34S]O4- + TSO4- = T[34S]O4- + HSO4- + -mole_balance T[34S](6)O4- +# +# S-2 reactions +# +S-2 + H[34S]- = [34S]-2 + HS- + -add_logk Log_alpha_34S_S-2/HS- 1.0 + -mole_balance [34S](-2) + -gamma 5.0000 0.0000 +# +# HS- reactions +# +HS- + HDO = DS- + H2O + log_k -0.301029995663 # -log10(2) + -add_logk Log_alpha_D_HS-/H2O(l) 1.0 + -mole_balance DS(-2) + -gamma 3.5000 0.0000 + +HS- + HTO = TS- + H2O + log_k -0.301029995663 # -log10(2) + -add_logk Log_alpha_T_HS-/H2O(l) 1.0 + -mole_balance TS(-2) + -gamma 3.5000 0.0000 + +HS- + [34S]O4-2 = H[34S]- + SO4-2 + -add_logk Log_alpha_34S_HS-/SO4-2 1.0 + -mole_balance H[34S](-2) + -gamma 3.5000 0.0000 + +H[34S]- + DS- = D[34S]- + HS- + -gamma 3.5000 0.0000 + -mole_balance D[34S](-2) + +H[34S]- + TS- = T[34S]- + HS- + -gamma 3.5000 0.0000 + -mole_balance T[34S](-2) +# +# H2S reactions +# +H2S + HDO = HDS + H2O + -add_logk Log_alpha_D_H2S(aq)/H2O(l) 1.0 + -mole_balance HDS(-2) + +2HDS = D2S + H2S + log_k -0.602059991327962396 # -log10(4) + -mole_balance D2S(-2) + +H2S + HTO = HTS + H2O + -add_logk Log_alpha_T_H2S(aq)/H2O(l) 1.0 + -mole_balance HTS(-2) + +2HTS = T2S + H2S + log_k -0.602059991327962396 # -log10(4) + -mole_balance T2S(-2) + +HDS + HTS = DTS + H2S + log_k -0.301029995663 # log10(1/2) + -mole_balance DTS(-2) + +H[34S]- + H2S = H2[34S] + HS- + -add_logk Log_alpha_34S_H2S(aq)/HS- 1.0 + -mole_balance H2[34S](-2) + +H2[34S] + HDS = HD[34S] + H2S + -mole_balance HD[34S](-2) + +H2[34S] + D2S = D2[34S] + H2S + -mole_balance D2[34S](-2) + +H2[34S] + HTS = HT[34S] + H2S + -mole_balance HT[34S](-2) + +H2[34S] + T2S = T2[34S] + H2S + -mole_balance T2[34S](-2) + +H2[34S] + DTS = DT[34S] + H2S + -mole_balance DT[34S](-2) +# +# NO2- reactions +# Updated March 20, 2006 +# Updated September 19, 2006 +# Checked September 19, 2006 +# +[15N]O3- + NO2- = [15N]O2- + NO3- + -add_logk Log_alpha_15N_NO2-/NO3- 1.0 + -gamma 3.0000 0.0000 +# +# N2 reactions +# +N2 + [15N]O3- = N[15N] + NO3- + log_k 0.301029995663 # log10(2) + -add_logk Log_alpha_15N_N2(aq)/NO3- 1.0 + -mole_balance [15N](0)N(0) +2N[15N] = [15N]2 + N2 + log_k -0.602059991327962396 # -log10(4) + -mole_balance [15N](0)2 +# +# NH3 reactions +# +HDO + NH3 = NH2D + H2O + log_k 0.176091259055 # log10(1.5) + -add_logk Log_alpha_D_NH3(aq)/H2O(l) 1.0 + +2NH2D = NHD2 + NH3 + log_k -0.477121254719 # -log10(3) + +3NH2D = ND3 + 2NH3 + -logk -1.431363764158 # log10(1/27) + +HTO + NH3 = NH2T + H2O + log_k 0.176091259055 # log10(1.5) + -add_logk Log_alpha_T_NH3(aq)/H2O(l) 1.0 + +2NH2T = NHT2 + NH3 + log_k -0.477121254719662 # log10(1/3) + +3NH2T = NT3 + 2NH3 + -logk -1.431363764158 # log10(1/27) + +NHD2 + NH2T = ND2T + NH3 + log_k -0.477121254719 # -log10(3) + +NH2D + NHT2 = NDT2 + NH3 + log_k -0.477121254719 # -log10(3) + +# Checked September 19, 2006 + +NH3 + [15N]O3- = [15N]H3 + NO3- + -add_logk Log_alpha_15N_NH3(aq)/NO3- 1.0 + -mole_balance [15N](-3)H3 + +[15N]H3 + NH2D = [15N]H2D + NH3 +[15N]H3 + NHD2 = [15N]HD2 + NH3 +[15N]H3 + ND3 = [15N]D3 + NH3 +[15N]H3 + NH2T = [15N]H2T + NH3 +[15N]H3 + NHT2 = [15N]HT2 + NH3 +[15N]H3 + NT3 = [15N]T3 + NH3 +[15N]H3 + ND2T = [15N]D2T + NH3 +[15N]H3 + NDT2 = [15N]DT2 + NH3 +# +# NH4+ reactions +# Updated September 19, 2006 +# Checked September 19, 2006 +# +HDO + NH4+ = NH3D+ + H2O + log_k 0.301029995663 # log10(2) + -add_logk Log_alpha_D_NH4+/H2O(l) 1.0 + -mole_balance N(-3)H3D + -gamma 2.5000 0.0000 + +2NH3D+ = NH2D2+ + NH4+ + log_k -0.42596873227228 # log10(3/8) + -mole_balance N(-3)H2D2 + -gamma 2.5000 0.0000 + +3NH3D+ = NHD3+ + 2NH4+ + log_k -1.20411998265 # log10(1/16) + -mole_balance N(-3)HD3 + -gamma 2.5000 0.0000 + +4NH3D+ = ND4+ + 3NH4+ + log_k -2.408239965311 # log10(1/256) + -mole_balance N(-3)D4 + -gamma 2.5000 0.0000 + +HTO + NH4+ = NH3T+ + H2O + log_k 0.301029995663 # log10(2) + -add_logk Log_alpha_T_NH4+/H2O(l) 1.0 + -mole_balance N(-3)H3T + -gamma 2.5000 0.0000 + +2NH3T+ = NH2T2+ + NH4+ + log_k -0.42596873227228 # log10(3/8) + -mole_balance N(-3)H2T2 + -gamma 2.5000 0.0000 + +3NH3T+ = NHT3+ + 2NH4+ + log_k -1.20411998265 # log10(1/16) + -mole_balance N(-3)HT3 + -gamma 2.5000 0.0000 + +4NH3T+ = NT4+ + 3NH4+ + log_k -2.408239965311 # log10(1/256) + -mole_balance N(-3)T4 + -gamma 2.5000 0.0000 +# +# Updated September 19, 2006 +# Checked September 19, 2006 +# +NHD3+ + NH3T+ = ND3T+ + NH4+ + log_k -0.602059991327962396 # -log10(4) + -mole_balance N(-3)D3T + -gamma 2.5000 0.0000 + +NH2D2+ + NH2T2+ = ND2T2+ + NH4+ + log_k -0.7781512503836 # -log10(6) + -mole_balance N(-3)D2T2 + -gamma 2.5000 0.0000 + +NH3D+ + NHT3+ = NDT3+ + NH4+ + log_k -0.602059991327962396 # -log10(4) + -mole_balance N(-3)DT3 + -gamma 2.5000 0.0000 + +[15N]H3 + NH4+ = [15N]H4+ + NH3 + -add_logk Log_alpha_15N_NH4+/NH3(aq) 1.0 + -mole_balance [15N](-3)H4 + -gamma 2.5000 0.0000 + +[15N]H4+ + NH3D+ = [15N]H3D+ + NH4+ + -mole_balance [15N](-3)H3D + -gamma 2.5000 0.0000 + +[15N]H4+ + NH2D2+ = [15N]H2D2+ + NH4+ + -mole_balance [15N](-3)H2D2 + -gamma 2.5000 0.0000 + +[15N]H4+ + NHD3+ = [15N]HD3+ + NH4+ + -mole_balance [15N](-3)HD3 + -gamma 2.5000 0.0000 + +[15N]H4+ + ND4+ = [15N]D4+ + NH4+ + -mole_balance [15N](-3)D4+ + -gamma 2.5000 0.0000 + +[15N]H4+ + NH3T+ = [15N]H3T+ + NH4+ + -mole_balance [15N](-3)H3T + -gamma 2.5000 0.0000 + +[15N]H4+ + NH2T2+ = [15N]H2T2+ + NH4+ + -mole_balance [15N](-3)H2T2 + -gamma 2.5000 0.0000 + +[15N]H4+ + NHT3+ = [15N]HT3+ + NH4+ + -mole_balance [15N](-3)HT3 + -gamma 2.5000 0.0000 + +[15N]H4+ + NT4+ = [15N]T4+ + NH4+ + -mole_balance [15N](-3)T4+ + -gamma 2.5000 0.0000 + +[15N]H4+ + ND3T+ = [15N]D3T+ + NH4+ + -mole_balance [15N](-3)D3T + -gamma 2.5000 0.0000 + +[15N]H4+ + ND2T2+ = [15N]D2T2+ + NH4+ + -mole_balance [15N](-3)D2T2 + -gamma 2.5000 0.0000 + +[15N]H4+ + NDT3+ = [15N]DT3+ + NH4+ + -mole_balance [15N](-3)DT3 + -gamma 2.5000 0.0000 +# +# Missing NH4SO4- reactions +# +# +# Missing PO4-2 reactions +# +# +# Missing HPO4-2 reactions +# +# +# Missing H2PO4- reactions +# +# +# Added HF reactions 16Dec09 +# +HF + HDO = DF + H2O +HF + HTO = TF + H2O +# +# Added HF2- reactions 16Dec09 +# +HF2- + HDO = DF2- + H2O +HF2- + HTO = TF2- + H2O +# +# CaOH reactions +# +CaOH+ + [18O]H- = Ca[18O]H+ + OH- + -mole_balance Ca[18O]H +CaOH+ + OD- = CaOD+ + OH- + -mole_balance CaOD +CaOH+ + [18O]D- = Ca[18O]D+ + OH- + -mole_balance Ca[18O]D +CaOH+ + OT- = CaOT+ + OH- + -mole_balance CaOT+ +CaOH+ + [18O]T- = Ca[18O]T+ + OH- + -mole_balance Ca[18O]T +# +# CaCO3 reactions +# +CaCO3 + CO2[18O]-2 = CaCO2[18O] + CO3-2 +CaCO3 + CO[18O]2-2 = CaCO[18O]2 + CO3-2 +CaCO3 + C[18O]3-2 = CaC[18O]3 + CO3-2 +CaCO3 + [13C]O3-2 = Ca[13C]O3 + CO3-2 +CaCO3 + [13C]O2[18O]-2 = Ca[13C]O2[18O] + CO3-2 +CaCO3 + [13C]O[18O]2-2 = Ca[13C]O[18O]2 + CO3-2 +CaCO3 + [13C][18O]3-2 = Ca[13C][18O]3 + CO3-2 +CaCO3 + [14C]O3-2 = Ca[14C]O3 + CO3-2 +CaCO3 + [14C]O2[18O]-2 = Ca[14C]O2[18O] + CO3-2 +CaCO3 + [14C]O[18O]2-2 = Ca[14C]O[18O]2 + CO3-2 +CaCO3 + [14C][18O]3-2 = Ca[14C][18O]3 + CO3-2 +# +# CaHCO3+ reactions +# +CaHCO3+ + HCO2[18O]- = CaHCO2[18O]+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + HCO[18O]O- = CaHCO[18O]O+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + HC[18O]O2- = CaHC[18O]O2+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + HCO[18O]2- = CaHCO[18O]2+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + HC[18O]O[18O]- = CaHC[18O]O[18O]+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + HC[18O]2O- = CaHC[18O]2O+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + HC[18O]3- = CaHC[18O]3+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + H[13C]O3- = CaH[13C]O3+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + H[13C]O2[18O]- = CaH[13C]O2[18O]+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + H[13C]O[18O]O- = CaH[13C]O[18O]O+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + H[13C][18O]O2- = CaH[13C][18O]O2+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + H[13C]O[18O]2- = CaH[13C]O[18O]2+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + H[13C][18O]O[18O]- = CaH[13C][18O]O[18O]+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + H[13C][18O]2O- = CaH[13C][18O]2O+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + H[13C][18O]3- = CaH[13C][18O]3+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + H[14C]O3- = CaH[14C]O3+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + H[14C]O2[18O]- = CaH[14C]O2[18O]+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + H[14C]O[18O]O- = CaH[14C]O[18O]O+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + H[14C][18O]O2- = CaH[14C][18O]O2+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + H[14C]O[18O]2- = CaH[14C]O[18O]2+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + H[14C][18O]O[18O]- = CaH[14C][18O]O[18O]+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + H[14C][18O]2O- = CaH[14C][18O]2O+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + H[14C][18O]3- = CaH[14C][18O]3+ + HCO3- + -gamma 5.4000 0.0000 + +# DCO3- +CaHCO3+ + DCO3- = CaDCO3+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + DCO2[18O]- = CaDCO2[18O]+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + DCO[18O]O- = CaDCO[18O]O+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + DC[18O]O2- = CaDC[18O]O2+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + DCO[18O]2- = CaDCO[18O]2+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + DC[18O]O[18O]- = CaDC[18O]O[18O]+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + DC[18O]2O- = CaDC[18O]2O+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + DC[18O]3- = CaDC[18O]3+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + D[13C]O3- = CaD[13C]O3+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + D[13C]O2[18O]- = CaD[13C]O2[18O]+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + D[13C]O[18O]O- = CaD[13C]O[18O]O+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + D[13C][18O]O2- = CaD[13C][18O]O2+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + D[13C]O[18O]2- = CaD[13C]O[18O]2+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + D[13C][18O]O[18O]- = CaD[13C][18O]O[18O]+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + D[13C][18O]2O- = CaD[13C][18O]2O+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + D[13C][18O]3- = CaD[13C][18O]3+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + D[14C]O3- = CaD[14C]O3+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + D[14C]O2[18O]- = CaD[14C]O2[18O]+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + D[14C]O[18O]O- = CaD[14C]O[18O]O+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + D[14C][18O]O2- = CaD[14C][18O]O2+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + D[14C]O[18O]2- = CaD[14C]O[18O]2+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + D[14C][18O]O[18O]- = CaD[14C][18O]O[18O]+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + D[14C][18O]2O- = CaD[14C][18O]2O+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + D[14C][18O]3- = CaD[14C][18O]3+ + HCO3- + -gamma 5.4000 0.0000 + +# TCO3- +CaHCO3+ + TCO3- = CaTCO3+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + TCO2[18O]- = CaTCO2[18O]+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + TCO[18O]O- = CaTCO[18O]O+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + TC[18O]O2- = CaTC[18O]O2+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + TCO[18O]2- = CaTCO[18O]2+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + TC[18O]O[18O]- = CaTC[18O]O[18O]+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + TC[18O]2O- = CaTC[18O]2O+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + TC[18O]3- = CaTC[18O]3+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + T[13C]O3- = CaT[13C]O3+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + T[13C]O2[18O]- = CaT[13C]O2[18O]+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + T[13C]O[18O]O- = CaT[13C]O[18O]O+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + T[13C][18O]O2- = CaT[13C][18O]O2+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + T[13C]O[18O]2- = CaT[13C]O[18O]2+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + T[13C][18O]O[18O]- = CaT[13C][18O]O[18O]+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + T[13C][18O]2O- = CaT[13C][18O]2O+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + T[13C][18O]3- = CaT[13C][18O]3+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + T[14C]O3- = CaT[14C]O3+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + T[14C]O2[18O]- = CaT[14C]O2[18O]+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + T[14C]O[18O]O- = CaT[14C]O[18O]O+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + T[14C][18O]O2- = CaT[14C][18O]O2+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + T[14C]O[18O]2- = CaT[14C]O[18O]2+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + T[14C][18O]O[18O]- = CaT[14C][18O]O[18O]+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + T[14C][18O]2O- = CaT[14C][18O]2O+ + HCO3- + -gamma 5.4000 0.0000 + +CaHCO3+ + T[14C][18O]3- = CaT[14C][18O]3+ + HCO3- + -gamma 5.4000 0.0000 +# +# CaSO4 reactions +# +# Updated May 17, 2006 +CaSO4 + [34S]O4-2 = Ca[34S]O4 + SO4-2 +# +# CaHSO4+ reactions +# +CaHSO4+ + H[34S]O4- = CaH[34S]O4+ + HSO4- +CaHSO4+ + D[34S]O4- = CaD[34S]O4+ + HSO4- +CaHSO4+ + T[34S]O4- = CaT[34S]O4+ + HSO4- +# +# Missing CaPO4- reactions +# +# +# Missing CaHPO4 reactions +# +# +# Missing CaH2PO4+ reactions +# +# +# MgOH+ reactions +# +MgOH+ + [18O]H- = Mg[18O]H+ + OH- +MgOH+ + OD- = MgOD+ + OH- +MgOH+ + [18O]D- = Mg[18O]D+ + OH- +MgOH+ + OT- = MgOT+ + OH- +MgOH+ + [18O]T- = Mg[18O]T+ + OH- +# +# MgCO3 reactions +# +MgCO3 + CO2[18O]-2 = MgCO2[18O] + CO3-2 +MgCO3 + CO[18O]2-2 = MgCO[18O]2 + CO3-2 +MgCO3 + C[18O]3-2 = MgC[18O]3 + CO3-2 +MgCO3 + [13C]O3-2 = Mg[13C]O3 + CO3-2 +MgCO3 + [13C]O2[18O]-2 = Mg[13C]O2[18O] + CO3-2 +MgCO3 + [13C]O[18O]2-2 = Mg[13C]O[18O]2 + CO3-2 +MgCO3 + [13C][18O]3-2 = Mg[13C][18O]3 + CO3-2 +MgCO3 + [14C]O3-2 = Mg[14C]O3 + CO3-2 +MgCO3 + [14C]O2[18O]-2 = Mg[14C]O2[18O] + CO3-2 +MgCO3 + [14C]O[18O]2-2 = Mg[14C]O[18O]2 + CO3-2 +MgCO3 + [14C][18O]3-2 = Mg[14C][18O]3 + CO3-2 +# +# MgHCO3+ reactions +# +MgHCO3+ + HCO2[18O]- = MgHCO2[18O]+ + HCO3- +MgHCO3+ + HCO[18O]O- = MgHCO[18O]O+ + HCO3- +MgHCO3+ + HC[18O]O2- = MgHC[18O]O2+ + HCO3- +MgHCO3+ + HCO[18O]2- = MgHCO[18O]2+ + HCO3- +MgHCO3+ + HC[18O]O[18O]- = MgHC[18O]O[18O]+ + HCO3- +MgHCO3+ + HC[18O]2O- = MgHC[18O]2O+ + HCO3- +MgHCO3+ + HC[18O]3- = MgHC[18O]3+ + HCO3- +MgHCO3+ + H[13C]O3- = MgH[13C]O3+ + HCO3- +MgHCO3+ + H[13C]O2[18O]- = MgH[13C]O2[18O]+ + HCO3- +MgHCO3+ + H[13C]O[18O]O- = MgH[13C]O[18O]O+ + HCO3- +MgHCO3+ + H[13C][18O]O2- = MgH[13C][18O]O2+ + HCO3- +MgHCO3+ + H[13C]O[18O]2- = MgH[13C]O[18O]2+ + HCO3- +MgHCO3+ + H[13C][18O]O[18O]- = MgH[13C][18O]O[18O]+ + HCO3- +MgHCO3+ + H[13C][18O]2O- = MgH[13C][18O]2O+ + HCO3- +MgHCO3+ + H[13C][18O]3- = MgH[13C][18O]3+ + HCO3- +MgHCO3+ + H[14C]O3- = MgH[14C]O3+ + HCO3- +MgHCO3+ + H[14C]O2[18O]- = MgH[14C]O2[18O]+ + HCO3- +MgHCO3+ + H[14C]O[18O]O- = MgH[14C]O[18O]O+ + HCO3- +MgHCO3+ + H[14C][18O]O2- = MgH[14C][18O]O2+ + HCO3- +MgHCO3+ + H[14C]O[18O]2- = MgH[14C]O[18O]2+ + HCO3- +MgHCO3+ + H[14C][18O]O[18O]- = MgH[14C][18O]O[18O]+ + HCO3- +MgHCO3+ + H[14C][18O]2O- = MgH[14C][18O]2O+ + HCO3- +MgHCO3+ + H[14C][18O]3- = MgH[14C][18O]3+ + HCO3- + +# DCO3- +MgHCO3+ + DCO3- = MgDCO3+ + HCO3- +MgHCO3+ + DCO2[18O]- = MgDCO2[18O]+ + HCO3- +MgHCO3+ + DCO[18O]O- = MgDCO[18O]O+ + HCO3- +MgHCO3+ + DC[18O]O2- = MgDC[18O]O2+ + HCO3- +MgHCO3+ + DCO[18O]2- = MgDCO[18O]2+ + HCO3- +MgHCO3+ + DC[18O]O[18O]- = MgDC[18O]O[18O]+ + HCO3- +MgHCO3+ + DC[18O]2O- = MgDC[18O]2O+ + HCO3- +MgHCO3+ + DC[18O]3- = MgDC[18O]3+ + HCO3- +MgHCO3+ + D[13C]O3- = MgD[13C]O3+ + HCO3- +MgHCO3+ + D[13C]O2[18O]- = MgD[13C]O2[18O]+ + HCO3- +MgHCO3+ + D[13C]O[18O]O- = MgD[13C]O[18O]O+ + HCO3- +MgHCO3+ + D[13C][18O]O2- = MgD[13C][18O]O2+ + HCO3- +MgHCO3+ + D[13C]O[18O]2- = MgD[13C]O[18O]2+ + HCO3- +MgHCO3+ + D[13C][18O]O[18O]- = MgD[13C][18O]O[18O]+ + HCO3- +MgHCO3+ + D[13C][18O]2O- = MgD[13C][18O]2O+ + HCO3- +MgHCO3+ + D[13C][18O]3- = MgD[13C][18O]3+ + HCO3- +MgHCO3+ + D[14C]O3- = MgD[14C]O3+ + HCO3- +MgHCO3+ + D[14C]O2[18O]- = MgD[14C]O2[18O]+ + HCO3- +MgHCO3+ + D[14C]O[18O]O- = MgD[14C]O[18O]O+ + HCO3- +MgHCO3+ + D[14C][18O]O2- = MgD[14C][18O]O2+ + HCO3- +MgHCO3+ + D[14C]O[18O]2- = MgD[14C]O[18O]2+ + HCO3- +MgHCO3+ + D[14C][18O]O[18O]- = MgD[14C][18O]O[18O]+ + HCO3- +MgHCO3+ + D[14C][18O]2O- = MgD[14C][18O]2O+ + HCO3- +MgHCO3+ + D[14C][18O]3- = MgD[14C][18O]3+ + HCO3- + +# TCO3- +MgHCO3+ + TCO3- = MgTCO3+ + HCO3- +MgHCO3+ + TCO2[18O]- = MgTCO2[18O]+ + HCO3- +MgHCO3+ + TCO[18O]O- = MgTCO[18O]O+ + HCO3- +MgHCO3+ + TC[18O]O2- = MgTC[18O]O2+ + HCO3- +MgHCO3+ + TCO[18O]2- = MgTCO[18O]2+ + HCO3- +MgHCO3+ + TC[18O]O[18O]- = MgTC[18O]O[18O]+ + HCO3- +MgHCO3+ + TC[18O]2O- = MgTC[18O]2O+ + HCO3- +MgHCO3+ + TC[18O]3- = MgTC[18O]3+ + HCO3- +MgHCO3+ + T[13C]O3- = MgT[13C]O3+ + HCO3- +MgHCO3+ + T[13C]O2[18O]- = MgT[13C]O2[18O]+ + HCO3- +MgHCO3+ + T[13C]O[18O]O- = MgT[13C]O[18O]O+ + HCO3- +MgHCO3+ + T[13C][18O]O2- = MgT[13C][18O]O2+ + HCO3- +MgHCO3+ + T[13C]O[18O]2- = MgT[13C]O[18O]2+ + HCO3- +MgHCO3+ + T[13C][18O]O[18O]- = MgT[13C][18O]O[18O]+ + HCO3- +MgHCO3+ + T[13C][18O]2O- = MgT[13C][18O]2O+ + HCO3- +MgHCO3+ + T[13C][18O]3- = MgT[13C][18O]3+ + HCO3- +MgHCO3+ + T[14C]O3- = MgT[14C]O3+ + HCO3- +MgHCO3+ + T[14C]O2[18O]- = MgT[14C]O2[18O]+ + HCO3- +MgHCO3+ + T[14C]O[18O]O- = MgT[14C]O[18O]O+ + HCO3- +MgHCO3+ + T[14C][18O]O2- = MgT[14C][18O]O2+ + HCO3- +MgHCO3+ + T[14C]O[18O]2- = MgT[14C]O[18O]2+ + HCO3- +MgHCO3+ + T[14C][18O]O[18O]- = MgT[14C][18O]O[18O]+ + HCO3- +MgHCO3+ + T[14C][18O]2O- = MgT[14C][18O]2O+ + HCO3- +MgHCO3+ + T[14C][18O]3- = MgT[14C][18O]3+ + HCO3- +# +# MgSO4 reactions +# +MgSO4 + [34S]O4-2 = Mg[34S]O4 + SO4-2 +# +# Missing MgPO4- reactions +# +# +# Missing MgHPO4 reactions +# +# +# Missing Mg2PO4+ reactions +# +# +# NaOH reactions +# +NaOH + [18O]H- = Na[18O]H + OH- +NaOH + OD- = NaOD + OH- +NaOH + [18O]D- = Na[18O]D + OH- +NaOH + OT- = NaOT + OH- +NaOH + [18O]T- = Na[18O]T + OH- +# +# NaCO3- reactions +# +NaCO3- + CO2[18O]-2 = NaCO2[18O]- + CO3-2 +NaCO3- + CO[18O]2-2 = NaCO[18O]2- + CO3-2 +NaCO3- + C[18O]3-2 = NaC[18O]3- + CO3-2 +NaCO3- + [13C]O3-2 = Na[13C]O3- + CO3-2 +NaCO3- + [13C]O2[18O]-2 = Na[13C]O2[18O]- + CO3-2 +NaCO3- + [13C]O[18O]2-2 = Na[13C]O[18O]2- + CO3-2 +NaCO3- + [13C][18O]3-2 = Na[13C][18O]3- + CO3-2 +NaCO3- + [14C]O3-2 = Na[14C]O3- + CO3-2 +NaCO3- + [14C]O2[18O]-2 = Na[14C]O2[18O]- + CO3-2 +NaCO3- + [14C]O[18O]2-2 = Na[14C]O[18O]2- + CO3-2 +NaCO3- + [14C][18O]3-2 = Na[14C][18O]3- + CO3-2 +# +# NaHCO3 reactions +# +NaHCO3 + HCO2[18O]- = NaHCO2[18O] + HCO3- +NaHCO3 + HCO[18O]O- = NaHCO[18O]O + HCO3- +NaHCO3 + HC[18O]O2- = NaHC[18O]O2 + HCO3- +NaHCO3 + HCO[18O]2- = NaHCO[18O]2 + HCO3- +NaHCO3 + HC[18O]O[18O]- = NaHC[18O]O[18O] + HCO3- +NaHCO3 + HC[18O]2O- = NaHC[18O]2O + HCO3- +NaHCO3 + HC[18O]3- = NaHC[18O]3 + HCO3- +NaHCO3 + H[13C]O3- = NaH[13C]O3 + HCO3- +NaHCO3 + H[13C]O2[18O]- = NaH[13C]O2[18O] + HCO3- +NaHCO3 + H[13C]O[18O]O- = NaH[13C]O[18O]O + HCO3- +NaHCO3 + H[13C][18O]O2- = NaH[13C][18O]O2 + HCO3- +NaHCO3 + H[13C]O[18O]2- = NaH[13C]O[18O]2 + HCO3- +NaHCO3 + H[13C][18O]O[18O]- = NaH[13C][18O]O[18O] + HCO3- +NaHCO3 + H[13C][18O]2O- = NaH[13C][18O]2O + HCO3- +NaHCO3 + H[13C][18O]3- = NaH[13C][18O]3 + HCO3- +NaHCO3 + H[14C]O3- = NaH[14C]O3 + HCO3- +NaHCO3 + H[14C]O2[18O]- = NaH[14C]O2[18O] + HCO3- +NaHCO3 + H[14C]O[18O]O- = NaH[14C]O[18O]O + HCO3- +NaHCO3 + H[14C][18O]O2- = NaH[14C][18O]O2 + HCO3- +NaHCO3 + H[14C]O[18O]2- = NaH[14C]O[18O]2 + HCO3- +NaHCO3 + H[14C][18O]O[18O]- = NaH[14C][18O]O[18O] + HCO3- +NaHCO3 + H[14C][18O]2O- = NaH[14C][18O]2O + HCO3- +NaHCO3 + H[14C][18O]3- = NaH[14C][18O]3 + HCO3- + +# DCO3- +NaHCO3 + DCO3- = NaDCO3 + HCO3- +NaHCO3 + DCO2[18O]- = NaDCO2[18O] + HCO3- +NaHCO3 + DCO[18O]O- = NaDCO[18O]O + HCO3- +NaHCO3 + DC[18O]O2- = NaDC[18O]O2 + HCO3- +NaHCO3 + DCO[18O]2- = NaDCO[18O]2 + HCO3- +NaHCO3 + DC[18O]O[18O]- = NaDC[18O]O[18O] + HCO3- +NaHCO3 + DC[18O]2O- = NaDC[18O]2O + HCO3- +NaHCO3 + DC[18O]3- = NaDC[18O]3 + HCO3- +NaHCO3 + D[13C]O3- = NaD[13C]O3 + HCO3- +NaHCO3 + D[13C]O2[18O]- = NaD[13C]O2[18O] + HCO3- +NaHCO3 + D[13C]O[18O]O- = NaD[13C]O[18O]O + HCO3- +NaHCO3 + D[13C][18O]O2- = NaD[13C][18O]O2 + HCO3- +NaHCO3 + D[13C]O[18O]2- = NaD[13C]O[18O]2 + HCO3- +NaHCO3 + D[13C][18O]O[18O]- = NaD[13C][18O]O[18O] + HCO3- +NaHCO3 + D[13C][18O]2O- = NaD[13C][18O]2O + HCO3- +NaHCO3 + D[13C][18O]3- = NaD[13C][18O]3 + HCO3- +NaHCO3 + D[14C]O3- = NaD[14C]O3 + HCO3- +NaHCO3 + D[14C]O2[18O]- = NaD[14C]O2[18O] + HCO3- +NaHCO3 + D[14C]O[18O]O- = NaD[14C]O[18O]O + HCO3- +NaHCO3 + D[14C][18O]O2- = NaD[14C][18O]O2 + HCO3- +NaHCO3 + D[14C]O[18O]2- = NaD[14C]O[18O]2 + HCO3- +NaHCO3 + D[14C][18O]O[18O]- = NaD[14C][18O]O[18O] + HCO3- +NaHCO3 + D[14C][18O]2O- = NaD[14C][18O]2O + HCO3- +NaHCO3 + D[14C][18O]3- = NaD[14C][18O]3 + HCO3- + +# TCO3- +NaHCO3 + TCO3- = NaTCO3 + HCO3- +NaHCO3 + TCO2[18O]- = NaTCO2[18O] + HCO3- +NaHCO3 + TCO[18O]O- = NaTCO[18O]O + HCO3- +NaHCO3 + TC[18O]O2- = NaTC[18O]O2 + HCO3- +NaHCO3 + TCO[18O]2- = NaTCO[18O]2 + HCO3- +NaHCO3 + TC[18O]O[18O]- = NaTC[18O]O[18O] + HCO3- +NaHCO3 + TC[18O]2O- = NaTC[18O]2O + HCO3- +NaHCO3 + TC[18O]3- = NaTC[18O]3 + HCO3- +NaHCO3 + T[13C]O3- = NaT[13C]O3 + HCO3- +NaHCO3 + T[13C]O2[18O]- = NaT[13C]O2[18O] + HCO3- +NaHCO3 + T[13C]O[18O]O- = NaT[13C]O[18O]O + HCO3- +NaHCO3 + T[13C][18O]O2- = NaT[13C][18O]O2 + HCO3- +NaHCO3 + T[13C]O[18O]2- = NaT[13C]O[18O]2 + HCO3- +NaHCO3 + T[13C][18O]O[18O]- = NaT[13C][18O]O[18O] + HCO3- +NaHCO3 + T[13C][18O]2O- = NaT[13C][18O]2O + HCO3- +NaHCO3 + T[13C][18O]3- = NaT[13C][18O]3 + HCO3- +NaHCO3 + T[14C]O3- = NaT[14C]O3 + HCO3- +NaHCO3 + T[14C]O2[18O]- = NaT[14C]O2[18O] + HCO3- +NaHCO3 + T[14C]O[18O]O- = NaT[14C]O[18O]O + HCO3- +NaHCO3 + T[14C][18O]O2- = NaT[14C][18O]O2 + HCO3- +NaHCO3 + T[14C]O[18O]2- = NaT[14C]O[18O]2 + HCO3- +NaHCO3 + T[14C][18O]O[18O]- = NaT[14C][18O]O[18O] + HCO3- +NaHCO3 + T[14C][18O]2O- = NaT[14C][18O]2O + HCO3- +NaHCO3 + T[14C][18O]3- = NaT[14C][18O]3 + HCO3- +# +# NaSO4- reactions +# +NaSO4- + [34S]O4-2 = Na[34S]O4- + SO4-2 +# +# Missing NaHPO4- reactions +# +# +# KOH reactions +# +KOH + [18O]H- = K[18O]H + OH- +KOH + OD- = KOD + OH- +KOH + [18O]D- = K[18O]D + OH- +KOH + OT- = KOT + OH- +KOH + [18O]T- = K[18O]T + OH- +# +# KSO4- reactions +# +KSO4- + [34S]O4-2 = K[34S]O4- + SO4-2 +# +# Added FeOH+ reactions 16Dec09 +# +FeOH+ + OD- = FeOD+ + OH- +FeOH+ + OT- = FeOT+ + OH- +FeOH+ + [18O]H- = Fe[18O]H+ + OH- +FeOH+ + [18O]D- = Fe[18O]D+ + OH- +FeOH+ + [18O]T- = Fe[18O]T+ + OH- +# +# Added FeCO3 reactions 16Dec09 +# Checked 17Dec09 +# +FeCO3 + CO2[18O]-2 = FeCO2[18O] + CO3-2 +FeCO3 + CO[18O]2-2 = FeCO[18O]2 + CO3-2 +FeCO3 + C[18O]3-2 = FeC[18O]3 + CO3-2 +FeCO3 + [13C]O3-2 = Fe[13C]O3 + CO3-2 +FeCO3 + [13C]O2[18O]-2 = Fe[13C]O2[18O] + CO3-2 +FeCO3 + [13C]O[18O]2-2 = Fe[13C]O[18O]2 + CO3-2 +FeCO3 + [13C][18O]3-2 = Fe[13C][18O]3 + CO3-2 +FeCO3 + [14C]O3-2 = Fe[14C]O3 + CO3-2 +FeCO3 + [14C]O2[18O]-2 = Fe[14C]O2[18O] + CO3-2 +FeCO3 + [14C]O[18O]2-2 = Fe[14C]O[18O]2 + CO3-2 +FeCO3 + [14C][18O]3-2 = Fe[14C][18O]3 + CO3-2 +# +# Added FeHCO3+ reactions 16Dec09 +# Revised 17Dec09 +# +FeHCO3+ + HCO2[18O]- = FeHCO2[18O]+ + HCO3- +FeHCO3+ + HCO[18O]O- = FeHCO[18O]O+ + HCO3- +FeHCO3+ + HCO[18O]2- = FeHCO[18O]2+ + HCO3- +FeHCO3+ + HC[18O]O2- = FeHC[18O]O2+ + HCO3- +FeHCO3+ + HC[18O]O[18O]- = FeHC[18O]O[18O]+ + HCO3- +FeHCO3+ + HC[18O]2O- = FeHC[18O]2O+ + HCO3- +FeHCO3+ + HC[18O]3- = FeHC[18O]3+ + HCO3- +FeHCO3+ + H[13C]O3- = FeH[13C]O3+ + HCO3- +FeHCO3+ + H[13C]O2[18O]- = FeH[13C]O2[18O]+ + HCO3- +FeHCO3+ + H[13C]O[18O]O- = FeH[13C]O[18O]O+ + HCO3- +FeHCO3+ + H[13C]O[18O]2- = FeH[13C]O[18O]2+ + HCO3- +FeHCO3+ + H[13C][18O]O2- = FeH[13C][18O]O2+ + HCO3- +FeHCO3+ + H[13C][18O]O[18O]- = FeH[13C][18O]O[18O]+ + HCO3- +FeHCO3+ + H[13C][18O]2O- = FeH[13C][18O]2O+ + HCO3- +FeHCO3+ + H[13C][18O]3- = FeH[13C][18O]3+ + HCO3- +FeHCO3+ + H[14C]O3- = FeH[14C]O3+ + HCO3- +FeHCO3+ + H[14C]O2[18O]- = FeH[14C]O2[18O]+ + HCO3- +FeHCO3+ + H[14C]O[18O]O- = FeH[14C]O[18O]O+ + HCO3- +FeHCO3+ + H[14C]O[18O]2- = FeH[14C]O[18O]2+ + HCO3- +FeHCO3+ + H[14C][18O]O2- = FeH[14C][18O]O2+ + HCO3- +FeHCO3+ + H[14C][18O]O[18O]- = FeH[14C][18O]O[18O]+ + HCO3- +FeHCO3+ + H[14C][18O]2O- = FeH[14C][18O]2O+ + HCO3- +FeHCO3+ + H[14C][18O]3- = FeH[14C][18O]3+ + HCO3- +FeHCO3+ + DCO3- = FeDCO3+ + HCO3- +FeHCO3+ + DCO2[18O]- = FeDCO2[18O]+ + HCO3- +FeHCO3+ + DCO[18O]O- = FeDCO[18O]O+ + HCO3- +FeHCO3+ + DCO[18O]2- = FeDCO[18O]2+ + HCO3- +FeHCO3+ + DC[18O]O2- = FeDC[18O]O2+ + HCO3- +FeHCO3+ + DC[18O]O[18O]- = FeDC[18O]O[18O]+ + HCO3- +FeHCO3+ + DC[18O]2O- = FeDC[18O]2O+ + HCO3- +FeHCO3+ + DC[18O]3- = FeDC[18O]3+ + HCO3- +FeHCO3+ + D[13C]O3- = FeD[13C]O3+ + HCO3- +FeHCO3+ + D[13C]O2[18O]- = FeD[13C]O2[18O]+ + HCO3- +FeHCO3+ + D[13C]O[18O]O- = FeD[13C]O[18O]O+ + HCO3- +FeHCO3+ + D[13C]O[18O]2- = FeD[13C]O[18O]2+ + HCO3- +FeHCO3+ + D[13C][18O]O2- = FeD[13C][18O]O2+ + HCO3- +FeHCO3+ + D[13C][18O]O[18O]- = FeD[13C][18O]O[18O]+ + HCO3- +FeHCO3+ + D[13C][18O]2O- = FeD[13C][18O]2O+ + HCO3- +FeHCO3+ + D[13C][18O]3- = FeD[13C][18O]3+ + HCO3- +FeHCO3+ + D[14C]O3- = FeD[14C]O3+ + HCO3- +FeHCO3+ + D[14C]O2[18O]- = FeD[14C]O2[18O]+ + HCO3- +FeHCO3+ + D[14C]O[18O]O- = FeD[14C]O[18O]O+ + HCO3- +FeHCO3+ + D[14C]O[18O]2- = FeD[14C]O[18O]2+ + HCO3- +FeHCO3+ + D[14C][18O]O2- = FeD[14C][18O]O2+ + HCO3- +FeHCO3+ + D[14C][18O]O[18O]- = FeD[14C][18O]O[18O]+ + HCO3- +FeHCO3+ + D[14C][18O]2O- = FeD[14C][18O]2O+ + HCO3- +FeHCO3+ + D[14C][18O]3- = FeD[14C][18O]3+ + HCO3- +FeHCO3+ + TCO3- = FeTCO3+ + HCO3- +FeHCO3+ + TCO2[18O]- = FeTCO2[18O]+ + HCO3- +FeHCO3+ + TCO[18O]O- = FeTCO[18O]O+ + HCO3- +FeHCO3+ + TCO[18O]2- = FeTCO[18O]2+ + HCO3- +FeHCO3+ + TC[18O]O2- = FeTC[18O]O2+ + HCO3- +FeHCO3+ + TC[18O]O[18O]- = FeTC[18O]O[18O]+ + HCO3- +FeHCO3+ + TC[18O]2O- = FeTC[18O]2O+ + HCO3- +FeHCO3+ + TC[18O]3- = FeTC[18O]3+ + HCO3- +FeHCO3+ + T[13C]O3- = FeT[13C]O3+ + HCO3- +FeHCO3+ + T[13C]O2[18O]- = FeT[13C]O2[18O]+ + HCO3- +FeHCO3+ + T[13C]O[18O]O- = FeT[13C]O[18O]O+ + HCO3- +FeHCO3+ + T[13C]O[18O]2- = FeT[13C]O[18O]2+ + HCO3- +FeHCO3+ + T[13C][18O]O2- = FeT[13C][18O]O2+ + HCO3- +FeHCO3+ + T[13C][18O]O[18O]- = FeT[13C][18O]O[18O]+ + HCO3- +FeHCO3+ + T[13C][18O]2O- = FeT[13C][18O]2O+ + HCO3- +FeHCO3+ + T[13C][18O]3- = FeT[13C][18O]3+ + HCO3- +FeHCO3+ + T[14C]O3- = FeT[14C]O3+ + HCO3- +FeHCO3+ + T[14C]O2[18O]- = FeT[14C]O2[18O]+ + HCO3- +FeHCO3+ + T[14C]O[18O]O- = FeT[14C]O[18O]O+ + HCO3- +FeHCO3+ + T[14C]O[18O]2- = FeT[14C]O[18O]2+ + HCO3- +FeHCO3+ + T[14C][18O]O2- = FeT[14C][18O]O2+ + HCO3- +FeHCO3+ + T[14C][18O]O[18O]- = FeT[14C][18O]O[18O]+ + HCO3- +FeHCO3+ + T[14C][18O]2O- = FeT[14C][18O]2O+ + HCO3- +FeHCO3+ + T[14C][18O]3- = FeT[14C][18O]3+ + HCO3- +# +# Added FeSO4 reactions 16Dec09 +# +FeSO4 + [34S]O4-2 = Fe[34S]O4 + SO4-2 +# +# Added FeHSO4+ reactions 16Dec09 +# +FeHSO4+ + DSO4- = FeDSO4+ + HSO4- +FeHSO4+ + TSO4- = FeTSO4+ + HSO4- +FeHSO4+ + H[34S]O4- = FeH[34S]O4+ + HSO4- +FeHSO4+ + D[34S]O4- = FeD[34S]O4+ + HSO4- +FeHSO4+ + T[34S]O4- = FeT[34S]O4+ + HSO4- +# +# Added Fe(HS)2 reactions 16Dec09 +# Revised 17Dec09, limited the number of species +# +Fe(HS)2 + HS- + DS- = FeHSDS + 2HS- +Fe(HS)2 + HS- + TS- = FeHSTS + 2HS- +Fe(HS)2 + HS- + H[34S]- = FeHSH[34S] + 2HS- +Fe(HS)2 + HS- + D[34S]- = FeHSD[34S] + 2HS- +Fe(HS)2 + HS- + T[34S]- = FeHST[34S] + 2HS- +Fe(HS)2 + DS- + HS- = FeDSHS + 2HS- +Fe(HS)2 + DS- + DS- = FeDSDS + 2HS- +Fe(HS)2 + DS- + TS- = FeDSTS + 2HS- +Fe(HS)2 + DS- + H[34S]- = FeDSH[34S] + 2HS- +Fe(HS)2 + DS- + D[34S]- = FeDSD[34S] + 2HS- +Fe(HS)2 + DS- + T[34S]- = FeDST[34S] + 2HS- +Fe(HS)2 + TS- + HS- = FeTSHS + 2HS- +Fe(HS)2 + TS- + DS- = FeTSDS + 2HS- +Fe(HS)2 + TS- + H[34S]- = FeTSH[34S] + 2HS- +Fe(HS)2 + TS- + D[34S]- = FeTSD[34S] + 2HS- +Fe(HS)2 + H[34S]- + HS- = FeH[34S]HS + 2HS- +Fe(HS)2 + H[34S]- + DS- = FeH[34S]DS + 2HS- +Fe(HS)2 + H[34S]- + TS- = FeH[34S]TS + 2HS- +Fe(HS)2 + H[34S]- + H[34S]- = FeH[34S]H[34S] + 2HS- +Fe(HS)2 + H[34S]- + D[34S]- = FeH[34S]D[34S] + 2HS- +Fe(HS)2 + H[34S]- + T[34S]- = FeH[34S]T[34S] + 2HS- +Fe(HS)2 + D[34S]- + HS- = FeD[34S]HS + 2HS- +Fe(HS)2 + D[34S]- + DS- = FeD[34S]DS + 2HS- +Fe(HS)2 + D[34S]- + TS- = FeD[34S]TS + 2HS- +Fe(HS)2 + D[34S]- + H[34S]- = FeD[34S]H[34S] + 2HS- +Fe(HS)2 + D[34S]- + D[34S]- = FeD[34S]D[34S] + 2HS- +Fe(HS)2 + D[34S]- + T[34S]- = FeD[34S]T[34S] + 2HS- +Fe(HS)2 + T[34S]- + HS- = FeT[34S]HS + 2HS- +Fe(HS)2 + T[34S]- + DS- = FeT[34S]DS + 2HS- +Fe(HS)2 + T[34S]- + H[34S]- = FeT[34S]H[34S] + 2HS- +Fe(HS)2 + T[34S]- + D[34S]- = FeT[34S]D[34S] + 2HS- +# +# Added Fe(HS)3- reactions 16Dec09 +# Revised 17Dec09, limited the number of species +# +Fe(HS)3- + HS- + HS- + DS- = FeHSHSDS- + 3HS- +Fe(HS)3- + HS- + HS- + TS- = FeHSHSTS- + 3HS- +Fe(HS)3- + HS- + HS- + H[34S]- = FeHSHSH[34S]- + 3HS- +Fe(HS)3- + HS- + HS- + D[34S]- = FeHSHSD[34S]- + 3HS- +Fe(HS)3- + HS- + HS- + T[34S]- = FeHSHST[34S]- + 3HS- +Fe(HS)3- + HS- + DS- + HS- = FeHSDSHS- + 3HS- +Fe(HS)3- + HS- + DS- + DS- = FeHSDSDS- + 3HS- +Fe(HS)3- + HS- + DS- + TS- = FeHSDSTS- + 3HS- +Fe(HS)3- + HS- + DS- + H[34S]- = FeHSDSH[34S]- + 3HS- +Fe(HS)3- + HS- + DS- + D[34S]- = FeHSDSD[34S]- + 3HS- +Fe(HS)3- + HS- + DS- + T[34S]- = FeHSDST[34S]- + 3HS- +Fe(HS)3- + HS- + TS- + HS- = FeHSTSHS- + 3HS- +Fe(HS)3- + HS- + TS- + DS- = FeHSTSDS- + 3HS- +Fe(HS)3- + HS- + TS- + H[34S]- = FeHSTSH[34S]- + 3HS- +Fe(HS)3- + HS- + TS- + D[34S]- = FeHSTSD[34S]- + 3HS- +Fe(HS)3- + HS- + H[34S]- + HS- = FeHSH[34S]HS- + 3HS- +Fe(HS)3- + HS- + H[34S]- + DS- = FeHSH[34S]DS- + 3HS- +Fe(HS)3- + HS- + H[34S]- + TS- = FeHSH[34S]TS- + 3HS- +Fe(HS)3- + HS- + H[34S]- + H[34S]- = FeHSH[34S]H[34S]- + 3HS- +Fe(HS)3- + HS- + H[34S]- + D[34S]- = FeHSH[34S]D[34S]- + 3HS- +Fe(HS)3- + HS- + H[34S]- + T[34S]- = FeHSH[34S]T[34S]- + 3HS- +Fe(HS)3- + HS- + D[34S]- + HS- = FeHSD[34S]HS- + 3HS- +Fe(HS)3- + HS- + D[34S]- + DS- = FeHSD[34S]DS- + 3HS- +Fe(HS)3- + HS- + D[34S]- + TS- = FeHSD[34S]TS- + 3HS- +Fe(HS)3- + HS- + D[34S]- + H[34S]- = FeHSD[34S]H[34S]- + 3HS- +Fe(HS)3- + HS- + D[34S]- + D[34S]- = FeHSD[34S]D[34S]- + 3HS- +Fe(HS)3- + HS- + D[34S]- + T[34S]- = FeHSD[34S]T[34S]- + 3HS- +Fe(HS)3- + HS- + T[34S]- + HS- = FeHST[34S]HS- + 3HS- +Fe(HS)3- + HS- + T[34S]- + DS- = FeHST[34S]DS- + 3HS- +Fe(HS)3- + HS- + T[34S]- + H[34S]- = FeHST[34S]H[34S]- + 3HS- +Fe(HS)3- + HS- + T[34S]- + D[34S]- = FeHST[34S]D[34S]- + 3HS- +Fe(HS)3- + DS- + HS- + HS- = FeDSHSHS- + 3HS- +Fe(HS)3- + DS- + HS- + DS- = FeDSHSDS- + 3HS- +Fe(HS)3- + DS- + HS- + TS- = FeDSHSTS- + 3HS- +Fe(HS)3- + DS- + HS- + H[34S]- = FeDSHSH[34S]- + 3HS- +Fe(HS)3- + DS- + HS- + D[34S]- = FeDSHSD[34S]- + 3HS- +Fe(HS)3- + DS- + HS- + T[34S]- = FeDSHST[34S]- + 3HS- +Fe(HS)3- + DS- + DS- + HS- = FeDSDSHS- + 3HS- +Fe(HS)3- + DS- + DS- + TS- = FeDSDSTS- + 3HS- +Fe(HS)3- + DS- + DS- + H[34S]- = FeDSDSH[34S]- + 3HS- +Fe(HS)3- + DS- + DS- + T[34S]- = FeDSDST[34S]- + 3HS- +Fe(HS)3- + DS- + TS- + HS- = FeDSTSHS- + 3HS- +Fe(HS)3- + DS- + TS- + DS- = FeDSTSDS- + 3HS- +Fe(HS)3- + DS- + TS- + H[34S]- = FeDSTSH[34S]- + 3HS- +Fe(HS)3- + DS- + TS- + D[34S]- = FeDSTSD[34S]- + 3HS- +Fe(HS)3- + DS- + H[34S]- + HS- = FeDSH[34S]HS- + 3HS- +Fe(HS)3- + DS- + H[34S]- + DS- = FeDSH[34S]DS- + 3HS- +Fe(HS)3- + DS- + H[34S]- + TS- = FeDSH[34S]TS- + 3HS- +Fe(HS)3- + DS- + H[34S]- + H[34S]- = FeDSH[34S]H[34S]- + 3HS- +Fe(HS)3- + DS- + H[34S]- + D[34S]- = FeDSH[34S]D[34S]- + 3HS- +Fe(HS)3- + DS- + H[34S]- + T[34S]- = FeDSH[34S]T[34S]- + 3HS- +Fe(HS)3- + DS- + D[34S]- + HS- = FeDSD[34S]HS- + 3HS- +Fe(HS)3- + DS- + D[34S]- + TS- = FeDSD[34S]TS- + 3HS- +Fe(HS)3- + DS- + D[34S]- + H[34S]- = FeDSD[34S]H[34S]- + 3HS- +Fe(HS)3- + DS- + T[34S]- + HS- = FeDST[34S]HS- + 3HS- +Fe(HS)3- + DS- + T[34S]- + DS- = FeDST[34S]DS- + 3HS- +Fe(HS)3- + DS- + T[34S]- + H[34S]- = FeDST[34S]H[34S]- + 3HS- +Fe(HS)3- + TS- + HS- + HS- = FeTSHSHS- + 3HS- +Fe(HS)3- + TS- + HS- + DS- = FeTSHSDS- + 3HS- +Fe(HS)3- + TS- + HS- + H[34S]- = FeTSHSH[34S]- + 3HS- +Fe(HS)3- + TS- + HS- + D[34S]- = FeTSHSD[34S]- + 3HS- +Fe(HS)3- + TS- + DS- + HS- = FeTSDSHS- + 3HS- +Fe(HS)3- + TS- + DS- + DS- = FeTSDSDS- + 3HS- +Fe(HS)3- + TS- + DS- + H[34S]- = FeTSDSH[34S]- + 3HS- +Fe(HS)3- + TS- + DS- + D[34S]- = FeTSDSD[34S]- + 3HS- +Fe(HS)3- + TS- + H[34S]- + HS- = FeTSH[34S]HS- + 3HS- +Fe(HS)3- + TS- + H[34S]- + DS- = FeTSH[34S]DS- + 3HS- +Fe(HS)3- + TS- + H[34S]- + H[34S]- = FeTSH[34S]H[34S]- + 3HS- +Fe(HS)3- + TS- + H[34S]- + D[34S]- = FeTSH[34S]D[34S]- + 3HS- +Fe(HS)3- + TS- + D[34S]- + HS- = FeTSD[34S]HS- + 3HS- +Fe(HS)3- + TS- + D[34S]- + DS- = FeTSD[34S]DS- + 3HS- +Fe(HS)3- + TS- + D[34S]- + H[34S]- = FeTSD[34S]H[34S]- + 3HS- +Fe(HS)3- + H[34S]- + HS- + HS- = FeH[34S]HSHS- + 3HS- +Fe(HS)3- + H[34S]- + HS- + DS- = FeH[34S]HSDS- + 3HS- +Fe(HS)3- + H[34S]- + HS- + TS- = FeH[34S]HSTS- + 3HS- +Fe(HS)3- + H[34S]- + HS- + H[34S]- = FeH[34S]HSH[34S]- + 3HS- +Fe(HS)3- + H[34S]- + HS- + D[34S]- = FeH[34S]HSD[34S]- + 3HS- +Fe(HS)3- + H[34S]- + HS- + T[34S]- = FeH[34S]HST[34S]- + 3HS- +Fe(HS)3- + H[34S]- + DS- + HS- = FeH[34S]DSHS- + 3HS- +Fe(HS)3- + H[34S]- + DS- + DS- = FeH[34S]DSDS- + 3HS- +Fe(HS)3- + H[34S]- + DS- + TS- = FeH[34S]DSTS- + 3HS- +Fe(HS)3- + H[34S]- + DS- + H[34S]- = FeH[34S]DSH[34S]- + 3HS- +Fe(HS)3- + H[34S]- + DS- + D[34S]- = FeH[34S]DSD[34S]- + 3HS- +Fe(HS)3- + H[34S]- + DS- + T[34S]- = FeH[34S]DST[34S]- + 3HS- +Fe(HS)3- + H[34S]- + TS- + HS- = FeH[34S]TSHS- + 3HS- +Fe(HS)3- + H[34S]- + TS- + DS- = FeH[34S]TSDS- + 3HS- +Fe(HS)3- + H[34S]- + TS- + H[34S]- = FeH[34S]TSH[34S]- + 3HS- +Fe(HS)3- + H[34S]- + TS- + D[34S]- = FeH[34S]TSD[34S]- + 3HS- +Fe(HS)3- + H[34S]- + H[34S]- + HS- = FeH[34S]H[34S]HS- + 3HS- +Fe(HS)3- + H[34S]- + H[34S]- + DS- = FeH[34S]H[34S]DS- + 3HS- +Fe(HS)3- + H[34S]- + H[34S]- + TS- = FeH[34S]H[34S]TS- + 3HS- +Fe(HS)3- + H[34S]- + H[34S]- + H[34S]- = FeH[34S]H[34S]H[34S]- + 3HS- +Fe(HS)3- + H[34S]- + H[34S]- + D[34S]- = FeH[34S]H[34S]D[34S]- + 3HS- +Fe(HS)3- + H[34S]- + H[34S]- + T[34S]- = FeH[34S]H[34S]T[34S]- + 3HS- +Fe(HS)3- + H[34S]- + D[34S]- + HS- = FeH[34S]D[34S]HS- + 3HS- +Fe(HS)3- + H[34S]- + D[34S]- + DS- = FeH[34S]D[34S]DS- + 3HS- +Fe(HS)3- + H[34S]- + D[34S]- + TS- = FeH[34S]D[34S]TS- + 3HS- +Fe(HS)3- + H[34S]- + D[34S]- + H[34S]- = FeH[34S]D[34S]H[34S]- + 3HS- +Fe(HS)3- + H[34S]- + T[34S]- + HS- = FeH[34S]T[34S]HS- + 3HS- +Fe(HS)3- + H[34S]- + T[34S]- + DS- = FeH[34S]T[34S]DS- + 3HS- +Fe(HS)3- + H[34S]- + T[34S]- + H[34S]- = FeH[34S]T[34S]H[34S]- + 3HS- +Fe(HS)3- + D[34S]- + HS- + HS- = FeD[34S]HSHS- + 3HS- +Fe(HS)3- + D[34S]- + HS- + DS- = FeD[34S]HSDS- + 3HS- +Fe(HS)3- + D[34S]- + HS- + TS- = FeD[34S]HSTS- + 3HS- +Fe(HS)3- + D[34S]- + HS- + H[34S]- = FeD[34S]HSH[34S]- + 3HS- +Fe(HS)3- + D[34S]- + HS- + D[34S]- = FeD[34S]HSD[34S]- + 3HS- +Fe(HS)3- + D[34S]- + HS- + T[34S]- = FeD[34S]HST[34S]- + 3HS- +Fe(HS)3- + D[34S]- + DS- + HS- = FeD[34S]DSHS- + 3HS- +Fe(HS)3- + D[34S]- + DS- + TS- = FeD[34S]DSTS- + 3HS- +Fe(HS)3- + D[34S]- + DS- + H[34S]- = FeD[34S]DSH[34S]- + 3HS- +Fe(HS)3- + D[34S]- + TS- + HS- = FeD[34S]TSHS- + 3HS- +Fe(HS)3- + D[34S]- + TS- + DS- = FeD[34S]TSDS- + 3HS- +Fe(HS)3- + D[34S]- + TS- + H[34S]- = FeD[34S]TSH[34S]- + 3HS- +Fe(HS)3- + D[34S]- + H[34S]- + HS- = FeD[34S]H[34S]HS- + 3HS- +Fe(HS)3- + D[34S]- + H[34S]- + DS- = FeD[34S]H[34S]DS- + 3HS- +Fe(HS)3- + D[34S]- + H[34S]- + TS- = FeD[34S]H[34S]TS- + 3HS- +Fe(HS)3- + D[34S]- + H[34S]- + H[34S]- = FeD[34S]H[34S]H[34S]- + 3HS- +Fe(HS)3- + D[34S]- + D[34S]- + HS- = FeD[34S]D[34S]HS- + 3HS- +Fe(HS)3- + D[34S]- + T[34S]- + HS- = FeD[34S]T[34S]HS- + 3HS- +Fe(HS)3- + T[34S]- + HS- + HS- = FeT[34S]HSHS- + 3HS- +Fe(HS)3- + T[34S]- + HS- + DS- = FeT[34S]HSDS- + 3HS- +Fe(HS)3- + T[34S]- + HS- + H[34S]- = FeT[34S]HSH[34S]- + 3HS- +Fe(HS)3- + T[34S]- + HS- + D[34S]- = FeT[34S]HSD[34S]- + 3HS- +Fe(HS)3- + T[34S]- + DS- + HS- = FeT[34S]DSHS- + 3HS- +Fe(HS)3- + T[34S]- + DS- + DS- = FeT[34S]DSDS- + 3HS- +Fe(HS)3- + T[34S]- + DS- + H[34S]- = FeT[34S]DSH[34S]- + 3HS- +Fe(HS)3- + T[34S]- + H[34S]- + HS- = FeT[34S]H[34S]HS- + 3HS- +Fe(HS)3- + T[34S]- + H[34S]- + DS- = FeT[34S]H[34S]DS- + 3HS- +Fe(HS)3- + T[34S]- + H[34S]- + H[34S]- = FeT[34S]H[34S]H[34S]- + 3HS- +Fe(HS)3- + T[34S]- + D[34S]- + HS- = FeT[34S]D[34S]HS- + 3HS- +# +# Missing FeHPO4 reactions +# +# +# Missing FeH2PO4+ reactions +# +# +# Added FeOH+2 reactions 16Dec09 +# +FeOH+2 + OD- = FeOD+2 + OH- +FeOH+2 + OT- = FeOT+2 + OH- +FeOH+2 + [18O]H- = Fe[18O]H+2 + OH- +FeOH+2 + [18O]D- = Fe[18O]D+2 + OH- +FeOH+2 + [18O]T- = Fe[18O]T+2 + OH- +# +# Added Fe(OH)2+ reactions 16Dec09 +# Revised 17Dec09, limited the number of species +# +Fe(OH)2+ + OH- + OD- = FeOHOD+ + 2OH- +Fe(OH)2+ + OH- + OT- = FeOHOT+ + 2OH- +Fe(OH)2+ + OH- + [18O]H- = FeOH[18O]H+ + 2OH- +Fe(OH)2+ + OH- + [18O]D- = FeOH[18O]D+ + 2OH- +Fe(OH)2+ + OH- + [18O]T- = FeOH[18O]T+ + 2OH- +Fe(OH)2+ + OD- + OH- = FeODOH+ + 2OH- +Fe(OH)2+ + OD- + OD- = FeODOD+ + 2OH- +Fe(OH)2+ + OD- + OT- = FeODOT+ + 2OH- +Fe(OH)2+ + OD- + [18O]H- = FeOD[18O]H+ + 2OH- +Fe(OH)2+ + OD- + [18O]D- = FeOD[18O]D+ + 2OH- +Fe(OH)2+ + OD- + [18O]T- = FeOD[18O]T+ + 2OH- +Fe(OH)2+ + OT- + OH- = FeOTOH+ + 2OH- +Fe(OH)2+ + OT- + OD- = FeOTOD+ + 2OH- +Fe(OH)2+ + OT- + [18O]H- = FeOT[18O]H+ + 2OH- +Fe(OH)2+ + OT- + [18O]D- = FeOT[18O]D+ + 2OH- +Fe(OH)2+ + [18O]H- + OH- = Fe[18O]HOH+ + 2OH- +Fe(OH)2+ + [18O]H- + OD- = Fe[18O]HOD+ + 2OH- +Fe(OH)2+ + [18O]H- + OT- = Fe[18O]HOT+ + 2OH- +Fe(OH)2+ + [18O]H- + [18O]H- = Fe[18O]H[18O]H+ + 2OH- +Fe(OH)2+ + [18O]H- + [18O]D- = Fe[18O]H[18O]D+ + 2OH- +Fe(OH)2+ + [18O]H- + [18O]T- = Fe[18O]H[18O]T+ + 2OH- +Fe(OH)2+ + [18O]D- + OH- = Fe[18O]DOH+ + 2OH- +Fe(OH)2+ + [18O]D- + OD- = Fe[18O]DOD+ + 2OH- +Fe(OH)2+ + [18O]D- + OT- = Fe[18O]DOT+ + 2OH- +Fe(OH)2+ + [18O]D- + [18O]H- = Fe[18O]D[18O]H+ + 2OH- +Fe(OH)2+ + [18O]D- + [18O]D- = Fe[18O]D[18O]D+ + 2OH- +Fe(OH)2+ + [18O]D- + [18O]T- = Fe[18O]D[18O]T+ + 2OH- +Fe(OH)2+ + [18O]T- + OH- = Fe[18O]TOH+ + 2OH- +Fe(OH)2+ + [18O]T- + OD- = Fe[18O]TOD+ + 2OH- +Fe(OH)2+ + [18O]T- + [18O]H- = Fe[18O]T[18O]H+ + 2OH- +Fe(OH)2+ + [18O]T- + [18O]D- = Fe[18O]T[18O]D+ + 2OH- +# +# Added Fe(OH)3 reactions 16Dec09 +# Revised 17Dec09, limited the number of species +# +Fe(OH)3 + OH- + OH- + OD- = FeOHOHOD + 3OH- +Fe(OH)3 + OH- + OH- + OT- = FeOHOHOT + 3OH- +Fe(OH)3 + OH- + OH- + [18O]H- = FeOHOH[18O]H + 3OH- +Fe(OH)3 + OH- + OH- + [18O]D- = FeOHOH[18O]D + 3OH- +Fe(OH)3 + OH- + OH- + [18O]T- = FeOHOH[18O]T + 3OH- +Fe(OH)3 + OH- + OD- + OH- = FeOHODOH + 3OH- +Fe(OH)3 + OH- + OD- + OD- = FeOHODOD + 3OH- +Fe(OH)3 + OH- + OD- + OT- = FeOHODOT + 3OH- +Fe(OH)3 + OH- + OD- + [18O]H- = FeOHOD[18O]H + 3OH- +Fe(OH)3 + OH- + OD- + [18O]D- = FeOHOD[18O]D + 3OH- +Fe(OH)3 + OH- + OD- + [18O]T- = FeOHOD[18O]T + 3OH- +Fe(OH)3 + OH- + OT- + OH- = FeOHOTOH + 3OH- +Fe(OH)3 + OH- + OT- + OD- = FeOHOTOD + 3OH- +Fe(OH)3 + OH- + OT- + [18O]H- = FeOHOT[18O]H + 3OH- +Fe(OH)3 + OH- + OT- + [18O]D- = FeOHOT[18O]D + 3OH- +Fe(OH)3 + OH- + [18O]H- + OH- = FeOH[18O]HOH + 3OH- +Fe(OH)3 + OH- + [18O]H- + OD- = FeOH[18O]HOD + 3OH- +Fe(OH)3 + OH- + [18O]H- + OT- = FeOH[18O]HOT + 3OH- +Fe(OH)3 + OH- + [18O]H- + [18O]H- = FeOH[18O]H[18O]H + 3OH- +Fe(OH)3 + OH- + [18O]H- + [18O]D- = FeOH[18O]H[18O]D + 3OH- +Fe(OH)3 + OH- + [18O]H- + [18O]T- = FeOH[18O]H[18O]T + 3OH- +Fe(OH)3 + OH- + [18O]D- + OH- = FeOH[18O]DOH + 3OH- +Fe(OH)3 + OH- + [18O]D- + OD- = FeOH[18O]DOD + 3OH- +Fe(OH)3 + OH- + [18O]D- + OT- = FeOH[18O]DOT + 3OH- +Fe(OH)3 + OH- + [18O]D- + [18O]H- = FeOH[18O]D[18O]H + 3OH- +Fe(OH)3 + OH- + [18O]D- + [18O]D- = FeOH[18O]D[18O]D + 3OH- +Fe(OH)3 + OH- + [18O]D- + [18O]T- = FeOH[18O]D[18O]T + 3OH- +Fe(OH)3 + OH- + [18O]T- + OH- = FeOH[18O]TOH + 3OH- +Fe(OH)3 + OH- + [18O]T- + OD- = FeOH[18O]TOD + 3OH- +Fe(OH)3 + OH- + [18O]T- + [18O]H- = FeOH[18O]T[18O]H + 3OH- +Fe(OH)3 + OH- + [18O]T- + [18O]D- = FeOH[18O]T[18O]D + 3OH- +Fe(OH)3 + OD- + OH- + OH- = FeODOHOH + 3OH- +Fe(OH)3 + OD- + OH- + OD- = FeODOHOD + 3OH- +Fe(OH)3 + OD- + OH- + OT- = FeODOHOT + 3OH- +Fe(OH)3 + OD- + OH- + [18O]H- = FeODOH[18O]H + 3OH- +Fe(OH)3 + OD- + OH- + [18O]D- = FeODOH[18O]D + 3OH- +Fe(OH)3 + OD- + OH- + [18O]T- = FeODOH[18O]T + 3OH- +Fe(OH)3 + OD- + OD- + OH- = FeODODOH + 3OH- +Fe(OH)3 + OD- + OD- + OT- = FeODODOT + 3OH- +Fe(OH)3 + OD- + OD- + [18O]H- = FeODOD[18O]H + 3OH- +Fe(OH)3 + OD- + OD- + [18O]T- = FeODOD[18O]T + 3OH- +Fe(OH)3 + OD- + OT- + OH- = FeODOTOH + 3OH- +Fe(OH)3 + OD- + OT- + OD- = FeODOTOD + 3OH- +Fe(OH)3 + OD- + OT- + [18O]H- = FeODOT[18O]H + 3OH- +Fe(OH)3 + OD- + OT- + [18O]D- = FeODOT[18O]D + 3OH- +Fe(OH)3 + OD- + [18O]H- + OH- = FeOD[18O]HOH + 3OH- +Fe(OH)3 + OD- + [18O]H- + OD- = FeOD[18O]HOD + 3OH- +Fe(OH)3 + OD- + [18O]H- + OT- = FeOD[18O]HOT + 3OH- +Fe(OH)3 + OD- + [18O]H- + [18O]H- = FeOD[18O]H[18O]H + 3OH- +Fe(OH)3 + OD- + [18O]H- + [18O]D- = FeOD[18O]H[18O]D + 3OH- +Fe(OH)3 + OD- + [18O]H- + [18O]T- = FeOD[18O]H[18O]T + 3OH- +Fe(OH)3 + OD- + [18O]D- + OH- = FeOD[18O]DOH + 3OH- +Fe(OH)3 + OD- + [18O]D- + OT- = FeOD[18O]DOT + 3OH- +Fe(OH)3 + OD- + [18O]D- + [18O]H- = FeOD[18O]D[18O]H + 3OH- +Fe(OH)3 + OD- + [18O]T- + OH- = FeOD[18O]TOH + 3OH- +Fe(OH)3 + OD- + [18O]T- + OD- = FeOD[18O]TOD + 3OH- +Fe(OH)3 + OD- + [18O]T- + [18O]H- = FeOD[18O]T[18O]H + 3OH- +Fe(OH)3 + OT- + OH- + OH- = FeOTOHOH + 3OH- +Fe(OH)3 + OT- + OH- + OD- = FeOTOHOD + 3OH- +Fe(OH)3 + OT- + OH- + [18O]H- = FeOTOH[18O]H + 3OH- +Fe(OH)3 + OT- + OH- + [18O]D- = FeOTOH[18O]D + 3OH- +Fe(OH)3 + OT- + OD- + OH- = FeOTODOH + 3OH- +Fe(OH)3 + OT- + OD- + OD- = FeOTODOD + 3OH- +Fe(OH)3 + OT- + OD- + [18O]H- = FeOTOD[18O]H + 3OH- +Fe(OH)3 + OT- + OD- + [18O]D- = FeOTOD[18O]D + 3OH- +Fe(OH)3 + OT- + [18O]H- + OH- = FeOT[18O]HOH + 3OH- +Fe(OH)3 + OT- + [18O]H- + OD- = FeOT[18O]HOD + 3OH- +Fe(OH)3 + OT- + [18O]H- + [18O]H- = FeOT[18O]H[18O]H + 3OH- +Fe(OH)3 + OT- + [18O]H- + [18O]D- = FeOT[18O]H[18O]D + 3OH- +Fe(OH)3 + OT- + [18O]D- + OH- = FeOT[18O]DOH + 3OH- +Fe(OH)3 + OT- + [18O]D- + OD- = FeOT[18O]DOD + 3OH- +Fe(OH)3 + OT- + [18O]D- + [18O]H- = FeOT[18O]D[18O]H + 3OH- +Fe(OH)3 + [18O]H- + OH- + OH- = Fe[18O]HOHOH + 3OH- +Fe(OH)3 + [18O]H- + OH- + OD- = Fe[18O]HOHOD + 3OH- +Fe(OH)3 + [18O]H- + OH- + OT- = Fe[18O]HOHOT + 3OH- +Fe(OH)3 + [18O]H- + OH- + [18O]H- = Fe[18O]HOH[18O]H + 3OH- +Fe(OH)3 + [18O]H- + OH- + [18O]D- = Fe[18O]HOH[18O]D + 3OH- +Fe(OH)3 + [18O]H- + OH- + [18O]T- = Fe[18O]HOH[18O]T + 3OH- +Fe(OH)3 + [18O]H- + OD- + OH- = Fe[18O]HODOH + 3OH- +Fe(OH)3 + [18O]H- + OD- + OD- = Fe[18O]HODOD + 3OH- +Fe(OH)3 + [18O]H- + OD- + OT- = Fe[18O]HODOT + 3OH- +Fe(OH)3 + [18O]H- + OD- + [18O]H- = Fe[18O]HOD[18O]H + 3OH- +Fe(OH)3 + [18O]H- + OD- + [18O]D- = Fe[18O]HOD[18O]D + 3OH- +Fe(OH)3 + [18O]H- + OD- + [18O]T- = Fe[18O]HOD[18O]T + 3OH- +Fe(OH)3 + [18O]H- + OT- + OH- = Fe[18O]HOTOH + 3OH- +Fe(OH)3 + [18O]H- + OT- + OD- = Fe[18O]HOTOD + 3OH- +Fe(OH)3 + [18O]H- + OT- + [18O]H- = Fe[18O]HOT[18O]H + 3OH- +Fe(OH)3 + [18O]H- + OT- + [18O]D- = Fe[18O]HOT[18O]D + 3OH- +Fe(OH)3 + [18O]H- + [18O]H- + OH- = Fe[18O]H[18O]HOH + 3OH- +Fe(OH)3 + [18O]H- + [18O]H- + OD- = Fe[18O]H[18O]HOD + 3OH- +Fe(OH)3 + [18O]H- + [18O]H- + OT- = Fe[18O]H[18O]HOT + 3OH- +Fe(OH)3 + [18O]H- + [18O]D- + OH- = Fe[18O]H[18O]DOH + 3OH- +Fe(OH)3 + [18O]H- + [18O]D- + OD- = Fe[18O]H[18O]DOD + 3OH- +Fe(OH)3 + [18O]H- + [18O]D- + OT- = Fe[18O]H[18O]DOT + 3OH- +Fe(OH)3 + [18O]H- + [18O]T- + OH- = Fe[18O]H[18O]TOH + 3OH- +Fe(OH)3 + [18O]H- + [18O]T- + OD- = Fe[18O]H[18O]TOD + 3OH- +Fe(OH)3 + [18O]D- + OH- + OH- = Fe[18O]DOHOH + 3OH- +Fe(OH)3 + [18O]D- + OH- + OD- = Fe[18O]DOHOD + 3OH- +Fe(OH)3 + [18O]D- + OH- + OT- = Fe[18O]DOHOT + 3OH- +Fe(OH)3 + [18O]D- + OH- + [18O]H- = Fe[18O]DOH[18O]H + 3OH- +Fe(OH)3 + [18O]D- + OH- + [18O]D- = Fe[18O]DOH[18O]D + 3OH- +Fe(OH)3 + [18O]D- + OH- + [18O]T- = Fe[18O]DOH[18O]T + 3OH- +Fe(OH)3 + [18O]D- + OD- + OH- = Fe[18O]DODOH + 3OH- +Fe(OH)3 + [18O]D- + OD- + OT- = Fe[18O]DODOT + 3OH- +Fe(OH)3 + [18O]D- + OD- + [18O]H- = Fe[18O]DOD[18O]H + 3OH- +Fe(OH)3 + [18O]D- + OT- + OH- = Fe[18O]DOTOH + 3OH- +Fe(OH)3 + [18O]D- + OT- + OD- = Fe[18O]DOTOD + 3OH- +Fe(OH)3 + [18O]D- + OT- + [18O]H- = Fe[18O]DOT[18O]H + 3OH- +Fe(OH)3 + [18O]D- + [18O]H- + OH- = Fe[18O]D[18O]HOH + 3OH- +Fe(OH)3 + [18O]D- + [18O]H- + OD- = Fe[18O]D[18O]HOD + 3OH- +Fe(OH)3 + [18O]D- + [18O]H- + OT- = Fe[18O]D[18O]HOT + 3OH- +Fe(OH)3 + [18O]D- + [18O]D- + OH- = Fe[18O]D[18O]DOH + 3OH- +Fe(OH)3 + [18O]D- + [18O]T- + OH- = Fe[18O]D[18O]TOH + 3OH- +Fe(OH)3 + [18O]T- + OH- + OH- = Fe[18O]TOHOH + 3OH- +Fe(OH)3 + [18O]T- + OH- + OD- = Fe[18O]TOHOD + 3OH- +Fe(OH)3 + [18O]T- + OH- + [18O]H- = Fe[18O]TOH[18O]H + 3OH- +Fe(OH)3 + [18O]T- + OH- + [18O]D- = Fe[18O]TOH[18O]D + 3OH- +Fe(OH)3 + [18O]T- + OD- + OH- = Fe[18O]TODOH + 3OH- +Fe(OH)3 + [18O]T- + OD- + OD- = Fe[18O]TODOD + 3OH- +Fe(OH)3 + [18O]T- + OD- + [18O]H- = Fe[18O]TOD[18O]H + 3OH- +Fe(OH)3 + [18O]T- + [18O]H- + OH- = Fe[18O]T[18O]HOH + 3OH- +Fe(OH)3 + [18O]T- + [18O]H- + OD- = Fe[18O]T[18O]HOD + 3OH- +Fe(OH)3 + [18O]T- + [18O]D- + OH- = Fe[18O]T[18O]DOH + 3OH- +# +# Added Fe(OH)4- reactions 16Dec09 +# Revised 17Dec09, limited the number of species +# +Fe(OH)4- + OH- + OH- + OH- + OD- = FeOHOHOHOD- + 4OH- +Fe(OH)4- + OH- + OH- + OH- + OT- = FeOHOHOHOT- + 4OH- +Fe(OH)4- + OH- + OH- + OH- + [18O]H- = FeOHOHOH[18O]H- + 4OH- +Fe(OH)4- + OH- + OH- + OH- + [18O]D- = FeOHOHOH[18O]D- + 4OH- +Fe(OH)4- + OH- + OH- + OH- + [18O]T- = FeOHOHOH[18O]T- + 4OH- +Fe(OH)4- + OH- + OH- + OD- + OH- = FeOHOHODOH- + 4OH- +Fe(OH)4- + OH- + OH- + OD- + OD- = FeOHOHODOD- + 4OH- +Fe(OH)4- + OH- + OH- + OD- + OT- = FeOHOHODOT- + 4OH- +Fe(OH)4- + OH- + OH- + OD- + [18O]H- = FeOHOHOD[18O]H- + 4OH- +Fe(OH)4- + OH- + OH- + OD- + [18O]D- = FeOHOHOD[18O]D- + 4OH- +Fe(OH)4- + OH- + OH- + OD- + [18O]T- = FeOHOHOD[18O]T- + 4OH- +Fe(OH)4- + OH- + OH- + OT- + OH- = FeOHOHOTOH- + 4OH- +Fe(OH)4- + OH- + OH- + OT- + OD- = FeOHOHOTOD- + 4OH- +Fe(OH)4- + OH- + OH- + OT- + [18O]H- = FeOHOHOT[18O]H- + 4OH- +Fe(OH)4- + OH- + OH- + OT- + [18O]D- = FeOHOHOT[18O]D- + 4OH- +Fe(OH)4- + OH- + OH- + [18O]H- + OH- = FeOHOH[18O]HOH- + 4OH- +Fe(OH)4- + OH- + OH- + [18O]H- + OD- = FeOHOH[18O]HOD- + 4OH- +Fe(OH)4- + OH- + OH- + [18O]H- + OT- = FeOHOH[18O]HOT- + 4OH- +Fe(OH)4- + OH- + OH- + [18O]H- + [18O]H- = FeOHOH[18O]H[18O]H- + 4OH- +Fe(OH)4- + OH- + OH- + [18O]H- + [18O]D- = FeOHOH[18O]H[18O]D- + 4OH- +Fe(OH)4- + OH- + OH- + [18O]H- + [18O]T- = FeOHOH[18O]H[18O]T- + 4OH- +Fe(OH)4- + OH- + OH- + [18O]D- + OH- = FeOHOH[18O]DOH- + 4OH- +Fe(OH)4- + OH- + OH- + [18O]D- + OD- = FeOHOH[18O]DOD- + 4OH- +Fe(OH)4- + OH- + OH- + [18O]D- + OT- = FeOHOH[18O]DOT- + 4OH- +Fe(OH)4- + OH- + OH- + [18O]D- + [18O]H- = FeOHOH[18O]D[18O]H- + 4OH- +Fe(OH)4- + OH- + OH- + [18O]D- + [18O]D- = FeOHOH[18O]D[18O]D- + 4OH- +Fe(OH)4- + OH- + OH- + [18O]D- + [18O]T- = FeOHOH[18O]D[18O]T- + 4OH- +Fe(OH)4- + OH- + OH- + [18O]T- + OH- = FeOHOH[18O]TOH- + 4OH- +Fe(OH)4- + OH- + OH- + [18O]T- + OD- = FeOHOH[18O]TOD- + 4OH- +Fe(OH)4- + OH- + OH- + [18O]T- + [18O]H- = FeOHOH[18O]T[18O]H- + 4OH- +Fe(OH)4- + OH- + OH- + [18O]T- + [18O]D- = FeOHOH[18O]T[18O]D- + 4OH- +Fe(OH)4- + OH- + OD- + OH- + OH- = FeOHODOHOH- + 4OH- +Fe(OH)4- + OH- + OD- + OH- + OD- = FeOHODOHOD- + 4OH- +Fe(OH)4- + OH- + OD- + OH- + OT- = FeOHODOHOT- + 4OH- +Fe(OH)4- + OH- + OD- + OH- + [18O]H- = FeOHODOH[18O]H- + 4OH- +Fe(OH)4- + OH- + OD- + OH- + [18O]D- = FeOHODOH[18O]D- + 4OH- +Fe(OH)4- + OH- + OD- + OH- + [18O]T- = FeOHODOH[18O]T- + 4OH- +Fe(OH)4- + OH- + OD- + OD- + OH- = FeOHODODOH- + 4OH- +Fe(OH)4- + OH- + OD- + OD- + OT- = FeOHODODOT- + 4OH- +Fe(OH)4- + OH- + OD- + OD- + [18O]H- = FeOHODOD[18O]H- + 4OH- +Fe(OH)4- + OH- + OD- + OD- + [18O]T- = FeOHODOD[18O]T- + 4OH- +Fe(OH)4- + OH- + OD- + OT- + OH- = FeOHODOTOH- + 4OH- +Fe(OH)4- + OH- + OD- + OT- + OD- = FeOHODOTOD- + 4OH- +Fe(OH)4- + OH- + OD- + OT- + [18O]H- = FeOHODOT[18O]H- + 4OH- +Fe(OH)4- + OH- + OD- + OT- + [18O]D- = FeOHODOT[18O]D- + 4OH- +Fe(OH)4- + OH- + OD- + [18O]H- + OH- = FeOHOD[18O]HOH- + 4OH- +Fe(OH)4- + OH- + OD- + [18O]H- + OD- = FeOHOD[18O]HOD- + 4OH- +Fe(OH)4- + OH- + OD- + [18O]H- + OT- = FeOHOD[18O]HOT- + 4OH- +Fe(OH)4- + OH- + OD- + [18O]H- + [18O]H- = FeOHOD[18O]H[18O]H- + 4OH- +Fe(OH)4- + OH- + OD- + [18O]H- + [18O]D- = FeOHOD[18O]H[18O]D- + 4OH- +Fe(OH)4- + OH- + OD- + [18O]H- + [18O]T- = FeOHOD[18O]H[18O]T- + 4OH- +Fe(OH)4- + OH- + OD- + [18O]D- + OH- = FeOHOD[18O]DOH- + 4OH- +Fe(OH)4- + OH- + OD- + [18O]D- + OT- = FeOHOD[18O]DOT- + 4OH- +Fe(OH)4- + OH- + OD- + [18O]D- + [18O]H- = FeOHOD[18O]D[18O]H- + 4OH- +Fe(OH)4- + OH- + OD- + [18O]T- + OH- = FeOHOD[18O]TOH- + 4OH- +Fe(OH)4- + OH- + OD- + [18O]T- + OD- = FeOHOD[18O]TOD- + 4OH- +Fe(OH)4- + OH- + OD- + [18O]T- + [18O]H- = FeOHOD[18O]T[18O]H- + 4OH- +Fe(OH)4- + OH- + OT- + OH- + OH- = FeOHOTOHOH- + 4OH- +Fe(OH)4- + OH- + OT- + OH- + OD- = FeOHOTOHOD- + 4OH- +Fe(OH)4- + OH- + OT- + OH- + [18O]H- = FeOHOTOH[18O]H- + 4OH- +Fe(OH)4- + OH- + OT- + OH- + [18O]D- = FeOHOTOH[18O]D- + 4OH- +Fe(OH)4- + OH- + OT- + OD- + OH- = FeOHOTODOH- + 4OH- +Fe(OH)4- + OH- + OT- + OD- + OD- = FeOHOTODOD- + 4OH- +Fe(OH)4- + OH- + OT- + OD- + [18O]H- = FeOHOTOD[18O]H- + 4OH- +Fe(OH)4- + OH- + OT- + OD- + [18O]D- = FeOHOTOD[18O]D- + 4OH- +Fe(OH)4- + OH- + OT- + [18O]H- + OH- = FeOHOT[18O]HOH- + 4OH- +Fe(OH)4- + OH- + OT- + [18O]H- + OD- = FeOHOT[18O]HOD- + 4OH- +Fe(OH)4- + OH- + OT- + [18O]H- + [18O]H- = FeOHOT[18O]H[18O]H- + 4OH- +Fe(OH)4- + OH- + OT- + [18O]H- + [18O]D- = FeOHOT[18O]H[18O]D- + 4OH- +Fe(OH)4- + OH- + OT- + [18O]D- + OH- = FeOHOT[18O]DOH- + 4OH- +Fe(OH)4- + OH- + OT- + [18O]D- + OD- = FeOHOT[18O]DOD- + 4OH- +Fe(OH)4- + OH- + OT- + [18O]D- + [18O]H- = FeOHOT[18O]D[18O]H- + 4OH- +Fe(OH)4- + OH- + [18O]H- + OH- + OH- = FeOH[18O]HOHOH- + 4OH- +Fe(OH)4- + OH- + [18O]H- + OH- + OD- = FeOH[18O]HOHOD- + 4OH- +Fe(OH)4- + OH- + [18O]H- + OH- + OT- = FeOH[18O]HOHOT- + 4OH- +Fe(OH)4- + OH- + [18O]H- + OH- + [18O]H- = FeOH[18O]HOH[18O]H- + 4OH- +Fe(OH)4- + OH- + [18O]H- + OH- + [18O]D- = FeOH[18O]HOH[18O]D- + 4OH- +Fe(OH)4- + OH- + [18O]H- + OH- + [18O]T- = FeOH[18O]HOH[18O]T- + 4OH- +Fe(OH)4- + OH- + [18O]H- + OD- + OH- = FeOH[18O]HODOH- + 4OH- +Fe(OH)4- + OH- + [18O]H- + OD- + OD- = FeOH[18O]HODOD- + 4OH- +Fe(OH)4- + OH- + [18O]H- + OD- + OT- = FeOH[18O]HODOT- + 4OH- +Fe(OH)4- + OH- + [18O]H- + OD- + [18O]H- = FeOH[18O]HOD[18O]H- + 4OH- +Fe(OH)4- + OH- + [18O]H- + OD- + [18O]D- = FeOH[18O]HOD[18O]D- + 4OH- +Fe(OH)4- + OH- + [18O]H- + OD- + [18O]T- = FeOH[18O]HOD[18O]T- + 4OH- +Fe(OH)4- + OH- + [18O]H- + OT- + OH- = FeOH[18O]HOTOH- + 4OH- +Fe(OH)4- + OH- + [18O]H- + OT- + OD- = FeOH[18O]HOTOD- + 4OH- +Fe(OH)4- + OH- + [18O]H- + OT- + [18O]H- = FeOH[18O]HOT[18O]H- + 4OH- +Fe(OH)4- + OH- + [18O]H- + OT- + [18O]D- = FeOH[18O]HOT[18O]D- + 4OH- +Fe(OH)4- + OH- + [18O]H- + [18O]H- + OH- = FeOH[18O]H[18O]HOH- + 4OH- +Fe(OH)4- + OH- + [18O]H- + [18O]H- + OD- = FeOH[18O]H[18O]HOD- + 4OH- +Fe(OH)4- + OH- + [18O]H- + [18O]H- + OT- = FeOH[18O]H[18O]HOT- + 4OH- +Fe(OH)4- + OH- + [18O]H- + [18O]D- + OH- = FeOH[18O]H[18O]DOH- + 4OH- +Fe(OH)4- + OH- + [18O]H- + [18O]D- + OD- = FeOH[18O]H[18O]DOD- + 4OH- +Fe(OH)4- + OH- + [18O]H- + [18O]D- + OT- = FeOH[18O]H[18O]DOT- + 4OH- +Fe(OH)4- + OH- + [18O]H- + [18O]T- + OH- = FeOH[18O]H[18O]TOH- + 4OH- +Fe(OH)4- + OH- + [18O]H- + [18O]T- + OD- = FeOH[18O]H[18O]TOD- + 4OH- +Fe(OH)4- + OH- + [18O]D- + OH- + OH- = FeOH[18O]DOHOH- + 4OH- +Fe(OH)4- + OH- + [18O]D- + OH- + OD- = FeOH[18O]DOHOD- + 4OH- +Fe(OH)4- + OH- + [18O]D- + OH- + OT- = FeOH[18O]DOHOT- + 4OH- +Fe(OH)4- + OH- + [18O]D- + OH- + [18O]H- = FeOH[18O]DOH[18O]H- + 4OH- +Fe(OH)4- + OH- + [18O]D- + OH- + [18O]D- = FeOH[18O]DOH[18O]D- + 4OH- +Fe(OH)4- + OH- + [18O]D- + OH- + [18O]T- = FeOH[18O]DOH[18O]T- + 4OH- +Fe(OH)4- + OH- + [18O]D- + OD- + OH- = FeOH[18O]DODOH- + 4OH- +Fe(OH)4- + OH- + [18O]D- + OD- + OT- = FeOH[18O]DODOT- + 4OH- +Fe(OH)4- + OH- + [18O]D- + OD- + [18O]H- = FeOH[18O]DOD[18O]H- + 4OH- +Fe(OH)4- + OH- + [18O]D- + OT- + OH- = FeOH[18O]DOTOH- + 4OH- +Fe(OH)4- + OH- + [18O]D- + OT- + OD- = FeOH[18O]DOTOD- + 4OH- +Fe(OH)4- + OH- + [18O]D- + OT- + [18O]H- = FeOH[18O]DOT[18O]H- + 4OH- +Fe(OH)4- + OH- + [18O]D- + [18O]H- + OH- = FeOH[18O]D[18O]HOH- + 4OH- +Fe(OH)4- + OH- + [18O]D- + [18O]H- + OD- = FeOH[18O]D[18O]HOD- + 4OH- +Fe(OH)4- + OH- + [18O]D- + [18O]H- + OT- = FeOH[18O]D[18O]HOT- + 4OH- +Fe(OH)4- + OH- + [18O]D- + [18O]D- + OH- = FeOH[18O]D[18O]DOH- + 4OH- +Fe(OH)4- + OH- + [18O]D- + [18O]T- + OH- = FeOH[18O]D[18O]TOH- + 4OH- +Fe(OH)4- + OH- + [18O]T- + OH- + OH- = FeOH[18O]TOHOH- + 4OH- +Fe(OH)4- + OH- + [18O]T- + OH- + OD- = FeOH[18O]TOHOD- + 4OH- +Fe(OH)4- + OH- + [18O]T- + OH- + [18O]H- = FeOH[18O]TOH[18O]H- + 4OH- +Fe(OH)4- + OH- + [18O]T- + OH- + [18O]D- = FeOH[18O]TOH[18O]D- + 4OH- +Fe(OH)4- + OH- + [18O]T- + OD- + OH- = FeOH[18O]TODOH- + 4OH- +Fe(OH)4- + OH- + [18O]T- + OD- + OD- = FeOH[18O]TODOD- + 4OH- +Fe(OH)4- + OH- + [18O]T- + OD- + [18O]H- = FeOH[18O]TOD[18O]H- + 4OH- +Fe(OH)4- + OH- + [18O]T- + [18O]H- + OH- = FeOH[18O]T[18O]HOH- + 4OH- +Fe(OH)4- + OH- + [18O]T- + [18O]H- + OD- = FeOH[18O]T[18O]HOD- + 4OH- +Fe(OH)4- + OH- + [18O]T- + [18O]D- + OH- = FeOH[18O]T[18O]DOH- + 4OH- +Fe(OH)4- + OD- + OH- + OH- + OH- = FeODOHOHOH- + 4OH- +Fe(OH)4- + OD- + OH- + OH- + OD- = FeODOHOHOD- + 4OH- +Fe(OH)4- + OD- + OH- + OH- + OT- = FeODOHOHOT- + 4OH- +Fe(OH)4- + OD- + OH- + OH- + [18O]H- = FeODOHOH[18O]H- + 4OH- +Fe(OH)4- + OD- + OH- + OH- + [18O]D- = FeODOHOH[18O]D- + 4OH- +Fe(OH)4- + OD- + OH- + OH- + [18O]T- = FeODOHOH[18O]T- + 4OH- +Fe(OH)4- + OD- + OH- + OD- + OH- = FeODOHODOH- + 4OH- +Fe(OH)4- + OD- + OH- + OD- + OT- = FeODOHODOT- + 4OH- +Fe(OH)4- + OD- + OH- + OD- + [18O]H- = FeODOHOD[18O]H- + 4OH- +Fe(OH)4- + OD- + OH- + OD- + [18O]T- = FeODOHOD[18O]T- + 4OH- +Fe(OH)4- + OD- + OH- + OT- + OH- = FeODOHOTOH- + 4OH- +Fe(OH)4- + OD- + OH- + OT- + OD- = FeODOHOTOD- + 4OH- +Fe(OH)4- + OD- + OH- + OT- + [18O]H- = FeODOHOT[18O]H- + 4OH- +Fe(OH)4- + OD- + OH- + OT- + [18O]D- = FeODOHOT[18O]D- + 4OH- +Fe(OH)4- + OD- + OH- + [18O]H- + OH- = FeODOH[18O]HOH- + 4OH- +Fe(OH)4- + OD- + OH- + [18O]H- + OD- = FeODOH[18O]HOD- + 4OH- +Fe(OH)4- + OD- + OH- + [18O]H- + OT- = FeODOH[18O]HOT- + 4OH- +Fe(OH)4- + OD- + OH- + [18O]H- + [18O]H- = FeODOH[18O]H[18O]H- + 4OH- +Fe(OH)4- + OD- + OH- + [18O]H- + [18O]D- = FeODOH[18O]H[18O]D- + 4OH- +Fe(OH)4- + OD- + OH- + [18O]H- + [18O]T- = FeODOH[18O]H[18O]T- + 4OH- +Fe(OH)4- + OD- + OH- + [18O]D- + OH- = FeODOH[18O]DOH- + 4OH- +Fe(OH)4- + OD- + OH- + [18O]D- + OT- = FeODOH[18O]DOT- + 4OH- +Fe(OH)4- + OD- + OH- + [18O]D- + [18O]H- = FeODOH[18O]D[18O]H- + 4OH- +Fe(OH)4- + OD- + OH- + [18O]T- + OH- = FeODOH[18O]TOH- + 4OH- +Fe(OH)4- + OD- + OH- + [18O]T- + OD- = FeODOH[18O]TOD- + 4OH- +Fe(OH)4- + OD- + OH- + [18O]T- + [18O]H- = FeODOH[18O]T[18O]H- + 4OH- +Fe(OH)4- + OD- + OD- + OH- + OH- = FeODODOHOH- + 4OH- +Fe(OH)4- + OD- + OD- + OH- + OT- = FeODODOHOT- + 4OH- +Fe(OH)4- + OD- + OD- + OH- + [18O]H- = FeODODOH[18O]H- + 4OH- +Fe(OH)4- + OD- + OD- + OH- + [18O]T- = FeODODOH[18O]T- + 4OH- +Fe(OH)4- + OD- + OD- + OT- + OH- = FeODODOTOH- + 4OH- +Fe(OH)4- + OD- + OD- + OT- + [18O]H- = FeODODOT[18O]H- + 4OH- +Fe(OH)4- + OD- + OD- + [18O]H- + OH- = FeODOD[18O]HOH- + 4OH- +Fe(OH)4- + OD- + OD- + [18O]H- + OT- = FeODOD[18O]HOT- + 4OH- +Fe(OH)4- + OD- + OD- + [18O]H- + [18O]H- = FeODOD[18O]H[18O]H- + 4OH- +Fe(OH)4- + OD- + OD- + [18O]T- + OH- = FeODOD[18O]TOH- + 4OH- +Fe(OH)4- + OD- + OT- + OH- + OH- = FeODOTOHOH- + 4OH- +Fe(OH)4- + OD- + OT- + OH- + OD- = FeODOTOHOD- + 4OH- +Fe(OH)4- + OD- + OT- + OH- + [18O]H- = FeODOTOH[18O]H- + 4OH- +Fe(OH)4- + OD- + OT- + OH- + [18O]D- = FeODOTOH[18O]D- + 4OH- +Fe(OH)4- + OD- + OT- + OD- + OH- = FeODOTODOH- + 4OH- +Fe(OH)4- + OD- + OT- + OD- + [18O]H- = FeODOTOD[18O]H- + 4OH- +Fe(OH)4- + OD- + OT- + [18O]H- + OH- = FeODOT[18O]HOH- + 4OH- +Fe(OH)4- + OD- + OT- + [18O]H- + OD- = FeODOT[18O]HOD- + 4OH- +Fe(OH)4- + OD- + OT- + [18O]H- + [18O]H- = FeODOT[18O]H[18O]H- + 4OH- +Fe(OH)4- + OD- + OT- + [18O]D- + OH- = FeODOT[18O]DOH- + 4OH- +Fe(OH)4- + OD- + [18O]H- + OH- + OH- = FeOD[18O]HOHOH- + 4OH- +Fe(OH)4- + OD- + [18O]H- + OH- + OD- = FeOD[18O]HOHOD- + 4OH- +Fe(OH)4- + OD- + [18O]H- + OH- + OT- = FeOD[18O]HOHOT- + 4OH- +Fe(OH)4- + OD- + [18O]H- + OH- + [18O]H- = FeOD[18O]HOH[18O]H- + 4OH- +Fe(OH)4- + OD- + [18O]H- + OH- + [18O]D- = FeOD[18O]HOH[18O]D- + 4OH- +Fe(OH)4- + OD- + [18O]H- + OH- + [18O]T- = FeOD[18O]HOH[18O]T- + 4OH- +Fe(OH)4- + OD- + [18O]H- + OD- + OH- = FeOD[18O]HODOH- + 4OH- +Fe(OH)4- + OD- + [18O]H- + OD- + OT- = FeOD[18O]HODOT- + 4OH- +Fe(OH)4- + OD- + [18O]H- + OD- + [18O]H- = FeOD[18O]HOD[18O]H- + 4OH- +Fe(OH)4- + OD- + [18O]H- + OT- + OH- = FeOD[18O]HOTOH- + 4OH- +Fe(OH)4- + OD- + [18O]H- + OT- + OD- = FeOD[18O]HOTOD- + 4OH- +Fe(OH)4- + OD- + [18O]H- + OT- + [18O]H- = FeOD[18O]HOT[18O]H- + 4OH- +Fe(OH)4- + OD- + [18O]H- + [18O]H- + OH- = FeOD[18O]H[18O]HOH- + 4OH- +Fe(OH)4- + OD- + [18O]H- + [18O]H- + OD- = FeOD[18O]H[18O]HOD- + 4OH- +Fe(OH)4- + OD- + [18O]H- + [18O]H- + OT- = FeOD[18O]H[18O]HOT- + 4OH- +Fe(OH)4- + OD- + [18O]H- + [18O]D- + OH- = FeOD[18O]H[18O]DOH- + 4OH- +Fe(OH)4- + OD- + [18O]H- + [18O]T- + OH- = FeOD[18O]H[18O]TOH- + 4OH- +Fe(OH)4- + OD- + [18O]D- + OH- + OH- = FeOD[18O]DOHOH- + 4OH- +Fe(OH)4- + OD- + [18O]D- + OH- + OT- = FeOD[18O]DOHOT- + 4OH- +Fe(OH)4- + OD- + [18O]D- + OH- + [18O]H- = FeOD[18O]DOH[18O]H- + 4OH- +Fe(OH)4- + OD- + [18O]D- + OT- + OH- = FeOD[18O]DOTOH- + 4OH- +Fe(OH)4- + OD- + [18O]D- + [18O]H- + OH- = FeOD[18O]D[18O]HOH- + 4OH- +Fe(OH)4- + OD- + [18O]T- + OH- + OH- = FeOD[18O]TOHOH- + 4OH- +Fe(OH)4- + OD- + [18O]T- + OH- + OD- = FeOD[18O]TOHOD- + 4OH- +Fe(OH)4- + OD- + [18O]T- + OH- + [18O]H- = FeOD[18O]TOH[18O]H- + 4OH- +Fe(OH)4- + OD- + [18O]T- + OD- + OH- = FeOD[18O]TODOH- + 4OH- +Fe(OH)4- + OD- + [18O]T- + [18O]H- + OH- = FeOD[18O]T[18O]HOH- + 4OH- +Fe(OH)4- + OT- + OH- + OH- + OH- = FeOTOHOHOH- + 4OH- +Fe(OH)4- + OT- + OH- + OH- + OD- = FeOTOHOHOD- + 4OH- +Fe(OH)4- + OT- + OH- + OH- + [18O]H- = FeOTOHOH[18O]H- + 4OH- +Fe(OH)4- + OT- + OH- + OH- + [18O]D- = FeOTOHOH[18O]D- + 4OH- +Fe(OH)4- + OT- + OH- + OD- + OH- = FeOTOHODOH- + 4OH- +Fe(OH)4- + OT- + OH- + OD- + OD- = FeOTOHODOD- + 4OH- +Fe(OH)4- + OT- + OH- + OD- + [18O]H- = FeOTOHOD[18O]H- + 4OH- +Fe(OH)4- + OT- + OH- + OD- + [18O]D- = FeOTOHOD[18O]D- + 4OH- +Fe(OH)4- + OT- + OH- + [18O]H- + OH- = FeOTOH[18O]HOH- + 4OH- +Fe(OH)4- + OT- + OH- + [18O]H- + OD- = FeOTOH[18O]HOD- + 4OH- +Fe(OH)4- + OT- + OH- + [18O]H- + [18O]H- = FeOTOH[18O]H[18O]H- + 4OH- +Fe(OH)4- + OT- + OH- + [18O]H- + [18O]D- = FeOTOH[18O]H[18O]D- + 4OH- +Fe(OH)4- + OT- + OH- + [18O]D- + OH- = FeOTOH[18O]DOH- + 4OH- +Fe(OH)4- + OT- + OH- + [18O]D- + OD- = FeOTOH[18O]DOD- + 4OH- +Fe(OH)4- + OT- + OH- + [18O]D- + [18O]H- = FeOTOH[18O]D[18O]H- + 4OH- +Fe(OH)4- + OT- + OD- + OH- + OH- = FeOTODOHOH- + 4OH- +Fe(OH)4- + OT- + OD- + OH- + OD- = FeOTODOHOD- + 4OH- +Fe(OH)4- + OT- + OD- + OH- + [18O]H- = FeOTODOH[18O]H- + 4OH- +Fe(OH)4- + OT- + OD- + OH- + [18O]D- = FeOTODOH[18O]D- + 4OH- +Fe(OH)4- + OT- + OD- + OD- + OH- = FeOTODODOH- + 4OH- +Fe(OH)4- + OT- + OD- + OD- + [18O]H- = FeOTODOD[18O]H- + 4OH- +Fe(OH)4- + OT- + OD- + [18O]H- + OH- = FeOTOD[18O]HOH- + 4OH- +Fe(OH)4- + OT- + OD- + [18O]H- + OD- = FeOTOD[18O]HOD- + 4OH- +Fe(OH)4- + OT- + OD- + [18O]H- + [18O]H- = FeOTOD[18O]H[18O]H- + 4OH- +Fe(OH)4- + OT- + OD- + [18O]D- + OH- = FeOTOD[18O]DOH- + 4OH- +Fe(OH)4- + OT- + [18O]H- + OH- + OH- = FeOT[18O]HOHOH- + 4OH- +Fe(OH)4- + OT- + [18O]H- + OH- + OD- = FeOT[18O]HOHOD- + 4OH- +Fe(OH)4- + OT- + [18O]H- + OH- + [18O]H- = FeOT[18O]HOH[18O]H- + 4OH- +Fe(OH)4- + OT- + [18O]H- + OH- + [18O]D- = FeOT[18O]HOH[18O]D- + 4OH- +Fe(OH)4- + OT- + [18O]H- + OD- + OH- = FeOT[18O]HODOH- + 4OH- +Fe(OH)4- + OT- + [18O]H- + OD- + OD- = FeOT[18O]HODOD- + 4OH- +Fe(OH)4- + OT- + [18O]H- + OD- + [18O]H- = FeOT[18O]HOD[18O]H- + 4OH- +Fe(OH)4- + OT- + [18O]H- + [18O]H- + OH- = FeOT[18O]H[18O]HOH- + 4OH- +Fe(OH)4- + OT- + [18O]H- + [18O]H- + OD- = FeOT[18O]H[18O]HOD- + 4OH- +Fe(OH)4- + OT- + [18O]H- + [18O]D- + OH- = FeOT[18O]H[18O]DOH- + 4OH- +Fe(OH)4- + OT- + [18O]D- + OH- + OH- = FeOT[18O]DOHOH- + 4OH- +Fe(OH)4- + OT- + [18O]D- + OH- + OD- = FeOT[18O]DOHOD- + 4OH- +Fe(OH)4- + OT- + [18O]D- + OH- + [18O]H- = FeOT[18O]DOH[18O]H- + 4OH- +Fe(OH)4- + OT- + [18O]D- + OD- + OH- = FeOT[18O]DODOH- + 4OH- +Fe(OH)4- + OT- + [18O]D- + [18O]H- + OH- = FeOT[18O]D[18O]HOH- + 4OH- +Fe(OH)4- + [18O]H- + OH- + OH- + OH- = Fe[18O]HOHOHOH- + 4OH- +Fe(OH)4- + [18O]H- + OH- + OH- + OD- = Fe[18O]HOHOHOD- + 4OH- +Fe(OH)4- + [18O]H- + OH- + OH- + OT- = Fe[18O]HOHOHOT- + 4OH- +Fe(OH)4- + [18O]H- + OH- + OH- + [18O]H- = Fe[18O]HOHOH[18O]H- + 4OH- +Fe(OH)4- + [18O]H- + OH- + OH- + [18O]D- = Fe[18O]HOHOH[18O]D- + 4OH- +Fe(OH)4- + [18O]H- + OH- + OH- + [18O]T- = Fe[18O]HOHOH[18O]T- + 4OH- +Fe(OH)4- + [18O]H- + OH- + OD- + OH- = Fe[18O]HOHODOH- + 4OH- +Fe(OH)4- + [18O]H- + OH- + OD- + OD- = Fe[18O]HOHODOD- + 4OH- +Fe(OH)4- + [18O]H- + OH- + OD- + OT- = Fe[18O]HOHODOT- + 4OH- +Fe(OH)4- + [18O]H- + OH- + OD- + [18O]H- = Fe[18O]HOHOD[18O]H- + 4OH- +Fe(OH)4- + [18O]H- + OH- + OD- + [18O]D- = Fe[18O]HOHOD[18O]D- + 4OH- +Fe(OH)4- + [18O]H- + OH- + OD- + [18O]T- = Fe[18O]HOHOD[18O]T- + 4OH- +Fe(OH)4- + [18O]H- + OH- + OT- + OH- = Fe[18O]HOHOTOH- + 4OH- +Fe(OH)4- + [18O]H- + OH- + OT- + OD- = Fe[18O]HOHOTOD- + 4OH- +Fe(OH)4- + [18O]H- + OH- + OT- + [18O]H- = Fe[18O]HOHOT[18O]H- + 4OH- +Fe(OH)4- + [18O]H- + OH- + OT- + [18O]D- = Fe[18O]HOHOT[18O]D- + 4OH- +Fe(OH)4- + [18O]H- + OH- + [18O]H- + OH- = Fe[18O]HOH[18O]HOH- + 4OH- +Fe(OH)4- + [18O]H- + OH- + [18O]H- + OD- = Fe[18O]HOH[18O]HOD- + 4OH- +Fe(OH)4- + [18O]H- + OH- + [18O]H- + OT- = Fe[18O]HOH[18O]HOT- + 4OH- +Fe(OH)4- + [18O]H- + OH- + [18O]D- + OH- = Fe[18O]HOH[18O]DOH- + 4OH- +Fe(OH)4- + [18O]H- + OH- + [18O]D- + OD- = Fe[18O]HOH[18O]DOD- + 4OH- +Fe(OH)4- + [18O]H- + OH- + [18O]D- + OT- = Fe[18O]HOH[18O]DOT- + 4OH- +Fe(OH)4- + [18O]H- + OH- + [18O]T- + OH- = Fe[18O]HOH[18O]TOH- + 4OH- +Fe(OH)4- + [18O]H- + OH- + [18O]T- + OD- = Fe[18O]HOH[18O]TOD- + 4OH- +Fe(OH)4- + [18O]H- + OD- + OH- + OH- = Fe[18O]HODOHOH- + 4OH- +Fe(OH)4- + [18O]H- + OD- + OH- + OD- = Fe[18O]HODOHOD- + 4OH- +Fe(OH)4- + [18O]H- + OD- + OH- + OT- = Fe[18O]HODOHOT- + 4OH- +Fe(OH)4- + [18O]H- + OD- + OH- + [18O]H- = Fe[18O]HODOH[18O]H- + 4OH- +Fe(OH)4- + [18O]H- + OD- + OH- + [18O]D- = Fe[18O]HODOH[18O]D- + 4OH- +Fe(OH)4- + [18O]H- + OD- + OH- + [18O]T- = Fe[18O]HODOH[18O]T- + 4OH- +Fe(OH)4- + [18O]H- + OD- + OD- + OH- = Fe[18O]HODODOH- + 4OH- +Fe(OH)4- + [18O]H- + OD- + OD- + OT- = Fe[18O]HODODOT- + 4OH- +Fe(OH)4- + [18O]H- + OD- + OD- + [18O]H- = Fe[18O]HODOD[18O]H- + 4OH- +Fe(OH)4- + [18O]H- + OD- + OT- + OH- = Fe[18O]HODOTOH- + 4OH- +Fe(OH)4- + [18O]H- + OD- + OT- + OD- = Fe[18O]HODOTOD- + 4OH- +Fe(OH)4- + [18O]H- + OD- + OT- + [18O]H- = Fe[18O]HODOT[18O]H- + 4OH- +Fe(OH)4- + [18O]H- + OD- + [18O]H- + OH- = Fe[18O]HOD[18O]HOH- + 4OH- +Fe(OH)4- + [18O]H- + OD- + [18O]H- + OD- = Fe[18O]HOD[18O]HOD- + 4OH- +Fe(OH)4- + [18O]H- + OD- + [18O]H- + OT- = Fe[18O]HOD[18O]HOT- + 4OH- +Fe(OH)4- + [18O]H- + OD- + [18O]D- + OH- = Fe[18O]HOD[18O]DOH- + 4OH- +Fe(OH)4- + [18O]H- + OD- + [18O]T- + OH- = Fe[18O]HOD[18O]TOH- + 4OH- +Fe(OH)4- + [18O]H- + OT- + OH- + OH- = Fe[18O]HOTOHOH- + 4OH- +Fe(OH)4- + [18O]H- + OT- + OH- + OD- = Fe[18O]HOTOHOD- + 4OH- +Fe(OH)4- + [18O]H- + OT- + OH- + [18O]H- = Fe[18O]HOTOH[18O]H- + 4OH- +Fe(OH)4- + [18O]H- + OT- + OH- + [18O]D- = Fe[18O]HOTOH[18O]D- + 4OH- +Fe(OH)4- + [18O]H- + OT- + OD- + OH- = Fe[18O]HOTODOH- + 4OH- +Fe(OH)4- + [18O]H- + OT- + OD- + OD- = Fe[18O]HOTODOD- + 4OH- +Fe(OH)4- + [18O]H- + OT- + OD- + [18O]H- = Fe[18O]HOTOD[18O]H- + 4OH- +Fe(OH)4- + [18O]H- + OT- + [18O]H- + OH- = Fe[18O]HOT[18O]HOH- + 4OH- +Fe(OH)4- + [18O]H- + OT- + [18O]H- + OD- = Fe[18O]HOT[18O]HOD- + 4OH- +Fe(OH)4- + [18O]H- + OT- + [18O]D- + OH- = Fe[18O]HOT[18O]DOH- + 4OH- +Fe(OH)4- + [18O]H- + [18O]H- + OH- + OH- = Fe[18O]H[18O]HOHOH- + 4OH- +Fe(OH)4- + [18O]H- + [18O]H- + OH- + OD- = Fe[18O]H[18O]HOHOD- + 4OH- +Fe(OH)4- + [18O]H- + [18O]H- + OH- + OT- = Fe[18O]H[18O]HOHOT- + 4OH- +Fe(OH)4- + [18O]H- + [18O]H- + OD- + OH- = Fe[18O]H[18O]HODOH- + 4OH- +Fe(OH)4- + [18O]H- + [18O]H- + OD- + OD- = Fe[18O]H[18O]HODOD- + 4OH- +Fe(OH)4- + [18O]H- + [18O]H- + OD- + OT- = Fe[18O]H[18O]HODOT- + 4OH- +Fe(OH)4- + [18O]H- + [18O]H- + OT- + OH- = Fe[18O]H[18O]HOTOH- + 4OH- +Fe(OH)4- + [18O]H- + [18O]H- + OT- + OD- = Fe[18O]H[18O]HOTOD- + 4OH- +Fe(OH)4- + [18O]H- + [18O]D- + OH- + OH- = Fe[18O]H[18O]DOHOH- + 4OH- +Fe(OH)4- + [18O]H- + [18O]D- + OH- + OD- = Fe[18O]H[18O]DOHOD- + 4OH- +Fe(OH)4- + [18O]H- + [18O]D- + OH- + OT- = Fe[18O]H[18O]DOHOT- + 4OH- +Fe(OH)4- + [18O]H- + [18O]D- + OD- + OH- = Fe[18O]H[18O]DODOH- + 4OH- +Fe(OH)4- + [18O]H- + [18O]D- + OT- + OH- = Fe[18O]H[18O]DOTOH- + 4OH- +Fe(OH)4- + [18O]H- + [18O]T- + OH- + OH- = Fe[18O]H[18O]TOHOH- + 4OH- +Fe(OH)4- + [18O]H- + [18O]T- + OH- + OD- = Fe[18O]H[18O]TOHOD- + 4OH- +Fe(OH)4- + [18O]H- + [18O]T- + OD- + OH- = Fe[18O]H[18O]TODOH- + 4OH- +Fe(OH)4- + [18O]D- + OH- + OH- + OH- = Fe[18O]DOHOHOH- + 4OH- +Fe(OH)4- + [18O]D- + OH- + OH- + OD- = Fe[18O]DOHOHOD- + 4OH- +Fe(OH)4- + [18O]D- + OH- + OH- + OT- = Fe[18O]DOHOHOT- + 4OH- +Fe(OH)4- + [18O]D- + OH- + OH- + [18O]H- = Fe[18O]DOHOH[18O]H- + 4OH- +Fe(OH)4- + [18O]D- + OH- + OH- + [18O]D- = Fe[18O]DOHOH[18O]D- + 4OH- +Fe(OH)4- + [18O]D- + OH- + OH- + [18O]T- = Fe[18O]DOHOH[18O]T- + 4OH- +Fe(OH)4- + [18O]D- + OH- + OD- + OH- = Fe[18O]DOHODOH- + 4OH- +Fe(OH)4- + [18O]D- + OH- + OD- + OT- = Fe[18O]DOHODOT- + 4OH- +Fe(OH)4- + [18O]D- + OH- + OD- + [18O]H- = Fe[18O]DOHOD[18O]H- + 4OH- +Fe(OH)4- + [18O]D- + OH- + OT- + OH- = Fe[18O]DOHOTOH- + 4OH- +Fe(OH)4- + [18O]D- + OH- + OT- + OD- = Fe[18O]DOHOTOD- + 4OH- +Fe(OH)4- + [18O]D- + OH- + OT- + [18O]H- = Fe[18O]DOHOT[18O]H- + 4OH- +Fe(OH)4- + [18O]D- + OH- + [18O]H- + OH- = Fe[18O]DOH[18O]HOH- + 4OH- +Fe(OH)4- + [18O]D- + OH- + [18O]H- + OD- = Fe[18O]DOH[18O]HOD- + 4OH- +Fe(OH)4- + [18O]D- + OH- + [18O]H- + OT- = Fe[18O]DOH[18O]HOT- + 4OH- +Fe(OH)4- + [18O]D- + OH- + [18O]D- + OH- = Fe[18O]DOH[18O]DOH- + 4OH- +Fe(OH)4- + [18O]D- + OH- + [18O]T- + OH- = Fe[18O]DOH[18O]TOH- + 4OH- +Fe(OH)4- + [18O]D- + OD- + OH- + OH- = Fe[18O]DODOHOH- + 4OH- +Fe(OH)4- + [18O]D- + OD- + OH- + OT- = Fe[18O]DODOHOT- + 4OH- +Fe(OH)4- + [18O]D- + OD- + OH- + [18O]H- = Fe[18O]DODOH[18O]H- + 4OH- +Fe(OH)4- + [18O]D- + OD- + OT- + OH- = Fe[18O]DODOTOH- + 4OH- +Fe(OH)4- + [18O]D- + OD- + [18O]H- + OH- = Fe[18O]DOD[18O]HOH- + 4OH- +Fe(OH)4- + [18O]D- + OT- + OH- + OH- = Fe[18O]DOTOHOH- + 4OH- +Fe(OH)4- + [18O]D- + OT- + OH- + OD- = Fe[18O]DOTOHOD- + 4OH- +Fe(OH)4- + [18O]D- + OT- + OH- + [18O]H- = Fe[18O]DOTOH[18O]H- + 4OH- +Fe(OH)4- + [18O]D- + OT- + OD- + OH- = Fe[18O]DOTODOH- + 4OH- +Fe(OH)4- + [18O]D- + OT- + [18O]H- + OH- = Fe[18O]DOT[18O]HOH- + 4OH- +Fe(OH)4- + [18O]D- + [18O]H- + OH- + OH- = Fe[18O]D[18O]HOHOH- + 4OH- +Fe(OH)4- + [18O]D- + [18O]H- + OH- + OD- = Fe[18O]D[18O]HOHOD- + 4OH- +Fe(OH)4- + [18O]D- + [18O]H- + OH- + OT- = Fe[18O]D[18O]HOHOT- + 4OH- +Fe(OH)4- + [18O]D- + [18O]H- + OD- + OH- = Fe[18O]D[18O]HODOH- + 4OH- +Fe(OH)4- + [18O]D- + [18O]H- + OT- + OH- = Fe[18O]D[18O]HOTOH- + 4OH- +Fe(OH)4- + [18O]D- + [18O]D- + OH- + OH- = Fe[18O]D[18O]DOHOH- + 4OH- +Fe(OH)4- + [18O]D- + [18O]T- + OH- + OH- = Fe[18O]D[18O]TOHOH- + 4OH- +Fe(OH)4- + [18O]T- + OH- + OH- + OH- = Fe[18O]TOHOHOH- + 4OH- +Fe(OH)4- + [18O]T- + OH- + OH- + OD- = Fe[18O]TOHOHOD- + 4OH- +Fe(OH)4- + [18O]T- + OH- + OH- + [18O]H- = Fe[18O]TOHOH[18O]H- + 4OH- +Fe(OH)4- + [18O]T- + OH- + OH- + [18O]D- = Fe[18O]TOHOH[18O]D- + 4OH- +Fe(OH)4- + [18O]T- + OH- + OD- + OH- = Fe[18O]TOHODOH- + 4OH- +Fe(OH)4- + [18O]T- + OH- + OD- + OD- = Fe[18O]TOHODOD- + 4OH- +Fe(OH)4- + [18O]T- + OH- + OD- + [18O]H- = Fe[18O]TOHOD[18O]H- + 4OH- +Fe(OH)4- + [18O]T- + OH- + [18O]H- + OH- = Fe[18O]TOH[18O]HOH- + 4OH- +Fe(OH)4- + [18O]T- + OH- + [18O]H- + OD- = Fe[18O]TOH[18O]HOD- + 4OH- +Fe(OH)4- + [18O]T- + OH- + [18O]D- + OH- = Fe[18O]TOH[18O]DOH- + 4OH- +Fe(OH)4- + [18O]T- + OD- + OH- + OH- = Fe[18O]TODOHOH- + 4OH- +Fe(OH)4- + [18O]T- + OD- + OH- + OD- = Fe[18O]TODOHOD- + 4OH- +Fe(OH)4- + [18O]T- + OD- + OH- + [18O]H- = Fe[18O]TODOH[18O]H- + 4OH- +Fe(OH)4- + [18O]T- + OD- + OD- + OH- = Fe[18O]TODODOH- + 4OH- +Fe(OH)4- + [18O]T- + OD- + [18O]H- + OH- = Fe[18O]TOD[18O]HOH- + 4OH- +Fe(OH)4- + [18O]T- + [18O]H- + OH- + OH- = Fe[18O]T[18O]HOHOH- + 4OH- +Fe(OH)4- + [18O]T- + [18O]H- + OH- + OD- = Fe[18O]T[18O]HOHOD- + 4OH- +Fe(OH)4- + [18O]T- + [18O]H- + OD- + OH- = Fe[18O]T[18O]HODOH- + 4OH- +Fe(OH)4- + [18O]T- + [18O]D- + OH- + OH- = Fe[18O]T[18O]DOHOH- + 4OH- +# +# Added Fe2(OH)2+4 reactions 16Dec09 +# Revised 17Dec09, limited the number of species +# +Fe2(OH)2+4 + OH- + OD- = Fe2OHOD+4 + 2OH- +Fe2(OH)2+4 + OH- + OT- = Fe2OHOT+4 + 2OH- +Fe2(OH)2+4 + OH- + [18O]H- = Fe2OH[18O]H+4 + 2OH- +Fe2(OH)2+4 + OH- + [18O]D- = Fe2OH[18O]D+4 + 2OH- +Fe2(OH)2+4 + OH- + [18O]T- = Fe2OH[18O]T+4 + 2OH- +Fe2(OH)2+4 + OD- + OH- = Fe2ODOH+4 + 2OH- +Fe2(OH)2+4 + OD- + OD- = Fe2ODOD+4 + 2OH- +Fe2(OH)2+4 + OD- + OT- = Fe2ODOT+4 + 2OH- +Fe2(OH)2+4 + OD- + [18O]H- = Fe2OD[18O]H+4 + 2OH- +Fe2(OH)2+4 + OD- + [18O]D- = Fe2OD[18O]D+4 + 2OH- +Fe2(OH)2+4 + OD- + [18O]T- = Fe2OD[18O]T+4 + 2OH- +Fe2(OH)2+4 + OT- + OH- = Fe2OTOH+4 + 2OH- +Fe2(OH)2+4 + OT- + OD- = Fe2OTOD+4 + 2OH- +Fe2(OH)2+4 + OT- + [18O]H- = Fe2OT[18O]H+4 + 2OH- +Fe2(OH)2+4 + OT- + [18O]D- = Fe2OT[18O]D+4 + 2OH- +Fe2(OH)2+4 + [18O]H- + OH- = Fe2[18O]HOH+4 + 2OH- +Fe2(OH)2+4 + [18O]H- + OD- = Fe2[18O]HOD+4 + 2OH- +Fe2(OH)2+4 + [18O]H- + OT- = Fe2[18O]HOT+4 + 2OH- +Fe2(OH)2+4 + [18O]H- + [18O]H- = Fe2[18O]H[18O]H+4 + 2OH- +Fe2(OH)2+4 + [18O]H- + [18O]D- = Fe2[18O]H[18O]D+4 + 2OH- +Fe2(OH)2+4 + [18O]H- + [18O]T- = Fe2[18O]H[18O]T+4 + 2OH- +Fe2(OH)2+4 + [18O]D- + OH- = Fe2[18O]DOH+4 + 2OH- +Fe2(OH)2+4 + [18O]D- + OD- = Fe2[18O]DOD+4 + 2OH- +Fe2(OH)2+4 + [18O]D- + OT- = Fe2[18O]DOT+4 + 2OH- +Fe2(OH)2+4 + [18O]D- + [18O]H- = Fe2[18O]D[18O]H+4 + 2OH- +Fe2(OH)2+4 + [18O]D- + [18O]D- = Fe2[18O]D[18O]D+4 + 2OH- +Fe2(OH)2+4 + [18O]D- + [18O]T- = Fe2[18O]D[18O]T+4 + 2OH- +Fe2(OH)2+4 + [18O]T- + OH- = Fe2[18O]TOH+4 + 2OH- +Fe2(OH)2+4 + [18O]T- + OD- = Fe2[18O]TOD+4 + 2OH- +Fe2(OH)2+4 + [18O]T- + [18O]H- = Fe2[18O]T[18O]H+4 + 2OH- +Fe2(OH)2+4 + [18O]T- + [18O]D- = Fe2[18O]T[18O]D+4 + 2OH- +# +# Added Fe3(OH)4+5 reactions 16Dec09 +# Revised 17Dec09, limited the number of species +# +Fe3(OH)4+5 + OH- + OH- + OH- + OD- = Fe3OHOHOHOD+5 + 4OH- +Fe3(OH)4+5 + OH- + OH- + OH- + OT- = Fe3OHOHOHOT+5 + 4OH- +Fe3(OH)4+5 + OH- + OH- + OH- + [18O]H- = Fe3OHOHOH[18O]H+5 + 4OH- +Fe3(OH)4+5 + OH- + OH- + OH- + [18O]D- = Fe3OHOHOH[18O]D+5 + 4OH- +Fe3(OH)4+5 + OH- + OH- + OH- + [18O]T- = Fe3OHOHOH[18O]T+5 + 4OH- +Fe3(OH)4+5 + OH- + OH- + OD- + OH- = Fe3OHOHODOH+5 + 4OH- +Fe3(OH)4+5 + OH- + OH- + OD- + OD- = Fe3OHOHODOD+5 + 4OH- +Fe3(OH)4+5 + OH- + OH- + OD- + OT- = Fe3OHOHODOT+5 + 4OH- +Fe3(OH)4+5 + OH- + OH- + OD- + [18O]H- = Fe3OHOHOD[18O]H+5 + 4OH- +Fe3(OH)4+5 + OH- + OH- + OD- + [18O]D- = Fe3OHOHOD[18O]D+5 + 4OH- +Fe3(OH)4+5 + OH- + OH- + OD- + [18O]T- = Fe3OHOHOD[18O]T+5 + 4OH- +Fe3(OH)4+5 + OH- + OH- + OT- + OH- = Fe3OHOHOTOH+5 + 4OH- +Fe3(OH)4+5 + OH- + OH- + OT- + OD- = Fe3OHOHOTOD+5 + 4OH- +Fe3(OH)4+5 + OH- + OH- + OT- + [18O]H- = Fe3OHOHOT[18O]H+5 + 4OH- +Fe3(OH)4+5 + OH- + OH- + OT- + [18O]D- = Fe3OHOHOT[18O]D+5 + 4OH- +Fe3(OH)4+5 + OH- + OH- + [18O]H- + OH- = Fe3OHOH[18O]HOH+5 + 4OH- +Fe3(OH)4+5 + OH- + OH- + [18O]H- + OD- = Fe3OHOH[18O]HOD+5 + 4OH- +Fe3(OH)4+5 + OH- + OH- + [18O]H- + OT- = Fe3OHOH[18O]HOT+5 + 4OH- +Fe3(OH)4+5 + OH- + OH- + [18O]H- + [18O]H- = Fe3OHOH[18O]H[18O]H+5 + 4OH- +Fe3(OH)4+5 + OH- + OH- + [18O]H- + [18O]D- = Fe3OHOH[18O]H[18O]D+5 + 4OH- +Fe3(OH)4+5 + OH- + OH- + [18O]H- + [18O]T- = Fe3OHOH[18O]H[18O]T+5 + 4OH- +Fe3(OH)4+5 + OH- + OH- + [18O]D- + OH- = Fe3OHOH[18O]DOH+5 + 4OH- +Fe3(OH)4+5 + OH- + OH- + [18O]D- + OD- = Fe3OHOH[18O]DOD+5 + 4OH- +Fe3(OH)4+5 + OH- + OH- + [18O]D- + OT- = Fe3OHOH[18O]DOT+5 + 4OH- +Fe3(OH)4+5 + OH- + OH- + [18O]D- + [18O]H- = Fe3OHOH[18O]D[18O]H+5 + 4OH- +Fe3(OH)4+5 + OH- + OH- + [18O]D- + [18O]D- = Fe3OHOH[18O]D[18O]D+5 + 4OH- +Fe3(OH)4+5 + OH- + OH- + [18O]D- + [18O]T- = Fe3OHOH[18O]D[18O]T+5 + 4OH- +Fe3(OH)4+5 + OH- + OH- + [18O]T- + OH- = Fe3OHOH[18O]TOH+5 + 4OH- +Fe3(OH)4+5 + OH- + OH- + [18O]T- + OD- = Fe3OHOH[18O]TOD+5 + 4OH- +Fe3(OH)4+5 + OH- + OH- + [18O]T- + [18O]H- = Fe3OHOH[18O]T[18O]H+5 + 4OH- +Fe3(OH)4+5 + OH- + OH- + [18O]T- + [18O]D- = Fe3OHOH[18O]T[18O]D+5 + 4OH- +Fe3(OH)4+5 + OH- + OD- + OH- + OH- = Fe3OHODOHOH+5 + 4OH- +Fe3(OH)4+5 + OH- + OD- + OH- + OD- = Fe3OHODOHOD+5 + 4OH- +Fe3(OH)4+5 + OH- + OD- + OH- + OT- = Fe3OHODOHOT+5 + 4OH- +Fe3(OH)4+5 + OH- + OD- + OH- + [18O]H- = Fe3OHODOH[18O]H+5 + 4OH- +Fe3(OH)4+5 + OH- + OD- + OH- + [18O]D- = Fe3OHODOH[18O]D+5 + 4OH- +Fe3(OH)4+5 + OH- + OD- + OH- + [18O]T- = Fe3OHODOH[18O]T+5 + 4OH- +Fe3(OH)4+5 + OH- + OD- + OD- + OH- = Fe3OHODODOH+5 + 4OH- +Fe3(OH)4+5 + OH- + OD- + OD- + OT- = Fe3OHODODOT+5 + 4OH- +Fe3(OH)4+5 + OH- + OD- + OD- + [18O]H- = Fe3OHODOD[18O]H+5 + 4OH- +Fe3(OH)4+5 + OH- + OD- + OD- + [18O]T- = Fe3OHODOD[18O]T+5 + 4OH- +Fe3(OH)4+5 + OH- + OD- + OT- + OH- = Fe3OHODOTOH+5 + 4OH- +Fe3(OH)4+5 + OH- + OD- + OT- + OD- = Fe3OHODOTOD+5 + 4OH- +Fe3(OH)4+5 + OH- + OD- + OT- + [18O]H- = Fe3OHODOT[18O]H+5 + 4OH- +Fe3(OH)4+5 + OH- + OD- + OT- + [18O]D- = Fe3OHODOT[18O]D+5 + 4OH- +Fe3(OH)4+5 + OH- + OD- + [18O]H- + OH- = Fe3OHOD[18O]HOH+5 + 4OH- +Fe3(OH)4+5 + OH- + OD- + [18O]H- + OD- = Fe3OHOD[18O]HOD+5 + 4OH- +Fe3(OH)4+5 + OH- + OD- + [18O]H- + OT- = Fe3OHOD[18O]HOT+5 + 4OH- +Fe3(OH)4+5 + OH- + OD- + [18O]H- + [18O]H- = Fe3OHOD[18O]H[18O]H+5 + 4OH- +Fe3(OH)4+5 + OH- + OD- + [18O]H- + [18O]D- = Fe3OHOD[18O]H[18O]D+5 + 4OH- +Fe3(OH)4+5 + OH- + OD- + [18O]H- + [18O]T- = Fe3OHOD[18O]H[18O]T+5 + 4OH- +Fe3(OH)4+5 + OH- + OD- + [18O]D- + OH- = Fe3OHOD[18O]DOH+5 + 4OH- +Fe3(OH)4+5 + OH- + OD- + [18O]D- + OT- = Fe3OHOD[18O]DOT+5 + 4OH- +Fe3(OH)4+5 + OH- + OD- + [18O]D- + [18O]H- = Fe3OHOD[18O]D[18O]H+5 + 4OH- +Fe3(OH)4+5 + OH- + OD- + [18O]T- + OH- = Fe3OHOD[18O]TOH+5 + 4OH- +Fe3(OH)4+5 + OH- + OD- + [18O]T- + OD- = Fe3OHOD[18O]TOD+5 + 4OH- +Fe3(OH)4+5 + OH- + OD- + [18O]T- + [18O]H- = Fe3OHOD[18O]T[18O]H+5 + 4OH- +Fe3(OH)4+5 + OH- + OT- + OH- + OH- = Fe3OHOTOHOH+5 + 4OH- +Fe3(OH)4+5 + OH- + OT- + OH- + OD- = Fe3OHOTOHOD+5 + 4OH- +Fe3(OH)4+5 + OH- + OT- + OH- + [18O]H- = Fe3OHOTOH[18O]H+5 + 4OH- +Fe3(OH)4+5 + OH- + OT- + OH- + [18O]D- = Fe3OHOTOH[18O]D+5 + 4OH- +Fe3(OH)4+5 + OH- + OT- + OD- + OH- = Fe3OHOTODOH+5 + 4OH- +Fe3(OH)4+5 + OH- + OT- + OD- + OD- = Fe3OHOTODOD+5 + 4OH- +Fe3(OH)4+5 + OH- + OT- + OD- + [18O]H- = Fe3OHOTOD[18O]H+5 + 4OH- +Fe3(OH)4+5 + OH- + OT- + OD- + [18O]D- = Fe3OHOTOD[18O]D+5 + 4OH- +Fe3(OH)4+5 + OH- + OT- + [18O]H- + OH- = Fe3OHOT[18O]HOH+5 + 4OH- +Fe3(OH)4+5 + OH- + OT- + [18O]H- + OD- = Fe3OHOT[18O]HOD+5 + 4OH- +Fe3(OH)4+5 + OH- + OT- + [18O]H- + [18O]H- = Fe3OHOT[18O]H[18O]H+5 + 4OH- +Fe3(OH)4+5 + OH- + OT- + [18O]H- + [18O]D- = Fe3OHOT[18O]H[18O]D+5 + 4OH- +Fe3(OH)4+5 + OH- + OT- + [18O]D- + OH- = Fe3OHOT[18O]DOH+5 + 4OH- +Fe3(OH)4+5 + OH- + OT- + [18O]D- + OD- = Fe3OHOT[18O]DOD+5 + 4OH- +Fe3(OH)4+5 + OH- + OT- + [18O]D- + [18O]H- = Fe3OHOT[18O]D[18O]H+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]H- + OH- + OH- = Fe3OH[18O]HOHOH+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]H- + OH- + OD- = Fe3OH[18O]HOHOD+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]H- + OH- + OT- = Fe3OH[18O]HOHOT+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]H- + OH- + [18O]H- = Fe3OH[18O]HOH[18O]H+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]H- + OH- + [18O]D- = Fe3OH[18O]HOH[18O]D+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]H- + OH- + [18O]T- = Fe3OH[18O]HOH[18O]T+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]H- + OD- + OH- = Fe3OH[18O]HODOH+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]H- + OD- + OD- = Fe3OH[18O]HODOD+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]H- + OD- + OT- = Fe3OH[18O]HODOT+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]H- + OD- + [18O]H- = Fe3OH[18O]HOD[18O]H+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]H- + OD- + [18O]D- = Fe3OH[18O]HOD[18O]D+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]H- + OD- + [18O]T- = Fe3OH[18O]HOD[18O]T+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]H- + OT- + OH- = Fe3OH[18O]HOTOH+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]H- + OT- + OD- = Fe3OH[18O]HOTOD+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]H- + OT- + [18O]H- = Fe3OH[18O]HOT[18O]H+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]H- + OT- + [18O]D- = Fe3OH[18O]HOT[18O]D+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]H- + [18O]H- + OH- = Fe3OH[18O]H[18O]HOH+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]H- + [18O]H- + OD- = Fe3OH[18O]H[18O]HOD+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]H- + [18O]H- + OT- = Fe3OH[18O]H[18O]HOT+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]H- + [18O]D- + OH- = Fe3OH[18O]H[18O]DOH+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]H- + [18O]D- + OD- = Fe3OH[18O]H[18O]DOD+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]H- + [18O]D- + OT- = Fe3OH[18O]H[18O]DOT+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]H- + [18O]T- + OH- = Fe3OH[18O]H[18O]TOH+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]H- + [18O]T- + OD- = Fe3OH[18O]H[18O]TOD+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]D- + OH- + OH- = Fe3OH[18O]DOHOH+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]D- + OH- + OD- = Fe3OH[18O]DOHOD+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]D- + OH- + OT- = Fe3OH[18O]DOHOT+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]D- + OH- + [18O]H- = Fe3OH[18O]DOH[18O]H+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]D- + OH- + [18O]D- = Fe3OH[18O]DOH[18O]D+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]D- + OH- + [18O]T- = Fe3OH[18O]DOH[18O]T+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]D- + OD- + OH- = Fe3OH[18O]DODOH+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]D- + OD- + OT- = Fe3OH[18O]DODOT+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]D- + OD- + [18O]H- = Fe3OH[18O]DOD[18O]H+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]D- + OT- + OH- = Fe3OH[18O]DOTOH+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]D- + OT- + OD- = Fe3OH[18O]DOTOD+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]D- + OT- + [18O]H- = Fe3OH[18O]DOT[18O]H+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]D- + [18O]H- + OH- = Fe3OH[18O]D[18O]HOH+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]D- + [18O]H- + OD- = Fe3OH[18O]D[18O]HOD+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]D- + [18O]H- + OT- = Fe3OH[18O]D[18O]HOT+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]D- + [18O]D- + OH- = Fe3OH[18O]D[18O]DOH+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]D- + [18O]T- + OH- = Fe3OH[18O]D[18O]TOH+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]T- + OH- + OH- = Fe3OH[18O]TOHOH+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]T- + OH- + OD- = Fe3OH[18O]TOHOD+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]T- + OH- + [18O]H- = Fe3OH[18O]TOH[18O]H+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]T- + OH- + [18O]D- = Fe3OH[18O]TOH[18O]D+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]T- + OD- + OH- = Fe3OH[18O]TODOH+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]T- + OD- + OD- = Fe3OH[18O]TODOD+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]T- + OD- + [18O]H- = Fe3OH[18O]TOD[18O]H+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]T- + [18O]H- + OH- = Fe3OH[18O]T[18O]HOH+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]T- + [18O]H- + OD- = Fe3OH[18O]T[18O]HOD+5 + 4OH- +Fe3(OH)4+5 + OH- + [18O]T- + [18O]D- + OH- = Fe3OH[18O]T[18O]DOH+5 + 4OH- +Fe3(OH)4+5 + OD- + OH- + OH- + OH- = Fe3ODOHOHOH+5 + 4OH- +Fe3(OH)4+5 + OD- + OH- + OH- + OD- = Fe3ODOHOHOD+5 + 4OH- +Fe3(OH)4+5 + OD- + OH- + OH- + OT- = Fe3ODOHOHOT+5 + 4OH- +Fe3(OH)4+5 + OD- + OH- + OH- + [18O]H- = Fe3ODOHOH[18O]H+5 + 4OH- +Fe3(OH)4+5 + OD- + OH- + OH- + [18O]D- = Fe3ODOHOH[18O]D+5 + 4OH- +Fe3(OH)4+5 + OD- + OH- + OH- + [18O]T- = Fe3ODOHOH[18O]T+5 + 4OH- +Fe3(OH)4+5 + OD- + OH- + OD- + OH- = Fe3ODOHODOH+5 + 4OH- +Fe3(OH)4+5 + OD- + OH- + OD- + OT- = Fe3ODOHODOT+5 + 4OH- +Fe3(OH)4+5 + OD- + OH- + OD- + [18O]H- = Fe3ODOHOD[18O]H+5 + 4OH- +Fe3(OH)4+5 + OD- + OH- + OD- + [18O]T- = Fe3ODOHOD[18O]T+5 + 4OH- +Fe3(OH)4+5 + OD- + OH- + OT- + OH- = Fe3ODOHOTOH+5 + 4OH- +Fe3(OH)4+5 + OD- + OH- + OT- + OD- = Fe3ODOHOTOD+5 + 4OH- +Fe3(OH)4+5 + OD- + OH- + OT- + [18O]H- = Fe3ODOHOT[18O]H+5 + 4OH- +Fe3(OH)4+5 + OD- + OH- + OT- + [18O]D- = Fe3ODOHOT[18O]D+5 + 4OH- +Fe3(OH)4+5 + OD- + OH- + [18O]H- + OH- = Fe3ODOH[18O]HOH+5 + 4OH- +Fe3(OH)4+5 + OD- + OH- + [18O]H- + OD- = Fe3ODOH[18O]HOD+5 + 4OH- +Fe3(OH)4+5 + OD- + OH- + [18O]H- + OT- = Fe3ODOH[18O]HOT+5 + 4OH- +Fe3(OH)4+5 + OD- + OH- + [18O]H- + [18O]H- = Fe3ODOH[18O]H[18O]H+5 + 4OH- +Fe3(OH)4+5 + OD- + OH- + [18O]H- + [18O]D- = Fe3ODOH[18O]H[18O]D+5 + 4OH- +Fe3(OH)4+5 + OD- + OH- + [18O]H- + [18O]T- = Fe3ODOH[18O]H[18O]T+5 + 4OH- +Fe3(OH)4+5 + OD- + OH- + [18O]D- + OH- = Fe3ODOH[18O]DOH+5 + 4OH- +Fe3(OH)4+5 + OD- + OH- + [18O]D- + OT- = Fe3ODOH[18O]DOT+5 + 4OH- +Fe3(OH)4+5 + OD- + OH- + [18O]D- + [18O]H- = Fe3ODOH[18O]D[18O]H+5 + 4OH- +Fe3(OH)4+5 + OD- + OH- + [18O]T- + OH- = Fe3ODOH[18O]TOH+5 + 4OH- +Fe3(OH)4+5 + OD- + OH- + [18O]T- + OD- = Fe3ODOH[18O]TOD+5 + 4OH- +Fe3(OH)4+5 + OD- + OH- + [18O]T- + [18O]H- = Fe3ODOH[18O]T[18O]H+5 + 4OH- +Fe3(OH)4+5 + OD- + OD- + OH- + OH- = Fe3ODODOHOH+5 + 4OH- +Fe3(OH)4+5 + OD- + OD- + OH- + OT- = Fe3ODODOHOT+5 + 4OH- +Fe3(OH)4+5 + OD- + OD- + OH- + [18O]H- = Fe3ODODOH[18O]H+5 + 4OH- +Fe3(OH)4+5 + OD- + OD- + OH- + [18O]T- = Fe3ODODOH[18O]T+5 + 4OH- +Fe3(OH)4+5 + OD- + OD- + OT- + OH- = Fe3ODODOTOH+5 + 4OH- +Fe3(OH)4+5 + OD- + OD- + OT- + [18O]H- = Fe3ODODOT[18O]H+5 + 4OH- +Fe3(OH)4+5 + OD- + OD- + [18O]H- + OH- = Fe3ODOD[18O]HOH+5 + 4OH- +Fe3(OH)4+5 + OD- + OD- + [18O]H- + OT- = Fe3ODOD[18O]HOT+5 + 4OH- +Fe3(OH)4+5 + OD- + OD- + [18O]H- + [18O]H- = Fe3ODOD[18O]H[18O]H+5 + 4OH- +Fe3(OH)4+5 + OD- + OD- + [18O]T- + OH- = Fe3ODOD[18O]TOH+5 + 4OH- +Fe3(OH)4+5 + OD- + OT- + OH- + OH- = Fe3ODOTOHOH+5 + 4OH- +Fe3(OH)4+5 + OD- + OT- + OH- + OD- = Fe3ODOTOHOD+5 + 4OH- +Fe3(OH)4+5 + OD- + OT- + OH- + [18O]H- = Fe3ODOTOH[18O]H+5 + 4OH- +Fe3(OH)4+5 + OD- + OT- + OH- + [18O]D- = Fe3ODOTOH[18O]D+5 + 4OH- +Fe3(OH)4+5 + OD- + OT- + OD- + OH- = Fe3ODOTODOH+5 + 4OH- +Fe3(OH)4+5 + OD- + OT- + OD- + [18O]H- = Fe3ODOTOD[18O]H+5 + 4OH- +Fe3(OH)4+5 + OD- + OT- + [18O]H- + OH- = Fe3ODOT[18O]HOH+5 + 4OH- +Fe3(OH)4+5 + OD- + OT- + [18O]H- + OD- = Fe3ODOT[18O]HOD+5 + 4OH- +Fe3(OH)4+5 + OD- + OT- + [18O]H- + [18O]H- = Fe3ODOT[18O]H[18O]H+5 + 4OH- +Fe3(OH)4+5 + OD- + OT- + [18O]D- + OH- = Fe3ODOT[18O]DOH+5 + 4OH- +Fe3(OH)4+5 + OD- + [18O]H- + OH- + OH- = Fe3OD[18O]HOHOH+5 + 4OH- +Fe3(OH)4+5 + OD- + [18O]H- + OH- + OD- = Fe3OD[18O]HOHOD+5 + 4OH- +Fe3(OH)4+5 + OD- + [18O]H- + OH- + OT- = Fe3OD[18O]HOHOT+5 + 4OH- +Fe3(OH)4+5 + OD- + [18O]H- + OH- + [18O]H- = Fe3OD[18O]HOH[18O]H+5 + 4OH- +Fe3(OH)4+5 + OD- + [18O]H- + OH- + [18O]D- = Fe3OD[18O]HOH[18O]D+5 + 4OH- +Fe3(OH)4+5 + OD- + [18O]H- + OH- + [18O]T- = Fe3OD[18O]HOH[18O]T+5 + 4OH- +Fe3(OH)4+5 + OD- + [18O]H- + OD- + OH- = Fe3OD[18O]HODOH+5 + 4OH- +Fe3(OH)4+5 + OD- + [18O]H- + OD- + OT- = Fe3OD[18O]HODOT+5 + 4OH- +Fe3(OH)4+5 + OD- + [18O]H- + OD- + [18O]H- = Fe3OD[18O]HOD[18O]H+5 + 4OH- +Fe3(OH)4+5 + OD- + [18O]H- + OT- + OH- = Fe3OD[18O]HOTOH+5 + 4OH- +Fe3(OH)4+5 + OD- + [18O]H- + OT- + OD- = Fe3OD[18O]HOTOD+5 + 4OH- +Fe3(OH)4+5 + OD- + [18O]H- + OT- + [18O]H- = Fe3OD[18O]HOT[18O]H+5 + 4OH- +Fe3(OH)4+5 + OD- + [18O]H- + [18O]H- + OH- = Fe3OD[18O]H[18O]HOH+5 + 4OH- +Fe3(OH)4+5 + OD- + [18O]H- + [18O]H- + OD- = Fe3OD[18O]H[18O]HOD+5 + 4OH- +Fe3(OH)4+5 + OD- + [18O]H- + [18O]H- + OT- = Fe3OD[18O]H[18O]HOT+5 + 4OH- +Fe3(OH)4+5 + OD- + [18O]H- + [18O]D- + OH- = Fe3OD[18O]H[18O]DOH+5 + 4OH- +Fe3(OH)4+5 + OD- + [18O]H- + [18O]T- + OH- = Fe3OD[18O]H[18O]TOH+5 + 4OH- +Fe3(OH)4+5 + OD- + [18O]D- + OH- + OH- = Fe3OD[18O]DOHOH+5 + 4OH- +Fe3(OH)4+5 + OD- + [18O]D- + OH- + OT- = Fe3OD[18O]DOHOT+5 + 4OH- +Fe3(OH)4+5 + OD- + [18O]D- + OH- + [18O]H- = Fe3OD[18O]DOH[18O]H+5 + 4OH- +Fe3(OH)4+5 + OD- + [18O]D- + OT- + OH- = Fe3OD[18O]DOTOH+5 + 4OH- +Fe3(OH)4+5 + OD- + [18O]D- + [18O]H- + OH- = Fe3OD[18O]D[18O]HOH+5 + 4OH- +Fe3(OH)4+5 + OD- + [18O]T- + OH- + OH- = Fe3OD[18O]TOHOH+5 + 4OH- +Fe3(OH)4+5 + OD- + [18O]T- + OH- + OD- = Fe3OD[18O]TOHOD+5 + 4OH- +Fe3(OH)4+5 + OD- + [18O]T- + OH- + [18O]H- = Fe3OD[18O]TOH[18O]H+5 + 4OH- +Fe3(OH)4+5 + OD- + [18O]T- + OD- + OH- = Fe3OD[18O]TODOH+5 + 4OH- +Fe3(OH)4+5 + OD- + [18O]T- + [18O]H- + OH- = Fe3OD[18O]T[18O]HOH+5 + 4OH- +Fe3(OH)4+5 + OT- + OH- + OH- + OH- = Fe3OTOHOHOH+5 + 4OH- +Fe3(OH)4+5 + OT- + OH- + OH- + OD- = Fe3OTOHOHOD+5 + 4OH- +Fe3(OH)4+5 + OT- + OH- + OH- + [18O]H- = Fe3OTOHOH[18O]H+5 + 4OH- +Fe3(OH)4+5 + OT- + OH- + OH- + [18O]D- = Fe3OTOHOH[18O]D+5 + 4OH- +Fe3(OH)4+5 + OT- + OH- + OD- + OH- = Fe3OTOHODOH+5 + 4OH- +Fe3(OH)4+5 + OT- + OH- + OD- + OD- = Fe3OTOHODOD+5 + 4OH- +Fe3(OH)4+5 + OT- + OH- + OD- + [18O]H- = Fe3OTOHOD[18O]H+5 + 4OH- +Fe3(OH)4+5 + OT- + OH- + OD- + [18O]D- = Fe3OTOHOD[18O]D+5 + 4OH- +Fe3(OH)4+5 + OT- + OH- + [18O]H- + OH- = Fe3OTOH[18O]HOH+5 + 4OH- +Fe3(OH)4+5 + OT- + OH- + [18O]H- + OD- = Fe3OTOH[18O]HOD+5 + 4OH- +Fe3(OH)4+5 + OT- + OH- + [18O]H- + [18O]H- = Fe3OTOH[18O]H[18O]H+5 + 4OH- +Fe3(OH)4+5 + OT- + OH- + [18O]H- + [18O]D- = Fe3OTOH[18O]H[18O]D+5 + 4OH- +Fe3(OH)4+5 + OT- + OH- + [18O]D- + OH- = Fe3OTOH[18O]DOH+5 + 4OH- +Fe3(OH)4+5 + OT- + OH- + [18O]D- + OD- = Fe3OTOH[18O]DOD+5 + 4OH- +Fe3(OH)4+5 + OT- + OH- + [18O]D- + [18O]H- = Fe3OTOH[18O]D[18O]H+5 + 4OH- +Fe3(OH)4+5 + OT- + OD- + OH- + OH- = Fe3OTODOHOH+5 + 4OH- +Fe3(OH)4+5 + OT- + OD- + OH- + OD- = Fe3OTODOHOD+5 + 4OH- +Fe3(OH)4+5 + OT- + OD- + OH- + [18O]H- = Fe3OTODOH[18O]H+5 + 4OH- +Fe3(OH)4+5 + OT- + OD- + OH- + [18O]D- = Fe3OTODOH[18O]D+5 + 4OH- +Fe3(OH)4+5 + OT- + OD- + OD- + OH- = Fe3OTODODOH+5 + 4OH- +Fe3(OH)4+5 + OT- + OD- + OD- + [18O]H- = Fe3OTODOD[18O]H+5 + 4OH- +Fe3(OH)4+5 + OT- + OD- + [18O]H- + OH- = Fe3OTOD[18O]HOH+5 + 4OH- +Fe3(OH)4+5 + OT- + OD- + [18O]H- + OD- = Fe3OTOD[18O]HOD+5 + 4OH- +Fe3(OH)4+5 + OT- + OD- + [18O]H- + [18O]H- = Fe3OTOD[18O]H[18O]H+5 + 4OH- +Fe3(OH)4+5 + OT- + OD- + [18O]D- + OH- = Fe3OTOD[18O]DOH+5 + 4OH- +Fe3(OH)4+5 + OT- + [18O]H- + OH- + OH- = Fe3OT[18O]HOHOH+5 + 4OH- +Fe3(OH)4+5 + OT- + [18O]H- + OH- + OD- = Fe3OT[18O]HOHOD+5 + 4OH- +Fe3(OH)4+5 + OT- + [18O]H- + OH- + [18O]H- = Fe3OT[18O]HOH[18O]H+5 + 4OH- +Fe3(OH)4+5 + OT- + [18O]H- + OH- + [18O]D- = Fe3OT[18O]HOH[18O]D+5 + 4OH- +Fe3(OH)4+5 + OT- + [18O]H- + OD- + OH- = Fe3OT[18O]HODOH+5 + 4OH- +Fe3(OH)4+5 + OT- + [18O]H- + OD- + OD- = Fe3OT[18O]HODOD+5 + 4OH- +Fe3(OH)4+5 + OT- + [18O]H- + OD- + [18O]H- = Fe3OT[18O]HOD[18O]H+5 + 4OH- +Fe3(OH)4+5 + OT- + [18O]H- + [18O]H- + OH- = Fe3OT[18O]H[18O]HOH+5 + 4OH- +Fe3(OH)4+5 + OT- + [18O]H- + [18O]H- + OD- = Fe3OT[18O]H[18O]HOD+5 + 4OH- +Fe3(OH)4+5 + OT- + [18O]H- + [18O]D- + OH- = Fe3OT[18O]H[18O]DOH+5 + 4OH- +Fe3(OH)4+5 + OT- + [18O]D- + OH- + OH- = Fe3OT[18O]DOHOH+5 + 4OH- +Fe3(OH)4+5 + OT- + [18O]D- + OH- + OD- = Fe3OT[18O]DOHOD+5 + 4OH- +Fe3(OH)4+5 + OT- + [18O]D- + OH- + [18O]H- = Fe3OT[18O]DOH[18O]H+5 + 4OH- +Fe3(OH)4+5 + OT- + [18O]D- + OD- + OH- = Fe3OT[18O]DODOH+5 + 4OH- +Fe3(OH)4+5 + OT- + [18O]D- + [18O]H- + OH- = Fe3OT[18O]D[18O]HOH+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OH- + OH- + OH- = Fe3[18O]HOHOHOH+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OH- + OH- + OD- = Fe3[18O]HOHOHOD+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OH- + OH- + OT- = Fe3[18O]HOHOHOT+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OH- + OH- + [18O]H- = Fe3[18O]HOHOH[18O]H+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OH- + OH- + [18O]D- = Fe3[18O]HOHOH[18O]D+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OH- + OH- + [18O]T- = Fe3[18O]HOHOH[18O]T+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OH- + OD- + OH- = Fe3[18O]HOHODOH+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OH- + OD- + OD- = Fe3[18O]HOHODOD+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OH- + OD- + OT- = Fe3[18O]HOHODOT+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OH- + OD- + [18O]H- = Fe3[18O]HOHOD[18O]H+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OH- + OD- + [18O]D- = Fe3[18O]HOHOD[18O]D+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OH- + OD- + [18O]T- = Fe3[18O]HOHOD[18O]T+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OH- + OT- + OH- = Fe3[18O]HOHOTOH+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OH- + OT- + OD- = Fe3[18O]HOHOTOD+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OH- + OT- + [18O]H- = Fe3[18O]HOHOT[18O]H+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OH- + OT- + [18O]D- = Fe3[18O]HOHOT[18O]D+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OH- + [18O]H- + OH- = Fe3[18O]HOH[18O]HOH+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OH- + [18O]H- + OD- = Fe3[18O]HOH[18O]HOD+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OH- + [18O]H- + OT- = Fe3[18O]HOH[18O]HOT+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OH- + [18O]D- + OH- = Fe3[18O]HOH[18O]DOH+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OH- + [18O]D- + OD- = Fe3[18O]HOH[18O]DOD+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OH- + [18O]D- + OT- = Fe3[18O]HOH[18O]DOT+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OH- + [18O]T- + OH- = Fe3[18O]HOH[18O]TOH+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OH- + [18O]T- + OD- = Fe3[18O]HOH[18O]TOD+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OD- + OH- + OH- = Fe3[18O]HODOHOH+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OD- + OH- + OD- = Fe3[18O]HODOHOD+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OD- + OH- + OT- = Fe3[18O]HODOHOT+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OD- + OH- + [18O]H- = Fe3[18O]HODOH[18O]H+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OD- + OH- + [18O]D- = Fe3[18O]HODOH[18O]D+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OD- + OH- + [18O]T- = Fe3[18O]HODOH[18O]T+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OD- + OD- + OH- = Fe3[18O]HODODOH+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OD- + OD- + OT- = Fe3[18O]HODODOT+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OD- + OD- + [18O]H- = Fe3[18O]HODOD[18O]H+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OD- + OT- + OH- = Fe3[18O]HODOTOH+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OD- + OT- + OD- = Fe3[18O]HODOTOD+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OD- + OT- + [18O]H- = Fe3[18O]HODOT[18O]H+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OD- + [18O]H- + OH- = Fe3[18O]HOD[18O]HOH+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OD- + [18O]H- + OD- = Fe3[18O]HOD[18O]HOD+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OD- + [18O]H- + OT- = Fe3[18O]HOD[18O]HOT+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OD- + [18O]D- + OH- = Fe3[18O]HOD[18O]DOH+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OD- + [18O]T- + OH- = Fe3[18O]HOD[18O]TOH+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OT- + OH- + OH- = Fe3[18O]HOTOHOH+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OT- + OH- + OD- = Fe3[18O]HOTOHOD+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OT- + OH- + [18O]H- = Fe3[18O]HOTOH[18O]H+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OT- + OH- + [18O]D- = Fe3[18O]HOTOH[18O]D+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OT- + OD- + OH- = Fe3[18O]HOTODOH+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OT- + OD- + OD- = Fe3[18O]HOTODOD+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OT- + OD- + [18O]H- = Fe3[18O]HOTOD[18O]H+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OT- + [18O]H- + OH- = Fe3[18O]HOT[18O]HOH+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OT- + [18O]H- + OD- = Fe3[18O]HOT[18O]HOD+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + OT- + [18O]D- + OH- = Fe3[18O]HOT[18O]DOH+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + [18O]H- + OH- + OH- = Fe3[18O]H[18O]HOHOH+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + [18O]H- + OH- + OD- = Fe3[18O]H[18O]HOHOD+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + [18O]H- + OH- + OT- = Fe3[18O]H[18O]HOHOT+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + [18O]H- + OD- + OH- = Fe3[18O]H[18O]HODOH+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + [18O]H- + OD- + OD- = Fe3[18O]H[18O]HODOD+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + [18O]H- + OD- + OT- = Fe3[18O]H[18O]HODOT+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + [18O]H- + OT- + OH- = Fe3[18O]H[18O]HOTOH+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + [18O]H- + OT- + OD- = Fe3[18O]H[18O]HOTOD+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + [18O]D- + OH- + OH- = Fe3[18O]H[18O]DOHOH+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + [18O]D- + OH- + OD- = Fe3[18O]H[18O]DOHOD+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + [18O]D- + OH- + OT- = Fe3[18O]H[18O]DOHOT+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + [18O]D- + OD- + OH- = Fe3[18O]H[18O]DODOH+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + [18O]D- + OT- + OH- = Fe3[18O]H[18O]DOTOH+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + [18O]T- + OH- + OH- = Fe3[18O]H[18O]TOHOH+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + [18O]T- + OH- + OD- = Fe3[18O]H[18O]TOHOD+5 + 4OH- +Fe3(OH)4+5 + [18O]H- + [18O]T- + OD- + OH- = Fe3[18O]H[18O]TODOH+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + OH- + OH- + OH- = Fe3[18O]DOHOHOH+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + OH- + OH- + OD- = Fe3[18O]DOHOHOD+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + OH- + OH- + OT- = Fe3[18O]DOHOHOT+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + OH- + OH- + [18O]H- = Fe3[18O]DOHOH[18O]H+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + OH- + OH- + [18O]D- = Fe3[18O]DOHOH[18O]D+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + OH- + OH- + [18O]T- = Fe3[18O]DOHOH[18O]T+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + OH- + OD- + OH- = Fe3[18O]DOHODOH+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + OH- + OD- + OT- = Fe3[18O]DOHODOT+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + OH- + OD- + [18O]H- = Fe3[18O]DOHOD[18O]H+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + OH- + OT- + OH- = Fe3[18O]DOHOTOH+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + OH- + OT- + OD- = Fe3[18O]DOHOTOD+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + OH- + OT- + [18O]H- = Fe3[18O]DOHOT[18O]H+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + OH- + [18O]H- + OH- = Fe3[18O]DOH[18O]HOH+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + OH- + [18O]H- + OD- = Fe3[18O]DOH[18O]HOD+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + OH- + [18O]H- + OT- = Fe3[18O]DOH[18O]HOT+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + OH- + [18O]D- + OH- = Fe3[18O]DOH[18O]DOH+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + OH- + [18O]T- + OH- = Fe3[18O]DOH[18O]TOH+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + OD- + OH- + OH- = Fe3[18O]DODOHOH+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + OD- + OH- + OT- = Fe3[18O]DODOHOT+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + OD- + OH- + [18O]H- = Fe3[18O]DODOH[18O]H+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + OD- + OT- + OH- = Fe3[18O]DODOTOH+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + OD- + [18O]H- + OH- = Fe3[18O]DOD[18O]HOH+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + OT- + OH- + OH- = Fe3[18O]DOTOHOH+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + OT- + OH- + OD- = Fe3[18O]DOTOHOD+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + OT- + OH- + [18O]H- = Fe3[18O]DOTOH[18O]H+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + OT- + OD- + OH- = Fe3[18O]DOTODOH+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + OT- + [18O]H- + OH- = Fe3[18O]DOT[18O]HOH+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + [18O]H- + OH- + OH- = Fe3[18O]D[18O]HOHOH+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + [18O]H- + OH- + OD- = Fe3[18O]D[18O]HOHOD+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + [18O]H- + OH- + OT- = Fe3[18O]D[18O]HOHOT+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + [18O]H- + OD- + OH- = Fe3[18O]D[18O]HODOH+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + [18O]H- + OT- + OH- = Fe3[18O]D[18O]HOTOH+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + [18O]D- + OH- + OH- = Fe3[18O]D[18O]DOHOH+5 + 4OH- +Fe3(OH)4+5 + [18O]D- + [18O]T- + OH- + OH- = Fe3[18O]D[18O]TOHOH+5 + 4OH- +Fe3(OH)4+5 + [18O]T- + OH- + OH- + OH- = Fe3[18O]TOHOHOH+5 + 4OH- +Fe3(OH)4+5 + [18O]T- + OH- + OH- + OD- = Fe3[18O]TOHOHOD+5 + 4OH- +Fe3(OH)4+5 + [18O]T- + OH- + OH- + [18O]H- = Fe3[18O]TOHOH[18O]H+5 + 4OH- +Fe3(OH)4+5 + [18O]T- + OH- + OH- + [18O]D- = Fe3[18O]TOHOH[18O]D+5 + 4OH- +Fe3(OH)4+5 + [18O]T- + OH- + OD- + OH- = Fe3[18O]TOHODOH+5 + 4OH- +Fe3(OH)4+5 + [18O]T- + OH- + OD- + OD- = Fe3[18O]TOHODOD+5 + 4OH- +Fe3(OH)4+5 + [18O]T- + OH- + OD- + [18O]H- = Fe3[18O]TOHOD[18O]H+5 + 4OH- +Fe3(OH)4+5 + [18O]T- + OH- + [18O]H- + OH- = Fe3[18O]TOH[18O]HOH+5 + 4OH- +Fe3(OH)4+5 + [18O]T- + OH- + [18O]H- + OD- = Fe3[18O]TOH[18O]HOD+5 + 4OH- +Fe3(OH)4+5 + [18O]T- + OH- + [18O]D- + OH- = Fe3[18O]TOH[18O]DOH+5 + 4OH- +Fe3(OH)4+5 + [18O]T- + OD- + OH- + OH- = Fe3[18O]TODOHOH+5 + 4OH- +Fe3(OH)4+5 + [18O]T- + OD- + OH- + OD- = Fe3[18O]TODOHOD+5 + 4OH- +Fe3(OH)4+5 + [18O]T- + OD- + OH- + [18O]H- = Fe3[18O]TODOH[18O]H+5 + 4OH- +Fe3(OH)4+5 + [18O]T- + OD- + OD- + OH- = Fe3[18O]TODODOH+5 + 4OH- +Fe3(OH)4+5 + [18O]T- + OD- + [18O]H- + OH- = Fe3[18O]TOD[18O]HOH+5 + 4OH- +Fe3(OH)4+5 + [18O]T- + [18O]H- + OH- + OH- = Fe3[18O]T[18O]HOHOH+5 + 4OH- +Fe3(OH)4+5 + [18O]T- + [18O]H- + OH- + OD- = Fe3[18O]T[18O]HOHOD+5 + 4OH- +Fe3(OH)4+5 + [18O]T- + [18O]H- + OD- + OH- = Fe3[18O]T[18O]HODOH+5 + 4OH- +Fe3(OH)4+5 + [18O]T- + [18O]D- + OH- + OH- = Fe3[18O]T[18O]DOHOH+5 + 4OH- +# +# Added FeSO4+ reactions 16Dec09 +# +FeSO4+ + [34S]O4-2 = Fe[34S]O4+ + SO4-2 +# +# Added FeHSO4+2 reactions 16Dec09 +# +FeHSO4+2 + DSO4- = FeDSO4+2 + HSO4- +FeHSO4+2 + TSO4- = FeTSO4+2 + HSO4- +FeHSO4+2 + H[34S]O4- = FeH[34S]O4+2 + HSO4- +FeHSO4+2 + D[34S]O4- = FeD[34S]O4+2 + HSO4- +FeHSO4+2 + T[34S]O4- = FeT[34S]O4+2 + HSO4- +# +# Added Fe(SO4)2- reactions 16Dec09 +# Revised 17Dec09 +# +Fe(SO4)2- + SO4-2 + [34S]O4-2 = FeSO4[34S]O4- + 2SO4-2 +Fe(SO4)2- + [34S]O4-2 + SO4-2 = Fe[34S]O4SO4- + 2SO4-2 +Fe(SO4)2- + [34S]O4-2 + [34S]O4-2 = Fe[34S]O4[34S]O4- + 2SO4-2 +# +# Missing FeHPO4+ reactions +# +# +# Missing FeH2PO4+2 reactions +# +# +# Added AlOH+2 reactions 16Dec09 +# +AlOH+2 + OD- = AlOD+2 + OH- +AlOH+2 + OT- = AlOT+2 + OH- +AlOH+2 + [18O]H- = Al[18O]H+2 + OH- +AlOH+2 + [18O]D- = Al[18O]D+2 + OH- +AlOH+2 + [18O]T- = Al[18O]T+2 + OH- +# +# Added Al(OH)2+ reactions 16Dec09 +# Revised 17Dec09, limited the number of species +# +Al(OH)2+ + OH- + OD- = AlOHOD+ + 2OH- +Al(OH)2+ + OH- + OT- = AlOHOT+ + 2OH- +Al(OH)2+ + OH- + [18O]H- = AlOH[18O]H+ + 2OH- +Al(OH)2+ + OH- + [18O]D- = AlOH[18O]D+ + 2OH- +Al(OH)2+ + OH- + [18O]T- = AlOH[18O]T+ + 2OH- +Al(OH)2+ + OD- + OH- = AlODOH+ + 2OH- +Al(OH)2+ + OD- + OD- = AlODOD+ + 2OH- +Al(OH)2+ + OD- + OT- = AlODOT+ + 2OH- +Al(OH)2+ + OD- + [18O]H- = AlOD[18O]H+ + 2OH- +Al(OH)2+ + OD- + [18O]D- = AlOD[18O]D+ + 2OH- +Al(OH)2+ + OD- + [18O]T- = AlOD[18O]T+ + 2OH- +Al(OH)2+ + OT- + OH- = AlOTOH+ + 2OH- +Al(OH)2+ + OT- + OD- = AlOTOD+ + 2OH- +Al(OH)2+ + OT- + [18O]H- = AlOT[18O]H+ + 2OH- +Al(OH)2+ + OT- + [18O]D- = AlOT[18O]D+ + 2OH- +Al(OH)2+ + [18O]H- + OH- = Al[18O]HOH+ + 2OH- +Al(OH)2+ + [18O]H- + OD- = Al[18O]HOD+ + 2OH- +Al(OH)2+ + [18O]H- + OT- = Al[18O]HOT+ + 2OH- +Al(OH)2+ + [18O]H- + [18O]H- = Al[18O]H[18O]H+ + 2OH- +Al(OH)2+ + [18O]H- + [18O]D- = Al[18O]H[18O]D+ + 2OH- +Al(OH)2+ + [18O]H- + [18O]T- = Al[18O]H[18O]T+ + 2OH- +Al(OH)2+ + [18O]D- + OH- = Al[18O]DOH+ + 2OH- +Al(OH)2+ + [18O]D- + OD- = Al[18O]DOD+ + 2OH- +Al(OH)2+ + [18O]D- + OT- = Al[18O]DOT+ + 2OH- +Al(OH)2+ + [18O]D- + [18O]H- = Al[18O]D[18O]H+ + 2OH- +Al(OH)2+ + [18O]D- + [18O]D- = Al[18O]D[18O]D+ + 2OH- +Al(OH)2+ + [18O]D- + [18O]T- = Al[18O]D[18O]T+ + 2OH- +Al(OH)2+ + [18O]T- + OH- = Al[18O]TOH+ + 2OH- +Al(OH)2+ + [18O]T- + OD- = Al[18O]TOD+ + 2OH- +Al(OH)2+ + [18O]T- + [18O]H- = Al[18O]T[18O]H+ + 2OH- +Al(OH)2+ + [18O]T- + [18O]D- = Al[18O]T[18O]D+ + 2OH- +# +# Added Al(OH)3 reactions 16Dec09 +# Revised 17Dec09, limited the number of species +# +Al(OH)3 + OH- + OH- + OD- = AlOHOHOD + 3OH- +Al(OH)3 + OH- + OH- + OT- = AlOHOHOT + 3OH- +Al(OH)3 + OH- + OH- + [18O]H- = AlOHOH[18O]H + 3OH- +Al(OH)3 + OH- + OH- + [18O]D- = AlOHOH[18O]D + 3OH- +Al(OH)3 + OH- + OH- + [18O]T- = AlOHOH[18O]T + 3OH- +Al(OH)3 + OH- + OD- + OH- = AlOHODOH + 3OH- +Al(OH)3 + OH- + OD- + OD- = AlOHODOD + 3OH- +Al(OH)3 + OH- + OD- + OT- = AlOHODOT + 3OH- +Al(OH)3 + OH- + OD- + [18O]H- = AlOHOD[18O]H + 3OH- +Al(OH)3 + OH- + OD- + [18O]D- = AlOHOD[18O]D + 3OH- +Al(OH)3 + OH- + OD- + [18O]T- = AlOHOD[18O]T + 3OH- +Al(OH)3 + OH- + OT- + OH- = AlOHOTOH + 3OH- +Al(OH)3 + OH- + OT- + OD- = AlOHOTOD + 3OH- +Al(OH)3 + OH- + OT- + [18O]H- = AlOHOT[18O]H + 3OH- +Al(OH)3 + OH- + OT- + [18O]D- = AlOHOT[18O]D + 3OH- +Al(OH)3 + OH- + [18O]H- + OH- = AlOH[18O]HOH + 3OH- +Al(OH)3 + OH- + [18O]H- + OD- = AlOH[18O]HOD + 3OH- +Al(OH)3 + OH- + [18O]H- + OT- = AlOH[18O]HOT + 3OH- +Al(OH)3 + OH- + [18O]H- + [18O]H- = AlOH[18O]H[18O]H + 3OH- +Al(OH)3 + OH- + [18O]H- + [18O]D- = AlOH[18O]H[18O]D + 3OH- +Al(OH)3 + OH- + [18O]H- + [18O]T- = AlOH[18O]H[18O]T + 3OH- +Al(OH)3 + OH- + [18O]D- + OH- = AlOH[18O]DOH + 3OH- +Al(OH)3 + OH- + [18O]D- + OD- = AlOH[18O]DOD + 3OH- +Al(OH)3 + OH- + [18O]D- + OT- = AlOH[18O]DOT + 3OH- +Al(OH)3 + OH- + [18O]D- + [18O]H- = AlOH[18O]D[18O]H + 3OH- +Al(OH)3 + OH- + [18O]D- + [18O]D- = AlOH[18O]D[18O]D + 3OH- +Al(OH)3 + OH- + [18O]D- + [18O]T- = AlOH[18O]D[18O]T + 3OH- +Al(OH)3 + OH- + [18O]T- + OH- = AlOH[18O]TOH + 3OH- +Al(OH)3 + OH- + [18O]T- + OD- = AlOH[18O]TOD + 3OH- +Al(OH)3 + OH- + [18O]T- + [18O]H- = AlOH[18O]T[18O]H + 3OH- +Al(OH)3 + OH- + [18O]T- + [18O]D- = AlOH[18O]T[18O]D + 3OH- +Al(OH)3 + OD- + OH- + OH- = AlODOHOH + 3OH- +Al(OH)3 + OD- + OH- + OD- = AlODOHOD + 3OH- +Al(OH)3 + OD- + OH- + OT- = AlODOHOT + 3OH- +Al(OH)3 + OD- + OH- + [18O]H- = AlODOH[18O]H + 3OH- +Al(OH)3 + OD- + OH- + [18O]D- = AlODOH[18O]D + 3OH- +Al(OH)3 + OD- + OH- + [18O]T- = AlODOH[18O]T + 3OH- +Al(OH)3 + OD- + OD- + OH- = AlODODOH + 3OH- +Al(OH)3 + OD- + OD- + OT- = AlODODOT + 3OH- +Al(OH)3 + OD- + OD- + [18O]H- = AlODOD[18O]H + 3OH- +Al(OH)3 + OD- + OD- + [18O]T- = AlODOD[18O]T + 3OH- +Al(OH)3 + OD- + OT- + OH- = AlODOTOH + 3OH- +Al(OH)3 + OD- + OT- + OD- = AlODOTOD + 3OH- +Al(OH)3 + OD- + OT- + [18O]H- = AlODOT[18O]H + 3OH- +Al(OH)3 + OD- + OT- + [18O]D- = AlODOT[18O]D + 3OH- +Al(OH)3 + OD- + [18O]H- + OH- = AlOD[18O]HOH + 3OH- +Al(OH)3 + OD- + [18O]H- + OD- = AlOD[18O]HOD + 3OH- +Al(OH)3 + OD- + [18O]H- + OT- = AlOD[18O]HOT + 3OH- +Al(OH)3 + OD- + [18O]H- + [18O]H- = AlOD[18O]H[18O]H + 3OH- +Al(OH)3 + OD- + [18O]H- + [18O]D- = AlOD[18O]H[18O]D + 3OH- +Al(OH)3 + OD- + [18O]H- + [18O]T- = AlOD[18O]H[18O]T + 3OH- +Al(OH)3 + OD- + [18O]D- + OH- = AlOD[18O]DOH + 3OH- +Al(OH)3 + OD- + [18O]D- + OT- = AlOD[18O]DOT + 3OH- +Al(OH)3 + OD- + [18O]D- + [18O]H- = AlOD[18O]D[18O]H + 3OH- +Al(OH)3 + OD- + [18O]T- + OH- = AlOD[18O]TOH + 3OH- +Al(OH)3 + OD- + [18O]T- + OD- = AlOD[18O]TOD + 3OH- +Al(OH)3 + OD- + [18O]T- + [18O]H- = AlOD[18O]T[18O]H + 3OH- +Al(OH)3 + OT- + OH- + OH- = AlOTOHOH + 3OH- +Al(OH)3 + OT- + OH- + OD- = AlOTOHOD + 3OH- +Al(OH)3 + OT- + OH- + [18O]H- = AlOTOH[18O]H + 3OH- +Al(OH)3 + OT- + OH- + [18O]D- = AlOTOH[18O]D + 3OH- +Al(OH)3 + OT- + OD- + OH- = AlOTODOH + 3OH- +Al(OH)3 + OT- + OD- + OD- = AlOTODOD + 3OH- +Al(OH)3 + OT- + OD- + [18O]H- = AlOTOD[18O]H + 3OH- +Al(OH)3 + OT- + OD- + [18O]D- = AlOTOD[18O]D + 3OH- +Al(OH)3 + OT- + [18O]H- + OH- = AlOT[18O]HOH + 3OH- +Al(OH)3 + OT- + [18O]H- + OD- = AlOT[18O]HOD + 3OH- +Al(OH)3 + OT- + [18O]H- + [18O]H- = AlOT[18O]H[18O]H + 3OH- +Al(OH)3 + OT- + [18O]H- + [18O]D- = AlOT[18O]H[18O]D + 3OH- +Al(OH)3 + OT- + [18O]D- + OH- = AlOT[18O]DOH + 3OH- +Al(OH)3 + OT- + [18O]D- + OD- = AlOT[18O]DOD + 3OH- +Al(OH)3 + OT- + [18O]D- + [18O]H- = AlOT[18O]D[18O]H + 3OH- +Al(OH)3 + [18O]H- + OH- + OH- = Al[18O]HOHOH + 3OH- +Al(OH)3 + [18O]H- + OH- + OD- = Al[18O]HOHOD + 3OH- +Al(OH)3 + [18O]H- + OH- + OT- = Al[18O]HOHOT + 3OH- +Al(OH)3 + [18O]H- + OH- + [18O]H- = Al[18O]HOH[18O]H + 3OH- +Al(OH)3 + [18O]H- + OH- + [18O]D- = Al[18O]HOH[18O]D + 3OH- +Al(OH)3 + [18O]H- + OH- + [18O]T- = Al[18O]HOH[18O]T + 3OH- +Al(OH)3 + [18O]H- + OD- + OH- = Al[18O]HODOH + 3OH- +Al(OH)3 + [18O]H- + OD- + OD- = Al[18O]HODOD + 3OH- +Al(OH)3 + [18O]H- + OD- + OT- = Al[18O]HODOT + 3OH- +Al(OH)3 + [18O]H- + OD- + [18O]H- = Al[18O]HOD[18O]H + 3OH- +Al(OH)3 + [18O]H- + OD- + [18O]D- = Al[18O]HOD[18O]D + 3OH- +Al(OH)3 + [18O]H- + OD- + [18O]T- = Al[18O]HOD[18O]T + 3OH- +Al(OH)3 + [18O]H- + OT- + OH- = Al[18O]HOTOH + 3OH- +Al(OH)3 + [18O]H- + OT- + OD- = Al[18O]HOTOD + 3OH- +Al(OH)3 + [18O]H- + OT- + [18O]H- = Al[18O]HOT[18O]H + 3OH- +Al(OH)3 + [18O]H- + OT- + [18O]D- = Al[18O]HOT[18O]D + 3OH- +Al(OH)3 + [18O]H- + [18O]H- + OH- = Al[18O]H[18O]HOH + 3OH- +Al(OH)3 + [18O]H- + [18O]H- + OD- = Al[18O]H[18O]HOD + 3OH- +Al(OH)3 + [18O]H- + [18O]H- + OT- = Al[18O]H[18O]HOT + 3OH- +Al(OH)3 + [18O]H- + [18O]D- + OH- = Al[18O]H[18O]DOH + 3OH- +Al(OH)3 + [18O]H- + [18O]D- + OD- = Al[18O]H[18O]DOD + 3OH- +Al(OH)3 + [18O]H- + [18O]D- + OT- = Al[18O]H[18O]DOT + 3OH- +Al(OH)3 + [18O]H- + [18O]T- + OH- = Al[18O]H[18O]TOH + 3OH- +Al(OH)3 + [18O]H- + [18O]T- + OD- = Al[18O]H[18O]TOD + 3OH- +Al(OH)3 + [18O]D- + OH- + OH- = Al[18O]DOHOH + 3OH- +Al(OH)3 + [18O]D- + OH- + OD- = Al[18O]DOHOD + 3OH- +Al(OH)3 + [18O]D- + OH- + OT- = Al[18O]DOHOT + 3OH- +Al(OH)3 + [18O]D- + OH- + [18O]H- = Al[18O]DOH[18O]H + 3OH- +Al(OH)3 + [18O]D- + OH- + [18O]D- = Al[18O]DOH[18O]D + 3OH- +Al(OH)3 + [18O]D- + OH- + [18O]T- = Al[18O]DOH[18O]T + 3OH- +Al(OH)3 + [18O]D- + OD- + OH- = Al[18O]DODOH + 3OH- +Al(OH)3 + [18O]D- + OD- + OT- = Al[18O]DODOT + 3OH- +Al(OH)3 + [18O]D- + OD- + [18O]H- = Al[18O]DOD[18O]H + 3OH- +Al(OH)3 + [18O]D- + OT- + OH- = Al[18O]DOTOH + 3OH- +Al(OH)3 + [18O]D- + OT- + OD- = Al[18O]DOTOD + 3OH- +Al(OH)3 + [18O]D- + OT- + [18O]H- = Al[18O]DOT[18O]H + 3OH- +Al(OH)3 + [18O]D- + [18O]H- + OH- = Al[18O]D[18O]HOH + 3OH- +Al(OH)3 + [18O]D- + [18O]H- + OD- = Al[18O]D[18O]HOD + 3OH- +Al(OH)3 + [18O]D- + [18O]H- + OT- = Al[18O]D[18O]HOT + 3OH- +Al(OH)3 + [18O]D- + [18O]D- + OH- = Al[18O]D[18O]DOH + 3OH- +Al(OH)3 + [18O]D- + [18O]T- + OH- = Al[18O]D[18O]TOH + 3OH- +Al(OH)3 + [18O]T- + OH- + OH- = Al[18O]TOHOH + 3OH- +Al(OH)3 + [18O]T- + OH- + OD- = Al[18O]TOHOD + 3OH- +Al(OH)3 + [18O]T- + OH- + [18O]H- = Al[18O]TOH[18O]H + 3OH- +Al(OH)3 + [18O]T- + OH- + [18O]D- = Al[18O]TOH[18O]D + 3OH- +Al(OH)3 + [18O]T- + OD- + OH- = Al[18O]TODOH + 3OH- +Al(OH)3 + [18O]T- + OD- + OD- = Al[18O]TODOD + 3OH- +Al(OH)3 + [18O]T- + OD- + [18O]H- = Al[18O]TOD[18O]H + 3OH- +Al(OH)3 + [18O]T- + [18O]H- + OH- = Al[18O]T[18O]HOH + 3OH- +Al(OH)3 + [18O]T- + [18O]H- + OD- = Al[18O]T[18O]HOD + 3OH- +Al(OH)3 + [18O]T- + [18O]D- + OH- = Al[18O]T[18O]DOH + 3OH- +# +# Added Al(OH)4- reactions 16Dec09 +# Revised 17Dec09, limited the number of species +# +Al(OH)4- + OH- + OH- + OH- + OD- = AlOHOHOHOD- + 4OH- +Al(OH)4- + OH- + OH- + OH- + OT- = AlOHOHOHOT- + 4OH- +Al(OH)4- + OH- + OH- + OH- + [18O]H- = AlOHOHOH[18O]H- + 4OH- +Al(OH)4- + OH- + OH- + OH- + [18O]D- = AlOHOHOH[18O]D- + 4OH- +Al(OH)4- + OH- + OH- + OH- + [18O]T- = AlOHOHOH[18O]T- + 4OH- +Al(OH)4- + OH- + OH- + OD- + OH- = AlOHOHODOH- + 4OH- +Al(OH)4- + OH- + OH- + OD- + OD- = AlOHOHODOD- + 4OH- +Al(OH)4- + OH- + OH- + OD- + OT- = AlOHOHODOT- + 4OH- +Al(OH)4- + OH- + OH- + OD- + [18O]H- = AlOHOHOD[18O]H- + 4OH- +Al(OH)4- + OH- + OH- + OD- + [18O]D- = AlOHOHOD[18O]D- + 4OH- +Al(OH)4- + OH- + OH- + OD- + [18O]T- = AlOHOHOD[18O]T- + 4OH- +Al(OH)4- + OH- + OH- + OT- + OH- = AlOHOHOTOH- + 4OH- +Al(OH)4- + OH- + OH- + OT- + OD- = AlOHOHOTOD- + 4OH- +Al(OH)4- + OH- + OH- + OT- + [18O]H- = AlOHOHOT[18O]H- + 4OH- +Al(OH)4- + OH- + OH- + OT- + [18O]D- = AlOHOHOT[18O]D- + 4OH- +Al(OH)4- + OH- + OH- + [18O]H- + OH- = AlOHOH[18O]HOH- + 4OH- +Al(OH)4- + OH- + OH- + [18O]H- + OD- = AlOHOH[18O]HOD- + 4OH- +Al(OH)4- + OH- + OH- + [18O]H- + OT- = AlOHOH[18O]HOT- + 4OH- +Al(OH)4- + OH- + OH- + [18O]H- + [18O]H- = AlOHOH[18O]H[18O]H- + 4OH- +Al(OH)4- + OH- + OH- + [18O]H- + [18O]D- = AlOHOH[18O]H[18O]D- + 4OH- +Al(OH)4- + OH- + OH- + [18O]H- + [18O]T- = AlOHOH[18O]H[18O]T- + 4OH- +Al(OH)4- + OH- + OH- + [18O]D- + OH- = AlOHOH[18O]DOH- + 4OH- +Al(OH)4- + OH- + OH- + [18O]D- + OD- = AlOHOH[18O]DOD- + 4OH- +Al(OH)4- + OH- + OH- + [18O]D- + OT- = AlOHOH[18O]DOT- + 4OH- +Al(OH)4- + OH- + OH- + [18O]D- + [18O]H- = AlOHOH[18O]D[18O]H- + 4OH- +Al(OH)4- + OH- + OH- + [18O]D- + [18O]D- = AlOHOH[18O]D[18O]D- + 4OH- +Al(OH)4- + OH- + OH- + [18O]D- + [18O]T- = AlOHOH[18O]D[18O]T- + 4OH- +Al(OH)4- + OH- + OH- + [18O]T- + OH- = AlOHOH[18O]TOH- + 4OH- +Al(OH)4- + OH- + OH- + [18O]T- + OD- = AlOHOH[18O]TOD- + 4OH- +Al(OH)4- + OH- + OH- + [18O]T- + [18O]H- = AlOHOH[18O]T[18O]H- + 4OH- +Al(OH)4- + OH- + OH- + [18O]T- + [18O]D- = AlOHOH[18O]T[18O]D- + 4OH- +Al(OH)4- + OH- + OD- + OH- + OH- = AlOHODOHOH- + 4OH- +Al(OH)4- + OH- + OD- + OH- + OD- = AlOHODOHOD- + 4OH- +Al(OH)4- + OH- + OD- + OH- + OT- = AlOHODOHOT- + 4OH- +Al(OH)4- + OH- + OD- + OH- + [18O]H- = AlOHODOH[18O]H- + 4OH- +Al(OH)4- + OH- + OD- + OH- + [18O]D- = AlOHODOH[18O]D- + 4OH- +Al(OH)4- + OH- + OD- + OH- + [18O]T- = AlOHODOH[18O]T- + 4OH- +Al(OH)4- + OH- + OD- + OD- + OH- = AlOHODODOH- + 4OH- +Al(OH)4- + OH- + OD- + OD- + OT- = AlOHODODOT- + 4OH- +Al(OH)4- + OH- + OD- + OD- + [18O]H- = AlOHODOD[18O]H- + 4OH- +Al(OH)4- + OH- + OD- + OD- + [18O]T- = AlOHODOD[18O]T- + 4OH- +Al(OH)4- + OH- + OD- + OT- + OH- = AlOHODOTOH- + 4OH- +Al(OH)4- + OH- + OD- + OT- + OD- = AlOHODOTOD- + 4OH- +Al(OH)4- + OH- + OD- + OT- + [18O]H- = AlOHODOT[18O]H- + 4OH- +Al(OH)4- + OH- + OD- + OT- + [18O]D- = AlOHODOT[18O]D- + 4OH- +Al(OH)4- + OH- + OD- + [18O]H- + OH- = AlOHOD[18O]HOH- + 4OH- +Al(OH)4- + OH- + OD- + [18O]H- + OD- = AlOHOD[18O]HOD- + 4OH- +Al(OH)4- + OH- + OD- + [18O]H- + OT- = AlOHOD[18O]HOT- + 4OH- +Al(OH)4- + OH- + OD- + [18O]H- + [18O]H- = AlOHOD[18O]H[18O]H- + 4OH- +Al(OH)4- + OH- + OD- + [18O]H- + [18O]D- = AlOHOD[18O]H[18O]D- + 4OH- +Al(OH)4- + OH- + OD- + [18O]H- + [18O]T- = AlOHOD[18O]H[18O]T- + 4OH- +Al(OH)4- + OH- + OD- + [18O]D- + OH- = AlOHOD[18O]DOH- + 4OH- +Al(OH)4- + OH- + OD- + [18O]D- + OT- = AlOHOD[18O]DOT- + 4OH- +Al(OH)4- + OH- + OD- + [18O]D- + [18O]H- = AlOHOD[18O]D[18O]H- + 4OH- +Al(OH)4- + OH- + OD- + [18O]T- + OH- = AlOHOD[18O]TOH- + 4OH- +Al(OH)4- + OH- + OD- + [18O]T- + OD- = AlOHOD[18O]TOD- + 4OH- +Al(OH)4- + OH- + OD- + [18O]T- + [18O]H- = AlOHOD[18O]T[18O]H- + 4OH- +Al(OH)4- + OH- + OT- + OH- + OH- = AlOHOTOHOH- + 4OH- +Al(OH)4- + OH- + OT- + OH- + OD- = AlOHOTOHOD- + 4OH- +Al(OH)4- + OH- + OT- + OH- + [18O]H- = AlOHOTOH[18O]H- + 4OH- +Al(OH)4- + OH- + OT- + OH- + [18O]D- = AlOHOTOH[18O]D- + 4OH- +Al(OH)4- + OH- + OT- + OD- + OH- = AlOHOTODOH- + 4OH- +Al(OH)4- + OH- + OT- + OD- + OD- = AlOHOTODOD- + 4OH- +Al(OH)4- + OH- + OT- + OD- + [18O]H- = AlOHOTOD[18O]H- + 4OH- +Al(OH)4- + OH- + OT- + OD- + [18O]D- = AlOHOTOD[18O]D- + 4OH- +Al(OH)4- + OH- + OT- + [18O]H- + OH- = AlOHOT[18O]HOH- + 4OH- +Al(OH)4- + OH- + OT- + [18O]H- + OD- = AlOHOT[18O]HOD- + 4OH- +Al(OH)4- + OH- + OT- + [18O]H- + [18O]H- = AlOHOT[18O]H[18O]H- + 4OH- +Al(OH)4- + OH- + OT- + [18O]H- + [18O]D- = AlOHOT[18O]H[18O]D- + 4OH- +Al(OH)4- + OH- + OT- + [18O]D- + OH- = AlOHOT[18O]DOH- + 4OH- +Al(OH)4- + OH- + OT- + [18O]D- + OD- = AlOHOT[18O]DOD- + 4OH- +Al(OH)4- + OH- + OT- + [18O]D- + [18O]H- = AlOHOT[18O]D[18O]H- + 4OH- +Al(OH)4- + OH- + [18O]H- + OH- + OH- = AlOH[18O]HOHOH- + 4OH- +Al(OH)4- + OH- + [18O]H- + OH- + OD- = AlOH[18O]HOHOD- + 4OH- +Al(OH)4- + OH- + [18O]H- + OH- + OT- = AlOH[18O]HOHOT- + 4OH- +Al(OH)4- + OH- + [18O]H- + OH- + [18O]H- = AlOH[18O]HOH[18O]H- + 4OH- +Al(OH)4- + OH- + [18O]H- + OH- + [18O]D- = AlOH[18O]HOH[18O]D- + 4OH- +Al(OH)4- + OH- + [18O]H- + OH- + [18O]T- = AlOH[18O]HOH[18O]T- + 4OH- +Al(OH)4- + OH- + [18O]H- + OD- + OH- = AlOH[18O]HODOH- + 4OH- +Al(OH)4- + OH- + [18O]H- + OD- + OD- = AlOH[18O]HODOD- + 4OH- +Al(OH)4- + OH- + [18O]H- + OD- + OT- = AlOH[18O]HODOT- + 4OH- +Al(OH)4- + OH- + [18O]H- + OD- + [18O]H- = AlOH[18O]HOD[18O]H- + 4OH- +Al(OH)4- + OH- + [18O]H- + OD- + [18O]D- = AlOH[18O]HOD[18O]D- + 4OH- +Al(OH)4- + OH- + [18O]H- + OD- + [18O]T- = AlOH[18O]HOD[18O]T- + 4OH- +Al(OH)4- + OH- + [18O]H- + OT- + OH- = AlOH[18O]HOTOH- + 4OH- +Al(OH)4- + OH- + [18O]H- + OT- + OD- = AlOH[18O]HOTOD- + 4OH- +Al(OH)4- + OH- + [18O]H- + OT- + [18O]H- = AlOH[18O]HOT[18O]H- + 4OH- +Al(OH)4- + OH- + [18O]H- + OT- + [18O]D- = AlOH[18O]HOT[18O]D- + 4OH- +Al(OH)4- + OH- + [18O]H- + [18O]H- + OH- = AlOH[18O]H[18O]HOH- + 4OH- +Al(OH)4- + OH- + [18O]H- + [18O]H- + OD- = AlOH[18O]H[18O]HOD- + 4OH- +Al(OH)4- + OH- + [18O]H- + [18O]H- + OT- = AlOH[18O]H[18O]HOT- + 4OH- +Al(OH)4- + OH- + [18O]H- + [18O]D- + OH- = AlOH[18O]H[18O]DOH- + 4OH- +Al(OH)4- + OH- + [18O]H- + [18O]D- + OD- = AlOH[18O]H[18O]DOD- + 4OH- +Al(OH)4- + OH- + [18O]H- + [18O]D- + OT- = AlOH[18O]H[18O]DOT- + 4OH- +Al(OH)4- + OH- + [18O]H- + [18O]T- + OH- = AlOH[18O]H[18O]TOH- + 4OH- +Al(OH)4- + OH- + [18O]H- + [18O]T- + OD- = AlOH[18O]H[18O]TOD- + 4OH- +Al(OH)4- + OH- + [18O]D- + OH- + OH- = AlOH[18O]DOHOH- + 4OH- +Al(OH)4- + OH- + [18O]D- + OH- + OD- = AlOH[18O]DOHOD- + 4OH- +Al(OH)4- + OH- + [18O]D- + OH- + OT- = AlOH[18O]DOHOT- + 4OH- +Al(OH)4- + OH- + [18O]D- + OH- + [18O]H- = AlOH[18O]DOH[18O]H- + 4OH- +Al(OH)4- + OH- + [18O]D- + OH- + [18O]D- = AlOH[18O]DOH[18O]D- + 4OH- +Al(OH)4- + OH- + [18O]D- + OH- + [18O]T- = AlOH[18O]DOH[18O]T- + 4OH- +Al(OH)4- + OH- + [18O]D- + OD- + OH- = AlOH[18O]DODOH- + 4OH- +Al(OH)4- + OH- + [18O]D- + OD- + OT- = AlOH[18O]DODOT- + 4OH- +Al(OH)4- + OH- + [18O]D- + OD- + [18O]H- = AlOH[18O]DOD[18O]H- + 4OH- +Al(OH)4- + OH- + [18O]D- + OT- + OH- = AlOH[18O]DOTOH- + 4OH- +Al(OH)4- + OH- + [18O]D- + OT- + OD- = AlOH[18O]DOTOD- + 4OH- +Al(OH)4- + OH- + [18O]D- + OT- + [18O]H- = AlOH[18O]DOT[18O]H- + 4OH- +Al(OH)4- + OH- + [18O]D- + [18O]H- + OH- = AlOH[18O]D[18O]HOH- + 4OH- +Al(OH)4- + OH- + [18O]D- + [18O]H- + OD- = AlOH[18O]D[18O]HOD- + 4OH- +Al(OH)4- + OH- + [18O]D- + [18O]H- + OT- = AlOH[18O]D[18O]HOT- + 4OH- +Al(OH)4- + OH- + [18O]D- + [18O]D- + OH- = AlOH[18O]D[18O]DOH- + 4OH- +Al(OH)4- + OH- + [18O]D- + [18O]T- + OH- = AlOH[18O]D[18O]TOH- + 4OH- +Al(OH)4- + OH- + [18O]T- + OH- + OH- = AlOH[18O]TOHOH- + 4OH- +Al(OH)4- + OH- + [18O]T- + OH- + OD- = AlOH[18O]TOHOD- + 4OH- +Al(OH)4- + OH- + [18O]T- + OH- + [18O]H- = AlOH[18O]TOH[18O]H- + 4OH- +Al(OH)4- + OH- + [18O]T- + OH- + [18O]D- = AlOH[18O]TOH[18O]D- + 4OH- +Al(OH)4- + OH- + [18O]T- + OD- + OH- = AlOH[18O]TODOH- + 4OH- +Al(OH)4- + OH- + [18O]T- + OD- + OD- = AlOH[18O]TODOD- + 4OH- +Al(OH)4- + OH- + [18O]T- + OD- + [18O]H- = AlOH[18O]TOD[18O]H- + 4OH- +Al(OH)4- + OH- + [18O]T- + [18O]H- + OH- = AlOH[18O]T[18O]HOH- + 4OH- +Al(OH)4- + OH- + [18O]T- + [18O]H- + OD- = AlOH[18O]T[18O]HOD- + 4OH- +Al(OH)4- + OH- + [18O]T- + [18O]D- + OH- = AlOH[18O]T[18O]DOH- + 4OH- +Al(OH)4- + OD- + OH- + OH- + OH- = AlODOHOHOH- + 4OH- +Al(OH)4- + OD- + OH- + OH- + OD- = AlODOHOHOD- + 4OH- +Al(OH)4- + OD- + OH- + OH- + OT- = AlODOHOHOT- + 4OH- +Al(OH)4- + OD- + OH- + OH- + [18O]H- = AlODOHOH[18O]H- + 4OH- +Al(OH)4- + OD- + OH- + OH- + [18O]D- = AlODOHOH[18O]D- + 4OH- +Al(OH)4- + OD- + OH- + OH- + [18O]T- = AlODOHOH[18O]T- + 4OH- +Al(OH)4- + OD- + OH- + OD- + OH- = AlODOHODOH- + 4OH- +Al(OH)4- + OD- + OH- + OD- + OT- = AlODOHODOT- + 4OH- +Al(OH)4- + OD- + OH- + OD- + [18O]H- = AlODOHOD[18O]H- + 4OH- +Al(OH)4- + OD- + OH- + OD- + [18O]T- = AlODOHOD[18O]T- + 4OH- +Al(OH)4- + OD- + OH- + OT- + OH- = AlODOHOTOH- + 4OH- +Al(OH)4- + OD- + OH- + OT- + OD- = AlODOHOTOD- + 4OH- +Al(OH)4- + OD- + OH- + OT- + [18O]H- = AlODOHOT[18O]H- + 4OH- +Al(OH)4- + OD- + OH- + OT- + [18O]D- = AlODOHOT[18O]D- + 4OH- +Al(OH)4- + OD- + OH- + [18O]H- + OH- = AlODOH[18O]HOH- + 4OH- +Al(OH)4- + OD- + OH- + [18O]H- + OD- = AlODOH[18O]HOD- + 4OH- +Al(OH)4- + OD- + OH- + [18O]H- + OT- = AlODOH[18O]HOT- + 4OH- +Al(OH)4- + OD- + OH- + [18O]H- + [18O]H- = AlODOH[18O]H[18O]H- + 4OH- +Al(OH)4- + OD- + OH- + [18O]H- + [18O]D- = AlODOH[18O]H[18O]D- + 4OH- +Al(OH)4- + OD- + OH- + [18O]H- + [18O]T- = AlODOH[18O]H[18O]T- + 4OH- +Al(OH)4- + OD- + OH- + [18O]D- + OH- = AlODOH[18O]DOH- + 4OH- +Al(OH)4- + OD- + OH- + [18O]D- + OT- = AlODOH[18O]DOT- + 4OH- +Al(OH)4- + OD- + OH- + [18O]D- + [18O]H- = AlODOH[18O]D[18O]H- + 4OH- +Al(OH)4- + OD- + OH- + [18O]T- + OH- = AlODOH[18O]TOH- + 4OH- +Al(OH)4- + OD- + OH- + [18O]T- + OD- = AlODOH[18O]TOD- + 4OH- +Al(OH)4- + OD- + OH- + [18O]T- + [18O]H- = AlODOH[18O]T[18O]H- + 4OH- +Al(OH)4- + OD- + OD- + OH- + OH- = AlODODOHOH- + 4OH- +Al(OH)4- + OD- + OD- + OH- + OT- = AlODODOHOT- + 4OH- +Al(OH)4- + OD- + OD- + OH- + [18O]H- = AlODODOH[18O]H- + 4OH- +Al(OH)4- + OD- + OD- + OH- + [18O]T- = AlODODOH[18O]T- + 4OH- +Al(OH)4- + OD- + OD- + OT- + OH- = AlODODOTOH- + 4OH- +Al(OH)4- + OD- + OD- + OT- + [18O]H- = AlODODOT[18O]H- + 4OH- +Al(OH)4- + OD- + OD- + [18O]H- + OH- = AlODOD[18O]HOH- + 4OH- +Al(OH)4- + OD- + OD- + [18O]H- + OT- = AlODOD[18O]HOT- + 4OH- +Al(OH)4- + OD- + OD- + [18O]H- + [18O]H- = AlODOD[18O]H[18O]H- + 4OH- +Al(OH)4- + OD- + OD- + [18O]T- + OH- = AlODOD[18O]TOH- + 4OH- +Al(OH)4- + OD- + OT- + OH- + OH- = AlODOTOHOH- + 4OH- +Al(OH)4- + OD- + OT- + OH- + OD- = AlODOTOHOD- + 4OH- +Al(OH)4- + OD- + OT- + OH- + [18O]H- = AlODOTOH[18O]H- + 4OH- +Al(OH)4- + OD- + OT- + OH- + [18O]D- = AlODOTOH[18O]D- + 4OH- +Al(OH)4- + OD- + OT- + OD- + OH- = AlODOTODOH- + 4OH- +Al(OH)4- + OD- + OT- + OD- + [18O]H- = AlODOTOD[18O]H- + 4OH- +Al(OH)4- + OD- + OT- + [18O]H- + OH- = AlODOT[18O]HOH- + 4OH- +Al(OH)4- + OD- + OT- + [18O]H- + OD- = AlODOT[18O]HOD- + 4OH- +Al(OH)4- + OD- + OT- + [18O]H- + [18O]H- = AlODOT[18O]H[18O]H- + 4OH- +Al(OH)4- + OD- + OT- + [18O]D- + OH- = AlODOT[18O]DOH- + 4OH- +Al(OH)4- + OD- + [18O]H- + OH- + OH- = AlOD[18O]HOHOH- + 4OH- +Al(OH)4- + OD- + [18O]H- + OH- + OD- = AlOD[18O]HOHOD- + 4OH- +Al(OH)4- + OD- + [18O]H- + OH- + OT- = AlOD[18O]HOHOT- + 4OH- +Al(OH)4- + OD- + [18O]H- + OH- + [18O]H- = AlOD[18O]HOH[18O]H- + 4OH- +Al(OH)4- + OD- + [18O]H- + OH- + [18O]D- = AlOD[18O]HOH[18O]D- + 4OH- +Al(OH)4- + OD- + [18O]H- + OH- + [18O]T- = AlOD[18O]HOH[18O]T- + 4OH- +Al(OH)4- + OD- + [18O]H- + OD- + OH- = AlOD[18O]HODOH- + 4OH- +Al(OH)4- + OD- + [18O]H- + OD- + OT- = AlOD[18O]HODOT- + 4OH- +Al(OH)4- + OD- + [18O]H- + OD- + [18O]H- = AlOD[18O]HOD[18O]H- + 4OH- +Al(OH)4- + OD- + [18O]H- + OT- + OH- = AlOD[18O]HOTOH- + 4OH- +Al(OH)4- + OD- + [18O]H- + OT- + OD- = AlOD[18O]HOTOD- + 4OH- +Al(OH)4- + OD- + [18O]H- + OT- + [18O]H- = AlOD[18O]HOT[18O]H- + 4OH- +Al(OH)4- + OD- + [18O]H- + [18O]H- + OH- = AlOD[18O]H[18O]HOH- + 4OH- +Al(OH)4- + OD- + [18O]H- + [18O]H- + OD- = AlOD[18O]H[18O]HOD- + 4OH- +Al(OH)4- + OD- + [18O]H- + [18O]H- + OT- = AlOD[18O]H[18O]HOT- + 4OH- +Al(OH)4- + OD- + [18O]H- + [18O]D- + OH- = AlOD[18O]H[18O]DOH- + 4OH- +Al(OH)4- + OD- + [18O]H- + [18O]T- + OH- = AlOD[18O]H[18O]TOH- + 4OH- +Al(OH)4- + OD- + [18O]D- + OH- + OH- = AlOD[18O]DOHOH- + 4OH- +Al(OH)4- + OD- + [18O]D- + OH- + OT- = AlOD[18O]DOHOT- + 4OH- +Al(OH)4- + OD- + [18O]D- + OH- + [18O]H- = AlOD[18O]DOH[18O]H- + 4OH- +Al(OH)4- + OD- + [18O]D- + OT- + OH- = AlOD[18O]DOTOH- + 4OH- +Al(OH)4- + OD- + [18O]D- + [18O]H- + OH- = AlOD[18O]D[18O]HOH- + 4OH- +Al(OH)4- + OD- + [18O]T- + OH- + OH- = AlOD[18O]TOHOH- + 4OH- +Al(OH)4- + OD- + [18O]T- + OH- + OD- = AlOD[18O]TOHOD- + 4OH- +Al(OH)4- + OD- + [18O]T- + OH- + [18O]H- = AlOD[18O]TOH[18O]H- + 4OH- +Al(OH)4- + OD- + [18O]T- + OD- + OH- = AlOD[18O]TODOH- + 4OH- +Al(OH)4- + OD- + [18O]T- + [18O]H- + OH- = AlOD[18O]T[18O]HOH- + 4OH- +Al(OH)4- + OT- + OH- + OH- + OH- = AlOTOHOHOH- + 4OH- +Al(OH)4- + OT- + OH- + OH- + OD- = AlOTOHOHOD- + 4OH- +Al(OH)4- + OT- + OH- + OH- + [18O]H- = AlOTOHOH[18O]H- + 4OH- +Al(OH)4- + OT- + OH- + OH- + [18O]D- = AlOTOHOH[18O]D- + 4OH- +Al(OH)4- + OT- + OH- + OD- + OH- = AlOTOHODOH- + 4OH- +Al(OH)4- + OT- + OH- + OD- + OD- = AlOTOHODOD- + 4OH- +Al(OH)4- + OT- + OH- + OD- + [18O]H- = AlOTOHOD[18O]H- + 4OH- +Al(OH)4- + OT- + OH- + OD- + [18O]D- = AlOTOHOD[18O]D- + 4OH- +Al(OH)4- + OT- + OH- + [18O]H- + OH- = AlOTOH[18O]HOH- + 4OH- +Al(OH)4- + OT- + OH- + [18O]H- + OD- = AlOTOH[18O]HOD- + 4OH- +Al(OH)4- + OT- + OH- + [18O]H- + [18O]H- = AlOTOH[18O]H[18O]H- + 4OH- +Al(OH)4- + OT- + OH- + [18O]H- + [18O]D- = AlOTOH[18O]H[18O]D- + 4OH- +Al(OH)4- + OT- + OH- + [18O]D- + OH- = AlOTOH[18O]DOH- + 4OH- +Al(OH)4- + OT- + OH- + [18O]D- + OD- = AlOTOH[18O]DOD- + 4OH- +Al(OH)4- + OT- + OH- + [18O]D- + [18O]H- = AlOTOH[18O]D[18O]H- + 4OH- +Al(OH)4- + OT- + OD- + OH- + OH- = AlOTODOHOH- + 4OH- +Al(OH)4- + OT- + OD- + OH- + OD- = AlOTODOHOD- + 4OH- +Al(OH)4- + OT- + OD- + OH- + [18O]H- = AlOTODOH[18O]H- + 4OH- +Al(OH)4- + OT- + OD- + OH- + [18O]D- = AlOTODOH[18O]D- + 4OH- +Al(OH)4- + OT- + OD- + OD- + OH- = AlOTODODOH- + 4OH- +Al(OH)4- + OT- + OD- + OD- + [18O]H- = AlOTODOD[18O]H- + 4OH- +Al(OH)4- + OT- + OD- + [18O]H- + OH- = AlOTOD[18O]HOH- + 4OH- +Al(OH)4- + OT- + OD- + [18O]H- + OD- = AlOTOD[18O]HOD- + 4OH- +Al(OH)4- + OT- + OD- + [18O]H- + [18O]H- = AlOTOD[18O]H[18O]H- + 4OH- +Al(OH)4- + OT- + OD- + [18O]D- + OH- = AlOTOD[18O]DOH- + 4OH- +Al(OH)4- + OT- + [18O]H- + OH- + OH- = AlOT[18O]HOHOH- + 4OH- +Al(OH)4- + OT- + [18O]H- + OH- + OD- = AlOT[18O]HOHOD- + 4OH- +Al(OH)4- + OT- + [18O]H- + OH- + [18O]H- = AlOT[18O]HOH[18O]H- + 4OH- +Al(OH)4- + OT- + [18O]H- + OH- + [18O]D- = AlOT[18O]HOH[18O]D- + 4OH- +Al(OH)4- + OT- + [18O]H- + OD- + OH- = AlOT[18O]HODOH- + 4OH- +Al(OH)4- + OT- + [18O]H- + OD- + OD- = AlOT[18O]HODOD- + 4OH- +Al(OH)4- + OT- + [18O]H- + OD- + [18O]H- = AlOT[18O]HOD[18O]H- + 4OH- +Al(OH)4- + OT- + [18O]H- + [18O]H- + OH- = AlOT[18O]H[18O]HOH- + 4OH- +Al(OH)4- + OT- + [18O]H- + [18O]H- + OD- = AlOT[18O]H[18O]HOD- + 4OH- +Al(OH)4- + OT- + [18O]H- + [18O]D- + OH- = AlOT[18O]H[18O]DOH- + 4OH- +Al(OH)4- + OT- + [18O]D- + OH- + OH- = AlOT[18O]DOHOH- + 4OH- +Al(OH)4- + OT- + [18O]D- + OH- + OD- = AlOT[18O]DOHOD- + 4OH- +Al(OH)4- + OT- + [18O]D- + OH- + [18O]H- = AlOT[18O]DOH[18O]H- + 4OH- +Al(OH)4- + OT- + [18O]D- + OD- + OH- = AlOT[18O]DODOH- + 4OH- +Al(OH)4- + OT- + [18O]D- + [18O]H- + OH- = AlOT[18O]D[18O]HOH- + 4OH- +Al(OH)4- + [18O]H- + OH- + OH- + OH- = Al[18O]HOHOHOH- + 4OH- +Al(OH)4- + [18O]H- + OH- + OH- + OD- = Al[18O]HOHOHOD- + 4OH- +Al(OH)4- + [18O]H- + OH- + OH- + OT- = Al[18O]HOHOHOT- + 4OH- +Al(OH)4- + [18O]H- + OH- + OH- + [18O]H- = Al[18O]HOHOH[18O]H- + 4OH- +Al(OH)4- + [18O]H- + OH- + OH- + [18O]D- = Al[18O]HOHOH[18O]D- + 4OH- +Al(OH)4- + [18O]H- + OH- + OH- + [18O]T- = Al[18O]HOHOH[18O]T- + 4OH- +Al(OH)4- + [18O]H- + OH- + OD- + OH- = Al[18O]HOHODOH- + 4OH- +Al(OH)4- + [18O]H- + OH- + OD- + OD- = Al[18O]HOHODOD- + 4OH- +Al(OH)4- + [18O]H- + OH- + OD- + OT- = Al[18O]HOHODOT- + 4OH- +Al(OH)4- + [18O]H- + OH- + OD- + [18O]H- = Al[18O]HOHOD[18O]H- + 4OH- +Al(OH)4- + [18O]H- + OH- + OD- + [18O]D- = Al[18O]HOHOD[18O]D- + 4OH- +Al(OH)4- + [18O]H- + OH- + OD- + [18O]T- = Al[18O]HOHOD[18O]T- + 4OH- +Al(OH)4- + [18O]H- + OH- + OT- + OH- = Al[18O]HOHOTOH- + 4OH- +Al(OH)4- + [18O]H- + OH- + OT- + OD- = Al[18O]HOHOTOD- + 4OH- +Al(OH)4- + [18O]H- + OH- + OT- + [18O]H- = Al[18O]HOHOT[18O]H- + 4OH- +Al(OH)4- + [18O]H- + OH- + OT- + [18O]D- = Al[18O]HOHOT[18O]D- + 4OH- +Al(OH)4- + [18O]H- + OH- + [18O]H- + OH- = Al[18O]HOH[18O]HOH- + 4OH- +Al(OH)4- + [18O]H- + OH- + [18O]H- + OD- = Al[18O]HOH[18O]HOD- + 4OH- +Al(OH)4- + [18O]H- + OH- + [18O]H- + OT- = Al[18O]HOH[18O]HOT- + 4OH- +Al(OH)4- + [18O]H- + OH- + [18O]D- + OH- = Al[18O]HOH[18O]DOH- + 4OH- +Al(OH)4- + [18O]H- + OH- + [18O]D- + OD- = Al[18O]HOH[18O]DOD- + 4OH- +Al(OH)4- + [18O]H- + OH- + [18O]D- + OT- = Al[18O]HOH[18O]DOT- + 4OH- +Al(OH)4- + [18O]H- + OH- + [18O]T- + OH- = Al[18O]HOH[18O]TOH- + 4OH- +Al(OH)4- + [18O]H- + OH- + [18O]T- + OD- = Al[18O]HOH[18O]TOD- + 4OH- +Al(OH)4- + [18O]H- + OD- + OH- + OH- = Al[18O]HODOHOH- + 4OH- +Al(OH)4- + [18O]H- + OD- + OH- + OD- = Al[18O]HODOHOD- + 4OH- +Al(OH)4- + [18O]H- + OD- + OH- + OT- = Al[18O]HODOHOT- + 4OH- +Al(OH)4- + [18O]H- + OD- + OH- + [18O]H- = Al[18O]HODOH[18O]H- + 4OH- +Al(OH)4- + [18O]H- + OD- + OH- + [18O]D- = Al[18O]HODOH[18O]D- + 4OH- +Al(OH)4- + [18O]H- + OD- + OH- + [18O]T- = Al[18O]HODOH[18O]T- + 4OH- +Al(OH)4- + [18O]H- + OD- + OD- + OH- = Al[18O]HODODOH- + 4OH- +Al(OH)4- + [18O]H- + OD- + OD- + OT- = Al[18O]HODODOT- + 4OH- +Al(OH)4- + [18O]H- + OD- + OD- + [18O]H- = Al[18O]HODOD[18O]H- + 4OH- +Al(OH)4- + [18O]H- + OD- + OT- + OH- = Al[18O]HODOTOH- + 4OH- +Al(OH)4- + [18O]H- + OD- + OT- + OD- = Al[18O]HODOTOD- + 4OH- +Al(OH)4- + [18O]H- + OD- + OT- + [18O]H- = Al[18O]HODOT[18O]H- + 4OH- +Al(OH)4- + [18O]H- + OD- + [18O]H- + OH- = Al[18O]HOD[18O]HOH- + 4OH- +Al(OH)4- + [18O]H- + OD- + [18O]H- + OD- = Al[18O]HOD[18O]HOD- + 4OH- +Al(OH)4- + [18O]H- + OD- + [18O]H- + OT- = Al[18O]HOD[18O]HOT- + 4OH- +Al(OH)4- + [18O]H- + OD- + [18O]D- + OH- = Al[18O]HOD[18O]DOH- + 4OH- +Al(OH)4- + [18O]H- + OD- + [18O]T- + OH- = Al[18O]HOD[18O]TOH- + 4OH- +Al(OH)4- + [18O]H- + OT- + OH- + OH- = Al[18O]HOTOHOH- + 4OH- +Al(OH)4- + [18O]H- + OT- + OH- + OD- = Al[18O]HOTOHOD- + 4OH- +Al(OH)4- + [18O]H- + OT- + OH- + [18O]H- = Al[18O]HOTOH[18O]H- + 4OH- +Al(OH)4- + [18O]H- + OT- + OH- + [18O]D- = Al[18O]HOTOH[18O]D- + 4OH- +Al(OH)4- + [18O]H- + OT- + OD- + OH- = Al[18O]HOTODOH- + 4OH- +Al(OH)4- + [18O]H- + OT- + OD- + OD- = Al[18O]HOTODOD- + 4OH- +Al(OH)4- + [18O]H- + OT- + OD- + [18O]H- = Al[18O]HOTOD[18O]H- + 4OH- +Al(OH)4- + [18O]H- + OT- + [18O]H- + OH- = Al[18O]HOT[18O]HOH- + 4OH- +Al(OH)4- + [18O]H- + OT- + [18O]H- + OD- = Al[18O]HOT[18O]HOD- + 4OH- +Al(OH)4- + [18O]H- + OT- + [18O]D- + OH- = Al[18O]HOT[18O]DOH- + 4OH- +Al(OH)4- + [18O]H- + [18O]H- + OH- + OH- = Al[18O]H[18O]HOHOH- + 4OH- +Al(OH)4- + [18O]H- + [18O]H- + OH- + OD- = Al[18O]H[18O]HOHOD- + 4OH- +Al(OH)4- + [18O]H- + [18O]H- + OH- + OT- = Al[18O]H[18O]HOHOT- + 4OH- +Al(OH)4- + [18O]H- + [18O]H- + OD- + OH- = Al[18O]H[18O]HODOH- + 4OH- +Al(OH)4- + [18O]H- + [18O]H- + OD- + OD- = Al[18O]H[18O]HODOD- + 4OH- +Al(OH)4- + [18O]H- + [18O]H- + OD- + OT- = Al[18O]H[18O]HODOT- + 4OH- +Al(OH)4- + [18O]H- + [18O]H- + OT- + OH- = Al[18O]H[18O]HOTOH- + 4OH- +Al(OH)4- + [18O]H- + [18O]H- + OT- + OD- = Al[18O]H[18O]HOTOD- + 4OH- +Al(OH)4- + [18O]H- + [18O]D- + OH- + OH- = Al[18O]H[18O]DOHOH- + 4OH- +Al(OH)4- + [18O]H- + [18O]D- + OH- + OD- = Al[18O]H[18O]DOHOD- + 4OH- +Al(OH)4- + [18O]H- + [18O]D- + OH- + OT- = Al[18O]H[18O]DOHOT- + 4OH- +Al(OH)4- + [18O]H- + [18O]D- + OD- + OH- = Al[18O]H[18O]DODOH- + 4OH- +Al(OH)4- + [18O]H- + [18O]D- + OT- + OH- = Al[18O]H[18O]DOTOH- + 4OH- +Al(OH)4- + [18O]H- + [18O]T- + OH- + OH- = Al[18O]H[18O]TOHOH- + 4OH- +Al(OH)4- + [18O]H- + [18O]T- + OH- + OD- = Al[18O]H[18O]TOHOD- + 4OH- +Al(OH)4- + [18O]H- + [18O]T- + OD- + OH- = Al[18O]H[18O]TODOH- + 4OH- +Al(OH)4- + [18O]D- + OH- + OH- + OH- = Al[18O]DOHOHOH- + 4OH- +Al(OH)4- + [18O]D- + OH- + OH- + OD- = Al[18O]DOHOHOD- + 4OH- +Al(OH)4- + [18O]D- + OH- + OH- + OT- = Al[18O]DOHOHOT- + 4OH- +Al(OH)4- + [18O]D- + OH- + OH- + [18O]H- = Al[18O]DOHOH[18O]H- + 4OH- +Al(OH)4- + [18O]D- + OH- + OH- + [18O]D- = Al[18O]DOHOH[18O]D- + 4OH- +Al(OH)4- + [18O]D- + OH- + OH- + [18O]T- = Al[18O]DOHOH[18O]T- + 4OH- +Al(OH)4- + [18O]D- + OH- + OD- + OH- = Al[18O]DOHODOH- + 4OH- +Al(OH)4- + [18O]D- + OH- + OD- + OT- = Al[18O]DOHODOT- + 4OH- +Al(OH)4- + [18O]D- + OH- + OD- + [18O]H- = Al[18O]DOHOD[18O]H- + 4OH- +Al(OH)4- + [18O]D- + OH- + OT- + OH- = Al[18O]DOHOTOH- + 4OH- +Al(OH)4- + [18O]D- + OH- + OT- + OD- = Al[18O]DOHOTOD- + 4OH- +Al(OH)4- + [18O]D- + OH- + OT- + [18O]H- = Al[18O]DOHOT[18O]H- + 4OH- +Al(OH)4- + [18O]D- + OH- + [18O]H- + OH- = Al[18O]DOH[18O]HOH- + 4OH- +Al(OH)4- + [18O]D- + OH- + [18O]H- + OD- = Al[18O]DOH[18O]HOD- + 4OH- +Al(OH)4- + [18O]D- + OH- + [18O]H- + OT- = Al[18O]DOH[18O]HOT- + 4OH- +Al(OH)4- + [18O]D- + OH- + [18O]D- + OH- = Al[18O]DOH[18O]DOH- + 4OH- +Al(OH)4- + [18O]D- + OH- + [18O]T- + OH- = Al[18O]DOH[18O]TOH- + 4OH- +Al(OH)4- + [18O]D- + OD- + OH- + OH- = Al[18O]DODOHOH- + 4OH- +Al(OH)4- + [18O]D- + OD- + OH- + OT- = Al[18O]DODOHOT- + 4OH- +Al(OH)4- + [18O]D- + OD- + OH- + [18O]H- = Al[18O]DODOH[18O]H- + 4OH- +Al(OH)4- + [18O]D- + OD- + OT- + OH- = Al[18O]DODOTOH- + 4OH- +Al(OH)4- + [18O]D- + OD- + [18O]H- + OH- = Al[18O]DOD[18O]HOH- + 4OH- +Al(OH)4- + [18O]D- + OT- + OH- + OH- = Al[18O]DOTOHOH- + 4OH- +Al(OH)4- + [18O]D- + OT- + OH- + OD- = Al[18O]DOTOHOD- + 4OH- +Al(OH)4- + [18O]D- + OT- + OH- + [18O]H- = Al[18O]DOTOH[18O]H- + 4OH- +Al(OH)4- + [18O]D- + OT- + OD- + OH- = Al[18O]DOTODOH- + 4OH- +Al(OH)4- + [18O]D- + OT- + [18O]H- + OH- = Al[18O]DOT[18O]HOH- + 4OH- +Al(OH)4- + [18O]D- + [18O]H- + OH- + OH- = Al[18O]D[18O]HOHOH- + 4OH- +Al(OH)4- + [18O]D- + [18O]H- + OH- + OD- = Al[18O]D[18O]HOHOD- + 4OH- +Al(OH)4- + [18O]D- + [18O]H- + OH- + OT- = Al[18O]D[18O]HOHOT- + 4OH- +Al(OH)4- + [18O]D- + [18O]H- + OD- + OH- = Al[18O]D[18O]HODOH- + 4OH- +Al(OH)4- + [18O]D- + [18O]H- + OT- + OH- = Al[18O]D[18O]HOTOH- + 4OH- +Al(OH)4- + [18O]D- + [18O]D- + OH- + OH- = Al[18O]D[18O]DOHOH- + 4OH- +Al(OH)4- + [18O]D- + [18O]T- + OH- + OH- = Al[18O]D[18O]TOHOH- + 4OH- +Al(OH)4- + [18O]T- + OH- + OH- + OH- = Al[18O]TOHOHOH- + 4OH- +Al(OH)4- + [18O]T- + OH- + OH- + OD- = Al[18O]TOHOHOD- + 4OH- +Al(OH)4- + [18O]T- + OH- + OH- + [18O]H- = Al[18O]TOHOH[18O]H- + 4OH- +Al(OH)4- + [18O]T- + OH- + OH- + [18O]D- = Al[18O]TOHOH[18O]D- + 4OH- +Al(OH)4- + [18O]T- + OH- + OD- + OH- = Al[18O]TOHODOH- + 4OH- +Al(OH)4- + [18O]T- + OH- + OD- + OD- = Al[18O]TOHODOD- + 4OH- +Al(OH)4- + [18O]T- + OH- + OD- + [18O]H- = Al[18O]TOHOD[18O]H- + 4OH- +Al(OH)4- + [18O]T- + OH- + [18O]H- + OH- = Al[18O]TOH[18O]HOH- + 4OH- +Al(OH)4- + [18O]T- + OH- + [18O]H- + OD- = Al[18O]TOH[18O]HOD- + 4OH- +Al(OH)4- + [18O]T- + OH- + [18O]D- + OH- = Al[18O]TOH[18O]DOH- + 4OH- +Al(OH)4- + [18O]T- + OD- + OH- + OH- = Al[18O]TODOHOH- + 4OH- +Al(OH)4- + [18O]T- + OD- + OH- + OD- = Al[18O]TODOHOD- + 4OH- +Al(OH)4- + [18O]T- + OD- + OH- + [18O]H- = Al[18O]TODOH[18O]H- + 4OH- +Al(OH)4- + [18O]T- + OD- + OD- + OH- = Al[18O]TODODOH- + 4OH- +Al(OH)4- + [18O]T- + OD- + [18O]H- + OH- = Al[18O]TOD[18O]HOH- + 4OH- +Al(OH)4- + [18O]T- + [18O]H- + OH- + OH- = Al[18O]T[18O]HOHOH- + 4OH- +Al(OH)4- + [18O]T- + [18O]H- + OH- + OD- = Al[18O]T[18O]HOHOD- + 4OH- +Al(OH)4- + [18O]T- + [18O]H- + OD- + OH- = Al[18O]T[18O]HODOH- + 4OH- +Al(OH)4- + [18O]T- + [18O]D- + OH- + OH- = Al[18O]T[18O]DOHOH- + 4OH- +# +# Added AlSO4+ reactions 16Dec09 +# +AlSO4+ + [34S]O4-2 = Al[34S]O4+ + SO4-2 +# +# Added Al(SO4)2- reactions 16Dec09 +# Revised 17Dec09, limited the number of species +# +Al(SO4)2- + SO4-2 + [34S]O4-2 = AlSO4[34S]O4- + 2SO4-2 +Al(SO4)2- + [34S]O4-2 + SO4-2 = Al[34S]O4SO4- + 2SO4-2 +Al(SO4)2- + [34S]O4-2 + [34S]O4-2 = Al[34S]O4[34S]O4- + 2SO4-2 +# +# Added AlHSO4+2 reactions 16Dec09 +# +AlHSO4+2 + DSO4- = AlDSO4+2 + HSO4- +AlHSO4+2 + TSO4- = AlTSO4+2 + HSO4- +AlHSO4+2 + H[34S]O4- = AlH[34S]O4+2 + HSO4- +AlHSO4+2 + D[34S]O4- = AlD[34S]O4+2 + HSO4- +AlHSO4+2 + T[34S]O4- = AlT[34S]O4+2 + HSO4- +# +# Missing H4SiO4 reactions +# +# +# Missing H3SiO4- reactions +# +# +# Missing H2SiO4-2 reactions +# + +############################################################################################### +PHASES +############################################################################################### +# +# Water vapor - Water +# last update March 20, 2006 +# Updated September 19, 2006 +# Checked September 19, 2006 +# +HDO(g) + HDO(g) + H2O(l) = H2O(g) + HDO(aq) + -add_logk Log_alpha_D_H2O(g)/H2O(l) -1.0 + +HTO(g) + HTO(g) + H2O(l) = H2O(g) + HTO(aq) + -add_logk Log_alpha_T_H2O(g)/H2O(l) -1.0 + +DTO(g) + DTO(g) + H2O(g) = HDO(g) + HTO(g) + log_k 0.301029995663 # log10(2) + +D2O(g) + D2O(g) + H2O(g) = 2HDO(g) + log_k 0.602059991327962396 # log10(4) + +T2O(g) + T2O(g) + H2O(g) = 2HTO(g) + log_k 0.602059991327962396 # log10(4) + +H2[18O](g) + H2[18O](g) + H2O(l) = H2O(g) + H2[18O](aq) + -add_logk Log_alpha_18O_H2O(g)/H2O(l) -1.0 + +HD[18O](g) + HD[18O](g) + H2O(g) = HDO(g) + H2[18O](g) + log_k 0.0 + +HT[18O](g) + HT[18O](g) + H2O(g) = HTO(g) + H2[18O](g) + log_k 0.0 + +D2[18O](g) + D2[18O](g) + H2O(g) = D2O(g) + H2[18O](g) + log_k 0.0 + +T2[18O](g) + T2[18O](g) + H2O(g) = T2O(g) + H2[18O](g) + log_k 0.0 + +DT[18O](g) + DT[18O](g) + H2O(g) = DTO(g) + H2[18O](g) + log_k 0.0 +# +# O2 gas - O2 aqueous +# last update March 20, 2006 +# Updated September 19, 2006 +# Checked September 19, 2006 +# +O[18O](g) + O[18O](g) + H2O(l) = O2(g) + H2[18O](aq) +## symmetry K ?? + -add_logk Log_alpha_18O_O2(g)/H2O(l) -1.0 + +[18O]2(g) + [18O]2(g) + O2(g) = 2O[18O](g) + log_k 0.602059991327962396 # log10(4) +# +# H2 gas - H2 aqueous +# last update March 20, 2006 +# Updated September 19, 2006 +# Checked September 19, 2006 +# +HD(g) + HD(g) + H2O(l) = H2(g) + HDO(aq) + -add_logk Log_alpha_D_H2(g)/H2O(l) -1.0 + +HT(g) + HT(g) + H2O(l) = H2(g) + HTO(aq) + -add_logk Log_alpha_T_H2(g)/H2O(l) -1.0 + +D2(g) + D2(g) + H2(g) = 2HD(g) + log_k 0.602059991327962396 # log10(4) + +T2(g) + T2(g) + H2(g) = 2HT(g) + log_k 0.602059991327962396 # log10(4) + +DT(g) + DT(g) + H2(g) = HD(g) + HT(g) + log_k 0.301029995663 # log10(2) +# +# CO2 gas - CO2 aqueous +# last update March 20, 2006 +# Updated September 19, 2006 +# Checked September 19, 2006 +# +CO[18O](g) + CO[18O](g) + H2O(l) = H2[18O](aq) + CO2(g) + log_k -0.301029995663 # -log10(2) + -add_logk Log_alpha_18O_CO2(g)/H2O(l) -1.0 + +C[18O]2(g) + C[18O]2(g) + CO2(g) = 2CO[18O](g) + log_k 0.602059991327962396 # log10(4) + +[13C]O2(g) + [13C]O2(g) + CO2(aq) = [13C]O2(aq) + CO2(g) + -add_logk Log_alpha_13C_CO2(g)/CO2(aq) -1.0 + +[13C]O[18O](g) + [13C]O[18O](g) + CO2(g) = [13C]O2(g) + CO[18O](g) + log_k 0 + +[13C][18O]2(g) + [13C][18O]2(g) + CO2(g) = C[18O]2(g) + [13C]O2(g) + log_k 0 + +[14C]O2(g) + [14C]O2(g) + CO2(aq) = [14C]O2(aq) + CO2(g) + -add_logk Log_alpha_14C_CO2(g)/CO2(aq) -1.0 + +[14C]O[18O](g) + [14C]O[18O](g) + CO2(g) = [14C]O2(g) + CO[18O](g) + log_k 0 + +[14C][18O]2(g) + [14C][18O]2(g) + CO2(g) = [14C]O2(g) + C[18O]2(g) + log_k 0 +# +# Calcite +# last update Feb 13, 2006 +# Updated September 19, 2006 +# Checked September 19, 2006 +# +CaCO2[18O](s) + CaCO2[18O](s) + H2O(l) = H2[18O](aq) + Calcite(s) + log_k -0.477121254719 # -log10(3) ??? + -add_logk Log_alpha_18O_Calcite/H2O(l) -1.0 + +CaCO[18O]2(s) + CaCO[18O]2(s) + Calcite(s) = 2CaCO2[18O](s) + log_k 0.477121254719 # log10(3) + +CaC[18O]3(s) + CaC[18O]3(s) + 2Calcite(s) = 3CaCO2[18O](s) + log_k 1.431363764158 # log10(27) + +Ca[13C]O3(s) + Ca[13C]O3(s) + CO2 = [13C]O2 + Calcite(s) + -add_logk Log_alpha_13C_Calcite/CO2(aq) -1.0 + +Ca[13C]O2[18O](s) + Ca[13C]O2[18O](s) + Calcite(s) = Ca[13C]O3(s) + CaCO2[18O](s) + log_k 0 + +Ca[13C]O[18O]2(s) + Ca[13C]O[18O]2(s) + Calcite(s) = Ca[13C]O3(s) + CaCO[18O]2(s) + log_k 0 + +Ca[13C][18O]3(s) + Ca[13C][18O]3(s) + Calcite(s) = Ca[13C]O3(s) + CaC[18O]3(s) + log_k 0 + +Ca[14C]O3(s) + Ca[14C]O3(s) + CO2 = Calcite(s) + [14C]O2 + -add_logk Log_alpha_14C_Calcite/CO2(aq) -1.0 + +Ca[14C]O2[18O](s) + Ca[14C]O2[18O](s) + Calcite(s) = Ca[14C]O3(s) + CaCO2[18O](s) + log_k 0 + +Ca[14C]O[18O]2(s) + Ca[14C]O[18O]2(s) + Calcite(s) = Ca[14C]O3(s) + CaCO[18O]2(s) + log_k 0 + +Ca[14C][18O]3(s) + Ca[14C][18O]3(s) + Calcite(s) = Ca[14C]O3(s) + CaC[18O]3(s) + log_k 0 +# +# Pyrite, March 20, 2006 +# Update September 28, 2006 +# Checked September 28, 2006 +# +Pyrite_FeS[34S] + FeS[34S](s) + HS- = Pyrite(s) + H[34S]- + -add_logk Log_alpha_34S_Pyrite/HS- -1.0 + +Pyrite_Fe[34S]S + Fe[34S]S(s) = Pyrite_FeS[34S](s) + +Pyrite_Fe[34S]2 + Fe[34S]2(s) + Pyrite(s) = 2Pyrite_FeS[34S](s) +# +# CH4 reactions +# last update March 20, 2006 +# Updated September 19, 2006 +# Checked September 19, 2006 +# +CH3D(g) + CH3D(g) + H2O(l) = CH4(g) + HDO(aq) + log_k -0.301029995663 # -log10(2) ??? + -add_logk Log_alpha_D_CH4(g)/H2O(l) -1.0 + +CH2D2(g) + CH2D2(g) + CH4(g) = 2CH3D(g) + log_k 0.42596873227228 # log10(8/3) + +CHD3(g) + CHD3(g) + 2CH4(g) = 3CH3D(g) + log_k 1.20411998265 # log10(16) + +CD4(g) + CD4(g) + 3CH4(g) = 4CH3D(g) + log_k 2.408239965311 # log10(256) + +CH3T(g) + CH3T(g) + H2O(l) = CH4(g) + HTO(aq) + log_k -0.301029995663 # -log10(2) ??? + -add_logk Log_alpha_T_CH4(g)/H2O(l) -1.0 + +CH2T2(g) + CH2T2(g) + CH4(g) = 2CH3T(g) + log_k 0.42596873227228 # log10(8/3) + +CHT3(g) + CHT3(g) + 2CH4(g) = 3CH3T(g) + log_k 1.20411998265 # log10(16) + +CT4(g) + CT4(g) + 3CH4(g) = 4CH3T(g) + log_k 2.408239965311 # log10(256) + +CD3T(g) + CD3T(g) + CH4(g) = CHD3(g) + CH3T(g) + log_k 0.602059991327962396 # log10(4) + +CD2T2(g) + CD2T2(g) + CH4(g) = CH2D2(g) + CH2T2(g) + log_k 0.7781512503836 # log10(6) + +CDT3(g) + CDT3(g) + CH4(g) = CHT3(g) + CH3D(g) + log_k 0.602059991327962396 # log10(4) + +[13C]H4(g) + [13C]H4(g) + CO2(aq) = [13C]O2(aq) + CH4(g) + -add_logk Log_alpha_13C_CH4(g)/CO2(aq) -1.0 + +[13C]H3D(g) + [13C]H3D(g) + CH4(g) = CH3D(g) + [13C]H4(g) + +[13C]H2D2(g) + [13C]H2D2(g) + CH4(g) = CH2D2(g) + [13C]H4(g) + +[13C]HD3(g) + [13C]HD3(g) + CH4(g) = CHD3(g) + [13C]H4(g) + +[13C]D4(g) + [13C]D4(g) + CH4(g) = CD4(g) + [13C]H4(g) + +[13C]H3T(g) + [13C]H3T(g) + CH4(g) = CH3T(g) + [13C]H4(g) + +[13C]H2T2(g) + [13C]H2T2(g) + CH4(g) = CH2T2(g) + [13C]H4(g) + +[13C]HT3(g) + [13C]HT3(g) + CH4(g) = CHT3(g) + [13C]H4(g) + +[13C]T4(g) + [13C]T4(g) + CH4(g) = CT4(g) + [13C]H4(g) + +[13C]D3T(g) + [13C]D3T(g) + CH4(g) = CD3T(g) + [13C]H4(g) + +[13C]D2T2(g) + [13C]D2T2(g) + CH4(g) = CD2T2(g) + [13C]H4(g) + +[13C]DT3(g) + [13C]DT3(g) + CH4(g) = CDT3(g) + [13C]H4(g) + +[13C]T4(g) + [13C]T4(g) + CH4(g) = CT4(g) + [13C]H4(g) + +[14C]H4(g) + [14C]H4(g) + CO2(aq) = [14C]O2(aq) + CH4(g) + -add_logk Log_alpha_14C_CH4(g)/CO2(aq) -1.0 + +[14C]H3D(g) + [14C]H3D(g) + CH4(g) = CH3D(g) + [14C]H4(g) + +[14C]H2D2(g) + [14C]H2D2(g) + CH4(g) = CH2D2(g) + [14C]H4(g) + +[14C]HD3(g) + [14C]HD3(g) + CH4(g) = CHD3(g) + [14C]H4(g) + +[14C]D4(g) + [14C]D4(g) + CH4(g) = CD4(g) + [14C]H4(g) + +[14C]H3T(g) + [14C]H3T(g) + CH4(g) = CH3T(g) + [14C]H4(g) + +[14C]H2T2(g) + [14C]H2T2(g) + CH4(g) = CH2T2(g) + [14C]H4(g) + +[14C]HT3(g) + [14C]HT3(g) + CH4(g) = CHT3(g) + [14C]H4(g) + +[14C]T4(g) + [14C]T4(g) + CH4(g) = CT4(g) + [14C]H4(g) + +[14C]D3T(g) + [14C]D3T(g) + CH4(g) = CD3T(g) + [14C]H4(g) + +[14C]D2T2(g) + [14C]D2T2(g) + CH4(g) = CD2T2(g) + [14C]H4(g) + +[14C]DT3(g) + [14C]DT3(g) + CH4(g) = CDT3(g) + [14C]H4(g) + +[14C]T4(g) + [14C]T4(g) + CH4(g) = CT4(g) + [14C]H4(g) +# +# updated March 20, 2006 +# Updated September 28, 2006 +# Checked September 28, 2006 +# +HDS(g) + HDS(g) + H2S(aq) = HDS(aq) + H2S(g) + -add_logk Log_alpha_D_H2S(g)/H2S(aq) -1.0 + +D2S(g) + D2S(g) + H2S(g) = 2HDS(g) + log_k 0.602059991327962396 # log10(4) + +HTS(g) + HTS(g) + H2S(aq) = HTS(aq) + H2S(g) + -add_logk Log_alpha_T_H2S(g)/H2S(aq) -1.0 + +T2S(g) + T2S(g) + H2S(g) = 2HTS(g) + log_k 0.602059991327962396 # log10(4) + +DTS(g) + DTS(g) + H2S(g) = HDS(g) + HTS(g) + log_k 0.301029995663 # log10(2) + +H2[34S](g) + H2[34S](g) + H2S(aq) = H2[34S](aq) + H2S(g) + -add_logk Log_alpha_34S_H2S(g)/H2S(aq) -1.0 + +HD[34S](g) + HD[34S](g) + H2S(g) = HDS(g) + H2[34S](g) + +D2[34S](g) + D2[34S](g) + H2S(g) = D2S(g) + H2[34S](g) + +HT[34S](g) + HT[34S](g) + H2S(g) = HTS(g) + H2[34S](g) + +T2[34S](g) + T2[34S](g) + H2S(g) = T2S(g) + H2[34S](g) + +DT[34S](g) + DT[34S](g) + H2S(g) = DTS(g) + H2[34S](g) + +# +# Gypsum and anhydrite +# +Ca[34S]O4:2H2O + Ca[34S]O4:2H2O + SO4-2 = [34S]O4-2 + Gypsum(s) + -add_logk Log_alpha_34S_Gypsum/SO4-2 -1.0 + +Ca[34S]O4 + Ca[34S]O4 + SO4-2 = [34S]O4-2 + Anhydrite(s) + -add_logk Log_alpha_34S_Anhydrite/SO4-2 -1.0 +# +# Nitrogen phases +# Checked September 19, 2006 +# +N[15N](g) + N[15N](g) + N2(aq) = N[15N](aq) + N2(g) + -add_logk Log_alpha_15N_N2(g)/N2(aq) -1.0 + +[15N]2(g) + [15N]2(g) + N2(g) = 2N[15N](g) + log_k 0.602059991327962396 # log10(4) + +NH2D(g) + NH2D(g) + H2O(l) = NH3(g) + HDO(aq) +## symmetry K?? + -add_logk Log_alpha_D_NH3(g)/H2O(l) -1.0 + +NHD2(g) + NHD2(g) + NH3(g) = 2NH2D(g) + log_k 0.477121254719 # log10(3) + +ND3(g) + ND3(g) + 2NH3(g) = 3NH2D(g) + -logk 1.431363764158 # log10(27) + +NH2T(g) + NH2T(g) + H2O(l) = NH3(g) + HTO(aq) +## symmetry K?? + -add_logk Log_alpha_T_NH3(g)/H2O(l) -1.0 + +NHT2(g) + NHT2(g) + NH3(g) = 2NH2T(g) + log_k 0.477121254719 # log10(3) + +NT3(g) + NT3(g) + 2NH3(g) = 3NH2T(g) + -logk 1.431363764158 # log10(27) + +ND2T(g) + ND2T(g) + NH3(g) = NHD2(g) + NH2T(g) + log_k 0.477121254719 # log10(3) + +NDT2(g) + NDT2(g) + NH3(g) = NH2D(g) + NHT2(g) + log_k 0.477121254719 # log10(3) + +[15N]H3(g) + [15N]H3(g) + NH3(aq) = [15N]H3(aq) + NH3(g) + -add_logk Log_alpha_15N_NH3(g)/NH3(aq) -1.0 + +[15N]H2D(g) + [15N]H2D(g) + NH3(g) = NH2D(g) + [15N]H3(g) + +[15N]HD2(g) + [15N]HD2(g) + NH3(g) = NHD2(g) + [15N]H3(g) + +[15N]D3(g) + [15N]D3(g) + NH3(g) = ND3(g) + [15N]H3(g) + +[15N]H2T(g) + [15N]H2T(g) + NH3(g) = NH2T(g) + [15N]H3(g) + +[15N]HT2(g) + [15N]HT2(g) + NH3(g) = NHT2(g) + [15N]H3(g) + +[15N]T3(g) + [15N]T3(g) + NH3(g) = NT3(g) + [15N]H3(g) + +[15N]D2T(g) + [15N]D2T(g) + NH3(g) = ND2T(g) + [15N]H3(g) + +[15N]DT2(g) + [15N]DT2(g) + NH3(g) = NDT2(g) + [15N]H3(g) diff --git a/gtest/kinn20140218 b/gtest/kinn20140218 new file mode 100644 index 00000000..c35c0ce2 --- /dev/null +++ b/gtest/kinn20140218 @@ -0,0 +1,349 @@ +# +#*** PhreePlot 1 (Win32) *** 20:14:59 13 Feb 2014 +# Incorporating the PHREEQC library by DL Parkhurst, SR Charlton (USGS), +# & CAJ Appelo (Amsterdam) +# Hunt & Track by DG Kinniburgh, and DM Cooper, CEH (NERC) +# Fitting by MJD Powell (University of Cambridge) +# Postscript plotting by KE Kohler +# +#Input filename: C:\PhreePlot\unittests\custom\contouring\As3_logNaVspH.ppi. +# +#Calculating... 1 + +PRINT + -selected_output false + PHASES + Fix_H+ + H+ = H+ + log_k 0 +SOLUTION_MASTER_SPECIES + [N5] [N5]O3- 0 14 14 + Perchlorate Perchlorate- 0 35 35 +SOLUTION_SPECIES + [N5]O3- = [N5]O3- + log_k 0 + Perchlorate- = Perchlorate- + log_k 0 +SURFACE_MASTER_SPECIES + Goe_uni Goe_uniOH1.5 + Goe_tri Goe_triOH0.5 +SURFACE_SPECIES + Goe_triOH0.5 = Goe_triOH0.5 + -cd_music 0 0 0 0 0 + log_k 0 + Goe_triOH0.5 = Goe_triO-0.5 + 0.5H+ + -cd_music -0.5 0 0 0 0 + log_k 10 + Goe_triO-0.5 + H+ = Goe_triOH+0.5 + -cd_music 1 0 0 0 0 + log_k 9.20 + Goe_triO-0.5 + Li+ = Goe_triOLi+0.5 + -cd_music 0 1 0 0 0 + log_k 0.10 + Goe_triO-0.5 + Na+ = Goe_triONa+0.5 + -cd_music 0 1 0 0 0 + log_k -0.60 + Goe_triO-0.5 + K+ = Goe_triOK+0.5 + -cd_music 0 1 0 0 0 + log_k -1.61 + Goe_triO-0.5 + H+ + NO3- = Goe_triOHNO3-0.5 + -cd_music 1 -1 0 0 0 + log_k 8.52 + Goe_triO-0.5 + H+ + [N5]O3- = Goe_triOH[N5]O3-0.5 + -cd_music 1 -1 0 0 0 + log_k 8.52 + Goe_triO-0.5 + H+ + Cl- = Goe_triOHCl-0.5 + -cd_music 1 -1 0 0 0 + log_k 8.75 + Goe_uniOH1.5 = Goe_uniOH1.5 + -cd_music 0 0 0 0 0 + log_k 0 + Goe_uniOH1.5 = Goe_uniOH-0.5 + 0.5H+ + -cd_music -0.5 0 0 0 0 + log_k 10 + Goe_uniOH-0.5 + H+ = Goe_uniOH2+0.5 + -cd_music 1 0 0 0 0 + log_k 9.20 + Goe_uniOH-0.5 + Li+ = Goe_uniOHLi+0.5 + -cd_music 0 1 0 0 0 + log_k 0.10 + Goe_uniOH-0.5 + Na+ = Goe_uniOHNa+0.5 + -cd_music 0 1 0 0 0 + log_k -0.60 + Goe_uniOH-0.5 + K+ = Goe_uniOHK+0.5 + -cd_music 0 1 0 0 0 + log_k -1.61 + Goe_uniOH-0.5 + H+ + NO3- = Goe_uniOH2NO3-0.5 + -cd_music 1 -1 0 0 0 + log_k 8.52 + Goe_uniOH-0.5 + H+ + [N5]O3- = Goe_uniOH2[N5]O3-0.5 + -cd_music 1 -1 0 0 0 + log_k 8.52 + Goe_uniOH-0.5 + H+ + Cl- = Goe_uniOH2Cl-0.5 + -cd_music 1 -1 0 0 0 + log_k 8.75 + Goe_uniOH-0.5 + Ca+2 = Goe_uniOHCa+1.5 + log_k 2.85 + -cd_music 0.0 2.0 0 0 0 + Goe_triO-0.5 + Ca+2 = Goe_triOCa+1.5 + log_k 2.85 + -cd_music 0.0 2.0 0 0 0 + Goe_uniOH-0.5 + Ca+2 = Goe_uniOHCa+1.5 + log_k 3.69 + -cd_music 0.32 1.68 0 0 0 + Goe_uniOH-0.5 + Ca+2 + H2O = Goe_uniOHCaOH+0.5 + H+ + log_k -9.17 + -cd_music 0.32 0.68 0 0 0 + 2Goe_uniOH-0.5 + Mg+2 = (Goe_uniOH)2Mg+1 + log_k 4.89 + -cd_music 0.71 1.29 0 0 0 + 2Goe_uniOH-0.5 + Mg+2 + H2O = (Goe_uniOH)2MgOH + H+ + log_k -6.44 + -cd_music 0.71 0.29 0 0 0 + 2Goe_uniOH-0.5 + Cu+2 = (Goe_uniOH)2Cu+1 + log_k 9.18 + -cd_music 0.84 1.16 0 0 0 + 2Goe_uniOH-0.5 + Cu+2 + H2O = (Goe_uniOH)2CuOH + H+ + log_k 3.60 + -cd_music 0.84 0.16 0 0 0 + 2Goe_uniOH-0.5 + 2Cu+2 + 2H2O = (Goe_uniOH)2Cu2(OH)2+1 + 2H+ + log_k 3.65 + -cd_music 0.84 1.16 0 0 0 + 2Goe_uniOH-0.5 + 2Cu+2 + 3H2O = (Goe_uniOH)2Cu2(OH)3 + 3H+ + log_k -3.10 + -cd_music 0.84 0.16 0 0 0 + Goe_uniOH-0.5 + 2H+ + AsO4-3 = Goe_uniOAsO2OH-1.5 + H2O + log_k 26.60 + -cd_music 0.30 -1.30 0 0 0 + 2Goe_uniOH-0.5 + 2H+ + AsO4-3 = (Goe_uniO)2AsO2-2 + 2H2O + log_k 29.77 + -cd_music 0.47 -1.47 0 0 0 + 2Goe_uniOH-0.5 + 3H+ + AsO4-3 = (Goe_uniO)2AsOOH- + 2H2O + log_k 33.00 + -cd_music 0.58 -0.58 0 0 0 + Goe_uniOH-0.5 + H3AsO3 = Goe_uniOAs(OH)2-0.5 + H2O + log_k 4.91 + -cd_music 0.16 -0.16 0 0 0 + 2Goe_uniOH-0.5 + H3AsO3 = (Goe_uniO)2AsOH-1 + 2H2O + log_k 7.26 + -cd_music 0.34 -0.34 0 0 0 + Goe_uniOH-0.5 + 2H+ + PO4-3 = Goe_uniOPO2OH-1.5 + H2O + log_k 27.65 + -cd_music 0.28 -1.28 0 0 0 + 2Goe_uniOH-0.5 + 2H+ + PO4-3 = (Goe_uniO)2PO2-2 + 2H2O + log_k 29.77 + -cd_music 0.46 -1.46 0 0 0 + 2Goe_uniOH-0.5 + 2H+ + CO3-2 = (Goe_uniO)2CO- + 2H2O + log_k 22.33 + -cd_music 0.68 -0.68 0 0 0 + Goe_uniOH-0.5 + H+ + SO4-2 = Goe_uniOSO3-1.5 + H2O + log_k 9.37 + -cd_music 0.5 -1.5 0 0 0 + Goe_uniOH-0.5 + H+ + SO4-2 = Goe_uniOSO3-1.5 + H2O + log_k 11.06 + -cd_music 1 -1.84 -0.16 0 0 + 2Goe_uniOH-0.5 + H4SiO4 = (Goe_uniO)2Si(OH)2-1 + 2H2O + log_k 5.85 + -cd_music 0.29 -0.29 0 0 0 + 2Goe_uniOH-0.5 + 4H4SiO4 = (Goe_uniO)2SiOHOSi3O2(OH)7-1 + 5H2O + log_k 13.98 + -cd_music 0.29 -0.29 0 0 0 + 2Goe_uniOH-0.5 + 4H4SiO4 = (Goe_uniO)2SiOHOSi3O3(OH)6-2 + 5H2O + H+ + log_k 7.47 + -cd_music 0.29 -1.29 0 0 0 +SURFACE_MASTER_SPECIES + Fhy_unie Fhy_unieOH1.5 + Fhy_unic Fhy_unicOH1.5 + Fhy_tri Fhy_triOH0.5 +SURFACE_SPECIES + Fhy_triOH0.5 = Fhy_triOH0.5 + -cd_music 0 0 0 0 0 + log_k 0 + Fhy_triOH0.5 = Fhy_triO-0.5 + 0.5H+ + -cd_music -0.5 0 0 0 0 + log_k 10 + Fhy_triO-0.5 + H+ = Fhy_triOH+0.5 + -cd_music 1 0 0 0 0 + log_k 8.06 + Fhy_triO-0.5 + Na+ = Fhy_triONa+0.5 + -cd_music 0 1 0 0 0 + log_k -0.60 + Fhy_triO-0.5 + H+ + NO3- = Fhy_triOHNO3-0.5 + -cd_music 1 -1 0 0 0 + log_k 7.38 + Fhy_triO-0.5 + H+ + [N5]O3- = Fhy_triOH[N5]O3-0.5 + -cd_music 1 -1 0 0 0 + log_k 7.38 + Fhy_triO-0.5 + H+ + Cl- = Fhy_triOHCl-0.5 + -cd_music 1 -1 0 0 0 + log_k 7.61 + Fhy_triO-0.5 + H+ + Perchlorate- = Fhy_triOHPerchlorate-0.5 + -cd_music 1 -1 0 0 0 + log_k 6.36 + Fhy_unieOH1.5 = Fhy_unieOH1.5 + -cd_music 0 0 0 0 0 + log_k 0 + Fhy_unieOH1.5 = Fhy_unieOH-0.5 + 0.5H+ + -cd_music -0.5 0 0 0 0 + log_k 10 + Fhy_unieOH-0.5 + H+ = Fhy_unieOH2+0.5 + -cd_music 1 0 0 0 0 + log_k 8.06 + Fhy_unieOH-0.5 + Na+ = Fhy_unieOHNa+0.5 + -cd_music 0 1 0 0 0 + log_k -0.60 + Fhy_unieOH-0.5 + H+ + NO3- = Fhy_unieOH2NO3-0.5 + -cd_music 1 -1 0 0 0 + log_k 7.38 + Fhy_unieOH-0.5 + H+ + [N5]O3- = Fhy_unieOH2[N5]O3-0.5 + -cd_music 1 -1 0 0 0 + log_k 7.38 + Fhy_unieOH-0.5 + H+ + Cl- = Fhy_unieOH2Cl-0.5 + -cd_music 1 -1 0 0 0 + log_k 7.61 + Fhy_unieOH-0.5 + H+ + Perchlorate- = Fhy_unieOH2Perchlorate-0.5 + -cd_music 1 -1 0 0 0 + log_k 6.36 + Fhy_unicOH1.5 = Fhy_unicOH1.5 + -cd_music 0 0 0 0 0 + log_k 0 + Fhy_unicOH1.5 = Fhy_unicOH-0.5 + 0.5H+ + -cd_music -0.5 0 0 0 0 + log_k 10 + Fhy_unicOH-0.5 + H+ = Fhy_unicOH2+0.5 + -cd_music 1 0 0 0 0 + log_k 8.06 + Fhy_unicOH-0.5 + Na+ = Fhy_unicOHNa+0.5 + -cd_music 0 1 0 0 0 + log_k -0.60 + Fhy_unicOH-0.5 + H+ + NO3- = Fhy_unicOH2NO3-0.5 + -cd_music 1 -1 0 0 0 + log_k 7.38 + Fhy_unicOH-0.5 + H+ + [N5]O3- = Fhy_unicOH2[N5]O3-0.5 + -cd_music 1 -1 0 0 0 + log_k 7.38 + Fhy_unicOH-0.5 + H+ + Cl- = Fhy_unicOH2Cl-0.5 + -cd_music 1 -1 0 0 0 + log_k 7.61 + Fhy_unicOH-0.5 + H+ + Perchlorate- = Fhy_unicOH2Perchlorate-0.5 + -cd_music 1 -1 0 0 0 + log_k 6.36 + 2Fhy_unicOH-0.5 + 2H+ + CO3-2 = Fhy_unic2O2CO- + 2H2O + -cd_music 0.62 -0.62 0 0 0 + log_k 21.50 + 2Fhy_unieOH-0.5 + UO2+2 = Fhy_unie2(OH)2UO2+ + -cd_music 0.9 1.1 0 0 0 + log_k 9.0 + 2Fhy_unieOH-0.5 + UO2+2 + H2O = Fhy_unie2(OH)2UO2OH + H+ + -cd_music 0.9 0.1 0 0 0 + log_k 3.30 + 2Fhy_unieOH-0.5 + UO2+2 + 2H2O = Fhy_unie2(OH)2UO2(OH)2- + 2H+ + -cd_music 0.9 -0.9 0 0 0 + log_k -5.3 + 2Fhy_unieOH-0.5 + UO2+2 + CO3-2 + H2O = Fhy_unie2(OH)2UO2CO3(OH)-2 + H+ + -cd_music 0.9 -1.9 0 0 0 + log_k 10.49 + Fhy_unicOH-0.5 + UO2+2 + 3CO3-2 + H+ = Fhy_unic(OCO2)UO2(CO3)2-3.5 + H2O + -cd_music 0.33 -3.33 0 0 0 + log_k 36.63 + Fhy_unieOH-0.5 + UO2+2 + 3CO3-2 + H+ = Fhy_unie(OCO2)UO2(CO3)2-3.5 + H2O + -cd_music 0.33 -3.33 0 0 0 + log_k 36.63 + 2Fhy_unieOH-0.5 + 3UO2+2 + 6H2O = Fhy_unie2(OH)2(UO2)3(OH)6- + 6H+ + -cd_music 0.9 -0.9 0 0 0 + log_k -15.8 + 2Fhy_unieOH-0.5 + 3UO2+2 + CO3-2 + 3H2O = Fhy_unie2(OH)2(UO2)3(OH)3CO3 + 3H+ + -cd_music 0.9 0.1 0 0 0 + log_k 14.6 +END + + SOLUTION 1 + Temp 20 + pH 3.8 + units mol/kgw + Na 0.001 + Cl 0.001 + EQUILIBRIUM_PHASES 1 + Fix_H+ -4 NaOH + -force_equality true + O2(g) -70 + SURFACE 1 + Goe_uniOH1.5 3.5 98 0.1 + Goe_triOH0.5 2.7 + -cd_music + -sites_units density + -cap 0.85 0.75 + SAVE surface 2 +END +use surface 2 +SOLUTION 1 + Temp 20 + pH 3.8 + units mol/kgw + Na 0.001 + Cl 0.001 +REACTION +Na2HAsO4 1 +0.0001 in 1 step +PRINT + -selected_output true +SELECTED_OUTPUT + -reset false + -high_precision false +USER_PUNCH + -headings logNa pH I dissAs + 10 IF (TOT("As") > 0) THEN dissas = TOT("As") ELSE dissas = -99999 + 20 totna = TOT("Na") + 30 IF (totna > 0) THEN logna = LOG10(totna) ELSE logna = -99999 + 40 PUNCH logna, -la("H+"), mu, dissas + 50 PRINT "NaT = ", totna + EQUILIBRIUM_PHASES 1 + Fix_H+ -4 NaOH + -force_equality true + O2(g) -70 +END + SOLUTION 1 + Temp 20 + pH 3.8 + units mol/kgw + Na 0.00215443469 + Cl 0.00215443469 + EQUILIBRIUM_PHASES 1 + Fix_H+ -4 NaOH + -force_equality true + O2(g) -70 + SURFACE 1 + Goe_uniOH1.5 3.5 98 0.1 + Goe_triOH0.5 2.7 + -cd_music + -sites_units density + -cap 0.85 0.75 + SAVE surface 2 +END +use surface 2 +SOLUTION 1 + Temp 20 + pH 3.8 + units mol/kgw + Na 0.00215443469 + Cl 0.00215443469 +REACTION +Na2HAsO4 1 +0.0001 in 1 step +PRINT + -selected_output true +SELECTED_OUTPUT + -reset false + -high_precision false +USER_PUNCH + -headings logNa pH I dissAs + 10 IF (TOT("As") > 0) THEN dissas = TOT("As") ELSE dissas = -99999 + 20 totna = TOT("Na") + 30 IF (totna > 0) THEN logna = LOG10(totna) ELSE logna = -99999 + 40 PUNCH logna, -la("H+"), mu, dissas + 50 PRINT "NaT = ", totna + EQUILIBRIUM_PHASES 1 + Fix_H+ -4 NaOH + -force_equality true + O2(g) -70 +END \ No newline at end of file diff --git a/gtest/missing_e.dat b/gtest/missing_e.dat new file mode 100644 index 00000000..49fd4aa0 --- /dev/null +++ b/gtest/missing_e.dat @@ -0,0 +1,1556 @@ +SOLUTION_MASTER_SPECIES +# +#element species alk gfw_formula element_gfw +# +H H+ -1. H 1.008 +H(0) H2 0.0 H +H(1) H+ -1. 0.0 +##E e- 0.0 0.0 0.0 +O H2O 0.0 O 16.00 +O(0) O2 0.0 O +O(-2) H2O 0.0 0.0 +Ca Ca+2 0.0 Ca 40.08 +Mg Mg+2 0.0 Mg 24.312 +Na Na+ 0.0 Na 22.9898 +K K+ 0.0 K 39.102 +Fe Fe+2 0.0 Fe 55.847 +Fe(+2) Fe+2 0.0 Fe +Fe(+3) Fe+3 -2.0 Fe +Mn Mn+2 0.0 Mn 54.938 +Mn(+2) Mn+2 0.0 Mn +Mn(+3) Mn+3 0.0 Mn +Al Al+3 0.0 Al 26.9815 +Ba Ba+2 0.0 Ba 137.34 +Sr Sr+2 0.0 Sr 87.62 +Si H4SiO4 0.0 SiO2 28.0843 +Cl Cl- 0.0 Cl 35.453 +C CO3-2 2.0 HCO3 12.0111 +C(+4) CO3-2 2.0 HCO3 +C(-4) CH4 0.0 CH4 +Alkalinity CO3-2 1.0 Ca0.5(CO3)0.5 50.05 +S SO4-2 0.0 SO4 32.064 +S(6) SO4-2 0.0 SO4 +S(-2) HS- 1.0 S +N NO3- 0.0 N 14.0067 +N(+5) NO3- 0.0 N +N(+3) NO2- 0.0 N +N(0) N2 0.0 N +N(-3) NH4+ 0.0 N +B H3BO3 0.0 B 10.81 +P PO4-3 2.0 P 30.9738 +F F- 0.0 F 18.9984 +Li Li+ 0.0 Li 6.939 +Br Br- 0.0 Br 79.904 +Zn Zn+2 0.0 Zn 65.37 +Cd Cd+2 0.0 Cd 112.4 +Pb Pb+2 0.0 Pb 207.19 +Cu Cu+2 0.0 Cu 63.546 +Cu(+2) Cu+2 0.0 Cu +Cu(+1) Cu+1 0.0 Cu + +SOLUTION_SPECIES + +H+ = H+ + log_k 0.000 + -gamma 9.0000 0.0000 + +e- = e- + log_k 0.000 + +H2O = H2O + log_k 0.000 + +Ca+2 = Ca+2 + log_k 0.000 + -gamma 5.0000 0.1650 + +Mg+2 = Mg+2 + log_k 0.000 + -gamma 5.5000 0.2000 + +Na+ = Na+ + log_k 0.000 + -gamma 4.0000 0.0750 + +K+ = K+ + log_k 0.000 + -gamma 3.5000 0.0150 + +Fe+2 = Fe+2 + log_k 0.000 + -gamma 6.0000 0.0000 + +Mn+2 = Mn+2 + log_k 0.000 + -gamma 6.0000 0.0000 + +Al+3 = Al+3 + log_k 0.000 + -gamma 9.0000 0.0000 + +Ba+2 = Ba+2 + log_k 0.000 + -gamma 5.0000 0.0000 + +Sr+2 = Sr+2 + log_k 0.000 + -gamma 5.2600 0.1210 + +H4SiO4 = H4SiO4 + log_k 0.000 + +Cl- = Cl- + log_k 0.000 + -gamma 3.5000 0.0150 + +CO3-2 = CO3-2 + log_k 0.000 + -gamma 5.4000 0.0000 + +SO4-2 = SO4-2 + log_k 0.000 + -gamma 5.0000 -0.0400 + +NO3- = NO3- + log_k 0.000 + -gamma 3.0000 0.0000 + +H3BO3 = H3BO3 + log_k 0.000 + +PO4-3 = PO4-3 + log_k 0.000 + -gamma 4.0000 0.0000 + +F- = F- + log_k 0.000 + -gamma 3.5000 0.0000 + +Li+ = Li+ + log_k 0.000 + -gamma 6.0000 0.0000 + +Br- = Br- + log_k 0.000 + -gamma 3.0000 0.0000 + +Zn+2 = Zn+2 + log_k 0.000 + -gamma 5.0000 0.0000 + +Cd+2 = Cd+2 + log_k 0.000 + +Pb+2 = Pb+2 + log_k 0.000 + +Cu+2 = Cu+2 + log_k 0.000 + -gamma 6.0000 0.0000 + +H2O = OH- + H+ + log_k -14.000 + delta_h 13.362 kcal + -analytic -283.971 -0.05069842 13323.0 102.24447 -1119669.0 + -gamma 3.5000 0.0000 + +2 H2O = O2 + 4 H+ + 4 e- + log_k -86.08 + delta_h 134.79 kcal + +2 H+ + 2 e- = H2 + log_k -3.15 + delta_h -1.759 kcal + +CO3-2 + H+ = HCO3- + log_k 10.329 + delta_h -3.561 kcal + -analytic 107.8871 0.03252849 -5151.79 -38.92561 563713.9 + -gamma 5.4000 0.0000 + +CO3-2 + 2 H+ = CO2 + H2O + log_k 16.681 + delta_h -5.738 kcal + -analytic 464.1965 0.09344813 -26986.16 -165.75951 2248628.9 + +CO3-2 + 10 H+ + 8 e- = CH4 + 3 H2O + log_k 41.071 + delta_h -61.039 kcal + +SO4-2 + H+ = HSO4- + log_k 1.988 + delta_h 3.85 kcal + -analytic -56.889 0.006473 2307.9 19.8858 0.0 + +HS- = S-2 + H+ + log_k -12.918 + delta_h 12.1 kcal + -gamma 5.0000 0.0000 + +SO4-2 + 9 H+ + 8 e- = HS- + 4 H2O + log_k 33.65 + delta_h -60.140 kcal + -gamma 3.5000 0.0000 + +HS- + H+ = H2S + log_k 6.994 + delta_h -5.300 kcal + -analytical -11.17 0.02386 3279.0 + + +NO3- + 2 H+ + 2 e- = NO2- + H2O + log_k 28.570 + delta_h -43.760 kcal + -gamma 3.0000 0.0000 + +2 NO3- + 12 H+ + 10 e- = N2 + 6 H2O + log_k 207.080 + delta_h -312.130 kcal + +NH4+ = NH3 + H+ + log_k -9.252 + delta_h 12.48 kcal + -analytic 0.6322 -0.001225 -2835.76 + +NO3- + 10 H+ + 8 e- = NH4+ + 3 H2O + log_k 119.077 + delta_h -187.055 kcal + -gamma 2.5000 0.0000 + +NH4+ + SO4-2 = NH4SO4- + log_k 1.11 + +H3BO3 = H2BO3- + H+ + log_k -9.240 + delta_h 3.224 kcal +# -analytical 24.3919 0.012078 -1343.9 -13.2258 + +H3BO3 + F- = BF(OH)3- + log_k -0.400 + delta_h 1.850 kcal + +H3BO3 + 2 F- + H+ = BF2(OH)2- + H2O + log_k 7.63 + delta_h 1.618 kcal + +H3BO3 + 2 H+ + 3 F- = BF3OH- + 2 H2O + log_k 13.67 + delta_h -1.614 kcal + +H3BO3 + 3 H+ + 4 F- = BF4- + 3 H2O + log_k 20.28 + delta_h -1.846 kcal + +PO4-3 + H+ = HPO4-2 + log_k 12.346 + delta_h -3.530 kcal + -gamma 4.0000 0.0000 + +PO4-3 + 2 H+ = H2PO4- + log_k 19.553 + delta_h -4.520 kcal + -gamma 4.5000 0.0000 + +H+ + F- = HF + log_k 3.18 + delta_h 3.18 kcal + -analytic -2.033 0.012645 429.01 + +H+ + 2 F- = HF2- + log_k 3.760 + delta_h 4.550 kcal + +Ca+2 + H2O = CaOH+ + H+ + log_k -12.780 + +Ca+2 + CO3-2 = CaCO3 + log_k 3.224 + delta_h 3.545 kcal + -analytic -1228.732 -0.299440 35512.75 485.818 + +Ca+2 + CO3-2 + H+ = CaHCO3+ + log_k 11.435 + delta_h -0.871 kcal + -analytic 1317.0071 0.34546894 -39916.84 -517.70761 563713.9 + -gamma 5.4000 0.0000 + +Ca+2 + SO4-2 = CaSO4 + log_k 2.300 + delta_h 1.650 kcal + +Ca+2 + HSO4- = CaHSO4+ + log_k 1.08 + +Ca+2 + PO4-3 = CaPO4- + log_k 6.459 + delta_h 3.100 kcal + +Ca+2 + HPO4-2 = CaHPO4 + log_k 2.739 + delta_h 3.3 kcal + +Ca+2 + H2PO4- = CaH2PO4+ + log_k 1.408 + delta_h 3.4 kcal + +Ca+2 + F- = CaF+ + log_k 0.940 + delta_h 4.120 kcal + +Mg+2 + H2O = MgOH+ + H+ + log_k -11.440 + delta_h 15.952 kcal + +Mg+2 + CO3-2 = MgCO3 + log_k 2.98 + delta_h 2.713 kcal + -analytic 0.9910 0.00667 + +Mg+2 + H+ + CO3-2 = MgHCO3+ + log_k 11.399 + delta_h -2.771 kcal + -analytic 48.6721 0.03252849 -2614.335 -18.00263 563713.9 + +Mg+2 + SO4-2 = MgSO4 + log_k 2.370 + delta_h 4.550 kcal + +Mg+2 + PO4-3 = MgPO4- + log_k 6.589 + delta_h 3.100 kcal + +Mg+2 + HPO4-2 = MgHPO4 + log_k 2.87 + delta_h 3.3 kcal + +Mg+2 + H2PO4- = MgH2PO4+ + log_k 1.513 + delta_h 3.4 kcal + +Mg+2 + F- = MgF+ + log_k 1.820 + delta_h 3.200 kcal + +Na+ + H2O = NaOH + H+ + log_k -14.180 + +Na+ + CO3-2 = NaCO3- + log_k 1.270 + delta_h 8.910 kcal + +Na+ + HCO3- = NaHCO3 + log_k -0.25 + +Na+ + SO4-2 = NaSO4- + log_k 0.700 + delta_h 1.120 kcal + +Na+ + HPO4-2 = NaHPO4- + log_k 0.29 + +Na+ + F- = NaF + log_k -0.240 + +K+ + H2O = KOH + H+ + log_k -14.460 + +K+ + SO4-2 = KSO4- + log_k 0.850 + delta_h 2.250 kcal + -analytical 3.106 0.0 -673.6 + + +K+ + HPO4-2 = KHPO4- + log_k 0.29 + +Fe+2 + H2O = FeOH+ + H+ + log_k -9.500 + delta_h 13.200 kcal + +Fe+2 + Cl- = FeCl+ + log_k 0.140 + +Fe+2 + CO3-2 = FeCO3 + log_k 4.380 + +Fe+2 + HCO3- = FeHCO3+ + log_k 2.0 + +Fe+2 + SO4-2 = FeSO4 + log_k 2.250 + delta_h 3.230 kcal + +Fe+2 + HSO4- = FeHSO4+ + log_k 1.08 + +Fe+2 + 2HS- = Fe(HS)2 + log_k 8.95 + +Fe+2 + 3HS- = Fe(HS)3- + log_k 10.987 + +Fe+2 + HPO4-2 = FeHPO4 + log_k 3.6 + +Fe+2 + H2PO4- = FeH2PO4+ + log_k 2.7 + +Fe+2 + F- = FeF+ + log_k 1.000 + +Fe+2 = Fe+3 + e- + log_k -13.020 + delta_h 9.680 kcal + -gamma 9.0000 0.0000 + +Fe+3 + H2O = FeOH+2 + H+ + log_k -2.19 + delta_h 10.4 kcal + +Fe+3 + 2 H2O = Fe(OH)2+ + 2 H+ + log_k -5.67 + delta_h 17.1 kcal + +Fe+3 + 3 H2O = Fe(OH)3 + 3 H+ + log_k -12.56 + delta_h 24.8 kcal + +Fe+3 + 4 H2O = Fe(OH)4- + 4 H+ + log_k -21.6 + delta_h 31.9 kcal + +2 Fe+3 + 2 H2O = Fe2(OH)2+4 + 2 H+ + log_k -2.95 + delta_h 13.5 kcal + +3 Fe+3 + 4 H2O = Fe3(OH)4+5 + 4 H+ + log_k -6.3 + delta_h 14.3 kcal + +Fe+3 + Cl- = FeCl+2 + log_k 1.48 + delta_h 5.6 kcal + +Fe+3 + 2 Cl- = FeCl2+ + log_k 2.13 + +Fe+3 + 3 Cl- = FeCl3 + log_k 1.13 + +Fe+3 + SO4-2 = FeSO4+ + log_k 4.04 + delta_h 3.91 kcal + +Fe+3 + HSO4- = FeHSO4+2 + log_k 2.48 + +Fe+3 + 2 SO4-2 = Fe(SO4)2- + log_k 5.38 + delta_h 4.60 kcal + +Fe+3 + HPO4-2 = FeHPO4+ + log_k 5.43 + delta_h 5.76 kcal + +Fe+3 + H2PO4- = FeH2PO4+2 + log_k 5.43 + +Fe+3 + F- = FeF+2 + log_k 6.2 + delta_h 2.7 kcal + +Fe+3 + 2 F- = FeF2+ + log_k 10.8 + delta_h 4.8 kcal + +Fe+3 + 3 F- = FeF3 + log_k 14.0 + delta_h 5.4 kcal + +Mn+2 + H2O = MnOH+ + H+ + log_k -10.590 + delta_h 14.400 kcal + +Mn+2 + Cl- = MnCl+ + log_k 0.610 + +Mn+2 + 2 Cl- = MnCl2 + log_k 0.250 + +Mn+2 + 3 Cl- = MnCl3- + log_k -0.310 + +Mn+2 + CO3-2 = MnCO3 + log_k 4.900 + +Mn+2 + HCO3- = MnHCO3+ + log_k 1.95 + +Mn+2 + SO4-2 = MnSO4 + log_k 2.250 + delta_h 3.370 kcal + +Mn+2 + 2 NO3- = Mn(NO3)2 + log_k 0.600 + delta_h -0.396 kcal + +Mn+2 + F- = MnF+ + log_k 0.840 + +Mn+2 = Mn+3 + e- + log_k -25.510 + delta_h 25.800 kcal + +Al+3 + H2O = AlOH+2 + H+ + log_k -5.00 + delta_h 11.49 kcal + -analytic -38.253 0.0 -656.27 14.327 + +Al+3 + 2 H2O = Al(OH)2+ + 2 H+ + log_k -10.1 + delta_h 26.90 kcal + -analytic 88.500 0.0 -9391.6 -27.121 + +Al+3 + 3 H2O = Al(OH)3 + 3 H+ + log_k -16.9 + delta_h 39.89 kcal + -analytic 226.374 0.0 -18247.8 -73.597 + +Al+3 + 4 H2O = Al(OH)4- + 4 H+ + log_k -22.7 + delta_h 42.30 kcal + -analytic 51.578 0.0 -11168.9 -14.865 + +Al+3 + SO4-2 = AlSO4+ + log_k 3.5 + delta_h 2.29 kcal + +Al+3 + 2SO4-2 = Al(SO4)2- + log_k 5.0 + delta_h 3.11 kcal + +Al+3 + HSO4- = AlHSO4+2 + log_k 0.46 + +Al+3 + F- = AlF+2 + log_k 7.000 + delta_h 1.060 kcal + +Al+3 + 2 F- = AlF2+ + log_k 12.700 + delta_h 1.980 kcal + +Al+3 + 3 F- = AlF3 + log_k 16.800 + delta_h 2.160 kcal + +Al+3 + 4 F- = AlF4- + log_k 19.400 + delta_h 2.200 kcal + +Al+3 + 5 F- = AlF5-2 + log_k 20.600 + delta_h 1.840 kcal + +Al+3 + 6 F- = AlF6-3 + log_k 20.600 + delta_h -1.670 kcal + +H4SiO4 = H3SiO4- + H+ + log_k -9.83 + delta_h 6.12 kcal + -analytic -302.3724 -0.050698 15669.69 108.18466 -1119669.0 + +H4SiO4 = H2SiO4-2 + 2 H+ + log_k -23.0 + delta_h 17.6 kcal + -analytic -294.0184 -0.072650 11204.49 108.18466 -1119669.0 + +H4SiO4 + 4 H+ + 6 F- = SiF6-2 + 4 H2O + log_k 30.180 + delta_h -16.260 kcal + +Ba+2 + H2O = BaOH+ + H+ + log_k -13.470 + +Ba+2 + CO3-2 = BaCO3 + log_k 2.71 + delta_h 3.55 kcal + -analytic 0.113 0.008721 + +Ba+2 + HCO3- = BaHCO3+ + log_k 0.982 + delta_h 5.56 kcal + -analytical -3.0938 0.013669 0.0 0.0 0.0 + +Ba+2 + SO4-2 = BaSO4 + log_k 2.700 + +Sr+2 + H2O = SrOH+ + H+ + log_k -13.290 + -gamma 5.0000 0.0000 + +Sr+2 + CO3-2 + H+ = SrHCO3+ + log_k 11.509 + delta_h 2.489 kcal + -analytic 104.6391 0.04739549 -5151.79 -38.92561 563713.9 + -gamma 5.4000 0.0000 + +Sr+2 + CO3-2 = SrCO3 + log_k 2.81 + delta_h 5.22 kcal + -analytic -1.019 0.012826 + +Sr+2 + SO4-2 = SrSO4 + log_k 2.290 + delta_h 2.080 kcal + +Li+ + H2O = LiOH + H+ + log_k -13.640 + +Li+ + SO4-2 = LiSO4- + log_k 0.640 + +Cu+2 + e- = Cu+ + log_k 2.720 + delta_h 1.650 kcal + -gamma 2.5000 0.0000 + +Cu+2 + H2O = CuOH+ + H+ + log_k -8.000 + -gamma 4.0000 0.0000 + +Cu+2 + 2 H2O = Cu(OH)2 + 2 H+ + log_k -13.680 + +Cu+2 + 3 H2O = Cu(OH)3- + 3 H+ + log_k -26.900 + +Cu+2 + 4 H2O = Cu(OH)4-2 + 4 H+ + log_k -39.600 + +Cu+2 + SO4-2 = CuSO4 + log_k 2.310 + delta_h 1.220 kcal + +Zn+2 + H2O = ZnOH+ + H+ + log_k -8.96 + delta_h 13.4 kcal + +Zn+2 + 2 H2O = Zn(OH)2 + 2 H+ + log_k -16.900 + +Zn+2 + 3 H2O = Zn(OH)3- + 3 H+ + log_k -28.400 + +Zn+2 + 4 H2O = Zn(OH)4-2 + 4 H+ + log_k -41.200 + +Zn+2 + Cl- = ZnCl+ + log_k 0.43 + delta_h 7.79 kcal + +Zn+2 + 2 Cl- = ZnCl2 + log_k 0.45 + delta_h 8.5 kcal + +Zn+2 + 3Cl- = ZnCl3- + log_k 0.5 + delta_h 9.56 kcal + +Zn+2 + 4Cl- = ZnCl4-2 + log_k 0.2 + delta_h 10.96 kcal + +Zn+2 + CO3-2 = ZnCO3 + log_k 5.3 + +Zn+2 + 2CO3-2 = Zn(CO3)2-2 + log_k 9.63 + +Zn+2 + HCO3- = ZnHCO3+ + log_k 2.1 + +Zn+2 + SO4-2 = ZnSO4 + log_k 2.37 + delta_h 1.36 kcal + +Zn+2 + 2SO4-2 = Zn(SO4)2-2 + log_k 3.28 + +Cd+2 + H2O = CdOH+ + H+ + log_k -10.080 + delta_h 13.1 kcal + +Cd+2 + 2 H2O = Cd(OH)2 + 2 H+ + log_k -20.350 + +Cd+2 + 3 H2O = Cd(OH)3- + 3 H+ + log_k -33.300 + +Cd+2 + 4 H2O = Cd(OH)4-2 + 4 H+ + log_k -47.350 + +Cd+2 + Cl- = CdCl+ + log_k 1.980 + delta_h 0.59 kcal + +Cd+2 + 2 Cl- = CdCl2 + log_k 2.600 + delta_h 1.24 kcal + +Cd+2 + 3 Cl- = CdCl3- + log_k 2.400 + delta_h 3.9 kcal + +Cd+2 + CO3-2 = CdCO3 + log_k 2.9 + +Cd+2 + 2CO3-2 = Cd(CO3)2-2 + log_k 6.4 + +Cd+2 + HCO3- = CdHCO3+ + log_k 1.5 + +Cd+2 + SO4-2 = CdSO4 + log_k 2.460 + delta_h 1.08 kcal + +Cd+2 + 2SO4-2 = Cd(SO4)2-2 + log_k 3.5 + +Pb+2 + H2O = PbOH+ + H+ + log_k -7.710 + +Pb+2 + 2 H2O = Pb(OH)2 + 2 H+ + log_k -17.120 + +Pb+2 + 3 H2O = Pb(OH)3- + 3 H+ + log_k -28.060 + +Pb+2 + 4 H2O = Pb(OH)4-2 + 4 H+ + log_k -39.700 + +2 Pb+2 + H2O = Pb2OH+3 + H+ + log_k -6.360 + +Pb+2 + Cl- = PbCl+ + log_k 1.600 + delta_h 4.38 kcal + +Pb+2 + 2 Cl- = PbCl2 + log_k 1.800 + delta_h 1.08 kcal + +Pb+2 + 3 Cl- = PbCl3- + log_k 1.700 + delta_h 2.17 kcal + +Pb+2 + 4 Cl- = PbCl4-2 + log_k 1.380 + delta_h 3.53 kcal + +Pb+2 + CO3-2 = PbCO3 + log_k 7.240 + +Pb+2 + 2 CO3-2 = Pb(CO3)2-2 + log_k 10.640 + +Pb+2 + HCO3- = PbHCO3+ + log_k 2.9 + +Pb+2 + SO4-2 = PbSO4 + log_k 2.750 + +Pb+2 + 2 SO4-2 = Pb(SO4)2-2 + log_k 3.470 + +Pb+2 + NO3- = PbNO3+ + log_k 1.170 + +PHASES + +Calcite + CaCO3 = CO3-2 + Ca+2 + log_k -8.480 + delta_h -2.297 kcal + -analytic -171.9065 -0.077993 2839.319 71.595 + +Aragonite + CaCO3 = CO3-2 + Ca+2 + log_k -8.336 + delta_h -2.589 kcal + -analytic -171.9773 -0.077993 2903.293 71.595 + +Dolomite + CaMg(CO3)2 = Ca+2 + Mg+2 + 2 CO3-2 + log_k -17.090 + delta_h -9.436 kcal + +Siderite + FeCO3 = Fe+2 + CO3-2 + log_k -10.890 + delta_h -2.480 kcal + +Rhodochrosite + MnCO3 = Mn+2 + CO3-2 + log_k -11.130 + delta_h -1.430 kcal + +Strontianite + SrCO3 = Sr+2 + CO3-2 + log_k -9.271 + delta_h -0.400 kcal + -analytic 155.0305 0.0 -7239.594 -56.58638 + +Witherite + BaCO3 = Ba+2 + CO3-2 + log_k -8.562 + delta_h 0.703 kcal + -analytic 607.642 0.121098 -20011.25 -236.4948 + +Gypsum + CaSO4:2H2O = Ca+2 + SO4-2 + 2 H2O + log_k -4.580 + delta_h -0.109 kcal + -analytic 68.2401 0.0 -3221.51 -25.0627 + +Anhydrite + CaSO4 = Ca+2 + SO4-2 + log_k -4.360 + delta_h -1.710 kcal + -analytic 197.52 0.0 -8669.8 -69.835 + +Celestite + SrSO4 = Sr+2 + SO4-2 + log_k -6.630 + delta_h -1.037 kcal + -analytic -14805.9622 -2.4660924 756968.533 5436.3588 -40553604.0 + +Barite + BaSO4 = Ba+2 + SO4-2 + log_k -9.970 + delta_h 6.350 kcal + -analytic 136.035 0.0 -7680.41 -48.595 + +Hydroxyapatite + Ca5(PO4)3OH + 4 H+ = H2O + 3 HPO4-2 + 5 Ca+2 + log_k -3.421 + delta_h -36.155 kcal + +Fluorite + CaF2 = Ca+2 + 2 F- + log_k -10.600 + delta_h 4.690 kcal + -analytic 66.348 0.0 -4298.2 -25.271 + +SiO2(a) + SiO2 + 2 H2O = H4SiO4 + log_k -2.710 + delta_h 3.340 kcal + -analytic -0.26 0.0 -731.0 + +Chalcedony + SiO2 + 2 H2O = H4SiO4 + log_k -3.550 + delta_h 4.720 kcal + -analytic -0.09 0.0 -1032.0 + +Quartz + SiO2 + 2 H2O = H4SiO4 + log_k -3.980 + delta_h 5.990 kcal + -analytic 0.41 0.0 -1309.0 + +Gibbsite + Al(OH)3 + 3 H+ = Al+3 + 3 H2O + log_k 8.110 + delta_h -22.800 kcal + +Al(OH)3(a) + Al(OH)3 + 3 H+ = Al+3 + 3 H2O + log_k 10.800 + delta_h -26.500 kcal + +Kaolinite + Al2Si2O5(OH)4 + 6 H+ = H2O + 2 H4SiO4 + 2 Al+3 + log_k 7.435 + delta_h -35.300 kcal + +Albite + NaAlSi3O8 + 8 H2O = Na+ + Al(OH)4- + 3 H4SiO4 + log_k -18.002 + delta_h 25.896 kcal + +Anorthite + CaAl2Si2O8 + 8 H2O = Ca+2 + 2 Al(OH)4- + 2 H4SiO4 + log_k -19.714 + delta_h 11.580 kcal + +K-feldspar + KAlSi3O8 + 8 H2O = K+ + Al(OH)4- + 3 H4SiO4 + log_k -20.573 + delta_h 30.820 kcal + +K-mica + KAl3Si3O10(OH)2 + 10 H+ = K+ + 3 Al+3 + 3 H4SiO4 + log_k 12.703 + delta_h -59.376 kcal + +Chlorite(14A) + Mg5Al2Si3O10(OH)8 + 16H+ = 5Mg+2 + 2Al+3 + 3H4SiO4 + 6H2O + log_k 68.38 + delta_h -151.494 kcal + +Ca-Montmorillonite + Ca0.165Al2.33Si3.67O10(OH)2 + 12 H2O = 0.165Ca+2 + 2.33 Al(OH)4- + 3.67 H4SiO4 + 2 H+ + log_k -45.027 + delta_h 58.373 kcal + +Talc + Mg3Si4O10(OH)2 + 4 H2O + 6 H+ = 3 Mg+2 + 4 H4SiO4 + log_k 21.399 + delta_h -46.352 kcal + +Illite + K0.6Mg0.25Al2.3Si3.5O10(OH)2 + 11.2H2O = 0.6K+ + 0.25Mg+2 + 2.3Al(OH)4- + 3.5H4SiO4 + 1.2H+ + log_k -40.267 + delta_h 54.684 kcal + +Chrysotile + Mg3Si2O5(OH)4 + 6 H+ = H2O + 2 H4SiO4 + 3 Mg+2 + log_k 32.200 + delta_h -46.800 kcal + -analytic 13.248 0.0 10217.1 -6.1894 + +Sepiolite + Mg2Si3O7.5OH:3H2O + 4 H+ + 0.5H2O = 2 Mg+2 + 3 H4SiO4 + log_k 15.760 + delta_h -10.700 kcal + +Sepiolite(d) + Mg2Si3O7.5OH:3H2O + 4 H+ + 0.5H2O = 2 Mg+2 + 3 H4SiO4 + log_k 18.660 + +Hematite + Fe2O3 + 6 H+ = 2 Fe+3 + 3 H2O + log_k -4.008 + delta_h -30.845 kcal + +Goethite + FeOOH + 3 H+ = Fe+3 + 2 H2O + log_k -1.000 + delta_h -14.48 kcal + +Fe(OH)3(a) + Fe(OH)3 + 3 H+ = Fe+3 + 3 H2O + log_k 4.891 + +Pyrite + FeS2 + 2 H+ + 2 e- = Fe+2 + 2 HS- + log_k -18.479 + delta_h 11.300 kcal + +FeS(ppt) + FeS + H+ = Fe+2 + HS- + log_k -3.915 + +Mackinawite + FeS + H+ = Fe+2 + HS- + log_k -4.648 + +Sulfur + S + 2H+ + 2e- = H2S + log_k 4.882 + delta_h -9.5 kcal + +Vivianite + Fe3(PO4)2:8H2O = 3 Fe+2 + 2 PO4-3 + 8 H2O + log_k -36.000 + +Pyrolusite + MnO2 + 4 H+ + 2 e- = Mn+2 + 2 H2O + log_k 41.380 + delta_h -65.110 kcal + +Hausmannite + Mn3O4 + 8 H+ + 2 e- = 3 Mn+2 + 4 H2O + log_k 61.030 + delta_h -100.640 kcal + +Manganite + MnOOH + 3 H+ + e- = Mn+2 + 2 H2O + log_k 25.340 + +Pyrochroite + Mn(OH)2 + 2 H+ = Mn+2 + 2 H2O + log_k 15.200 + +Halite + NaCl = Na+ + Cl- + log_k 1.582 + delta_h 0.918 kcal + +CO2(g) + CO2 = CO2 + log_k -1.468 + delta_h -4.776 kcal + -analytic 108.3865 0.01985076 -6919.53 -40.45154 669365.0 + +O2(g) + O2 = O2 + log_k -2.960 + delta_h -1.844 kcal + +H2(g) + H2 = H2 + log_k -3.150 + delta_h -1.759 kcal + +H2O(g) + H2O = H2O + log_k 1.51 + delta_h -44.03 kJ +# Stumm and Morgan, from NBS and Robie, Hemmingway, and Fischer (1978) + +N2(g) + N2 = N2 + log_k -3.260 + delta_h -1.358 kcal + +H2S(g) + H2S = H2S + log_k -0.997 + delta_h -4.570 kcal + +CH4(g) + CH4 = CH4 + log_k -2.860 + delta_h -3.373 kcal + +NH3(g) + NH3 = NH3 + log_k 1.770 + delta_h -8.170 kcal + +Melanterite + FeSO4:7H2O = 7 H2O + Fe+2 + SO4-2 + log_k -2.209 + delta_h 4.910 kcal + -analytic 1.447 -0.004153 0.0 0.0 -214949.0 + +Alunite + KAl3(SO4)2(OH)6 + 6 H+ = K+ + 3 Al+3 + 2 SO4-2 + 6H2O + log_k -1.400 + delta_h -50.250 kcal + +Jarosite-K + KFe3(SO4)2(OH)6 + 6 H+ = 3 Fe+3 + 6 H2O + K+ + 2 SO4-2 + log_k -9.210 + delta_h -31.280 kcal + +Zn(OH)2(e) + Zn(OH)2 + 2 H+ = Zn+2 + 2 H2O + log_k 11.50 + +Smithsonite + ZnCO3 = Zn+2 + CO3-2 + log_k -10.000 + delta_h -4.36 kcal + +Sphalerite + ZnS + H+ = Zn+2 + HS- + log_k -11.618 + delta_h 8.250 kcal + +Willemite 289 + Zn2SiO4 + 4H+ = 2Zn+2 + H4SiO4 + log_k 15.33 + delta_h -33.37 kcal + +Cd(OH)2 + Cd(OH)2 + 2 H+ = Cd+2 + 2 H2O + log_k 13.650 + +Otavite 315 + CdCO3 = Cd+2 + CO3-2 + log_k -12.1 + delta_h -0.019 kcal + +CdSiO3 328 + CdSiO3 + H2O + 2H+ = Cd+2 + H4SiO4 + log_k 9.06 + delta_h -16.63 kcal + +CdSO4 329 + CdSO4 = Cd+2 + SO4-2 + log_k -0.1 + delta_h -14.74 kcal + +Cerrusite 365 + PbCO3 = Pb+2 + CO3-2 + log_k -13.13 + delta_h 4.86 kcal + +Anglesite 384 + PbSO4 = Pb+2 + SO4-2 + log_k -7.79 + delta_h 2.15 kcal + +Pb(OH)2 389 + Pb(OH)2 + 2H+ = Pb+2 + 2H2O + log_k 8.15 + delta_h -13.99 kcal + +EXCHANGE_MASTER_SPECIES + X X- +EXCHANGE_SPECIES + X- = X- + log_k 0.0 + + Na+ + X- = NaX + log_k 0.0 + -gamma 4.0 0.075 + + K+ + X- = KX + log_k 0.7 + -gamma 3.5 0.015 + delta_h -4.3 # Jardine & Sparks, 1984 + + Li+ + X- = LiX + log_k -0.08 + -gamma 6.0 0.0 + delta_h 1.4 # Merriam & Thomas, 1956 + + NH4+ + X- = NH4X + log_k 0.6 + -gamma 2.5 0.0 + delta_h -2.4 # Laudelout et al., 1968 + + Ca+2 + 2X- = CaX2 + log_k 0.8 + -gamma 5.0 0.165 + delta_h 7.2 # Van Bladel & Gheyl, 1980 + + Mg+2 + 2X- = MgX2 + log_k 0.6 + -gamma 5.5 0.2 + delta_h 7.4 # Laudelout et al., 1968 + + Sr+2 + 2X- = SrX2 + log_k 0.91 + -gamma 5.26 0.121 + delta_h 5.5 # Laudelout et al., 1968 + + Ba+2 + 2X- = BaX2 + log_k 0.91 + -gamma 5.0 0.0 + delta_h 4.5 # Laudelout et al., 1968 + + Mn+2 + 2X- = MnX2 + log_k 0.52 + -gamma 6.0 0.0 + + Fe+2 + 2X- = FeX2 + log_k 0.44 + -gamma 6.0 0.0 + + Cu+2 + 2X- = CuX2 + log_k 0.6 + -gamma 6.0 0.0 + + Zn+2 + 2X- = ZnX2 + log_k 0.8 + -gamma 5.0 0.0 + + Cd+2 + 2X- = CdX2 + log_k 0.8 + + Pb+2 + 2X- = PbX2 + log_k 1.05 + + Al+3 + 3X- = AlX3 + log_k 0.41 + -gamma 9.0 0.0 + + AlOH+2 + 2X- = AlOHX2 + log_k 0.89 + -gamma 0.0 0.0 +SURFACE_MASTER_SPECIES + Hfo_s Hfo_sOH + Hfo_w Hfo_wOH +SURFACE_SPECIES +# All surface data from +# Dzombak and Morel, 1990 +# +# +# Acid-base data from table 5.7 +# +# strong binding site--Hfo_s, + + Hfo_sOH = Hfo_sOH + log_k 0.0 + + Hfo_sOH + H+ = Hfo_sOH2+ + log_k 7.29 # = pKa1,int + + Hfo_sOH = Hfo_sO- + H+ + log_k -8.93 # = -pKa2,int + +# weak binding site--Hfo_w + + Hfo_wOH = Hfo_wOH + log_k 0.0 + + Hfo_wOH + H+ = Hfo_wOH2+ + log_k 7.29 # = pKa1,int + + Hfo_wOH = Hfo_wO- + H+ + log_k -8.93 # = -pKa2,int + +############################################### +# CATIONS # +############################################### +# +# Cations from table 10.1 or 10.5 +# +# Calcium + Hfo_sOH + Ca+2 = Hfo_sOHCa+2 + log_k 4.97 + + Hfo_wOH + Ca+2 = Hfo_wOCa+ + H+ + log_k -5.85 +# Strontium + Hfo_sOH + Sr+2 = Hfo_sOHSr+2 + log_k 5.01 + + Hfo_wOH + Sr+2 = Hfo_wOSr+ + H+ + log_k -6.58 + + Hfo_wOH + Sr+2 + H2O = Hfo_wOSrOH + 2H+ + log_k -17.60 +# Barium + Hfo_sOH + Ba+2 = Hfo_sOHBa+2 + log_k 5.46 + + Hfo_wOH + Ba+2 = Hfo_wOBa+ + H+ + log_k -7.2 # table 10.5 +# +# Cations from table 10.2 +# +# Cadmium + Hfo_sOH + Cd+2 = Hfo_sOCd+ + H+ + log_k 0.47 + + Hfo_wOH + Cd+2 = Hfo_wOCd+ + H+ + log_k -2.91 +# Zinc + Hfo_sOH + Zn+2 = Hfo_sOZn+ + H+ + log_k 0.99 + + Hfo_wOH + Zn+2 = Hfo_wOZn+ + H+ + log_k -1.99 +# Copper + Hfo_sOH + Cu+2 = Hfo_sOCu+ + H+ + log_k 2.89 + + Hfo_wOH + Cu+2 = Hfo_wOCu+ + H+ + log_k 0.6 # table 10.5 +# Lead + Hfo_sOH + Pb+2 = Hfo_sOPb+ + H+ + log_k 4.65 + + Hfo_wOH + Pb+2 = Hfo_wOPb+ + H+ + log_k 0.3 # table 10.5 +# +# Derived constants table 10.5 +# +# Magnesium + Hfo_wOH + Mg+2 = Hfo_wOMg+ + H+ + log_k -4.6 +# Manganese + Hfo_sOH + Mn+2 = Hfo_sOMn+ + H+ + log_k -0.4 # table 10.5 + + Hfo_wOH + Mn+2 = Hfo_wOMn+ + H+ + log_k -3.5 # table 10.5 +# Iron +# Hfo_sOH + Fe+2 = Hfo_sOFe+ + H+ +# log_k 0.7 # LFER using table 10.5 + +# Hfo_wOH + Fe+2 = Hfo_wOFe+ + H+ +# log_k -2.5 # LFER using table 10.5 + +# Iron, strong site: Appelo, Van der Weiden, Tournassat & Charlet, subm. + Hfo_sOH + Fe+2 = Hfo_sOFe+ + H+ + log_k -0.95 +# Iron, weak site: Liger et al., GCA 63, 2939, re-optimized for D&M + Hfo_wOH + Fe+2 = Hfo_wOFe+ + H+ + log_k -2.98 + + Hfo_wOH + Fe+2 + H2O = Hfo_wOFeOH + 2H+ + log_k -11.55 + +############################################### +# ANIONS # +############################################### +# +# Anions from table 10.6 +# +# Phosphate + Hfo_wOH + PO4-3 + 3H+ = Hfo_wH2PO4 + H2O + log_k 31.29 + + Hfo_wOH + PO4-3 + 2H+ = Hfo_wHPO4- + H2O + log_k 25.39 + + Hfo_wOH + PO4-3 + H+ = Hfo_wPO4-2 + H2O + log_k 17.72 +# +# Anions from table 10.7 +# +# Borate + Hfo_wOH + H3BO3 = Hfo_wH2BO3 + H2O + log_k 0.62 +# +# Anions from table 10.8 +# +# Sulfate + Hfo_wOH + SO4-2 + H+ = Hfo_wSO4- + H2O + log_k 7.78 + + Hfo_wOH + SO4-2 = Hfo_wOHSO4-2 + log_k 0.79 +# +# Derived constants table 10.10 +# + Hfo_wOH + F- + H+ = Hfo_wF + H2O + log_k 8.7 + + Hfo_wOH + F- = Hfo_wOHF- + log_k 1.6 +# +# Carbonate: Van Geen et al., 1994 reoptimized for HFO +# 0.15 g HFO/L has 0.344 mM sites == 2 g of Van Geen's Goethite/L +# +# Hfo_wOH + CO3-2 + H+ = Hfo_wCO3- + H2O +# log_k 12.56 +# +# Hfo_wOH + CO3-2 + 2H+= Hfo_wHCO3 + H2O +# log_k 20.62 + +# 9/19/96 +# Added analytical expression for H2S, NH3, KSO4. +# Added species CaHSO4+. +# Added delta H for Goethite. + +RATES + +########### +#K-feldspar +########### +# +# Sverdrup, H.U., 1990, The kinetics of base cation release due to +# chemical weathering: Lund University Press, Lund, 246 p. +# +# Example of KINETICS data block for K-feldspar rate: +# KINETICS 1 +# K-feldspar +# -m0 2.16 # 10% K-fsp, 0.1 mm cubes +# -m 1.94 +# -parms 1.36e4 0.1 + +K-feldspar + -start + 1 rem specific rate from Sverdrup, 1990, in kmol/m2/s + 2 rem parm(1) = 10 * (A/V, 1/dm) (recalc's sp. rate to mol/kgw) + 3 rem parm(2) = corrects for field rate relative to lab rate + 4 rem temp corr: from p. 162. E (kJ/mol) / R / 2.303 = H in H*(1/T-1/298) + + 10 dif_temp = 1/TK - 1/298 + 20 pk_H = 12.5 + 3134 * dif_temp + 30 pk_w = 15.3 + 1838 * dif_temp + 40 pk_OH = 14.2 + 3134 * dif_temp + 50 pk_CO2 = 14.6 + 1677 * dif_temp + #60 pk_org = 13.9 + 1254 * dif_temp # rate increase with DOC + 70 rate = 10^-pk_H * ACT("H+")^0.5 + 10^-pk_w + 10^-pk_OH * ACT("OH-")^0.3 + 71 rate = rate + 10^-pk_CO2 * (10^SI("CO2(g)"))^0.6 + #72 rate = rate + 10^-pk_org * TOT("Doc")^0.4 + 80 moles = parm(1) * parm(2) * rate * (1 - SR("K-feldspar")) * time + 81 rem decrease rate on precipitation + 90 if SR("K-feldspar") > 1 then moles = moles * 0.1 + 100 save moles + -end + +########### +#Albite +########### +# +# Sverdrup, H.U., 1990, The kinetics of base cation release due to +# chemical weathering: Lund University Press, Lund, 246 p. +# +# Example of KINETICS data block for Albite rate: +# KINETICS 1 +# Albite +# -m0 0.43 # 2% Albite, 0.1 mm cubes +# -parms 2.72e3 0.1 + +Albite + -start + 1 rem specific rate from Sverdrup, 1990, in kmol/m2/s + 2 rem parm(1) = 10 * (A/V, 1/dm) (recalc's sp. rate to mol/kgw) + 3 rem parm(2) = corrects for field rate relative to lab rate + 4 rem temp corr: from p. 162. E (kJ/mol) / R / 2.303 = H in H*(1/T-1/298) + + 10 dif_temp = 1/TK - 1/298 + 20 pk_H = 12.5 + 3359 * dif_temp + 30 pk_w = 14.8 + 2648 * dif_temp + 40 pk_OH = 13.7 + 3359 * dif_temp + #41 rem ^12.9 in Sverdrup, but larger than for oligoclase... + 50 pk_CO2 = 14.0 + 1677 * dif_temp + #60 pk_org = 12.5 + 1254 * dif_temp # ...rate increase for DOC + 70 rate = 10^-pk_H * ACT("H+")^0.5 + 10^-pk_w + 10^-pk_OH * ACT("OH-")^0.3 + 71 rate = rate + 10^-pk_CO2 * (10^SI("CO2(g)"))^0.6 + #72 rate = rate + 10^-pk_org * TOT("Doc")^0.4 + 80 moles = parm(1) * parm(2) * rate * (1 - SR("Albite")) * time + 81 rem decrease rate on precipitation + 90 if SR("Albite") > 1 then moles = moles * 0.1 + 100 save moles + -end + +######## +#Calcite +######## +# +# Plummer, L.N., Wigley, T.M.L., and Parkhurst, D.L., 1978, +# American Journal of Science, v. 278, p. 179-216. +# +# Example of KINETICS data block for calcite rate: +# +# KINETICS 1 +# Calcite +# -tol 1e-8 +# -m0 3.e-3 +# -m 3.e-3 +# -parms 5.0 0.6 +Calcite + -start + 1 REM Modified from Plummer and others, 1978 + 2 REM M = current moles of calcite + 3 REM M0 = initial moles of calcite + 4 REM parm(1) = Area/Volume, cm^2/L (or cm^2 per cell) + 5 REM parm(2) = exponent for M/M0 for surface area correction + 10 REM rate = 0 if no calcite and undersaturated + 20 si_cc = SI("Calcite") + 30 if (M <= 0 and si_cc < 0) then goto 300 + 40 k1 = 10^(0.198 - 444.0 / TK ) + 50 k2 = 10^(2.84 - 2177.0 / TK ) + 60 if TC <= 25 then k3 = 10^(-5.86 - 317.0 / TK ) + 70 if TC > 25 then k3 = 10^(-1.1 - 1737.0 / TK ) + 80 REM surface area calculation + 90 t = 1 + 100 if M0 > 0 then t = M/M0 + 110 if t = 0 then t = 1 + 120 area = PARM(1) * (t)^PARM(2) + 130 rf = k1 * ACT("H+") + k2 * ACT("CO2") + k3 * ACT("H2O") + 140 REM 1e-3 converts mmol to mol + 150 rate = area * 1e-3 * rf * (1 - 10^(2/3*si_cc)) + 160 moles = rate * TIME + 170 REM do not dissolve more calcite than present + 180 if (moles > M) then moles = M + 190 if (moles >= 0) then goto 300 + 200 REM do not precipitate more Ca or C(4) than present + 210 temp = TOT("Ca") + 220 mc = TOT("C(4)") + 230 if mc < temp then temp = mc + 240 if -moles > temp then moles = -temp + 300 SAVE moles + -end + +####### +#Pyrite +####### +# +# Williamson, M.A. and Rimstidt, J.D., 1994, +# Geochimica et Cosmochimica Acta, v. 58, p. 5443-5454. +# +# Example of KINETICS data block for pyrite rate: +# KINETICS 1 +# Pyrite +# -tol 1e-8 +# -m0 5.e-4 +# -m 5.e-4 +# -parms 2.0 0.67 .5 -0.11 +Pyrite + -start + 1 rem Williamson and Rimstidt, 1994 + 2 rem parm(1) = log10(A/V, 1/dm) parm(2) = exp for (m/m0) + 3 rem parm(3) = exp for O2 parm(4) = exp for H+ + + 10 if (m <= 0) then goto 200 + 20 if (si("Pyrite") >= 0) then goto 200 + 20 rate = -10.19 + parm(1) + parm(3)*lm("O2") + parm(4)*lm("H+") + parm(2)*log10(m/m0) + 30 moles = 10^rate * time + 40 if (moles > m) then moles = m + 200 save moles + -end + +########## +#Organic_C +########## +# +# Example of KINETICS data block for Organic_C rate: +# KINETICS 1 +# Organic_C +# -tol 1e-8 +# # m in mol/kgw +# -m0 5e-3 +# -m 5e-3 +Organic_C + -start + 1 rem Additive Monod kinetics + 2 rem Electron acceptors: O2, NO3, and SO4 + + 10 if (m <= 0) then goto 200 + 20 mO2 = mol("O2") + 30 mNO3 = tot("N(5)") + 40 mSO4 = tot("S(6)") + 50 rate = 1.57e-9*mO2/(2.94e-4 + mO2) + 1.67e-11*mNO3/(1.55e-4 + mNO3) + 60 rate = rate + 1.e-13*mSO4/(1.e-4 + mSO4) + 70 moles = rate * m * (m/m0) * time + 80 if (moles > m) then moles = m + 200 save moles + -end + +########### +#Pyrolusite +########### +# +# Postma, D. and Appelo, C.A.J., 2000, GCA 64, in press +# +# Example of KINETICS data block for Pyrolusite +# KINETICS 1-12 +# Pyrolusite +# -tol 1.e-7 +# -m0 0.1 +# -m 0.1 +Pyrolusite + -start + 5 if (m <= 0.0) then goto 200 + 7 sr_pl = sr("Pyrolusite") + 9 if abs(1 - sr_pl) < 0.1 then goto 200 + 10 if (sr_pl > 1.0) then goto 100 + #20 rem initially 1 mol Fe+2 = 0.5 mol pyrolusite. k*A/V = 1/time (3 cells) + #22 rem time (3 cells) = 1.432e4. 1/time = 6.98e-5 + 30 Fe_t = tot("Fe(2)") + 32 if Fe_t < 1.e-8 then goto 200 + 40 moles = 6.98e-5 * Fe_t * (m/m0)^0.67 * time * (1 - sr_pl) + 50 if moles > Fe_t / 2 then moles = Fe_t / 2 + 70 if moles > m then moles = m + 90 goto 200 + 100 Mn_t = tot("Mn") + 110 moles = 2e-3 * 6.98e-5 * (1-sr_pl) * time + 120 if moles <= -Mn_t then moles = -Mn_t + 200 save moles + -end +END diff --git a/gtest/multi_punch b/gtest/multi_punch new file mode 100644 index 00000000..b8cf29e7 --- /dev/null +++ b/gtest/multi_punch @@ -0,0 +1,105 @@ +SOLUTION 1 + pH 7 charge + Na 1 + Cl 1 + Ca 1 + C 2 +END +CALCULATE_VALUES +TOTAL_C +-start +10 save TOT("C") +-end +END +EQUILIBRIUM_PHASES 1 + CO2(g) -2 + Dolomite 0 +END +REACTION 1 + HCl 1 + 0.1 mmol +END +GAS_PHASE + -fixed_volume + N2(g) 1.2 +END +KINETICS + Calcite + -tol 1e-8 + -m0 3.e-3 + -m 3.e-3 + -parms 50 0.6 +END +SOLID_SOLUTION +Sulfate + -comp Anhydrite 1.0 + -comp Barite 1.0 +END +RUN_CELLS + -cell 1 +SELECTED_OUTPUT + -file multi_punch_1.sel + -reset false + -sim + -state + -solution + -dist + -time + -step + -pH + -pe + -reaction + -temperature + -alkalinity + -ionic_strength + -water + -charge_balance + -percent_error + -totals Na Ca + -molalities Na+ HCO3- + -activities Ca+2 CO3-2 + -equilibrium_phases CO2(g) dolomite + -saturation_indices Halite + -gases N2(g) + -kinetics Calcite + -solid_solutions Anhydrite Barite + -calculate_values TOTAL_C + -inverse false +SELECTED_OUTPUT 2 + -file multi_punch_2.sel + -si Halite Calcite +USER_PUNCH 20 +-heading Dummy +10 PUNCH "Dummy" +END +USER_PUNCH 2 +-heading DUMMY_1 DUMMY_2 +10 PUNCH "Dummy1", "Dummy2" +RUN_CELLS + -cell 1 +SELECTED_OUTPUT 1 + -active false +END +RUN_CELLS + -cell 1 +SELECTED_OUTPUT 1 + -active true +END +SOLUTION 2 + pH 7 charge +END +SOLUTION 3 + pH 7 charge + Na 1 + Cl 1 +END +INVERSE_MODELING + -solution 2 3 + -phases + Halite +SELECTED_OUTPUT 3 + -reset false + -file multi_punch_3.sel +END +RUN_CELLS + -cell 1 \ No newline at end of file diff --git a/gtest/multi_punch_no_set b/gtest/multi_punch_no_set new file mode 100644 index 00000000..890c1d5b --- /dev/null +++ b/gtest/multi_punch_no_set @@ -0,0 +1,102 @@ +SOLUTION 1 + pH 7 charge + Na 1 + Cl 1 + Ca 1 + C 2 +END +CALCULATE_VALUES +TOTAL_C +-start +10 save TOT("C") +-end +END +EQUILIBRIUM_PHASES 1 + CO2(g) -2 + Dolomite 0 +END +REACTION 1 + HCl 1 + 0.1 mmol +END +GAS_PHASE + -fixed_volume + N2(g) 1.2 +END +KINETICS + Calcite + -tol 1e-8 + -m0 3.e-3 + -m 3.e-3 + -parms 50 0.6 +END +SOLID_SOLUTION +Sulfate + -comp Anhydrite 1.0 + -comp Barite 1.0 +END +RUN_CELLS + -cell 1 +SELECTED_OUTPUT + -reset false + -sim + -state + -solution + -dist + -time + -step + -pH + -pe + -reaction + -temperature + -alkalinity + -ionic_strength + -water + -charge_balance + -percent_error + -totals Na Ca + -molalities Na+ HCO3- + -activities Ca+2 CO3-2 + -equilibrium_phases CO2(g) dolomite + -saturation_indices Halite + -gases N2(g) + -kinetics Calcite + -solid_solutions Anhydrite Barite + -calculate_values TOTAL_C + -inverse false +SELECTED_OUTPUT 2 + -si Halite Calcite +USER_PUNCH 20 +-heading Dummy +10 PUNCH "Dummy" +END +USER_PUNCH 2 +-heading DUMMY_1 DUMMY_2 +10 PUNCH "Dummy1", "Dummy2" +RUN_CELLS + -cell 1 +SELECTED_OUTPUT 1 + -active false +END +RUN_CELLS + -cell 1 +SELECTED_OUTPUT 1 + -active true +END +SOLUTION 2 + pH 7 charge +END +SOLUTION 3 + pH 7 charge + Na 1 + Cl 1 +END +INVERSE_MODELING + -solution 2 3 + -phases + Halite +SELECTED_OUTPUT 3 + -reset false +END +RUN_CELLS + -cell 1 \ No newline at end of file diff --git a/src/CSelectedOutput.hxx b/src/CSelectedOutput.hxx index fd1ab794..e5d20ef3 100644 --- a/src/CSelectedOutput.hxx +++ b/src/CSelectedOutput.hxx @@ -15,7 +15,13 @@ #include #include "CVar.hxx" -class CSelectedOutput +#if defined(_WINDLL) +#define IPQ_DLL_EXPORT __declspec(dllexport) +#else +#define IPQ_DLL_EXPORT +#endif + +class IPQ_DLL_EXPORT CSelectedOutput { public: CSelectedOutput(void); diff --git a/src/phreeqcpp/common/PHRQ_io.h b/src/phreeqcpp/common/PHRQ_io.h index 8c469248..f020b2eb 100644 --- a/src/phreeqcpp/common/PHRQ_io.h +++ b/src/phreeqcpp/common/PHRQ_io.h @@ -44,8 +44,8 @@ public: static void safe_close(std::ostream **stream_ptr); static void safe_close(FILE **file_ptr); void close_ostreams(void); - void Set_io_error_count(int i) {this->io_error_count = i;}; - int Get_io_error_count(void) {return this->io_error_count;}; + void Set_io_error_count(int i) {this->io_error_count = i;}; + int Get_io_error_count(void)const {return this->io_error_count;}; // istreams @@ -65,7 +65,7 @@ public: void Set_output_ostream(std::ostream * out) {this->output_ostream = out;}; std::ostream *Get_output_ostream(void) {return this->output_ostream;}; void Set_output_on(bool tf) {this->output_on = tf;}; - bool Get_output_on(void) {return this->output_on;}; + bool Get_output_on(void)const {return this->output_on;}; // log_ostream virtual bool log_open(const char *file_name, std::ios_base::openmode mode = std::ios_base::out); @@ -75,7 +75,7 @@ public: void Set_log_ostream(std::ostream * out) {this->log_ostream = out;} std::ostream *Get_log_ostream(void) {return this->log_ostream;} void Set_log_on(bool tf) {this->log_on = tf;} - bool Get_log_on(void) {return this->log_on;} + bool Get_log_on(void)const {return this->log_on;} // punch_ostream virtual bool punch_open(const char *file_name, std::ios_base::openmode mode = std::ios_base::out, int n_user = 1); @@ -94,19 +94,19 @@ public: void error_close(void); virtual void error_msg(const char * str, bool stop=false); void Set_error_ostream(std::ostream * out) {this->error_ostream = out;} - std::ostream *Get_error_ostream(void) {return this->error_ostream;} + std::ostream *Get_error_ostream(void)const {return this->error_ostream;} void Set_error_on(bool tf) {this->error_on = tf;} - bool Get_error_on(void) {return this->error_on;} + bool Get_error_on(void)const {return this->error_on;} virtual void warning_msg(const char *err_str); #else virtual bool error_open(const char *file_name, const char * mode = "w"); void error_flush(void); void error_close(void); virtual void error_msg(const char * str, bool stop=false); - void Set_error_file(FILE * out) {this->error_file = out;} - FILE *Get_error_file(void) {return this->error_file;} + void Set_error_file(FILE * out) {this->error_file = out;} + FILE *Get_error_file(void)const {return this->error_file;} void Set_error_on(bool tf) {this->error_on = tf;} - bool Get_error_on(void) {return this->error_on;} + bool Get_error_on(void)const {return this->error_on;} virtual void warning_msg(const char *err_str); #endif @@ -118,7 +118,7 @@ public: void Set_dump_ostream(std::ostream * out) {this->dump_ostream = out;}; std::ostream *Get_dump_ostream(void) {return this->dump_ostream;}; void Set_dump_on(bool tf) {this->dump_on = tf;}; - bool Get_dump_on(void) {return this->dump_on;}; + bool Get_dump_on(void)const {return this->dump_on;}; // fpunchf virtual void fpunchf(const char *name, const char *format, double d); @@ -130,17 +130,17 @@ public: virtual void screen_msg(const char * str); void Set_screen_on(bool tf) {this->screen_on = tf;}; - bool Get_screen_on(void) {return this->screen_on;}; + bool Get_screen_on(void)const {return this->screen_on;}; // input methods virtual int getc(void); virtual LINE_TYPE get_line(void); virtual LINE_TYPE get_logical_line(void); bool check_key(std::string::iterator begin, std::string::iterator end); - std::string & Get_m_line() {return m_line;} - std::string & Get_m_line_save() {return m_line_save;} - std::string & Get_accumulated() {return accumulated;} - LINE_TYPE Get_m_line_type() {return m_line_type;}; + std::string & Get_m_line() {return m_line;} + std::string & Get_m_line_save() {return m_line_save;} + std::string & Get_accumulated() {return accumulated;} + LINE_TYPE Get_m_line_type()const {return m_line_type;}; void Set_accumulate(bool tf) { if (tf) @@ -149,7 +149,7 @@ public: } this->accumulate = tf; } - Keywords::KEYWORDS Get_m_next_keyword() const {return m_next_keyword;} + Keywords::KEYWORDS Get_m_next_keyword() const {return m_next_keyword;} // echo enum ECHO_OPTION @@ -158,16 +158,16 @@ public: ECHO_OUTPUT }; virtual void echo_msg(const char * str); - void Set_echo_on(bool tf) {this->echo_on = tf;}; - bool Get_echo_on(void) {return this->echo_on;}; - void Set_echo_destination(ECHO_OPTION eo) {this->echo_destination = eo;}; - ECHO_OPTION Get_echo_destination(void) {return this->echo_destination;}; + void Set_echo_on(bool tf) {this->echo_on = tf;}; + bool Get_echo_on(void)const {return this->echo_on;}; + void Set_echo_destination(ECHO_OPTION eo) {this->echo_destination = eo;}; + ECHO_OPTION Get_echo_destination(void)const {return this->echo_destination;}; // data protected: - std::ostream *output_ostream; - std::ostream *log_ostream; - std::ostream *punch_ostream; + std::ostream *output_ostream; + std::ostream *log_ostream; + std::ostream *punch_ostream; #ifdef ERROR_OSTREAM std::ostream *error_ostream; #else diff --git a/tests/main.f90 b/tests/main.f90 index f55ca81e..900fa242 100644 --- a/tests/main.f90 +++ b/tests/main.f90 @@ -15,10 +15,17 @@ program test_f90 implicit none - + + INTEGER(KIND=4),PARAMETER :: EXIT_SUCCESS = 0 + INTEGER(KIND=4),PARAMETER :: EXIT_FAILURE = 1 + integer(KIND=4) F_MAIN integer(KIND=4) I - + I = F_MAIN() - end program test_f90 \ No newline at end of file + if (I .NE. EXIT_SUCCESS) then + STOP EXIT_FAILURE + endif + + end program test_f90