Skip to main content

Calling Phreeqc from Julia: a tutorial

In this post, I'm going to show how we can call Phreeqc from Julia to calculate the solubility of minerals in a solution. The workflow is very useful specially when one wants to conduct a sensitivity analysis and plot the results. Here is my workflow:

  • Create a Phreeqc input file in Julia
  • Save it to a text file
  • Call Phreeqc from Julia to run the created input file
  • Read the results from the output file created by Phreeqc
  • Plot the results

If you are on windows, you need to add phreeqc to the path so you can call it from the command line.

create a Phreeqc simulation file

The following string is a phreeqc input file that mixes 10.0 moles of anhydrite in 1 kg of demineralized water at 50 degree Celsius and 250 atm, and writes the molality of Ca ion in the aqueous solution to an output file named anhydrite_solubility.csv:

SOLUTION 1 Pure water
    pH      7.0
    temp    50.0
    pressure  10
    Anhydrite       0.0     10.0
    -file   anhydrite_solubility.csv
    -reset false
    -totals     Ca

You can save this code in a file names e.g., anhydrite_sol.phr, and run it by

phreeqc anhydrite_sol.phr

if you have phreeqc installed and in your path. In windows, you can download phreeqc for windows and run it.

Sensitivity analysis

My purpose here is to study the effect of thermodynamic models and databases, temperature, and pressure on the predicted solubility of anhydrite in water. It can be done manually, but I like to do it automatically from a Julia script. You ca do it in Matlab or any other tools of your choice.

The workflow

We first create the Phreeqc input file as an string in Julia. Then, we save that script into a file and call phreeqc to run it. We save the results in an output file and read it in Julia. Finally we plot the results. The following script shows how this can be done in Julia. We need to use the packages PyPlot for visualization and DataFrames for reading the output file.

In [1]:
using PyPlot, DataFrames
In [2]:
T_min = 25.0     # degC minimum temperature
T_max = 100.0    # degC maximum temperature
p_atm = 250       # atm pressure
T_range = collect(linspace(T_min, T_max, 20))
data_base = ["phreeqc.dat", "pitzer.dat"]
for db in data_base
    anhydrite_sol = zeros(0)
    for T in T_range
        phreeqc_input =
        DATABASE /usr/local/share/doc/phreeqc/database/$db
        SOLUTION 1 Pure water
            pH      7.0
            temp    $T
            pressure  $p_atm
            Anhydrite       0.0     10.0
            -file   anhydrite_solubility.csv
            -reset false
            -totals     Ca
        # save it to a file
        ph_file=open("phreeqc_input_file", "w")
        write(ph_file, phreeqc_input)
        # run it
        run(`phreeqc phreeqc_input_file`)
        # read the results
        ph_res=readtable("anhydrite_solubility.csv", separator = ' ')
        # plot the results
        push!(anhydrite_sol, ph_res[:Ca][end])
    plot(T_range, anhydrite_sol)
ylabel("Anhydrite solubility [mol/kgw]");

You probably need to change the path to the Phreeqc databeses in line 11 of the above code. Play with the value of pressure and see what happens. It is truely fascinating that increasing pressure can affect the solubility that much. Don't forget that it can only be captured by the Pitzer model in Phreeqc.
There is another way of calling Phreeqc from Julia that I will discuss later.


Comments powered by Disqus