def test_elements_molar_mass(guard_locale): old_locale = guard_locale database = Database("supcrt07.xml") assert old_locale == locale.setlocale(locale.LC_NUMERIC) check_molar_mass({ element.name(): element.molarMass() for element in database.elements() })
def test_invariant_database(): database = Database("supcrt07.xml") elements = {element.name(): element for element in database.elements()} assert len(elements) == 117 elements['H'].setMolarMass(10) assert 10 == elements['H'].molarMass() elements = {element.name(): element for element in database.elements()} assert pytest.approx(0.00100794) == elements['H'].molarMass()
def test_database_contains(): database = Database(str(get_test_data_dir() / "supcrt98_simplified.xml")) aqueous_species = database.aqueousSpecies() gaseous_species = database.gaseousSpecies() liquid_species = database.liquidSpecies() mineral_species = database.mineralSpecies() assert database.containsAqueousSpecies(aqueous_species[0].name()) assert database.containsGaseousSpecies(gaseous_species[0].name()) assert database.containsLiquidSpecies(liquid_species[0].name()) assert database.containsMineralSpecies(mineral_species[0].name())
def test_database_parse(): """ Test the fact that species should be added as liquid species even if the Type is Gaseous expected result: - liquid_species[0] = "H2S(liq)" -- added as liquid - gaseous_species[1] = "H2S(g)" -- added as gas """ database = Database(str(get_test_data_dir() / "supcrt98_simplified.xml")) gaseous_species = database.gaseousSpecies() liquid_species = database.liquidSpecies() assert gaseous_species[0].name() == "H2S(g)" assert liquid_species[0].name() == "H2S(liq)"
def kinetic_problem_with_h2o_hcl_caco3_mgco3_co2_calcite(): """ Build a kinetic problem with 1 kg of H2O, 1mmol of HCl which has calcite as a kinetic reaction """ database = Database("supcrt98.xml") editor = ChemicalEditor(database) editor.addAqueousPhaseWithElementsOf("H2O HCl CaCO3 MgCO3") editor.addGaseousPhase(["H2O(g)", "CO2(g)"]) editor.addMineralPhase("Calcite") calcite_reaction = editor.addMineralReaction("Calcite") calcite_reaction.setEquation("Calcite = Ca++ + CO3--") calcite_reaction.addMechanism("logk = -5.81 mol/(m2*s); Ea = 23.5 kJ/mol") calcite_reaction.addMechanism( "logk = -0.30 mol/(m2*s); Ea = 14.4 kJ/mol; a[H+] = 1.0") calcite_reaction.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") return (problem, reactions, partition)
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 equilibrium_problem_with_h2o_co2_nacl_halite_dissolved_60C_300bar(): """ Build a problem with H2O, H+, Na+, Cl-, HCO3-, CO2(aq), CO3-- and Halite at 60 °C and 300 bar """ database = Database("supcrt98.xml") editor = ChemicalEditor(database) aqueous = editor.addAqueousPhase( ["H2O(l)", "H+", "OH-", "Na+", "Cl-", "HCO3-", "CO2(aq)", "CO3--", "CO(aq)"] ) aqueous.setActivityModelDrummondCO2() gaseous = editor.addGaseousPhase(["H2O(g)", "CO2(g)"]) gaseous.setChemicalModelSpycherPruessEnnis() editor.addMineralPhase("Halite") system = ChemicalSystem(editor) problem = EquilibriumProblem(system) problem.add("H2O", 1, "kg") problem.add("CO2", 100, "g") problem.add("NaCl", 1, "mol") problem.setTemperature(60, "celsius") problem.setPressure(300, "bar") return (system, problem)
def test_equilibrium_CH4_CO2_H2S_liq_gas(temperature, pressure, num_regression): """ This test checks the capability of solving a ternary mixture with @param Temperature temperature in Kelvin which will be used to compute equilibrium @param Pressure pressure in bar which will be used to compute equilibrium """ db = Database("supcrt98.xml") editor = ChemicalEditor(db) eos_params = CubicEOSParams( phase_identification_method=PhaseIdentificationMethod. GibbsEnergyAndEquationOfStateMethod, ) editor.addGaseousPhase(["CH4(g)", "H2S(g)", "CO2(g)"]).setChemicalModelPengRobinson(eos_params) editor.addLiquidPhase(["CH4(liq)", "H2S(liq)", "CO2(liq)" ]).setChemicalModelPengRobinson(eos_params) system = ChemicalSystem(editor) problem = EquilibriumProblem(system) problem.setTemperature(temperature, "K") problem.setPressure(pressure, "bar") problem.add("CH4(g)", 0.60, "mol") problem.add("H2S(g)", 0.35, "mol") problem.add("CO2(g)", 0.05, "mol") solver = EquilibriumSolver(problem.system()) options = EquilibriumOptions() options.hessian = GibbsHessian.Exact options.nonlinear.max_iterations = 100 options.optimum.max_iterations = 200 options.optimum.ipnewton.step = StepMode.Conservative solver.setOptions(options) state = ChemicalState(system) result = solver.solve(state, problem) assert result.optimum.succeeded species_amount = { "CH4(g)": np.asarray([state.speciesAmount("CH4(g)")]), "H2S(g)": np.asarray([state.speciesAmount("H2S(g)")]), "CO2(g)": np.asarray([state.speciesAmount("CO2(g)")]), "CH4(liq)": np.asarray([state.speciesAmount("CH4(liq)")]), "H2S(liq)": np.asarray([state.speciesAmount("H2S(liq)")]), "CO2(liq)": np.asarray([state.speciesAmount("CO2(liq)")]), } num_regression.check(species_amount)
def test_locale_problem_with_pugixml(): locales = get_locales() at_least_one_locale_has_comma_for_decimal_separator = False at_least_one_valid_locale = False for loc in locales: if try_set_locale(loc): at_least_one_valid_locale = True if not at_least_one_locale_has_comma_for_decimal_separator: at_least_one_locale_has_comma_for_decimal_separator = locale_has_comma_for_decimal_separator( ) database = Database("supcrt07.xml") check_molar_mass({ element.name(): element.molarMass() for element in database.elements() }) assert at_least_one_valid_locale, "Couldn't find any valid locale to test"
def test_adding_and_getting_database_elements(): database = Database(str(get_test_data_dir() / "supcrt98_simplified.xml")) new_element = Element() new_element.setName("He") new_element.setMolarMass(4.002602e-3) database.addElement(new_element) elements = database.elements() assert elements[0].name() == "Fe" assert elements[0].molarMass() == pytest.approx(55.845e-3) assert elements[1].name() == "H" assert elements[1].molarMass() == pytest.approx(1.00794e-3) assert elements[2].name() == "He" assert elements[2].molarMass() == pytest.approx(4.002602e-3) assert elements[3].name() == "S" assert elements[3].molarMass() == pytest.approx(32.065e-3)
def test_add_phases_with_elements_wrong_use(): """Test the wrong usage of addAqueousPhaseWithElements.""" database = Database("supcrt98.xml") editor = ChemicalEditor(database) with pytest.raises(RuntimeError): editor.addAqueousPhaseWithElements("H2O(l) C Ca") with pytest.raises(RuntimeError): editor.addAqueousPhaseWithElements(["H2O C Ca"])
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 test_add_phases_right_use(): """Test the normal use of addAqueousPhase, addGaseousPhase and addMineralPhase.""" database = Database("supcrt98.xml") # Check adding phase by giving an string with all species list_of_aqueous_species_expected = r"H2O\(l\)\s*H\+\s*OH-\s*HCO3-\s*CO2\(aq\)\s*CO3--\s*" list_of_gaseous_species_expected = r"H2O\(g\)\s*CO2\(g\)\s*" list_of_liquid_species_expected = r"H2O\(liq\)\s*CO2\(liq\)\s*" list_of_mineral_species_expected = r"Graphite\s*" editor1 = ChemicalEditor(database) editor1.addAqueousPhase("H2O(l) H+ OH- HCO3- CO2(aq) CO3--") editor1.addGaseousPhase("H2O(g) CO2(g)") editor1.addLiquidPhase("H2O(liq) CO2(liq)") editor1.addMineralPhase("Graphite") aqueous_phase_1 = editor1.aqueousPhase() gaseous_phase_1 = editor1.gaseousPhase() liquid_phase_1 = editor1.liquidPhase() mineral_phases_1 = editor1.mineralPhases() aqueous_species_added_1 = _getting_species_names(aqueous_phase_1) gaseous_species_added_1 = _getting_species_names(gaseous_phase_1) liquid_species_added_1 = _getting_species_names(liquid_phase_1) mineral_species_added_1 = _getting_species_names(mineral_phases_1[0]) assert re.match(list_of_aqueous_species_expected, aqueous_species_added_1) assert re.match(list_of_gaseous_species_expected, gaseous_species_added_1) assert re.match(list_of_liquid_species_expected, liquid_species_added_1) assert re.match(list_of_mineral_species_expected, mineral_species_added_1) # Check adding phase by giving a list of string with all species editor2 = ChemicalEditor(database) editor2.addAqueousPhase( ["H2O(l)", "H+", "OH-", "HCO3-", "CO2(aq)", "CO3--"]) editor2.addGaseousPhase(["H2O(g)", "CO2(g)"]) editor2.addLiquidPhase(["H2O(liq)", "CO2(liq)"]) editor2.addMineralPhase(["Graphite"]) aqueous_phase_2 = editor2.aqueousPhase() gaseous_phase_2 = editor2.gaseousPhase() liquid_phase_2 = editor2.liquidPhase() mineral_phases_2 = editor2.mineralPhases() aqueous_species_added_2 = _getting_species_names(aqueous_phase_2) gaseous_species_added_2 = _getting_species_names(gaseous_phase_2) liquid_species_added_2 = _getting_species_names(liquid_phase_2) mineral_species_added_2 = _getting_species_names(mineral_phases_2[0]) assert re.match(list_of_aqueous_species_expected, aqueous_species_added_2) assert re.match(list_of_gaseous_species_expected, gaseous_species_added_2) assert re.match(list_of_liquid_species_expected, liquid_species_added_2) assert re.match(list_of_mineral_species_expected, mineral_species_added_2)
def kinetic_problem_with_h2o_nacl_caco3_mgco3_hcl_co2_calcite_magnesite_dolomite_halite( ): """ Build a kinetic problem with 1 kg of H2O, 1 mol of NaCl and 1 mol of CO2 which has the following kinetic reactions: calcite, Magnesite and Dolomite. """ database = Database("supcrt98.xml") editor = ChemicalEditor(database) editor.addAqueousPhaseWithElementsOf("H2O NaCl CaCO3 MgCO3 HCl") editor.addGaseousPhase(["H2O(g)", "CO2(g)"]) editor.addMineralPhase("Calcite") editor.addMineralPhase("Magnesite") editor.addMineralPhase("Dolomite") editor.addMineralPhase("Halite") calcite_reaction = editor.addMineralReaction("Calcite") calcite_reaction.setEquation("Calcite = Ca++ + CO3--") calcite_reaction.addMechanism("logk = -5.81 mol/(m2*s); Ea = 23.5 kJ/mol") calcite_reaction.addMechanism( "logk = -0.30 mol/(m2*s); Ea = 14.4 kJ/mol; a[H+] = 1.0") calcite_reaction.setSpecificSurfaceArea(10, "cm2/g") magnesite_reaction = editor.addMineralReaction("Magnesite") magnesite_reaction.setEquation("Magnesite = Mg++ + CO3--") magnesite_reaction.addMechanism( "logk = -9.34 mol/(m2*s); Ea = 23.5 kJ/mol") magnesite_reaction.addMechanism( "logk = -6.38 mol/(m2*s); Ea = 14.4 kJ/mol; a[H+] = 1.0") magnesite_reaction.setSpecificSurfaceArea(10, "cm2/g") dolomite_reaction = editor.addMineralReaction("Dolomite") dolomite_reaction.setEquation("Dolomite = Ca++ + Mg++ + 2*CO3--") dolomite_reaction.addMechanism("logk = -7.53 mol/(m2*s); Ea = 52.2 kJ/mol") dolomite_reaction.addMechanism( "logk = -3.19 mol/(m2*s); Ea = 36.1 kJ/mol; a[H+] = 0.5") dolomite_reaction.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") return (problem, reactions, partition)
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_chemical_editor_adding_and_getting_phases(): database = Database("supcrt98.xml") editor = ChemicalEditor(database) gaseous_phase = GaseousPhase() liquid_phase = LiquidPhase() mineral_phase = MineralPhase() editor.addPhase(gaseous_phase) editor.addPhase(liquid_phase) editor.addPhase(mineral_phase) assert editor.gaseousPhase().name() == gaseous_phase.name() assert editor.liquidPhase().name() == liquid_phase.name() assert editor.mineralPhases()[0].name() == mineral_phase.name()
def test_add_phases_with_elements_of_right_use(): """Test the normal use of addAqueousPhaseWithElementsOf, addGaseousPhaseWithElementsOf and addMineralPhaseWithElementsOf.""" database = Database("supcrt98.xml") editor1 = ChemicalEditor(database) editor1.addAqueousPhaseWithElementsOf("H2O Ca") editor1.addGaseousPhaseWithElementsOf("CO2 H") editor1.addMineralPhaseWithElementsOf("CaCO3") editor2 = ChemicalEditor(database) editor2.addAqueousPhaseWithElementsOf(["H2O", "Ca"]) editor2.addGaseousPhaseWithElementsOf(["CO2", "H"]) editor2.addMineralPhaseWithElementsOf(["CaCO3"]) system1 = ChemicalSystem(editor1) system2 = ChemicalSystem(editor2) _check_equivalent_chemical_systems(system1, system2)
def test_equilibrium_H2S_liq_gas(temperature, pressure, num_regression): db = Database("supcrt98.xml") editor = ChemicalEditor(db) eos_params = CubicEOSParams( model=CubicEOSModel.PengRobinson, phase_identification_method=PhaseIdentificationMethod. GibbsEnergyAndEquationOfStateMethod, ) editor.addGaseousPhase(["H2S(g)"]).setChemicalModelCubicEOS(eos_params) editor.addLiquidPhase(["H2S(liq)"]).setChemicalModelCubicEOS(eos_params) system = ChemicalSystem(editor) problem = EquilibriumProblem(system) problem.setTemperature(temperature, "K") problem.setPressure(pressure, "Pa") problem.add("H2S(g)", 1.0, "mol") solver = EquilibriumSolver(problem.system()) options = EquilibriumOptions() options.hessian = GibbsHessian.Exact options.nonlinear.max_iterations = 100 options.optimum.max_iterations = 200 options.optimum.ipnewton.step = StepMode.Conservative options.optimum.tolerance = 1e-17 solver.setOptions(options) state = ChemicalState(system) result = solver.solve(state, problem) assert result.optimum.succeeded species_amounts = { "H2S(g)": np.asarray([state.speciesAmount("H2S(g)")]), "H2S(liq)": np.asarray([state.speciesAmount("H2S(liq)")]), } num_regression.check(species_amounts)
def test_add_phases_wrong_use(): """Test the wrong usage of addAqueousPhase, addGaseousPhase and addMineralPhase.""" database = Database("supcrt98.xml") editor = ChemicalEditor(database) with pytest.raises(RuntimeError): editor.addAqueousPhase("H2O(l) C Ca") with pytest.raises(RuntimeError): editor.addAqueousPhase(["H2O C Ca"]) with pytest.raises(RuntimeError): editor.addGaseousPhase("CO2(g) H") with pytest.raises(RuntimeError): editor.addMineralPhase("Siderite C") with pytest.raises(RuntimeError): editor.addMineralPhase(["CaCO3"])
def equilibrium_problem_with_h2o_feoh2_feoh3_nh3_magnetite(): """ Build a problem with H2O, Fe(OH)2, Fe(OH)3, NH3 and Magnetite """ database = Database("supcrt98.xml") editor = ChemicalEditor(database) editor.addAqueousPhase("H2O Fe(OH)2 Fe(OH)3 NH3") editor.addGaseousPhase("NH3(g)") editor.addMineralPhase("Magnetite") system = ChemicalSystem(editor) problem = EquilibriumProblem(system) problem.add("H2O", 1, "kg") problem.add("Fe(OH)2", 1, "mol") problem.add("Fe(OH)3", 2, "mol") problem.add("NH3", 1, "mol") return (system, problem)
def equilibrium_inverse_with_h_o_na_cl_ca_c_calcite_ph_and_fixed_amounts(): """ Build a problem with H, O, Na, Cl, Ca, C and Calcite with defined pH and fixed species amount """ database = Database("supcrt98.xml") editor = ChemicalEditor(database) editor.addAqueousPhase("H O Na Cl Ca C") editor.addMineralPhase("Calcite") system = ChemicalSystem(editor) problem = EquilibriumInverseProblem(system) problem.add("H2O", 1, "kg") problem.add("NaCl", 0.1, "mol") problem.pH(8.0, "HCl", "NaOH") problem.fixSpeciesAmount("Calcite", 1, "mol") return (system, problem)
def equilibrium_inverse_with_h_o_na_cl_ca_mg_c_defined_ph(): """ Build a problem with H, Na, Cl, Ca, Mg, C with defined pH """ database = Database("supcrt98.xml") editor = ChemicalEditor(database) editor.addAqueousPhase("H O Na Cl Ca Mg C") editor.addGaseousPhase("H O C") system = ChemicalSystem(editor) problem = EquilibriumInverseProblem(system) problem.add("H2O", 1, "kg") problem.add("NaCl", 0.1, "mol") problem.add("CaCl2", 2, "mmol") problem.add("MgCl2", 4, "mmol") problem.pH(4.0, "CO2") return (system, problem)
def equilibrium_inverse_with_h2o_nacl_caco3_calcilte_and_fixed_mass(): """ Build a problem with H2O, NaCL, CaCO3, CO2, Calcite with fixed species mass and amount """ database = Database("supcrt98.xml") editor = ChemicalEditor(database) editor.addAqueousPhase("H2O NaCl CaCO3") editor.addGaseousPhase(["H2O(g)", "CO2(g)"]) editor.addMineralPhase("Calcite") system = ChemicalSystem(editor) problem = EquilibriumInverseProblem(system) problem.add("H2O", 1, "kg") problem.add("NaCl", 0.1, "mol") problem.fixSpeciesMass("Calcite", 100, "g") problem.fixSpeciesAmount("CO2(g)", 1.0, "mol") return (system, problem)
def test_database_looking_for_species_with_element(): database = Database(str(get_test_data_dir() / "supcrt98_simplified.xml")) aqueous_species_with_H_or_Fe = database.aqueousSpeciesWithElements( ["H", "S"]) gaseous_species_with_H_or_Fe = database.gaseousSpeciesWithElements( ["H", "S"]) liquid_species_with_H_or_Fe = database.liquidSpeciesWithElements( ["H", "S"]) mineral_species_with_H_or_Fe = database.mineralSpeciesWithElements( ["Fe", "S"]) assert aqueous_species_with_H_or_Fe[0].name() == "H2S(aq)" assert gaseous_species_with_H_or_Fe[0].name() == "H2S(g)" assert liquid_species_with_H_or_Fe[0].name() == "H2S(liq)" assert mineral_species_with_H_or_Fe[0].name() == "Pyrrhotite"
def test_CubicEOS_multiple_roots(): """ This problem leads to the following CubicEOS roots PR - Z1 = 1.00027728 Z2 = 0.0001655 Z3 = -0.0011024 since bmix = 1.635e-05 -> Z3 is an invalid root and since Z3 < Z2 < Z1 -> Z2 is an invalid root. Reaktoro should remove Z3, Z2 and proceed instead of removing only Z3 and raising the exception "Logic error: it was expected Z roots of size 3, but got: 2". """ database = Database("supcrt98.xml") editor = ChemicalEditor(database) editor.addAqueousPhaseWithElementsOf("H2O Fe(OH)2 Fe(OH)3 NH3") editor.addGaseousPhaseWithElementsOf("NH3") editor.addMineralPhase("Magnetite") system = ChemicalSystem(editor) state = ChemicalState(system) solver = EquilibriumSolver(system) temperature = 298.15 pressure = 1e5 b = [ 3.0, 122.01687012, 1.0, 63.50843506, 0.0, ] result = solver.approximate(state, temperature, pressure, b) assert result.optimum.succeeded # check that it doesn't raise an exception state.properties()
def equilibrium_problem_with_h2o_co2_nacl_halite_60C_300bar(): """ Build a problem with 1 kg of H2O, 100 g of CO2 and 0.1 mol of NaCl at 60 °C and 300 bar """ database = Database("supcrt98.xml") editor = ChemicalEditor(database) editor.addAqueousPhase("H2O NaCl CO2") editor.addGaseousPhase(["H2O(g)", "CO2(g)"]) editor.addMineralPhase("Halite") system = ChemicalSystem(editor) problem = EquilibriumProblem(system) problem.add("H2O", 1, "kg") problem.add("CO2", 100, "g") problem.add("NaCl", 0.1, "mol") problem.setTemperature(60, "celsius") problem.setPressure(300, "bar") return (system, problem)
def test_chemical_editor_create_system(): expected = [ "H2O(l)", "H+", "OH-", "H2O(g)", "CO2(g)", "H2O(liq)", "CO2(liq)", "Graphite" ] database = Database("supcrt98.xml") editor = ChemicalEditor(database) editor.addAqueousPhase("H2O(l) H+ OH-") editor.addGaseousPhase("H2O(g) CO2(g)") editor.addLiquidPhase("H2O(liq) CO2(liq)") editor.addMineralPhase("Graphite") system = ChemicalSystem(editor) species_name = [] for specie in system.species(): species_name.append(specie.name()) assert species_name == expected
def equilibrium_inverse_with_h_o_na_cl_ca_mg_c_fixed_amount_and_activity(): """ Build a problem with H, Na, Cl, Ca, Mg, C with fixed species amount, activity and defined pH """ database = Database("supcrt98.xml") editor = ChemicalEditor(database) editor.addAqueousPhase("H O Na Cl Ca Mg C") editor.addGaseousPhase("H O C") system = ChemicalSystem(editor) problem = EquilibriumInverseProblem(system) problem.add("H2O", 1, "kg") problem.add("NaCl", 0.1, "mol") problem.add("CaCl2", 2, "mmol") problem.add("MgCl2", 4, "mmol") problem.pH(3.0, "HCl") problem.fixSpeciesAmount("CO2(g)", 1.0, "mol") problem.fixSpeciesActivity("O2(g)", 0.20) return (system, problem)
def test_equilibrium_CH4_H2S_CO2_H2O_liq_gas_aq(temperature, pressure, num_regression): """ This test checks the capability of solving a system that has CH4, H2S, CO2, H2O with @param Temperature temperature in Kelvin which will be used to compute equilibrium @param Pressure pressure in bar which will be used to compute equilibrium """ db = Database("supcrt98.xml") editor = ChemicalEditor(db) eos_params = CubicEOSParams( phase_identification_method=PhaseIdentificationMethod. GibbsEnergyAndEquationOfStateMethod, ) editor.addAqueousPhase(["CO2(aq)", "H2S(aq)", "H2O(l)"]) editor.addGaseousPhase(["CH4(g)", "CO2(g)", "H2S(g)", "H2O(g)"]).setChemicalModelCubicEOS(eos_params) editor.addLiquidPhase(["CH4(liq)", "CO2(liq)", "H2S(liq)", "H2O(liq)"]).setChemicalModelCubicEOS(eos_params) system = ChemicalSystem(editor) problem = EquilibriumProblem(system) problem.setTemperature(temperature, "K") problem.setPressure(pressure, "bar") problem.add("H2O(g)", 0.50, "mol") problem.add("CO2(g)", 0.05, "mol") problem.add("H2S(g)", 0.40, "mol") problem.add("CH4(g)", 0.05, "mol") # This is a workaround to avoid an Eigen assertion when in Debug: # `DenseBase::resize() does not actually allow to resize.`, triggered by `y(iee) = optimum_state.y * RT;` problem.add("Z", 1e-15, "mol") solver = EquilibriumSolver(problem.system()) options = EquilibriumOptions() options.hessian = GibbsHessian.Exact options.nonlinear.max_iterations = 100 options.optimum.max_iterations = 200 options.optimum.ipnewton.step = StepMode.Conservative options.optimum.tolerance = 1e-14 solver.setOptions(options) state = ChemicalState(system) result = solver.solve(state, problem) assert result.optimum.succeeded species_amount = { "CO2(aq)": np.asarray([state.speciesAmount("CO2(g)")]), "H2S(aq)": np.asarray([state.speciesAmount("H2S(aq)")]), "H2O(l)": np.asarray([state.speciesAmount("H2O(l)")]), "CH4(g)": np.asarray([state.speciesAmount("CH4(g)")]), "CO2(g)": np.asarray([state.speciesAmount("CO2(g)")]), "H2S(g)": np.asarray([state.speciesAmount("H2S(g)")]), "H2O(g)": np.asarray([state.speciesAmount("H2O(g)")]), "CH4(liq)": np.asarray([state.speciesAmount("CH4(liq)")]), "CO2(liq)": np.asarray([state.speciesAmount("CO2(liq)")]), "H2S(liq)": np.asarray([state.speciesAmount("H2S(liq)")]), "H2O(liq)": np.asarray([state.speciesAmount("H2O(liq)")]), } num_regression.check(species_amount)
def test_different_results(state_regression): from reaktoro import ChemicalEditor, ChemicalState, ChemicalSystem, Database, EquilibriumProblem, EquilibriumSolver, Partition database = Database('supcrt07.xml') editor = ChemicalEditor(database) aqueous_elements = ["C", "Ca", "Cl", "Fe", "H", "Na", "O", "S", "Ba", "Sr"] aqueous_phase = editor.addAqueousPhaseWithElements(aqueous_elements) assert aqueous_phase.name() == 'Aqueous' mineral_species = [ "Anhydrite", "Barite", "Calcite", "Celestite", "Siderite", "Pyrrhotite" ] for mineral in mineral_species: editor.addMineralPhase(mineral) gaseous_species = ["CO2(g)", "H2S(g)", "CH4(g)"] editor.addGaseousPhase(gaseous_species) chemical_system = ChemicalSystem(editor) element_index = { e.name(): index for index, e in enumerate(chemical_system.elements()) } species_index = { s.name(): index for index, s in enumerate(chemical_system.species()) } phase_index = { p.name(): index for index, p in enumerate(chemical_system.phases()) } reaktoro_case = get_reaktoro_case() equilibrium_problem = EquilibriumProblem(chemical_system) equilibrium_problem.setTemperature(reaktoro_case.temperature_in_K) equilibrium_problem.setPressure(reaktoro_case.pressure_in_Pa) partition = Partition(chemical_system) partition.setInertPhases([phase_index['Gaseous']]) equilibrium_problem.setPartition(partition) chemical_state = ChemicalState(chemical_system) for name, index, molar_amount in reaktoro_case.species_amounts: assert index == species_index[name] chemical_state.setSpeciesAmount(index, molar_amount) equilibrium_problem.addState(chemical_state) solver = EquilibriumSolver(chemical_system) solver.setPartition(partition) result = solver.solve(chemical_state, equilibrium_problem) assert result.optimum.succeeded state_regression.check(chemical_state, default_tol=dict(atol=1e-5, rtol=1e-14))