def test_equilibrate_overload_6(setup, num_regression): """ An integration test that checks result's reproducibility of the calculation of a problem using equilibrate(ChemicalState& state, const Partition& partition, const EquilibriumOptions& options) @param setup a tuple that has some objects from problem setup (system, problem) """ (system, problem) = setup # find a state based on the equilibrium setup state = equilibrate(problem) # change pressure and temperature state.setTemperature(problem.temperature() + 5) state.setPressure(problem.pressure() + 5) options = EquilibriumOptions() partition = Partition(system) # compute equilibrium for state with new temperature and pressure equilibriumResult = equilibrate(state, partition, options) stateDict = convert_reaktoro_state_to_dict(state) num_regression.check(stateDict, default_tolerance=dict(atol=1e-5, rtol=1e-16))
def test_equilibrium_solver_with_equilibrate( partition_with_inert_gaseous_phase, chemical_system): problem = _create_equilibrium_problem(partition_with_inert_gaseous_phase) state = _create_chemical_state(chemical_system) # Compute equilibrium state; the amounts of CO2(g) and H2O(g) should remain the same equilibrate(state, problem) # Assert the amounts of CO2(g) and H2O(g) are the same as initially set assert state.speciesAmount('CO2(g)') == 1.0 assert state.speciesAmount('H2O(g)') == 0.001
def test_equilibrium_path(num_regression, tmpdir): """ An integration test that checks result's reproducibility of the calculation of an equilibrium path between two states """ database = Database("supcrt98.xml") editor = ChemicalEditor(database) editor.addAqueousPhase("H O C Na Cl") system = ChemicalSystem(editor) problem1 = EquilibriumProblem(system) problem1.add("H2O", 1, "kg") problem1.add("CO2", 0.5, "mol") problem1.add("HCl", 1, "mol") problem2 = EquilibriumProblem(system) problem2.add("H2O", 1, "kg") problem2.add("CO2", 0.5, "mol") problem2.add("NaOH", 2, "mol") state1 = equilibrate(problem1) state2 = equilibrate(problem2) path = EquilibriumPath(system) output = path.output() output.filename(tmpdir.dirname + "/equilibriumPathResult.txt") # Define which outputs will be written and checked output.add("t") output.add("pH") output.add("speciesMolality(HCO3-)") output.add("speciesMolality(CO2(aq))") output.add("speciesMolality(CO3--)") path.solve(state1, state2) pathTable = pd.read_csv( tmpdir.dirname + "/equilibriumPathResult.txt", index_col=None, delim_whitespace=True, ) pathDict = convert_dataframe_to_dict(pathTable) num_regression.check(pathDict)
def test_kinetic_path_solve_final_state(state_regression, setup, time_span, minerals_to_add): """ An integration test that checks result's reproducibility of the calculation of a kinetic problem and only check the final state @param setup a tuple that has some objects from kineticProblemSetup.py (problem, reactions, partition) @param time_span time information about the kinetic problem. time_span.ti = initial time time_span.tf = final time time_span.unit = ti and tf units """ (problem, reactions, partition) = setup state = equilibrate(problem) for mineral in minerals_to_add: state.setSpeciesMass(mineral.mineral_name, mineral.amount, mineral.unit) path = KineticPath(reactions) path.setPartition(partition) path.solve(state, time_span.ti, time_span.tf, time_span.unit) state_regression.check(state, default_tol=dict(atol=1e-5, rtol=1e-14))
def kinect_problem_with_h2o_hcl_caco3_mgco3_co2_calcite(): database = Database("supcrt98.xml") editor = ChemicalEditor(database) editor.addAqueousPhase("H2O HCl CaCO3 MgCO3") editor.addGaseousPhase(["H2O(g)", "CO2(g)"]) editor.addMineralPhase("Calcite") calciteReaction = editor.addMineralReaction("Calcite") calciteReaction.setEquation("Calcite = Ca++ + CO3--") calciteReaction.addMechanism("logk = -5.81 mol/(m2*s); Ea = 23.5 kJ/mol") calciteReaction.addMechanism( "logk = -0.30 mol/(m2*s); Ea = 14.4 kJ/mol; a[H+] = 1.0" ) calciteReaction.setSpecificSurfaceArea(10, "cm2/g") system = ChemicalSystem(editor) reactions = ReactionSystem(editor) partition = Partition(system) partition.setKineticPhases(["Calcite"]) problem = EquilibriumProblem(system) problem.setPartition(partition) problem.add("H2O", 1, "kg") problem.add("HCl", 1, "mmol") state = equilibrate(problem) state.setSpeciesMass("Calcite", 100, "g") return (state, reactions, partition)
def kinect_problem_with_h2o_nacl_caco3_mgco3_hcl_co2_calcite_magnesite_dolomite_halite(): database = Database("supcrt98.xml") editor = ChemicalEditor(database) editor.addAqueousPhase("H2O NaCl CaCO3 MgCO3 HCl") editor.addGaseousPhase(["H2O(g)", "CO2(g)"]) editor.addMineralPhase("Calcite") editor.addMineralPhase("Magnesite") editor.addMineralPhase("Dolomite") editor.addMineralPhase("Halite") calciteReaction = editor.addMineralReaction("Calcite") calciteReaction.setEquation("Calcite = Ca++ + CO3--") calciteReaction.addMechanism("logk = -5.81 mol/(m2*s); Ea = 23.5 kJ/mol") calciteReaction.addMechanism( "logk = -0.30 mol/(m2*s); Ea = 14.4 kJ/mol; a[H+] = 1.0" ) calciteReaction.setSpecificSurfaceArea(10, "cm2/g") magnesiteReaction = editor.addMineralReaction("Magnesite") magnesiteReaction.setEquation("Magnesite = Mg++ + CO3--") magnesiteReaction.addMechanism("logk = -9.34 mol/(m2*s); Ea = 23.5 kJ/mol") magnesiteReaction.addMechanism( "logk = -6.38 mol/(m2*s); Ea = 14.4 kJ/mol; a[H+] = 1.0" ) magnesiteReaction.setSpecificSurfaceArea(10, "cm2/g") dolomiteReaction = editor.addMineralReaction("Dolomite") dolomiteReaction.setEquation("Dolomite = Ca++ + Mg++ + 2*CO3--") dolomiteReaction.addMechanism("logk = -7.53 mol/(m2*s); Ea = 52.2 kJ/mol") dolomiteReaction.addMechanism( "logk = -3.19 mol/(m2*s); Ea = 36.1 kJ/mol; a[H+] = 0.5" ) dolomiteReaction.setSpecificSurfaceArea(10, "cm2/g") system = ChemicalSystem(editor) reactions = ReactionSystem(editor) partition = Partition(system) partition.setKineticSpecies(["Calcite", "Magnesite", "Dolomite"]) problem = EquilibriumProblem(system) problem.setPartition(partition) problem.add("H2O", 1, "kg") problem.add("NaCl", 1, "mol") problem.add("CO2", 1, "mol") state = equilibrate(problem) state.setSpeciesMass("Calcite", 100, "g") state.setSpeciesMass("Dolomite", 50, "g") return (state, reactions, partition)
def brine_co2_path(): editor = ChemicalEditor() editor.addAqueousPhaseWithElementsOf("H2O NaCl CaCO3 MgCO3") editor.addGaseousPhase(["H2O(g)", "CO2(g)"]) editor.addMineralPhase("Calcite") editor.addMineralPhase("Magnesite") editor.addMineralPhase("Dolomite") editor.addMineralPhase("Halite") editor.addMineralReaction("Calcite") \ .setEquation("Calcite = Ca++ + CO3--") \ .addMechanism("logk = -5.81 mol/(m2*s); Ea = 23.5 kJ/mol") \ .addMechanism("logk = -0.30 mol/(m2*s); Ea = 14.4 kJ/mol; a[H+] = 1.0") \ .setSpecificSurfaceArea(10, "cm2/g") editor.addMineralReaction("Magnesite") \ .setEquation("Magnesite = Mg++ + CO3--") \ .addMechanism("logk = -9.34 mol/(m2*s); Ea = 23.5 kJ/mol") \ .addMechanism("logk = -6.38 mol/(m2*s); Ea = 14.4 kJ/mol; a[H+] = 1.0") \ .setSpecificSurfaceArea(10, "cm2/g") editor.addMineralReaction("Dolomite") \ .setEquation("Dolomite = Ca++ + Mg++ + 2*CO3--") \ .addMechanism("logk = -7.53 mol/(m2*s); Ea = 52.2 kJ/mol") \ .addMechanism("logk = -3.19 mol/(m2*s); Ea = 36.1 kJ/mol; a[H+] = 0.5") \ .setSpecificSurfaceArea(10, "cm2/g") system = ChemicalSystem(editor) reactions = ReactionSystem(editor) partition = Partition(system) partition.setKineticSpecies(["Calcite", "Magnesite", "Dolomite"]) problem = EquilibriumProblem(system) problem.setPartition(partition) problem.setTemperature(60, "celsius") problem.setPressure(100, "bar") problem.add("H2O", 1, "kg") problem.add("NaCl", 0.5, "mol") problem.add("CO2", 1, "mol") state = equilibrate(problem) state.setSpeciesMass("Calcite", 100, "g") state.setSpeciesMass("Dolomite", 50, "g") path = KineticPath(reactions) path.setPartition(partition) return path, state
def test_equilibrate_overload_5(setup, state_regression): """ An integration test that checks result's reproducibility of the calculation of a problem using equilibrate(ChemicalState& state, const EquilibriumOptions& options) @param setup a tuple that has some objects from problem setup (system, problem) """ (system, problem) = setup # Find a state based on the equilibrium setup state = equilibrate(problem) # Change pressure and temperature state.setTemperature(problem.temperature() + 5) state.setPressure(problem.pressure() + 5) options = EquilibriumOptions() # Compute equilibrium for state with new temperature and pressure equilibriumResult = equilibrate(state, options) state_regression.check(state, default_tol=dict(atol=1e-5, rtol=1e-16))
def test_kinetic_path_solve_complete_path(table_regression, tmpdir, setup, time_span, checked_variables, minerals_to_add): """ An integration test that checks result's reproducibility of the calculation of a kinetic problem and check all the path @param setup a tuple that has some objects from kineticProblemSetup.py (problem, reactions, partition) @param time_span time information about the kinetic problem. time_span.ti = initial time time_span.tf = final time time_span.unit = ti and tf units @param checked_variables a list that has all the variables that will be tested """ (problem, reactions, partition) = setup state = equilibrate(problem) for mineral in minerals_to_add: state.setSpeciesMass(mineral.mineral_name, mineral.amount, mineral.unit) path = KineticPath(reactions) path.setPartition(partition) output = path.output() output.precision(16) output.filename(tmpdir.dirname + "/kinetictPathResult.txt") for checked_variable in checked_variables: output.add(checked_variable) path.solve(state, time_span.ti, time_span.tf, time_span.unit) path_kinetic_table = pd.read_csv( tmpdir.dirname + "/kinetictPathResult.txt", index_col=None, skiprows=1, delim_whitespace=True, ) path_kinetic_table.columns = checked_variables table_regression.check(path_kinetic_table, default_tol=dict(atol=1e-3, rtol=1e-14))
def test_equilibrate_overload_1(setup, state_regression): """ An integration test that checks result's reproducibility of the calculation of a problem using equilibrate(const EquilibriumProblem& problem) and equilibrate(const EquilibriumInverseProblem& problem) @param setup a tuple that has some objects from problem setup (system, problem) """ (system, problem) = setup equilibriumState = equilibrate(problem) state_regression.check(equilibriumState, default_tol=dict(atol=1e-5, rtol=1e-16))
def test_equilibrium_solver_solve_overload_1(setup, state_regression): """ An integration test that checks result's reproducibility of the calculation of an equilibrium of a state using EquilibriumSolver::solve(ChemicalState& state) @param setup a tuple that has some objects from problem setup (system, problem) """ (system, problem) = setup state = equilibrate(problem) state.setTemperature(problem.temperature() + 30) state.setPressure(problem.pressure() + 40) solver = EquilibriumSolver(system) solver.solve(state) state_regression.check(state, default_tol=dict(atol=1e-5, rtol=1e-16))
def test_equilibrate_overload_8(setup, state_regression): """ An integration test that checks result's reproducibility of the calculation of a problem using equilibrate(ChemicalState& state, const EquilibriumProblem& problem, const EquilibriumOptions& options) and equilibrate(ChemicalState& state, const EquilibriumInverseProblem& problem, const EquilibriumOptions& options) @param setup a tuple that has some objects from problem setup (system, problem) """ (system, problem) = setup state = ChemicalState(system) options = EquilibriumOptions() equilibriumResult = equilibrate(state, problem, options) state_regression.check(state, default_tol=dict(atol=1e-5, rtol=1e-16))
def test_equilibrate_overload_7(setup, num_regression): """ An integration test that checks result's reproducibility of the calculation of a problem using equilibrate(ChemicalState& state, const EquilibriumProblem& problem) and equilibrate(ChemicalState& state, const EquilibriumInverseProblem& problem) @param setup a tuple that has some objects from problem setup (system, problem) """ (system, problem) = setup state = ChemicalState(system) equilibriumResult = equilibrate(state, problem) stateDict = convert_reaktoro_state_to_dict(state) num_regression.check(stateDict, default_tolerance=dict(atol=1e-5, rtol=1e-16))
def test_chemicaltransport_step(num_regression): nx, ny, nz = 5, 5, 5 # number of cells along x, y, and z nsteps = 10 # number of time steps velocity = fire.Constant([1.0e-2, 0.0, 0.0]) # the velocity (in units of m/s) diffusion = fire.Constant( 1.0e-4) # the diffusion coefficient (in units of m2/s) dt = 1.0 # the time step (in units of s) T = 60.0 + 273.15 # the temperature (in units of K) P = 100 * 1e5 # the pressure (in units of Pa) mesh = fire.UnitCubeMesh(nx, ny, nz) V = fire.FunctionSpace(mesh, "CG", 1) # Initialise the database database = rkt.Database("supcrt98.xml") # Initialise the chemical editor editor = rkt.ChemicalEditor(database) editor.addAqueousPhase( "H2O(l) H+ OH- Na+ Cl- Ca++ Mg++ HCO3- CO2(aq) CO3--") editor.addMineralPhase("Quartz") editor.addMineralPhase("Calcite") editor.addMineralPhase("Dolomite") # Initialise the chemical system system = rkt.ChemicalSystem(editor) # Define the initial condition of the reactive transport modeling problem problem_ic = rkt.EquilibriumProblem(system) problem_ic.setTemperature(T) problem_ic.setPressure(P) problem_ic.add("H2O", 1.0, "kg") problem_ic.add("NaCl", 0.7, "mol") problem_ic.add("CaCO3", 10, "mol") problem_ic.add("SiO2", 10, "mol") # Define the boundary condition of the reactive transport modeling problem problem_bc = rkt.EquilibriumProblem(system) problem_bc.setTemperature(T) problem_bc.setPressure(P) problem_bc.add("H2O", 1.0, "kg") problem_bc.add("NaCl", 0.90, "mol") problem_bc.add("MgCl2", 0.05, "mol") problem_bc.add("CaCl2", 0.01, "mol") problem_bc.add("CO2", 0.75, "mol") # Calculate the equilibrium states for the initial and boundary conditions state_ic = rkt.equilibrate(problem_ic) state_bc = rkt.equilibrate(problem_bc) # Scale the volumes of the phases in the initial condition such that their sum is 1 m3 state_ic.scalePhaseVolume("Aqueous", 0.1, "m3") state_ic.scalePhaseVolume("Quartz", 0.882, "m3") state_ic.scalePhaseVolume("Calcite", 0.018, "m3") # Scale the volume of the boundary equilibrium state to 1 m3 state_bc.scaleVolume(1.0) # Initialise the chemical field field = rok.ChemicalField(system, V) field.fill(state_ic) # Initialize the chemical transport solver transport = rok.ChemicalTransportSolver(field) transport.addBoundaryCondition(state_bc, 1) # 1 means left side transport.setVelocity([velocity]) transport.setDiffusion([diffusion]) species_names_for_output = [ "Ca++", "Mg++", "Calcite", "Dolomite", "CO2(aq)", "HCO3-", "Cl-", "H2O(l)", ] element_names_for_output = ["H", "O", "C", "Ca", "Mg", "Na", "Cl"] species_amount_functions = [ fire.Function(V, name=name) for name in species_names_for_output ] element_amount_functions = [ fire.Function(V, name=name) for name in element_names_for_output ] step = 0 species_data = [] element_data = [] while step <= nsteps: transport.step(field, dt) # For each selected species, output its molar amounts for f in species_amount_functions: f.assign(field.speciesAmount(f.name())) species_data.append(f.dat.data) # For each selected species, output its molar amounts for f in element_amount_functions: f.assign(field.elementAmountInPhase(f.name(), "Aqueous")) element_data.append(f.dat.data) step += 1 species_data = { "n({})(step={})".format(name, i): u for i, (name, u) in enumerate(zip(species_names_for_output, species_data)) } element_data = { "b({})(step={})".format(name, i): u for i, (name, u) in enumerate(zip(element_names_for_output, element_data)) } data = {**species_data, **element_data} num_regression.check(data)
problem_ic.add("NaCl", 0.7, "mol") problem_ic.add("CaCO3", 10, "mol") problem_ic.add("SiO2", 10, "mol") # Define the boundary condition of the reactive transport modeling problem problem_bc = rkt.EquilibriumProblem(system) problem_bc.setTemperature(T) problem_bc.setPressure(P) problem_bc.add("H2O", 1.0, "kg") problem_bc.add("NaCl", 0.90, "mol") problem_bc.add("MgCl2", 0.05, "mol") problem_bc.add("CaCl2", 0.01, "mol") problem_bc.add("CO2", 0.75, "mol") # Calculate the equilibrium states for the initial and boundary conditions state_ic = rkt.equilibrate(problem_ic) state_bc = rkt.equilibrate(problem_bc) # Scale the volumes of the phases in the initial condition such that their sum is 1 m3 state_ic.scalePhaseVolume("Aqueous", 0.1, "m3") state_ic.scalePhaseVolume("Quartz", 0.882, "m3") state_ic.scalePhaseVolume("Calcite", 0.018, "m3") # Scale the volume of the boundary equilibrium state to 1 m3 state_bc.scaleVolume(1.0) # Initialise the chemical field field = rok.ChemicalField(system, V) field.fill(state_ic) # Initialize the chemical transport solver