Line data Source code
1 : //* This file is part of the MOOSE framework
2 : //* https://mooseframework.inl.gov
3 : //*
4 : //* All rights reserved, see COPYRIGHT for full restrictions
5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 : //*
7 : //* Licensed under LGPL 2.1, please see LICENSE for details
8 : //* https://www.gnu.org/licenses/lgpl-2.1.html
9 :
10 : #include "GeochemicalDatabaseValidator.h"
11 :
12 : #include "Conversion.h"
13 : #include "MooseUtils.h"
14 : #include "string"
15 :
16 961 : GeochemicalDatabaseValidator::GeochemicalDatabaseValidator(const FileName filename,
17 961 : const nlohmann::json & db)
18 961 : : _filename(filename), _root(db)
19 : {
20 961 : }
21 :
22 : void
23 961 : GeochemicalDatabaseValidator::validate()
24 : {
25 : // Check that the database has a Header key (required)
26 961 : if (!_root.contains("Header"))
27 2 : mooseError("The MOOSE database ", _filename, " does not have a required \"Header\" field");
28 :
29 : // Check that temperatures are present
30 959 : checkHeaderField("temperatures");
31 :
32 : // The size of the temperature array is used to check all other arrays, which must
33 : // have the same number of elements
34 958 : _temperature_size = _root["Header"]["temperatures"].size();
35 :
36 : // Now check that the values are all Real
37 958 : checkHeaderArray("temperatures");
38 :
39 : // Check the pressure values are present and are Reals
40 958 : checkHeaderField("pressures");
41 958 : checkHeaderArray("pressures");
42 :
43 : // Check activity model coefficients
44 958 : checkHeaderField("activity model");
45 :
46 : // If the activity model is Debye-Huckel, test the coefficients are also present
47 : // and are Reals
48 957 : if (_root["Header"]["activity model"] == "debye-huckel")
49 : {
50 956 : checkHeaderField("adh");
51 956 : checkHeaderArray("adh");
52 :
53 956 : checkHeaderField("bdh");
54 956 : checkHeaderArray("bdh");
55 :
56 956 : checkHeaderField("bdot");
57 1912 : checkHeaderArray("bdot");
58 : }
59 :
60 : // Check fugacity model is specified
61 957 : checkHeaderField("fugacity model");
62 :
63 : // If there are neutral species, check their arrays of coefficients
64 957 : if (_root["Header"].contains("neutral species"))
65 3820 : for (auto & ns : _root["Header"]["neutral species"].items())
66 11946 : for (auto & coeffs : ns.value().items())
67 : {
68 16256 : if (coeffs.key() == "note")
69 768 : continue;
70 :
71 : // Check that there are a correct number of values and that they are real numbers
72 7360 : auto values = coeffs.value();
73 14720 : checkArraySize(values, "Header:neutral species:" + ns.key() + ":" + coeffs.key());
74 22078 : checkArrayValues(values, "Header:neutral species:" + ns.key() + ":" + coeffs.key());
75 : }
76 :
77 : // Check the element data
78 27961 : for (auto & el : _root["elements"].items())
79 52102 : checkElements(el.key());
80 :
81 : // Check the basis species data
82 33011 : for (auto & species : _root["basis species"].items())
83 62202 : checkBasisSpecies(species.key());
84 :
85 : // Check the secondary species data
86 955 : if (_root.contains("secondary species"))
87 297282 : for (auto & species : _root["secondary species"].items())
88 590770 : checkSecondarySpecies(species.key());
89 :
90 : // Check the mineral species data
91 950 : if (_root.contains("mineral species"))
92 334487 : for (auto & species : _root["mineral species"].items())
93 665224 : checkMineralSpecies(species.key());
94 :
95 : // Check the sorbing mineral species data
96 949 : if (_root.contains("sorbing minerals"))
97 1690 : for (auto & species : _root["sorbing minerals"].items())
98 1748 : checkSorbingMineralSpecies(species.key());
99 :
100 : // Check the gas species data
101 949 : if (_root.contains("gas species"))
102 7990 : for (auto & species : _root["gas species"].items())
103 12920 : checkGasSpecies(species.key());
104 :
105 : // Check the redox couple data
106 949 : if (_root.contains("redox couples"))
107 29699 : for (auto & species : _root["redox couples"].items())
108 55614 : checkRedoxSpecies(species.key());
109 :
110 : // Check the oxide species data
111 949 : if (_root.contains("oxides"))
112 23456 : for (auto & species : _root["oxides"].items())
113 43848 : checkOxideSpecies(species.key());
114 :
115 : // Check the surface species data
116 949 : if (_root.contains("surface species"))
117 11204 : for (auto & species : _root["surface species"].items())
118 20776 : checkSurfaceSpecies(species.key());
119 949 : }
120 :
121 : bool
122 9396868 : GeochemicalDatabaseValidator::isValueReal(const nlohmann::json & value) const
123 : {
124 : if (value.is_number())
125 : return true;
126 : try
127 : {
128 134179 : MooseUtils::convert<Real>(value, true);
129 : }
130 4 : catch (const std::invalid_argument & err)
131 : {
132 : return false;
133 4 : }
134 :
135 134175 : return true;
136 : }
137 :
138 : void
139 12143 : GeochemicalDatabaseValidator::checkArrayValues(const nlohmann::json & array,
140 : const std::string field) const
141 : {
142 : // Check each value in the array can be successfully converted to a Real
143 121429 : for (auto & item : array.items())
144 97144 : if (!isValueReal(item.value()))
145 1 : mooseError("Array value ",
146 2 : nlohmann::to_string(item.value()),
147 : " in the ",
148 : field,
149 : " field of ",
150 1 : _filename,
151 : " cannot be converted to Real");
152 12142 : }
153 :
154 : void
155 664843 : GeochemicalDatabaseValidator::checkArrayValues(const std::string type,
156 : const std::string species,
157 : const std::string field) const
158 : {
159 : // Check each value in the array can be successfully converted to a Real
160 6643258 : for (auto & item : _root[type][species][field].items())
161 5313573 : if (!isValueReal(item.value()))
162 1 : mooseError("Array value ",
163 2 : nlohmann::to_string(item.value()),
164 : " in the ",
165 : field,
166 : " field of ",
167 : type,
168 : " ",
169 : species,
170 : " in ",
171 1 : _filename,
172 : " cannot be converted to Real");
173 664842 : }
174 :
175 : void
176 12144 : GeochemicalDatabaseValidator::checkArraySize(const nlohmann::json & array,
177 : const std::string field) const
178 : {
179 12144 : if (array.size() != _temperature_size)
180 1 : mooseError("The number of values in the ",
181 : field,
182 : " field of ",
183 1 : _filename,
184 : " is not equal to the number of temperature values");
185 12143 : }
186 :
187 : void
188 662260 : GeochemicalDatabaseValidator::checkArraySize(const std::string type,
189 : const std::string species,
190 : const std::string field) const
191 : {
192 662260 : if (_root[type][species][field].size() != _temperature_size)
193 1 : mooseError("The number of values in the ",
194 : field,
195 : " field of ",
196 : type,
197 : " ",
198 : species,
199 : " in ",
200 1 : _filename,
201 : " is not equal to the number of temperature values");
202 662259 : }
203 :
204 : void
205 6700 : GeochemicalDatabaseValidator::checkHeaderField(const std::string field) const
206 : {
207 6700 : if (!_root["Header"].contains(field))
208 2 : mooseError(
209 2 : "The MOOSE database ", _filename, " does not have a required \"Header:", field, "\" field");
210 6698 : }
211 :
212 : void
213 4784 : GeochemicalDatabaseValidator::checkHeaderArray(const std::string field) const
214 : {
215 : // Check that all values are real numbers and of size equal to the temperature
216 4784 : checkArraySize(_root["Header"][field], "Header:" + field);
217 4784 : checkArrayValues(_root["Header"][field], "Header:" + field);
218 4784 : }
219 :
220 : void
221 1839582 : GeochemicalDatabaseValidator::checkSpeciesValue(const std::string type,
222 : const std::string species,
223 : const std::string field) const
224 : {
225 1839582 : if (!_root[type].contains(species) || !_root[type][species].contains(field))
226 1 : mooseError("The ", type, " ", species, " in ", _filename, " does not have a ", field);
227 :
228 : // The field value should be a real number
229 1839581 : if (!isValueReal(_root[type][species][field]))
230 1 : mooseError(field,
231 : " value ",
232 1 : nlohmann::to_string(_root[type][species][field]),
233 : " of the ",
234 : type,
235 : " ",
236 : species,
237 : " in ",
238 1 : _filename,
239 : " cannot be converted to Real");
240 1839580 : }
241 :
242 : void
243 726549 : GeochemicalDatabaseValidator::checkSpeciesWeightValue(const std::string type,
244 : const std::string species,
245 : const std::string field) const
246 : {
247 726549 : if (!_root[type].contains(species) || !_root[type][species].contains(field))
248 1 : mooseError("The ", type, " ", species, " in ", _filename, " does not have a ", field);
249 :
250 : // Each weight value for each constituent should be a real number
251 3599665 : for (auto & item : _root[type][species][field].items())
252 2146570 : if (!isValueReal(item.value()))
253 1 : mooseError("Weight value ",
254 2 : nlohmann::to_string(item.value()),
255 : " of constituent ",
256 1 : item.key(),
257 : " of the ",
258 : type,
259 : " ",
260 : species,
261 : " in ",
262 1 : _filename,
263 : " cannot be converted to Real");
264 726547 : }
265 :
266 : void
267 26051 : GeochemicalDatabaseValidator::checkElements(const std::string element) const
268 : {
269 : // Check molecular weight can be converted to a Real
270 52102 : checkSpeciesValue("elements", element, "molecular weight");
271 26051 : }
272 :
273 : void
274 31101 : GeochemicalDatabaseValidator::checkBasisSpecies(const std::string species) const
275 : {
276 : // Check molecular weight can be converted to a Real
277 62202 : checkSpeciesValue("basis species", species, "molecular weight");
278 :
279 : // Check charge can be converted to a Real
280 62202 : checkSpeciesValue("basis species", species, "charge");
281 :
282 : // Check ionic radius can be converted to a Real
283 62202 : checkSpeciesValue("basis species", species, "radius");
284 :
285 : // Check element weights can be converted to a Real
286 62202 : checkSpeciesWeightValue("basis species", species, "elements");
287 31101 : }
288 :
289 : void
290 295385 : GeochemicalDatabaseValidator::checkSecondarySpecies(const std::string species) const
291 : {
292 : // Check molecular weight can be converted to a Real
293 590770 : checkSpeciesValue("secondary species", species, "molecular weight");
294 :
295 : // Check charge can be converted to a Real
296 590771 : checkSpeciesValue("secondary species", species, "charge");
297 :
298 : // Check ionic radius can be converted to a Real
299 590769 : checkSpeciesValue("secondary species", species, "radius");
300 :
301 : // Check basis species weights can be converted to a Real
302 590768 : checkSpeciesWeightValue("secondary species", species, "species");
303 :
304 : // Check the number of logk values and whether they can be converted to a Real
305 590763 : checkArraySize("secondary species", species, "logk");
306 590760 : checkArrayValues("secondary species", species, "logk");
307 295380 : }
308 :
309 : void
310 332612 : GeochemicalDatabaseValidator::checkMineralSpecies(const std::string species) const
311 : {
312 : // Check molecular weight can be converted to a Real
313 665224 : checkSpeciesValue("mineral species", species, "molecular weight");
314 :
315 : // Check molar volume can be converted to a Real
316 665224 : checkSpeciesValue("mineral species", species, "molar volume");
317 :
318 : // Check basis species weights can be converted to a Real
319 665224 : checkSpeciesWeightValue("mineral species", species, "species");
320 :
321 : // Check the number of logk values and whether they can be converted to a Real
322 665224 : checkArraySize("mineral species", species, "logk");
323 665225 : checkArrayValues("mineral species", species, "logk");
324 332611 : }
325 :
326 : void
327 874 : GeochemicalDatabaseValidator::checkSorbingMineralSpecies(const std::string species) const
328 : {
329 : // Check surface area can be converted to a Real
330 1748 : checkSpeciesValue("sorbing minerals", species, "surface area");
331 :
332 : // Check sorbing site weights can be converted to a Real
333 1748 : checkSpeciesWeightValue("sorbing minerals", species, "sorbing sites");
334 874 : }
335 :
336 : void
337 6460 : GeochemicalDatabaseValidator::checkGasSpecies(const std::string species) const
338 : {
339 : // Check molecular weight can be converted to a Real
340 12920 : checkSpeciesValue("gas species", species, "molecular weight");
341 :
342 : // Check basis species weights can be converted to a Real
343 12920 : checkSpeciesWeightValue("gas species", species, "species");
344 :
345 : // Check the number of logk values and whether they can be converted to a Real
346 12920 : checkArraySize("gas species", species, "logk");
347 12920 : checkArrayValues("gas species", species, "logk");
348 :
349 : // Check optional fugacity coefficients
350 6460 : if (_root["gas species"][species].contains("chi"))
351 5168 : checkArrayValues("gas species", species, "chi");
352 :
353 6460 : if (_root["gas species"][species].contains("Pcrit"))
354 9746 : checkSpeciesValue("gas species", species, "Pcrit");
355 :
356 6460 : if (_root["gas species"][species].contains("Tcrit"))
357 9746 : checkSpeciesValue("gas species", species, "Tcrit");
358 :
359 6460 : if (_root["gas species"][species].contains("omega"))
360 9746 : checkSpeciesValue("gas species", species, "omega");
361 6460 : }
362 :
363 : void
364 27807 : GeochemicalDatabaseValidator::checkRedoxSpecies(const std::string species) const
365 : {
366 : // Check molecular weight can be converted to a Real
367 55614 : checkSpeciesValue("redox couples", species, "molecular weight");
368 :
369 : // Check charge can be converted to a Real
370 55614 : checkSpeciesValue("redox couples", species, "charge");
371 :
372 : // Check ionic radius can be converted to a Real
373 55614 : checkSpeciesValue("redox couples", species, "radius");
374 :
375 : // Check basis species weights can be converted to a Real
376 55614 : checkSpeciesWeightValue("redox couples", species, "species");
377 :
378 : // Check the number of logk values and whether they can be converted to a Real
379 55614 : checkArraySize("redox couples", species, "logk");
380 55614 : checkArrayValues("redox couples", species, "logk");
381 27807 : }
382 :
383 : void
384 21924 : GeochemicalDatabaseValidator::checkOxideSpecies(const std::string species) const
385 : {
386 : // Check molecular weight can be converted to a Real
387 43848 : checkSpeciesValue("oxides", species, "molecular weight");
388 :
389 : // Check basis species weights can be converted to a Real
390 43848 : checkSpeciesWeightValue("oxides", species, "species");
391 21924 : }
392 :
393 : void
394 10388 : GeochemicalDatabaseValidator::checkSurfaceSpecies(const std::string species) const
395 : {
396 : // Check molecular weight can be converted to a Real
397 20776 : checkSpeciesValue("surface species", species, "molecular weight");
398 :
399 : // Check charge can be converted to a Real
400 20776 : checkSpeciesValue("surface species", species, "charge");
401 :
402 : // Check basis species weights can be converted to a Real
403 20776 : checkSpeciesWeightValue("surface species", species, "species");
404 :
405 : // Check equilibrium constants can be converted to a Real
406 20776 : checkSpeciesValue("surface species", species, "log K");
407 20776 : checkSpeciesValue("surface species", species, "dlogK/dT");
408 10388 : }
|