| Cantera 3.0.0

Loading...
Searching...
No Matches
YamlWriter.cpp
1// This file is part of Cantera. See License.txt in the top-level directory or
2// at https://cantera.org/license.txt for license and copyright information.
3
4#include "cantera/base/YamlWriter.h"
5#include "cantera/base/AnyMap.h"
6#include "cantera/base/Solution.h"
7#include "cantera/base/stringUtils.h"
8#include "cantera/thermo/ThermoPhase.h"
9#include "cantera/thermo/Species.h"
10#include "cantera/kinetics/Kinetics.h"
11#include "cantera/kinetics/Reaction.h"
12#include "cantera/transport/Transport.h"
13
14#include <fstream>
15#include <chrono>
16
17 namespace Cantera {
18
19 void YamlWriter::setHeader(const AnyMap& header) {
20 m_header = header;
21}
22
23 void YamlWriter::addPhase(shared_ptr<Solution> soln, bool includeAdjacent) {
24 for (auto& phase : m_phases) {
25 if (phase->name() == soln->name()) {
26 if (phase.get() == soln.get()) {
27 // This phase has already been added, so nothing needs to be done. This
28 // is expected in cases such as bulk phases adjacent to multiple
29 // surface phases.
30 return;
31 } else {
32 throw CanteraError("YamlWriter::addPhase",
33 "Duplicate phase name '{}'", soln->name());
34 }
35 }
36 }
37 m_phases.push_back(soln);
38 if (includeAdjacent) {
39 for (size_t i = 0; i < soln->nAdjacent(); i++) {
40 addPhase(soln->adjacent(i));
41 }
42 }
43}
44
45 void YamlWriter::addPhase(shared_ptr<ThermoPhase> thermo,
46 shared_ptr<Kinetics> kin,
47 shared_ptr<Transport> tran) {
48 auto soln = Solution::create();
49 soln->setThermo(thermo);
50 soln->setKinetics(kin);
51 soln->setTransport(tran);
52 addPhase(soln);
53}
54
55 string YamlWriter::toYamlString() const
56{
57 AnyMap output;
58 bool hasDescription = m_header.hasKey("description");
59 if (hasDescription) {
60 output["description"] = m_header["description"];
61 }
62 output["generator"] = "YamlWriter";
63 output["cantera-version"] = CANTERA_VERSION;
64 output["git-commit"] = gitCommit();
65 time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
66 output["date"] = trimCopy(std::ctime(&now));
67 if (hasDescription) {
68 output["description"].setLoc(-6, 0);
69 }
70 output["generator"].setLoc(-5, 0);
71 output["cantera-version"].setLoc(-4, 0);
72 output["git-commit"].setLoc(-3, 0);
73 output["date"].setLoc(-2, 0);
74
75 // Add remaining header information, ignoring obsolete information
76 set<string> exclude = {
77 "description", "generator", "cantera-version", "git-commit", "date"};
78 for (const auto& [key, value] : m_header) {
79 if (!exclude.count(key)) {
80 output[key] = value;
81 }
82 }
83
84 // Build phase definitions
85 vector<AnyMap> phaseDefs(m_phases.size());
86 size_t nspecies_total = 0;
87 for (size_t i = 0; i < m_phases.size(); i++) {
88 phaseDefs[i] = m_phases[i]->parameters(!m_skip_user_defined);
89 if (m_phases[i]->nAdjacent()) {
90 vector<string> adj_names;
91 for (size_t j = 0; j < m_phases[i]->nAdjacent(); j++) {
92 adj_names.push_back(m_phases[i]->adjacent(j)->name());
93 }
94 phaseDefs[i]["adjacent-phases"] = adj_names;
95 }
96 nspecies_total += m_phases[i]->thermo()->nSpecies();
97 }
98 output["phases"] = phaseDefs;
99
100 // Build species definitions for all phases
101 vector<AnyMap> speciesDefs;
102 speciesDefs.reserve(nspecies_total);
103 std::unordered_map<string, size_t> speciesDefIndex;
104 for (const auto& phase : m_phases) {
105 const auto thermo = phase->thermo();
106 for (const auto& name : thermo->speciesNames()) {
107 const auto& species = thermo->species(name);
108 AnyMap speciesDef = species->parameters(thermo.get(), !m_skip_user_defined);
109
110 if (speciesDefIndex.count(name) == 0) {
111 speciesDefs.emplace_back(speciesDef);
112 speciesDefIndex[name] = speciesDefs.size() - 1;
113 } else if (speciesDefs[speciesDefIndex[name]] != speciesDef) {
114 throw CanteraError("YamlWriter::toYamlString",
115 "Multiple species with different definitions are not "
116 "supported:\n>>>>>>\n{}\n======\n{}\n<<<<<<\n",
117 speciesDef.toYamlString(),
118 speciesDefs[speciesDefIndex[name]].toYamlString());
119 }
120 }
121 }
122 output["species"] = speciesDefs;
123
124 // build reaction definitions for all phases
125 map<string, vector<AnyMap>> allReactions;
126 for (const auto& phase : m_phases) {
127 const auto kin = phase->kinetics();
128 if (!kin || !kin->nReactions()) {
129 continue;
130 }
131 vector<AnyMap> reactions;
132 for (size_t i = 0; i < kin->nReactions(); i++) {
133 reactions.push_back(kin->reaction(i)->parameters(!m_skip_user_defined));
134 }
135 allReactions[phase->name()] = std::move(reactions);
136 }
137
138 // Figure out which phase definitions have identical sets of reactions,
139 // and can share a reaction definition section
140
141 // key: canonical phase in allReactions
142 // value: phases using this reaction set
143 map<string, vector<string>> phaseGroups;
144
145 for (const auto& phase : m_phases) {
146 const auto kin = phase->kinetics();
147 string name = phase->name();
148 if (!kin || !kin->nReactions()) {
149 continue;
150 }
151 bool match = false;
152 for (auto& [canonicalPhase, dependentPhases] : phaseGroups) {
153 if (allReactions[canonicalPhase] == allReactions[name]) {
154 dependentPhases.push_back(name);
155 allReactions.erase(name);
156 match = true;
157 break;
158 }
159 }
160 if (!match) {
161 phaseGroups[name].push_back(name);
162 }
163 }
164
165 // Generate the reactions section(s) in the output file
166 if (phaseGroups.size() == 1) {
167 output["reactions"] = std::move(allReactions[phaseGroups.begin()->first]);
168 } else {
169 for (const auto& [canonicalPhase, dependentPhases] : phaseGroups) {
170 string groupName;
171 for (auto& name : dependentPhases) {
172 groupName += name + "-";
173 }
174 groupName += "reactions";
175 output[groupName] = std::move(allReactions[canonicalPhase]);
176
177 for (auto& name : dependentPhases) {
178 AnyMap& phaseDef = output["phases"].getMapWhere("name", name);
179 phaseDef["reactions"] = vector<string>{groupName};
180 }
181 }
182 }
183
184 output.setMetadata("precision", AnyValue(m_float_precision));
185 output.setUnits(m_output_units);
186 return output.toYamlString();
187}
188
189 void YamlWriter::toYamlFile(const string& filename) const
190{
191 std::ofstream out(filename);
192 out << toYamlString();
193}
194
195 void YamlWriter::setUnits(const map<string, string>& units)
196{
197 m_output_units = UnitSystem();
198 m_output_units.setDefaults(units);
199}
200
201 void YamlWriter::setUnitSystem(const UnitSystem& units)
202{
203 m_output_units = units;
204}
205
206}
AnyMap.h
Kinetics.h
Base class for kinetics managers and also contains the kineticsmgr module documentation (see Kinetics...
Reaction.h
Solution.h
Species.h
Declaration for class Cantera::Species.
ThermoPhase.h
Header file for class ThermoPhase, the base class for phases with thermodynamic properties,...
Transport.h
Headers for the Transport object, which is the virtual base class for all transport property evaluato...
YamlWriter.h
Declaration for class Cantera::YamlWriter.
Cantera::AnyBase::setLoc
void setLoc(int line, int column)
For values which are derived from an input file, set the line and column of this value in that file.
Definition AnyMap.cpp:574
Cantera::AnyMap
A map of string keys to values whose type can vary at runtime.
Definition AnyMap.h:427
Cantera::AnyMap::size
size_t size() const
Returns the number of elements in this map.
Definition AnyMap.h:622
Cantera::AnyMap::hasKey
bool hasKey(const string &key) const
Returns true if the map contains an item named key.
Definition AnyMap.cpp:1423
Cantera::AnyMap::setMetadata
void setMetadata(const string &key, const AnyValue &value)
Set a metadata value that applies to this AnyMap and its children.
Definition AnyMap.cpp:1481
Cantera::AnyMap::setUnits
void setUnits(const UnitSystem &units)
Set the unit system for this AnyMap.
Definition AnyMap.cpp:1714
Cantera::AnyValue
A wrapper for a variable whose type is determined at runtime.
Definition AnyMap.h:86
Cantera::CanteraError
Base class for exceptions thrown by Cantera classes.
Definition ctexceptions.h:66
Cantera::Solution::create
static shared_ptr< Solution > create()
Create an empty Solution object.
Definition Solution.h:54
Cantera::UnitSystem
Unit conversion utility.
Definition Units.h:169
Cantera::UnitSystem::setDefaults
void setDefaults(std::initializer_list< string > units)
Set the default units to convert from when explicit units are not provided.
Definition Units.cpp:428
Cantera::YamlWriter::m_skip_user_defined
bool m_skip_user_defined
See skipUserDefined()
Definition YamlWriter.h:87
Cantera::YamlWriter::toYamlString
string toYamlString() const
Return a YAML string that contains the definitions for the added phases, species, and reactions.
Definition YamlWriter.cpp:55
Cantera::YamlWriter::setUnitSystem
void setUnitSystem(const UnitSystem &units=UnitSystem())
Set the units to be used in the output file.
Definition YamlWriter.cpp:201
Cantera::YamlWriter::m_float_precision
long int m_float_precision
See setPrecision()
Definition YamlWriter.h:84
Cantera::YamlWriter::m_header
AnyMap m_header
Top-level information used in YAML header block.
Definition YamlWriter.h:79
Cantera::YamlWriter::setHeader
void setHeader(const AnyMap &header)
Include top-level information used in YAML header block.
Definition YamlWriter.cpp:19
Cantera::YamlWriter::addPhase
void addPhase(shared_ptr< Solution > soln, bool includeAdjacent=true)
Include a phase definition for the specified Solution object.
Definition YamlWriter.cpp:23
Cantera::YamlWriter::m_output_units
UnitSystem m_output_units
Top-level units directive for the output file.
Definition YamlWriter.h:91
Cantera::YamlWriter::toYamlFile
void toYamlFile(const string &filename) const
Write the definitions for the added phases, species and reactions to the specified file.
Definition YamlWriter.cpp:189
Cantera::YamlWriter::setUnits
void setUnits(const map< string, string > &units={})
Set the units to be used in the output file.
Definition YamlWriter.cpp:195
Cantera::trimCopy
string trimCopy(const string &input)
Trim.
Definition stringUtils.cpp:215
Cantera::gitCommit
string gitCommit()
Returns the hash of the git commit from which Cantera was compiled, if known.
Definition global.cpp:150
Cantera
Namespace for the Cantera kernel.
Definition AnyMap.cpp:564
stringUtils.h
Contains declarations for string manipulation functions within Cantera.