Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : #ifndef InputProcessor_hh_INCLUDED
49 : #define InputProcessor_hh_INCLUDED
50 :
51 : // C++ Headers
52 : #include <map>
53 : #include <set>
54 : #include <string>
55 : #include <unordered_map>
56 : #include <vector>
57 :
58 : // ObjexxFCL Headers
59 : #include <ObjexxFCL/Array1D.hh>
60 : #include <ObjexxFCL/Array1S.fwd.hh>
61 : #include <ObjexxFCL/Optional.hh>
62 :
63 : #include <nlohmann/json.hpp>
64 :
65 : // EnergyPlus Headers
66 : #include <EnergyPlus/Data/BaseData.hh>
67 : #include <EnergyPlus/DataGlobals.hh>
68 : #include <EnergyPlus/EnergyPlus.hh>
69 : #include <EnergyPlus/InputProcessing/DataStorage.hh>
70 : #include <EnergyPlus/InputProcessing/IdfParser.hh>
71 : #include <EnergyPlus/InputProcessing/InputValidation.hh>
72 :
73 : class IdfParser;
74 : class Validation;
75 : struct EnergyPlusData;
76 :
77 : namespace EnergyPlus {
78 :
79 : void cleanEPJSON(nlohmann::json &epjson);
80 :
81 : class InputProcessor
82 : {
83 : public:
84 : using json = nlohmann::json;
85 :
86 : json::parser_callback_t callback;
87 :
88 : InputProcessor();
89 :
90 : static std::unique_ptr<InputProcessor> factory();
91 :
92 : template <typename T> T *objectFactory(EnergyPlusData &state, std::string const &objectName)
93 : {
94 : T *p = data->objectFactory<T>(objectName);
95 : if (p != nullptr) {
96 : return p;
97 : }
98 : auto const &fields = getFields(state, T::canonicalObjectType(), objectName);
99 : p = data->addObject<T>(objectName, fields);
100 : return p;
101 : }
102 :
103 : template <typename T> T *objectFactory(EnergyPlusData &state)
104 : {
105 : T *p = data->objectFactory<T>();
106 : if (p != nullptr) {
107 : return p;
108 : }
109 : auto const &fields = getFields(state, T::canonicalObjectType());
110 : p = data->addObject<T>(fields);
111 : return p;
112 : }
113 :
114 : std::pair<bool, std::string> convertInsensitiveObjectType(std::string const &objectType);
115 :
116 : void initializeMaps();
117 :
118 : void markObjectAsUsed(const std::string &objectType, const std::string &objectName);
119 :
120 : void processInput(EnergyPlusData &state);
121 :
122 : int getNumSectionsFound(std::string const &SectionWord);
123 :
124 : int getNumObjectsFound(EnergyPlusData &state, std::string_view const ObjectWord);
125 :
126 : bool findDefault(std::string &default_value, json const &schema_field_obj);
127 :
128 : bool findDefault(Real64 &default_value, json const &schema_field_obj);
129 :
130 : bool getDefaultValue(EnergyPlusData &state, std::string const &objectWord, std::string const &fieldName, Real64 &value);
131 :
132 : bool getDefaultValue(EnergyPlusData &state, std::string const &objectWord, std::string const &fieldName, std::string &value);
133 :
134 : std::string getAlphaFieldValue(json const &ep_object, json const &schema_obj_props, std::string const &fieldName, bool uc = true);
135 :
136 : Real64 getRealFieldValue(json const &ep_object, json const &schema_obj_props, std::string const &fieldName);
137 :
138 : int getIntFieldValue(json const &ep_object, json const &schema_obj_props, std::string const &fieldName);
139 :
140 : const json &getObjectSchemaProps(EnergyPlusData &state, std::string const &objectWord);
141 :
142 : std::pair<std::string, bool> getObjectItemValue(std::string const &field_value, json const &schema_field_obj);
143 :
144 : const json &getJSONObjectItem(EnergyPlusData &state, std::string_view ObjType, std::string_view ObjName);
145 :
146 : void getObjectItem(EnergyPlusData &state,
147 : std::string_view Object,
148 : int const Number,
149 : Array1S_string Alphas,
150 : int &NumAlphas,
151 : Array1D<Real64> &Numbers,
152 : int &NumNumbers,
153 : int &Status,
154 : ObjexxFCL::Optional<Array1D_bool> NumBlank = _,
155 : ObjexxFCL::Optional<Array1D_bool> AlphaBlank = _,
156 : ObjexxFCL::Optional<Array1D_string> AlphaFieldNames = _,
157 : ObjexxFCL::Optional<Array1D_string> NumericFieldNames = _);
158 :
159 : int getIDFObjNum(EnergyPlusData &state, std::string_view Object, int const Number);
160 :
161 : std::vector<std::string> getIDFOrderedKeys(EnergyPlusData &state, std::string_view Object);
162 :
163 : int getJSONObjNum(EnergyPlusData &state, std::string const &Object, int const Number);
164 :
165 : int getObjectItemNum(EnergyPlusData &state,
166 : std::string_view ObjType, // Object Type (ref: IDD Objects)
167 : std::string_view ObjName // Name of the object type
168 : );
169 :
170 : int getObjectItemNum(EnergyPlusData &state,
171 : std::string_view ObjType, // Object Type (ref: IDD Objects)
172 : std::string const &NameTypeVal, // Object "name" field type ( used as search key )
173 : std::string const &ObjName // Name of the object type
174 : );
175 :
176 : void getMaxSchemaArgs(int &NumArgs, int &NumAlpha, int &NumNumeric);
177 :
178 : void getObjectDefMaxArgs(EnergyPlusData &state,
179 : std::string_view const ObjectWord, // Object for definition
180 : int &NumArgs, // How many arguments (max) this Object can have
181 : int &NumAlpha, // How many Alpha arguments (max) this Object can have
182 : int &NumNumeric // How many Numeric arguments (max) this Object can have
183 : );
184 :
185 : void preProcessorCheck(EnergyPlusData &state, bool &PreP_Fatal); // True if a preprocessor flags a fatal error
186 :
187 : void preScanReportingVariables(EnergyPlusData &state);
188 :
189 : void reportIDFRecordsStats(EnergyPlusData &state);
190 :
191 : void reportOrphanRecordObjects(EnergyPlusData &state);
192 :
193 : const json &getObjectInstances(std::string const &ObjType);
194 :
195 : bool checkForUnsupportedObjects(EnergyPlusData &state);
196 :
197 : // void clear_state();
198 : private:
199 : friend class EnergyPlusFixture;
200 : friend class InputProcessorFixture;
201 :
202 : struct ObjectInfo
203 : {
204 1926545 : ObjectInfo() = default;
205 :
206 342576 : ObjectInfo(std::string const &objectType, std::string const &objectName) : objectType(objectType), objectName(objectName)
207 : {
208 342576 : }
209 :
210 : ObjectInfo(std::string &&objectType, std::string &&objectName) : objectType(objectType), objectName(objectName)
211 : {
212 : }
213 :
214 8047525 : bool operator<(const ObjectInfo &rhs) const
215 : {
216 8047525 : int cmp = this->objectType.compare(rhs.objectType);
217 8047525 : if (cmp == 0) {
218 2914584 : return this->objectName < rhs.objectName;
219 : }
220 5132941 : return cmp < 0;
221 : }
222 :
223 : std::string objectType = "";
224 : std::string objectName = "";
225 : };
226 :
227 : struct ObjectCache
228 : {
229 58030 : ObjectCache() = default;
230 :
231 : ObjectCache(json::const_iterator const &schemaIterator, std::vector<json::const_iterator> const &inputObjectIterators)
232 : : schemaIterator(schemaIterator), inputObjectIterators(inputObjectIterators)
233 : {
234 : }
235 :
236 : ObjectCache(json::const_iterator &&schemaIterator, std::vector<json::const_iterator> &&inputObjectIterators)
237 : : schemaIterator(schemaIterator), inputObjectIterators(inputObjectIterators)
238 : {
239 : }
240 :
241 : json::const_iterator schemaIterator;
242 : std::vector<json::const_iterator> inputObjectIterators;
243 : };
244 :
245 : struct MaxFields
246 : {
247 : MaxFields() = default;
248 : std::size_t max_fields = 0;
249 : std::size_t max_extensible_fields = 0;
250 : };
251 :
252 : MaxFields findMaxFields(
253 : EnergyPlusData &state, json const &ep_object, std::string const &extension_key, json const &legacy_idd, std::size_t const min_fields);
254 :
255 : void setObjectItemValue(EnergyPlusData &state,
256 : json const &ep_object,
257 : json const &ep_schema_object,
258 : std::string const &field,
259 : json const &legacy_field_info,
260 : int &alpha_index,
261 : int &numeric_index,
262 : bool within_max_fields,
263 : Array1S_string Alphas,
264 : int &NumAlphas,
265 : Array1D<Real64> &Numbers,
266 : int &NumNumbers,
267 : ObjexxFCL::Optional<Array1D_bool> NumBlank = _,
268 : ObjexxFCL::Optional<Array1D_bool> AlphaBlank = _,
269 : ObjexxFCL::Optional<Array1D_string> AlphaFieldNames = _,
270 : ObjexxFCL::Optional<Array1D_string> NumericFieldNames = _);
271 :
272 : void addVariablesForMonthlyReport(EnergyPlusData &state, std::string const &reportName);
273 :
274 : void addRecordToOutputVariableStructure(EnergyPlusData &state, std::string const &KeyValue, std::string const &VariableName);
275 :
276 : std::vector<std::string> const &validationErrors();
277 :
278 : std::vector<std::string> const &validationWarnings();
279 :
280 : bool checkVersionMatch(EnergyPlusData &state);
281 :
282 : bool processErrors(EnergyPlusData &state);
283 :
284 : json const &getFields(EnergyPlusData &state, std::string const &objectType, std::string const &objectName);
285 :
286 : json const &getFields(EnergyPlusData &state, std::string const &objectType);
287 :
288 : json const &getPatternProperties(EnergyPlusData &state, json const &schema_obj);
289 :
290 1277449 : inline std::string convertToUpper(std::string_view s)
291 : {
292 1277449 : std::string s2;
293 1277449 : size_t len = s.size();
294 1277449 : s2.resize(len);
295 39184430 : for (size_t i = 0; i < len; ++i) {
296 37906981 : char c = s[i];
297 37906981 : s2[i] = ('a' <= c && c <= 'z') ? c ^ 0x20 : c; // ASCII only
298 : }
299 1277449 : s2[len] = '\0';
300 1277449 : return s2;
301 0 : }
302 :
303 : using UnorderedObjectTypeMap = std::unordered_map<std::string, std::string>;
304 : using UnorderedObjectCacheMap = std::unordered_map<std::string, ObjectCache>;
305 : using UnusedObjectSet = std::set<ObjectInfo>;
306 :
307 : std::unique_ptr<IdfParser> idf_parser;
308 : std::unique_ptr<Validation> validation;
309 : std::unique_ptr<DataStorage> data;
310 : static const json &schema();
311 :
312 : public:
313 : json epJSON;
314 :
315 : private:
316 : // Maps OBJECTTYPE to ObjectType (example entry: {"ZONEHVAC:EQUIPMENTLIST", "ZoneHVAC:EquipmentList"})
317 : UnorderedObjectTypeMap caseInsensitiveObjectMap;
318 : // Maps ObjectType to ObjectCache (json::const_iterator const &schemaIterator, std::vector<json::const_iterator> const &inputObjectIterators)
319 : UnorderedObjectCacheMap objectCacheMap;
320 :
321 : // ObjectType to vector of ObjectName
322 : UnusedObjectSet unusedInputs;
323 : char s[129] = {0};
324 :
325 : }; // InputProcessor
326 :
327 : struct DataInputProcessing : BaseGlobalStruct
328 : {
329 : std::unique_ptr<InputProcessor> inputProcessor = InputProcessor::factory();
330 :
331 801 : void init_constant_state([[maybe_unused]] EnergyPlusData &state) override
332 : {
333 801 : }
334 :
335 801 : void init_state([[maybe_unused]] EnergyPlusData &state) override
336 : {
337 801 : }
338 :
339 0 : void clear_state() override
340 : {
341 0 : inputProcessor.reset();
342 0 : inputProcessor = EnergyPlus::InputProcessor::factory();
343 0 : }
344 : };
345 :
346 : } // namespace EnergyPlus
347 :
348 : #endif
|