Using ThermoFun from C++ and Python

The main ThermoFun class for doing calculations is the Engine class. With ThermoEngine you can do one calculaiton at a time.

Attention

When using the engine class calculations can only be done using the default S.I. units (e.g. Pa for pressure and K for temperature), for one given substance, temperature and pressure point at a time.

The Batch class is useful for doing batch calculations for a given list of substances, reactions, properties, and temperature and pressure grid. Options to set the input and output properties units are available.

An equivalent interface built using Pybind11 is available to use from Python

Engine class

Properties of substance

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#include "ThermoFun/ThermoFun.h"
using namespace std;

int main()
{
  // Create the engine object using a database file in JSON format
  // Examples of such files can be found in /Resources/databases/ folder or can be
  // retrieved from ThermoHub database using ThermoHubClient
  ThermoFun::Engine engine("aq17-thermofun.json");

  double T       = 398.15; double P = 1e7; // in K and Pa

  auto propAl    = engine.thermoPropertiesSubstance(T, P, "Al+3");

  // extracting values from results for the Gibbs energy
  double G0      = propAl.gibbs_energy.val; // value
  double G0dT    = propAl.gibbs_energy.ddt; // derivative with T = -S0
  double G0error = propAl.gibbs_energy.err; // propagated error

  return 0;
}

Properties of reaction

1
2
3
reaction_properties = engine.thermoPropertiesReaction(298.15, 1e5, "Cal = Ca+2 + CO3-2");
logK = reaction_properties.log_equilibrium_constant.val;
drG0 = reaction_properties.reaction_gibbs_energy.val;

Batch class

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include "ThermoFun/ThermoFun.h"
using namespace std;

int main()
{
    // Create the batch object using a database file in JSON
    ThermoFun::ThermoBatch batch("aq17.json");

    // Optional: set the solvent symbol used for calculating properties of aqueous species
    batch.setSolventSymbol("H2O@");

    // Optional: change default units
    batch.setPropertiesUnits({"temperature", "pressure"},{"degC","bar"});

    // Optional: change default digits
    batch.setPropertiesDigits({"gibbs_energy","entropy", "volume", "enthalpy", "temperature", "pressure"}, {0, 1, 2, 0, 0, 0});

    // Retrieve the entropy of H2O
    double H2Oentropy = batch.thermoPropertiesSubstance( 300, 2000, "H2O@", "entropy").toDouble();

    // Retrieve the derivative of G with respect to T
    double H2OdGdT = batch.thermoPropertiesSubstance( 300, 2000, "H2O", "entropy").toThermoScalar().ddt;

    // Write results to a comma separate files for a list of T-P pairs, substances, and properties
    batch.thermoPropertiesSubstance({{25, 1},{40, 1},{70, 100},{90, 100},{100, 100}}, // list of T-P pairs
                                    {"Al+3", "OH-", "SiO2@"},                         // list of substance symbols
                                    {"gibbs_energy","entropy", "volume", "enthalpy"}  // list of properties
                                  ).toCSV("results.csv");                            // output
    return 0;
}

Using data from ThermoHub

Example of retrieving a thermodynamic dataset from ThermoHub for initializing a ThermoFun batch calculation.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include "Thermofun/ThermoFun.h"
#include "ThermoHubClient/ThermoHubClient.h"
using namespace std;

int main()
{
    // database connection  (local or remote) using a configuration file
    // ThermoHubClient::DatabaseClient dbc("hub-connection-config.json");

    // default connection (remote) to db.thermohub.net
    ThermoHubClient::DatabaseClient dbc;

    // retrieve a database from ThermoHub server as a JSON file
    dbc.saveDatabase("psinagra-12-07") // this will save the database file psinagra-12-07-thermofun.json

    // Initialize an batch object using the database file
    ThermoFun::ThermoBatch batch("psinagra-12-07-thermofun.json");

    // Optional: set the solvent symbol used for calculating properties of aqueous species
    batch.setSolventSymbol("H2O@");

    // Optional set calculation and output preferences
    ThermoFun::BatchPreferences op;
    op.isFixed = true;
    op.reactionPropertiesFromReactants   = false;
    op.substancePropertiesFromReaction   = false;
    batch.setBatchPreferences(op);

    // Optional set units and significant digits
    batch.setPropertiesUnits({"temperature", "pressure"},{"degC","bar"});
    batch.setPropertiesDigits({ "reaction_gibbs_energy","reaction_entropy", "reaction_volume",
                                "reaction_enthalpy","logKr", "temperature", "pressure"}, {0, 4, 4, 4, 4, 0, 0});

    batch.thermoPropertiesReaction({{25,1}}, {"AmSO4+", "MgSiO3@"}, {"reaction_gibbs_energy", "reaction_entropy",
                                    "reaction_volume", "reaction_enthalpy", "logKr"}).toCSV("results.csv");

    batch.thermoPropertiesReaction({0,20,50,75},{0,0,0,0},{"AmSO4+", "MgSiO3@"}, {"reaction_gibbs_energy", "reaction_entropy",
                                    "reaction_volume", "reaction_enthalpy", "logKr"}).toCSV("results.csv");
}

Python interface

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import ThermoHubClient as client
Import ThermoFun as fun

print("\n# Initialize a database client object\n")
dbc = client.DatabaseClient()

print("\n# Retrieve a JSON database given a ThermoDataSet symbol\n")
db = dbc.getDatabase("cemdata18")

print("\n# Initialize an interface object using the database\n")
batch = fun.ThermoBatch(db)

print("\n# Optional: set the solvent symbol used for calculating properties of aqueous species\n")
batch.setSolventSymbol("H2O@")

print("\n# Optional set calculation and output preferences\n")
op = fun.BatchPreferences()
op.isFixed = True
op.reactionPropertiesFromReactants   = False
op.substancePropertiesFromReaction   = False
batch.setBatchPreferences(op)

print("\n# Optional set units and significant digits\n")
batch.setPropertiesUnits(["temperature", "pressure"],["degC","bar"])

batch.setPropertiesDigits(["gibbs_energy","entropy", "volume",
                            "enthalpy","logKr", "temperature", "pressure"], [0, 4, 4, 4, 4, 0, 0])

print("\n# Do calculations and write output\n")
batch.thermoPropertiesSubstance([[25,1]], ["Na(CO3)-", "Mg+2"], ["gibbs_energy", "entropy",
                                "volume", "enthalpy"]).toCSV("results_dbc.csv")

reaction_properties = engine.thermoPropertiesReaction(298.15, 1e5, "Cal = Ca+2 + CO3-2")
logK = reaction_properties.log_equilibrium_constant
f'logK (Cal = Ca+2 + CO3-2) is {logK.val}'