diff --git a/ChemistryLib/CreatePhreeqcIO.cpp b/ChemistryLib/CreatePhreeqcIO.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dd5ed3a468a88748d848fc05e77f068a4f8b7530 --- /dev/null +++ b/ChemistryLib/CreatePhreeqcIO.cpp @@ -0,0 +1,117 @@ +/** + * \copyright + * Copyright (c) 2012-2019, OpenGeoSys Community (http://www.opengeosys.org) + * Distributed under a Modified BSD License. + * See accompanying file LICENSE.txt or + * http://www.opengeosys.org/project/license + * + */ + +#include <fstream> + +#include "BaseLib/ConfigTreeUtil.h" +#include "BaseLib/Error.h" +#include "CreateOutput.h" +#include "CreatePhreeqcIO.h" +#include "PhreeqcIO.h" +#include "PhreeqcIOData/AqueousSolution.h" +#include "PhreeqcIOData/EquilibriumPhase.h" +#include "PhreeqcIOData/KineticReactant.h" +#include "PhreeqcIOData/ReactionRate.h" + +namespace ChemistryLib +{ +std::unique_ptr<PhreeqcIO> createPhreeqcIO( + std::size_t const num_nodes, + std::vector<std::pair<int, std::string>> const& + process_id_to_component_name_map, + boost::optional<BaseLib::ConfigTree> const& config, + std::string const& output_directory) +{ + auto const& num_chemical_systems = num_nodes; + + // database + //! \ogs_file_param{prj__chemical_system__database} + auto const database = config->getConfigParameter<std::string>("database"); + auto path_to_database = + BaseLib::joinPaths(BaseLib::getProjectDirectory(), database); + + if (BaseLib::IsFileExisting(path_to_database)) + { + INFO("Found the specified thermodynamic database: %s", + path_to_database.c_str()); + } + else + { + OGS_FATAL("Not found the specified thermodynamicdatabase: %s", + path_to_database.c_str()); + } + + // solution + auto const aqueous_solution_per_chem_sys = createAqueousSolution( + //! \ogs_file_param{prj__chemical_system__solution} + config->getConfigSubtree("solution")); + + auto const& components_per_chem_sys = + aqueous_solution_per_chem_sys.components; + for (auto const& component : components_per_chem_sys) + { + auto process_id_to_component_name_map_element = std::find_if( + process_id_to_component_name_map.begin(), + process_id_to_component_name_map.end(), + [&component](std::pair<int, std::string> const& map_element) { + return map_element.second == component.name; + }); + + if (process_id_to_component_name_map_element == + process_id_to_component_name_map.end()) + OGS_FATAL( + "Component %s given in <solution>/<components> is not found in " + "specified coupled processes (see " + "<process>/<process_variables>/<concentration>).", + component.name.c_str()); + } + if (components_per_chem_sys.size() + 1 != + process_id_to_component_name_map.size()) + OGS_FATAL( + "The number of components given in <solution>/<components> is not " + "in line with the number of transport processes - 1 which stands " + "for the transport process of hydrogen."); + + std::vector<AqueousSolution> aqueous_solutions( + num_chemical_systems, aqueous_solution_per_chem_sys); + + // equilibrium phases + auto const equilibrium_phases_per_chem_sys = createEquilibriumPhases( + //! \ogs_file_param{prj__chemical_system__equilibrium_phases} + config->getConfigSubtreeOptional("equilibrium_phases")); + std::vector<std::vector<EquilibriumPhase>> equilibrium_phases( + num_chemical_systems, equilibrium_phases_per_chem_sys); + + // kinetic reactants + auto const kinetic_reactants_per_chem_sys = createKineticReactants( + //! \ogs_file_param{prj__chemical_system__kinetic_reactants} + config->getConfigSubtreeOptional("kinetic_reactants")); + std::vector<std::vector<KineticReactant>> kinetic_reactants( + num_chemical_systems, kinetic_reactants_per_chem_sys); + + // rates + auto reaction_rates = createReactionRates( + //! \ogs_file_param{prj__chemical_system__rates} + config->getConfigSubtreeOptional("rates")); + + // output + auto const project_file_name = BaseLib::joinPaths( + output_directory, + BaseLib::extractBaseNameWithoutExtension(config->getProjectFileName())); + auto output = + createOutput(components_per_chem_sys, equilibrium_phases_per_chem_sys, + kinetic_reactants_per_chem_sys, project_file_name); + + return std::make_unique<PhreeqcIO>( + project_file_name, std::move(path_to_database), + std::move(aqueous_solutions), std::move(equilibrium_phases), + std::move(kinetic_reactants), std::move(reaction_rates), + std::move(output), process_id_to_component_name_map); +} +} // namespace ChemistryLib diff --git a/ChemistryLib/CreatePhreeqcIO.h b/ChemistryLib/CreatePhreeqcIO.h new file mode 100644 index 0000000000000000000000000000000000000000..57dd86b9513b1cd5e4040d949c74258c71775b3a --- /dev/null +++ b/ChemistryLib/CreatePhreeqcIO.h @@ -0,0 +1,34 @@ +/** + * \copyright + * Copyright (c) 2012-2019, OpenGeoSys Community (http://www.opengeosys.org) + * Distributed under a Modified BSD License. + * See accompanying file LICENSE.txt or + * http://www.opengeosys.org/project/license + * + */ + +#pragma once + +#include <memory> + +#include "PhreeqcIO.h" + +namespace BaseLib +{ +class ConfigTree; +} + +namespace ProcessLib +{ +class Process; +} + +namespace ChemistryLib +{ +std::unique_ptr<PhreeqcIO> createPhreeqcIO( + std::size_t const num_nodes, + std::vector<std::pair<int, std::string>> const& + process_id_to_component_name_map, + boost::optional<BaseLib::ConfigTree> const& config, + std::string const& output_directory); +} // namespace ChemistryLib diff --git a/ChemistryLib/PhreeqcIO.h b/ChemistryLib/PhreeqcIO.h new file mode 100644 index 0000000000000000000000000000000000000000..a88a7f58ff1e5707f509c11ab5cd23758647767f --- /dev/null +++ b/ChemistryLib/PhreeqcIO.h @@ -0,0 +1,59 @@ +/** + * \copyright + * Copyright (c) 2012-2019, OpenGeoSys Community (http://www.opengeosys.org) + * Distributed under a Modified BSD License. + * See accompanying file LICENSE.txt or + * http://www.opengeosys.org/project/license + * + */ + +#pragma once + +#include <memory> + +#include "MathLib/LinAlg/GlobalMatrixVectorTypes.h" +#include "Output.h" +#include "PhreeqcIOData/AqueousSolution.h" +#include "PhreeqcIOData/EquilibriumPhase.h" +#include "PhreeqcIOData/KineticReactant.h" +#include "PhreeqcIOData/ReactionRate.h" + +namespace ChemistryLib +{ +class PhreeqcIO +{ +public: + PhreeqcIO(std::string const& project_file_name, + std::string&& database, + std::vector<AqueousSolution>&& aqueous_solutions, + std::vector<std::vector<EquilibriumPhase>>&& equilibrium_phases, + std::vector<std::vector<KineticReactant>>&& kinetic_reactants, + std::vector<ReactionRate>&& reaction_rates, + std::unique_ptr<Output>&& output, + std::vector<std::pair<int, std::string>> const& + process_id_to_component_name_map) + : _phreeqc_input_file(project_file_name + "_phreeqc.inp"), + _database(std::move(database)), + _aqueous_solutions(std::move(aqueous_solutions)), + _equilibrium_phases(std::move(equilibrium_phases)), + _kinetic_reactants(std::move(kinetic_reactants)), + _reaction_rates(std::move(reaction_rates)), + _output(std::move(output)), + _process_id_to_component_name_map(process_id_to_component_name_map) + { + } + + std::string const _phreeqc_input_file; + +private: + std::string const _database; + std::vector<AqueousSolution> _aqueous_solutions; + std::vector<std::vector<EquilibriumPhase>> _equilibrium_phases; + std::vector<std::vector<KineticReactant>> _kinetic_reactants; + std::vector<ReactionRate> const _reaction_rates; + std::unique_ptr<Output> const _output; + std::vector<std::pair<int, std::string>> const& + _process_id_to_component_name_map; + double _dt; +}; +} // namespace ChemistryLib