Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2024, 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 : #include <cmath>
49 :
50 : #include <ObjexxFCL/ArrayS.functions.hh>
51 : #include <ObjexxFCL/time.hh>
52 :
53 : #include <EnergyPlus/Construction.hh>
54 : #include <EnergyPlus/Data/EnergyPlusData.hh>
55 : #include <EnergyPlus/DataEnvironment.hh>
56 : #include <EnergyPlus/DataGlobalConstants.hh>
57 : #include <EnergyPlus/DataHVACGlobals.hh>
58 : #include <EnergyPlus/DataRuntimeLanguage.hh>
59 : #include <EnergyPlus/DataStringGlobals.hh>
60 : #include <EnergyPlus/HeatBalFiniteDiffManager.hh>
61 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
62 : #include <EnergyPlus/OutputProcessor.hh>
63 : #include <EnergyPlus/PluginManager.hh>
64 : #include <EnergyPlus/UtilityRoutines.hh>
65 : #include <EnergyPlus/WeatherManager.hh>
66 : #include <EnergyPlus/api/datatransfer.h>
67 : #include <EnergyPlus/api/runtime.h>
68 :
69 : using namespace EnergyPlus;
70 :
71 0 : APIDataEntry *getAPIData(EnergyPlusState state, unsigned int *resultingSize)
72 : {
73 : struct LocalAPIDataEntry
74 : {
75 : std::string what;
76 : std::string name;
77 : std::string type;
78 : std::string key;
79 : std::string unit;
80 :
81 0 : LocalAPIDataEntry(std::string _what, std::string _name, std::string _type, std::string _key, std::string _unit)
82 0 : : what(std::move(_what)), name(std::move(_name)), type(std::move(_type)), key(std::move(_key)), unit(std::move(_unit))
83 : {
84 0 : }
85 : };
86 0 : std::vector<LocalAPIDataEntry> localDataEntries;
87 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
88 0 : for (auto const &availActuator : thisState->dataRuntimeLang->EMSActuatorAvailable) {
89 0 : if (availActuator.ComponentTypeName.empty() && availActuator.UniqueIDName.empty() && availActuator.ControlTypeName.empty()) {
90 0 : break;
91 : }
92 0 : localDataEntries.emplace_back(
93 0 : "Actuator", availActuator.ComponentTypeName, availActuator.ControlTypeName, availActuator.UniqueIDName, availActuator.Units);
94 : }
95 0 : for (auto const &availVariable : thisState->dataRuntimeLang->EMSInternalVarsAvailable) {
96 0 : if (availVariable.DataTypeName.empty() && availVariable.UniqueIDName.empty()) {
97 0 : break;
98 : }
99 0 : localDataEntries.emplace_back("InternalVariable", availVariable.DataTypeName, "", availVariable.UniqueIDName, availVariable.Units);
100 : }
101 0 : for (auto const &gVarName : thisState->dataPluginManager->globalVariableNames) {
102 0 : localDataEntries.emplace_back("PluginGlobalVariable", "", "", gVarName, "");
103 0 : }
104 0 : for (auto const &trend : thisState->dataPluginManager->trends) {
105 0 : localDataEntries.emplace_back("PluginTrendVariable,", "", "", trend.name, "");
106 0 : }
107 0 : for (auto const *meter : thisState->dataOutputProcessor->meters) {
108 0 : if (meter->Name.empty()) {
109 0 : break;
110 : }
111 0 : localDataEntries.emplace_back("OutputMeter", "", "", meter->Name, EnergyPlus::Constant::unitToString(meter->units));
112 0 : }
113 0 : for (auto const *variable : thisState->dataOutputProcessor->outVars) {
114 0 : if (variable->varType != EnergyPlus::OutputProcessor::VariableType::Real) continue;
115 0 : if (variable->name.empty() && variable->keyUC.empty()) {
116 0 : break;
117 : }
118 0 : localDataEntries.emplace_back("OutputVariable",
119 0 : variable->name,
120 : "",
121 0 : variable->keyUC,
122 0 : variable->units == EnergyPlus::Constant::Units::customEMS
123 0 : ? variable->unitNameCustomEMS
124 0 : : EnergyPlus::Constant::unitToString(variable->units));
125 0 : }
126 0 : *resultingSize = localDataEntries.size();
127 0 : auto *data = new APIDataEntry[*resultingSize];
128 0 : for (unsigned int i = 0; i < *resultingSize; i++) {
129 0 : data[i].what = new char[std::strlen(localDataEntries[i].what.c_str()) + 1];
130 0 : std::strcpy(data[i].what, localDataEntries[i].what.c_str());
131 0 : data[i].name = new char[std::strlen(localDataEntries[i].name.c_str()) + 1];
132 0 : std::strcpy(data[i].name, localDataEntries[i].name.c_str());
133 0 : data[i].key = new char[std::strlen(localDataEntries[i].key.c_str()) + 1];
134 0 : std::strcpy(data[i].key, localDataEntries[i].key.c_str());
135 0 : data[i].type = new char[std::strlen(localDataEntries[i].type.c_str()) + 1];
136 0 : std::strcpy(data[i].type, localDataEntries[i].type.c_str());
137 0 : data[i].unit = new char[std::strlen(localDataEntries[i].unit.c_str()) + 1];
138 0 : std::strcpy(data[i].unit, localDataEntries[i].unit.c_str());
139 : }
140 0 : return data;
141 0 : }
142 :
143 0 : void freeAPIData(const APIDataEntry *data, const unsigned int arraySize)
144 : {
145 0 : for (unsigned int i = 0; i < arraySize; i++) {
146 0 : delete[] data[i].what;
147 0 : delete[] data[i].name;
148 0 : delete[] data[i].key;
149 0 : delete[] data[i].type;
150 0 : delete[] data[i].unit;
151 : }
152 0 : delete[] data;
153 0 : }
154 :
155 0 : char *listAllAPIDataCSV(EnergyPlusState state)
156 : {
157 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
158 0 : std::string output = "**ACTUATORS**\n";
159 0 : for (auto const &availActuator : thisState->dataRuntimeLang->EMSActuatorAvailable) {
160 0 : if (availActuator.ComponentTypeName.empty() && availActuator.UniqueIDName.empty() && availActuator.ControlTypeName.empty()) {
161 0 : break;
162 : }
163 0 : output.append("Actuator,");
164 0 : output.append(availActuator.ComponentTypeName).append(",");
165 0 : output.append(availActuator.ControlTypeName).append(",");
166 0 : output.append(availActuator.UniqueIDName).append(",");
167 0 : output.append(availActuator.Units).append("\n");
168 : }
169 0 : output.append("**INTERNAL_VARIABLES**\n");
170 0 : for (auto const &availVariable : thisState->dataRuntimeLang->EMSInternalVarsAvailable) {
171 0 : if (availVariable.DataTypeName.empty() && availVariable.UniqueIDName.empty()) {
172 0 : break;
173 : }
174 0 : output.append("InternalVariable,");
175 0 : output.append(availVariable.DataTypeName).append(",");
176 0 : output.append(availVariable.UniqueIDName).append(",");
177 0 : output.append(availVariable.Units).append("\n");
178 : }
179 0 : output.append("**PLUGIN_GLOBAL_VARIABLES**\n");
180 0 : for (auto const &gVarName : thisState->dataPluginManager->globalVariableNames) {
181 0 : output.append("PluginGlobalVariable,");
182 0 : output.append(gVarName).append("\n");
183 0 : }
184 0 : output.append("**TRENDS**\n");
185 0 : for (auto const &trend : thisState->dataPluginManager->trends) {
186 0 : output.append("PluginTrendVariable,");
187 0 : output.append(trend.name).append("\n");
188 0 : }
189 0 : output.append("**METERS**\n");
190 0 : for (auto const *meter : thisState->dataOutputProcessor->meters) {
191 0 : if (meter->Name.empty()) {
192 0 : break;
193 : }
194 0 : output.append("OutputMeter").append(",");
195 0 : output.append(meter->Name).append(",");
196 0 : output.append(EnergyPlus::Constant::unitToString(meter->units)).append("\n");
197 0 : }
198 0 : output.append("**VARIABLES**\n");
199 0 : for (auto const *variable : thisState->dataOutputProcessor->outVars) {
200 0 : if (variable->varType != EnergyPlus::OutputProcessor::VariableType::Real) continue;
201 0 : if (variable->name.empty() && variable->keyUC.empty()) {
202 0 : break;
203 : }
204 0 : output.append("OutputVariable,");
205 0 : output.append(variable->name).append(",");
206 0 : output.append(variable->keyUC).append(",");
207 : output
208 0 : .append(variable->units == EnergyPlus::Constant::Units::customEMS ? variable->unitNameCustomEMS
209 0 : : EnergyPlus::Constant::unitToString(variable->units))
210 0 : .append("\n");
211 0 : }
212 : // note that we cannot just return a c_str to the local string, as the string will be destructed upon leaving
213 : // this function, and undefined behavior will occur.
214 : // instead make a deep copy, and the user must manage the new char * pointer
215 : // strcpy copies including the null-terminator, strlen doesn't include it
216 0 : char *p = new char[std::strlen(output.c_str()) + 1];
217 0 : std::strcpy(p, output.c_str());
218 0 : return p;
219 0 : }
220 :
221 317473 : int apiDataFullyReady(EnergyPlusState state)
222 : {
223 317473 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
224 317473 : if (thisState->dataPluginManager->fullyReady) {
225 309481 : return 1;
226 : }
227 7992 : return 0;
228 : }
229 :
230 0 : int apiErrorFlag(EnergyPlusState state)
231 : {
232 0 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
233 0 : if (thisState->dataPluginManager->apiErrorFlag) {
234 0 : return 1;
235 : }
236 0 : return 0;
237 : }
238 :
239 0 : void resetErrorFlag(EnergyPlusState state)
240 : {
241 0 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
242 0 : thisState->dataPluginManager->apiErrorFlag = false;
243 0 : }
244 :
245 0 : char *inputFilePath(EnergyPlusState state)
246 : {
247 0 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
248 0 : std::string const path_utf8 = EnergyPlus::FileSystem::toGenericString(thisState->dataStrGlobals->inputFilePath);
249 0 : char *p = new char[std::strlen(path_utf8.c_str()) + 1];
250 0 : std::strcpy(p, path_utf8.c_str());
251 0 : return p;
252 0 : }
253 :
254 0 : char *epwFilePath(EnergyPlusState state)
255 : {
256 0 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
257 0 : std::string const path_utf8 = EnergyPlus::FileSystem::toGenericString(thisState->files.inputWeatherFilePath.filePath);
258 0 : char *p = new char[std::strlen(path_utf8.c_str()) + 1];
259 0 : std::strcpy(p, path_utf8.c_str());
260 0 : return p;
261 0 : }
262 :
263 0 : char **getObjectNames(EnergyPlusState state, const char *objectType, unsigned int *resultingSize)
264 : {
265 0 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
266 0 : auto &epjson = thisState->dataInputProcessing->inputProcessor->epJSON;
267 0 : const auto instances = epjson.find(objectType);
268 0 : if (instances == epjson.end()) {
269 0 : *resultingSize = 0;
270 0 : return nullptr;
271 : }
272 0 : auto &instancesValue = instances.value();
273 0 : *resultingSize = instancesValue.size();
274 0 : char **data = new char *[*resultingSize];
275 0 : unsigned int i = -1;
276 0 : for (auto instance = instancesValue.begin(); instance != instancesValue.end(); ++instance) {
277 0 : i++;
278 0 : std::string s = std::string(instance.key());
279 0 : data[i] = new char[std::strlen(instance.key().data()) + 1];
280 0 : std::strcpy(data[i], instance.key().data());
281 0 : }
282 0 : return data;
283 0 : }
284 :
285 0 : void freeObjectNames(char **objectNames, unsigned int arraySize)
286 : {
287 : // as of right now we don't actually need to free the underlying strings, they exist in the epJSON instance, so just delete our array of pointers
288 : (void)arraySize;
289 : // no op to avoid compiler warning that this variable is unused, in the future, this may be needed so keeping it in the API now
290 0 : delete[] objectNames;
291 0 : }
292 :
293 13 : int getNumNodesInCondFDSurfaceLayer(EnergyPlusState state, const char *surfName, const char *matName)
294 : {
295 13 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
296 13 : std::string UCsurfName = EnergyPlus::Util::makeUPPER(surfName);
297 13 : std::string UCmatName = EnergyPlus::Util::makeUPPER(matName);
298 26 : return EnergyPlus::HeatBalFiniteDiffManager::numNodesInMaterialLayer(*thisState, UCsurfName, UCmatName);
299 13 : }
300 :
301 0 : void requestVariable(EnergyPlusState state, const char *type, const char *key)
302 : {
303 : // allow specifying a request for an output variable, so that E+ does not have to keep all of them in memory
304 : // should be called before energyplus is run!
305 : // note that the variable request array is cleared during clear_state, so if you run multiple E+ runs, these must be requested again each time.
306 0 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
307 0 : EnergyPlus::OutputProcessor::APIOutputVariableRequest request;
308 0 : request.varName = type;
309 0 : request.varKey = key;
310 0 : thisState->dataOutputProcessor->apiVarRequests.push_back(request);
311 0 : }
312 :
313 123 : int getVariableHandle(EnergyPlusState state, const char *type, const char *key)
314 : {
315 : // Variables are accessed through a single integer ID, but there are multiple internal types: real and integer.
316 : // I am going to make the integer handle span all both types, by carefully defining the handle.
317 : // basically, the handles are contiguous, with:
318 : // - index 1 being the first real variable handle
319 : // - index N being the highest real variable handle
320 : // - index N+1 being the first integer variable handle
321 : // - index N+M being the highest integer variable handle
322 : // In this function, it is as simple as looping over both types and continuing to increment
323 : // the handle carefully. In the getValue function it is just a matter of checking array sizes.
324 123 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
325 123 : std::string const typeUC = EnergyPlus::Util::makeUPPER(type);
326 123 : std::string const keyUC = EnergyPlus::Util::makeUPPER(key);
327 39235 : for (int i = 0; i < thisState->dataOutputProcessor->outVars.size(); i++) {
328 39230 : auto const *var = thisState->dataOutputProcessor->outVars[i];
329 39230 : if (typeUC == var->nameUC && keyUC == var->keyUC) {
330 118 : return i;
331 : }
332 : }
333 5 : return -1; // return -1 if it wasn't found
334 123 : }
335 :
336 651765 : Real64 getVariableValue(EnergyPlusState state, const int handle)
337 : {
338 : // this function works in conjunction with the plan set up in getVariableHandle
339 : // basically, the handles are contiguous, with:
340 : // - index 1 being the first real variable handle
341 : // - index N being the highest real variable handle
342 : // - index N+1 being the first integer variable handle
343 : // - index N+M being the highest integer variable handle
344 : // note that this function will return -1 if it cannot
345 651765 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
346 651765 : if (handle >= 0 && handle < thisState->dataOutputProcessor->outVars.size()) {
347 651765 : auto const *thisOutputVar = thisState->dataOutputProcessor->outVars[handle];
348 651765 : if (thisOutputVar->varType == EnergyPlus::OutputProcessor::VariableType::Real) {
349 651765 : return *(dynamic_cast<EnergyPlus::OutputProcessor::OutVarReal const *>(thisOutputVar))->Which;
350 : }
351 0 : if (thisOutputVar->varType == EnergyPlus::OutputProcessor::VariableType::Integer) {
352 0 : return (Real64) * (dynamic_cast<EnergyPlus::OutputProcessor::OutVarInt const *>(thisOutputVar))->Which;
353 : }
354 0 : if (thisState->dataGlobal->errorCallback) {
355 0 : std::cout << "ERROR: Variable at handle has type other than Real or Integer, returning zero but caller should take note and likely abort."
356 0 : << std::endl;
357 : } else {
358 : // must be running from python plugin, need to fatal out once the plugin is done
359 : // throw an error, set the fatal flag, and then return zero
360 0 : ShowSevereError(*thisState, fmt::format("Data Exchange API: Error in getVariableValue; received handle: {}", handle));
361 0 : ShowContinueError(*thisState,
362 : "The getVariableValue function will return 0 for now to allow the plugin to finish, then EnergyPlus will abort");
363 : }
364 0 : thisState->dataPluginManager->apiErrorFlag = true;
365 0 : return 0;
366 : }
367 0 : if (thisState->dataGlobal->errorCallback) {
368 0 : std::cout << "ERROR: Variable handle out of range in getVariableValue, returning zero but caller should take note and likely abort."
369 0 : << std::endl;
370 : } else {
371 : // must be running from python plugin, need to fatal out once the plugin is done
372 : // throw an error, set the fatal flag, and then return zero
373 0 : ShowSevereError(*thisState, fmt::format("Data Exchange API: Index error in getVariableValue; received handle: {}", handle));
374 0 : ShowContinueError(*thisState,
375 : "The getVariableValue function will return 0 for now to allow the plugin to finish, then EnergyPlus will abort");
376 : }
377 0 : thisState->dataPluginManager->apiErrorFlag = true;
378 0 : return 0;
379 : }
380 :
381 0 : int getMeterHandle(EnergyPlusState state, const char *meterName)
382 : {
383 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
384 0 : std::string const meterNameUC = EnergyPlus::Util::makeUPPER(meterName);
385 0 : const int i = EnergyPlus::GetMeterIndex(*thisState, meterNameUC);
386 0 : if (i == 0) {
387 : // inside E+, zero is meaningful, but through the API, I want to use negative one as a signal of a bad lookup
388 0 : return -1;
389 : }
390 0 : return i;
391 0 : }
392 :
393 0 : Real64 getMeterValue(EnergyPlusState state, int handle)
394 : {
395 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
396 0 : if (handle >= 0 && handle < thisState->dataOutputProcessor->meters.size()) {
397 0 : return EnergyPlus::GetCurrentMeterValue(*thisState, handle);
398 : }
399 0 : if (thisState->dataGlobal->errorCallback) {
400 0 : std::cout << "ERROR: Meter handle out of range in getMeterValue, returning zero but caller should take note and likely abort." << std::endl;
401 : } else {
402 : // must be running from python plugin, need to fatal out once the plugin is done
403 : // throw an error, set the fatal flag, and then return zero
404 0 : ShowSevereError(*thisState, fmt::format("Data Exchange API: Index error in getMeterValue; received handle: {}", handle));
405 0 : ShowContinueError(*thisState, "The getMeterValue function will return 0 for now to allow the plugin to finish, then EnergyPlus will abort");
406 : }
407 0 : thisState->dataPluginManager->apiErrorFlag = true;
408 0 : return 0;
409 : }
410 :
411 155 : int getActuatorHandle(EnergyPlusState state, const char *componentType, const char *controlType, const char *uniqueKey)
412 : {
413 155 : int handle = 0;
414 155 : std::string const typeUC = EnergyPlus::Util::makeUPPER(componentType);
415 155 : std::string const keyUC = EnergyPlus::Util::makeUPPER(uniqueKey);
416 155 : std::string const controlUC = EnergyPlus::Util::makeUPPER(controlType);
417 155 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
418 122565 : for (int ActuatorLoop = 1; ActuatorLoop <= thisState->dataRuntimeLang->numEMSActuatorsAvailable; ++ActuatorLoop) {
419 122562 : auto &availActuator = thisState->dataRuntimeLang->EMSActuatorAvailable(ActuatorLoop);
420 122562 : handle++;
421 122562 : std::string const actuatorTypeUC = EnergyPlus::Util::makeUPPER(availActuator.ComponentTypeName);
422 122562 : std::string const actuatorIDUC = EnergyPlus::Util::makeUPPER(availActuator.UniqueIDName);
423 122562 : std::string const actuatorControlUC = EnergyPlus::Util::makeUPPER(availActuator.ControlTypeName);
424 122562 : if (typeUC == actuatorTypeUC && keyUC == actuatorIDUC && controlUC == actuatorControlUC) {
425 152 : if (availActuator.handleCount > 0) {
426 : // If the handle is already used by an IDF EnergyManagementSystem:Actuator, we should warn the user
427 5 : bool foundActuator = false;
428 143 : for (auto const &usedActuator : thisState->dataRuntimeLang->EMSActuatorUsed) {
429 138 : if (usedActuator.ActuatorVariableNum == handle) {
430 0 : ShowWarningError(
431 : *thisState,
432 0 : "Data Exchange API: An EnergyManagementSystem:Actuator seems to be already defined in the EnergyPlus File and named '" +
433 0 : usedActuator.Name + "'.");
434 0 : ShowContinueError(
435 0 : *thisState, fmt::format("Occurred for componentType='{}', controlType='{}', uniqueKey='{}'.", typeUC, controlUC, keyUC));
436 0 : ShowContinueError(*thisState,
437 0 : fmt::format("The getActuatorHandle function will still return the handle (= {}) but caller "
438 : "should take note that there is a risk of overwritting.",
439 : handle));
440 0 : foundActuator = true;
441 0 : break;
442 : }
443 : }
444 5 : if (!foundActuator) {
445 5 : ShowWarningError(*thisState, "Data Exchange API: You seem to already have tried to get an Actuator Handle on this one.");
446 5 : ShowContinueError(*thisState,
447 5 : fmt::format("Occurred for componentType='{}', controlType='{}', uniqueKey='{}'.", typeUC, controlUC, keyUC));
448 5 : ShowContinueError(*thisState,
449 5 : fmt::format("The getActuatorHandle function will still return the handle (= {}) but caller should "
450 : "take note that there is a risk of overwritting.",
451 : handle));
452 : }
453 : }
454 152 : ++availActuator.handleCount;
455 :
456 152 : return handle;
457 : }
458 122866 : }
459 3 : return -1;
460 155 : }
461 :
462 89446 : void resetActuator(EnergyPlusState state, int handle)
463 : {
464 : // resets the actuator so that E+ will use the internally calculated value again
465 89446 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
466 89446 : if (handle >= 1 && handle <= thisState->dataRuntimeLang->numEMSActuatorsAvailable) {
467 89446 : const auto &theActuator(thisState->dataRuntimeLang->EMSActuatorAvailable(handle));
468 89446 : *theActuator.Actuated = false;
469 : } else {
470 0 : if (thisState->dataGlobal->errorCallback) {
471 0 : std::cout << "ERROR: Actuator handle out of range in resetActuator, returning but caller should take note and likely abort." << std::endl;
472 : } else {
473 : // must be running from python plugin, need to fatal out once the plugin is done
474 : // throw an error, set the fatal flag, and then return
475 0 : ShowSevereError(*thisState, fmt::format("Data Exchange API: index error in resetActuator; received handle: {}", handle));
476 0 : ShowContinueError(*thisState, "The resetActuator function will return to allow the plugin to finish, then EnergyPlus will abort");
477 : }
478 0 : thisState->dataPluginManager->apiErrorFlag = true;
479 : }
480 89446 : }
481 :
482 896842 : void setActuatorValue(EnergyPlusState state, const int handle, const Real64 value)
483 : {
484 896842 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
485 896842 : if (handle >= 1 && handle <= thisState->dataRuntimeLang->numEMSActuatorsAvailable) {
486 896842 : auto &theActuator(thisState->dataRuntimeLang->EMSActuatorAvailable(handle));
487 896842 : if (theActuator.RealValue) {
488 849262 : *theActuator.RealValue = value;
489 47580 : } else if (theActuator.IntValue) {
490 47580 : *theActuator.IntValue = static_cast<int>(std::lround(value));
491 : } else {
492 : // follow protocol from EMS manager, where 1.0 is true, 0.0 is false, and anything else is also false
493 0 : *theActuator.LogValue = value > 0.99999 && value < 1.00001;
494 : // allow small tolerance while passing between languages and types
495 : }
496 896842 : *theActuator.Actuated = true;
497 : } else {
498 0 : if (thisState->dataGlobal->errorCallback) {
499 0 : std::cout << "ERROR: Actuator handle out of range in setActuatorValue, returning but caller should take note and likely abort."
500 0 : << std::endl;
501 : } else {
502 : // must be running from python plugin, need to fatal out once the plugin is done
503 : // throw an error, set the fatal flag, and then return
504 0 : ShowSevereError(*thisState, fmt::format("Data Exchange API: index error in setActuatorValue; received handle: {}", handle));
505 0 : ShowContinueError(*thisState, "The setActuatorValue function will return to allow the plugin to finish, then EnergyPlus will abort");
506 : }
507 0 : thisState->dataPluginManager->apiErrorFlag = true;
508 : }
509 896842 : }
510 :
511 42362 : Real64 getActuatorValue(EnergyPlusState state, const int handle)
512 : {
513 42362 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
514 42362 : if (handle >= 1 && handle <= thisState->dataRuntimeLang->numEMSActuatorsAvailable) {
515 42362 : const auto &theActuator(thisState->dataRuntimeLang->EMSActuatorAvailable(handle));
516 42362 : if (theActuator.RealValue) {
517 42362 : return *theActuator.RealValue;
518 : }
519 0 : if (theActuator.IntValue) {
520 0 : return static_cast<float>(*theActuator.IntValue);
521 : }
522 : // follow protocol from EMS manager, where 1.0 is true, 0.0 is false, and anything else is also false
523 0 : if (*theActuator.LogValue) {
524 0 : return 1;
525 : }
526 0 : return 0;
527 : }
528 0 : if (thisState->dataGlobal->errorCallback) {
529 0 : std::cout << "ERROR: Actuator handle out of range in getActuatorValue, returning zero but caller should take note and likely abort."
530 0 : << std::endl;
531 : } else {
532 : // must be running from python plugin, need to fatal out once the plugin is done
533 : // throw an error, set the fatal flag, and then return 0
534 0 : ShowSevereError(*thisState, fmt::format("Data Exchange API: index error in getActuatorValue; received handle: {}", handle));
535 0 : ShowContinueError(*thisState,
536 : "The getActuatorValue function will return 0 for now to allow the plugin to finish, then EnergyPlus will abort");
537 : }
538 0 : thisState->dataPluginManager->apiErrorFlag = true;
539 0 : return 0;
540 : }
541 :
542 59 : int getInternalVariableHandle(EnergyPlusState state, const char *type, const char *key)
543 : {
544 59 : int handle = 0;
545 59 : std::string const typeUC = EnergyPlus::Util::makeUPPER(type);
546 59 : std::string const keyUC = EnergyPlus::Util::makeUPPER(key);
547 59 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
548 7747 : for (auto const &availVariable : thisState->dataRuntimeLang->EMSInternalVarsAvailable) {
549 : // TODO: this should stop at numEMSInternalVarsAvailable
550 7747 : handle++;
551 7747 : std::string const variableTypeUC = EnergyPlus::Util::makeUPPER(availVariable.DataTypeName);
552 7747 : std::string const variableIDUC = EnergyPlus::Util::makeUPPER(availVariable.UniqueIDName);
553 7747 : if (typeUC == variableTypeUC && keyUC == variableIDUC) {
554 59 : return handle;
555 : }
556 7806 : }
557 0 : return -1;
558 59 : }
559 :
560 558589 : Real64 getInternalVariableValue(EnergyPlusState state, int handle)
561 : {
562 558589 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
563 558589 : if (handle >= 1 && handle <= (int)thisState->dataRuntimeLang->numEMSInternalVarsAvailable) {
564 558589 : auto const &thisVar = thisState->dataRuntimeLang->EMSInternalVarsAvailable(handle);
565 558589 : if (thisVar.PntrVarTypeUsed == EnergyPlus::DataRuntimeLanguage::PtrDataType::Real) {
566 558589 : return *thisVar.RealValue;
567 : }
568 0 : if (thisVar.PntrVarTypeUsed == EnergyPlus::DataRuntimeLanguage::PtrDataType::Integer) {
569 0 : return (Real64)(*thisVar.IntValue);
570 : }
571 : // Doesn't look like this struct actually has a logical member type, so uh, throw here?
572 0 : std::cout << "ERROR: Invalid internal variable type here, developer issue., returning zero but caller should take note and likely abort."
573 0 : << std::endl;
574 0 : thisState->dataPluginManager->apiErrorFlag = true;
575 0 : return 0;
576 : }
577 0 : if (thisState->dataGlobal->errorCallback) {
578 : std::cout << "ERROR: Internal variable handle out of range in getInternalVariableValue, returning zero but caller should take note and "
579 0 : "likely abort."
580 0 : << std::endl;
581 : } else {
582 : // must be running from python plugin, need to fatal out once the plugin is done
583 : // throw an error, set the fatal flag, and then return 0
584 0 : ShowSevereError(*thisState, fmt::format("Data Exchange API: index error in getInternalVariableValue; received handle: {}", handle));
585 0 : ShowContinueError(*thisState,
586 : "The getInternalVariableValue function will return 0 for now to allow the plugin to finish, then EnergyPlus will abort");
587 : }
588 0 : thisState->dataPluginManager->apiErrorFlag = true;
589 0 : return 0;
590 : }
591 :
592 0 : int getEMSGlobalVariableHandle(EnergyPlusState state, const char *name)
593 : {
594 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
595 0 : int index = 0;
596 0 : for (auto const &erlVar : thisState->dataRuntimeLang->ErlVariable) {
597 0 : index++;
598 : // only respond if we are outside of the built-in EMS var range
599 0 : if (index < thisState->dataRuntimeLang->emsVarBuiltInStart || index > thisState->dataRuntimeLang->emsVarBuiltInEnd) {
600 0 : if (EnergyPlus::Util::SameString(name, erlVar.Name)) {
601 0 : return index;
602 : }
603 : }
604 : }
605 0 : return 0;
606 : }
607 :
608 0 : Real64 getEMSGlobalVariableValue(EnergyPlusState state, int handle)
609 : {
610 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
611 0 : auto const &erl = thisState->dataRuntimeLang;
612 0 : bool const insideBuiltInRange = handle >= erl->emsVarBuiltInStart && handle <= erl->emsVarBuiltInEnd;
613 0 : if (insideBuiltInRange || handle > thisState->dataRuntimeLang->NumErlVariables) {
614 : // need to fatal out once the process is done
615 : // throw an error, set the fatal flag, and then return 0
616 0 : EnergyPlus::ShowSevereError(
617 0 : *thisState, fmt::format("Data Exchange API: Problem -- index error in getEMSGlobalVariableValue; received handle: {}", handle));
618 0 : EnergyPlus::ShowContinueError(
619 : *thisState, "The getEMSGlobalVariableValue function will return 0 for now to allow the process to finish, then EnergyPlus will abort");
620 0 : thisState->dataPluginManager->apiErrorFlag = true;
621 0 : return 0;
622 : }
623 0 : return erl->ErlVariable(handle).Value.Number;
624 : }
625 :
626 0 : void setEMSGlobalVariableValue(EnergyPlusState state, int handle, Real64 value)
627 : {
628 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
629 0 : auto const &erl = thisState->dataRuntimeLang;
630 0 : bool const insideBuiltInRange = handle >= erl->emsVarBuiltInStart && handle <= erl->emsVarBuiltInEnd;
631 0 : if (insideBuiltInRange || handle > erl->NumErlVariables) {
632 : // need to fatal out once the plugin is done
633 : // throw an error, set the fatal flag, and then return
634 0 : EnergyPlus::ShowSevereError(
635 0 : *thisState, fmt::format("Data Exchange API: Problem -- index error in setEMSGlobalVariableValue; received handle: {}", handle));
636 0 : EnergyPlus::ShowContinueError(*thisState,
637 : "The setEMSGlobalVariableValue function will return to allow the plugin to finish, then EnergyPlus will abort");
638 0 : thisState->dataPluginManager->apiErrorFlag = true;
639 : }
640 0 : erl->ErlVariable(handle).Value.Number = value;
641 0 : }
642 :
643 30 : int getPluginGlobalVariableHandle(EnergyPlusState state, const char *name)
644 : {
645 30 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
646 30 : return thisState->dataPluginManager->pluginManager->getGlobalVariableHandle(*thisState, name);
647 : }
648 :
649 56185 : Real64 getPluginGlobalVariableValue(EnergyPlusState state, int handle)
650 : {
651 56185 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
652 56185 : if (handle < 0 || handle > thisState->dataPluginManager->pluginManager->maxGlobalVariableIndex) {
653 : // need to fatal out once the plugin is done
654 : // throw an error, set the fatal flag, and then return 0
655 0 : ShowSevereError(*thisState,
656 0 : fmt::format("Data Exchange API: Problem -- index error in getPluginGlobalVariableValue; received handle: {}", handle));
657 0 : ShowContinueError(
658 : *thisState, "The getPluginGlobalVariableValue function will return 0 for now to allow the plugin to finish, then EnergyPlus will abort");
659 0 : thisState->dataPluginManager->apiErrorFlag = true;
660 0 : return 0;
661 : }
662 56185 : return thisState->dataPluginManager->pluginManager->getGlobalVariableValue(*thisState, handle);
663 : }
664 :
665 411381 : void setPluginGlobalVariableValue(EnergyPlusState state, int handle, Real64 value)
666 : {
667 411381 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
668 411381 : if (handle < 0 || handle > thisState->dataPluginManager->pluginManager->maxGlobalVariableIndex) {
669 : // need to fatal out once the plugin is done
670 : // throw an error, set the fatal flag, and then return
671 0 : ShowSevereError(*thisState,
672 0 : fmt::format("Data Exchange API: Problem -- index error in setPluginGlobalVariableValue; received handle: {}", handle));
673 0 : ShowContinueError(*thisState,
674 : "The getPluginGlobalVariableValue function will return to allow the plugin to finish, then EnergyPlus will abort");
675 0 : thisState->dataPluginManager->apiErrorFlag = true;
676 : }
677 411381 : thisState->dataPluginManager->pluginManager->setGlobalVariableValue(*thisState, handle, value);
678 411381 : }
679 :
680 3 : int getPluginTrendVariableHandle(EnergyPlusState state, const char *name)
681 : {
682 3 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
683 3 : return EnergyPlus::PluginManagement::PluginManager::getTrendVariableHandle(*thisState, name);
684 : }
685 :
686 6346 : Real64 getPluginTrendVariableValue(EnergyPlusState state, int handle, int timeIndex)
687 : {
688 6346 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
689 6346 : if (handle < 0 || handle > thisState->dataPluginManager->pluginManager->maxTrendVariableIndex) {
690 : // need to fatal out once the plugin is done
691 : // throw an error, set the fatal flag, and then return
692 0 : ShowSevereError(*thisState,
693 0 : fmt::format("Data Exchange API: Problem -- index error in getPluginTrendVariableValue; received handle: {}", handle));
694 0 : ShowContinueError(*thisState,
695 : "The getPluginTrendVariableValue function will return 0 to allow the plugin to finish, then EnergyPlus will abort");
696 0 : thisState->dataPluginManager->apiErrorFlag = true;
697 0 : return 0;
698 : }
699 6346 : if (timeIndex < 1 || timeIndex > EnergyPlus::PluginManagement::PluginManager::getTrendVariableHistorySize(*thisState, handle)) {
700 : // need to fatal out once the plugin is done
701 : // throw an error, set the fatal flag, and then return
702 0 : ShowSevereError(
703 : *thisState,
704 0 : fmt::format("Data Exchange API: Problem -- trend history count argument out of range in getPluginTrendVariableValue; received value: {}",
705 : timeIndex));
706 0 : ShowContinueError(*thisState,
707 : "The getPluginTrendVariableValue function will return 0 to allow the plugin to finish, then EnergyPlus will abort");
708 0 : thisState->dataPluginManager->apiErrorFlag = true;
709 0 : return 0;
710 : }
711 6346 : return EnergyPlus::PluginManagement::PluginManager::getTrendVariableValue(*thisState, handle, timeIndex);
712 : }
713 :
714 2016 : Real64 getPluginTrendVariableAverage(EnergyPlusState state, int handle, int count)
715 : {
716 2016 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
717 2016 : if (handle < 0 || handle > thisState->dataPluginManager->pluginManager->maxTrendVariableIndex) {
718 : // need to fatal out once the plugin is done
719 : // throw an error, set the fatal flag, and then return
720 0 : ShowSevereError(*thisState,
721 0 : fmt::format("Data Exchange API: Problem -- index error in getPluginTrendVariableAverage; received handle: {}", handle));
722 0 : ShowContinueError(*thisState,
723 : "The getPluginTrendVariableAverage function will return 0 to allow the plugin to finish, then EnergyPlus will abort");
724 0 : thisState->dataPluginManager->apiErrorFlag = true;
725 0 : return 0;
726 : }
727 2016 : if (count < 2 || count > EnergyPlus::PluginManagement::PluginManager::getTrendVariableHistorySize(*thisState, handle)) {
728 : // need to fatal out once the plugin is done
729 : // throw an error, set the fatal flag, and then return
730 0 : ShowSevereError(
731 : *thisState,
732 0 : fmt::format(
733 : "Data Exchange API: Problem -- trend history count argument out of range in getPluginTrendVariableAverage; received value: {}",
734 : count));
735 0 : ShowContinueError(*thisState,
736 : "The getPluginTrendVariableAverage function will return 0 to allow the plugin to finish, then EnergyPlus will abort");
737 0 : thisState->dataPluginManager->apiErrorFlag = true;
738 0 : return 0;
739 : }
740 2016 : return EnergyPlus::PluginManagement::PluginManager::getTrendVariableAverage(*thisState, handle, count);
741 : }
742 :
743 0 : Real64 getPluginTrendVariableMin(EnergyPlusState state, int handle, int count)
744 : {
745 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
746 0 : if (handle < 0 || handle > thisState->dataPluginManager->pluginManager->maxTrendVariableIndex) {
747 : // need to fatal out once the plugin is done
748 : // throw an error, set the fatal flag, and then return
749 0 : ShowSevereError(*thisState,
750 0 : fmt::format("Data Exchange API: Problem -- index error in getPluginTrendVariableMin; received handle: {}", handle));
751 0 : ShowContinueError(*thisState,
752 : "The getPluginTrendVariableMin function will return 0 to allow the plugin to finish, then EnergyPlus will abort");
753 0 : thisState->dataPluginManager->apiErrorFlag = true;
754 0 : return 0;
755 : }
756 0 : if (count < 2 || count > EnergyPlus::PluginManagement::PluginManager::getTrendVariableHistorySize(*thisState, handle)) {
757 : // need to fatal out once the plugin is done
758 : // throw an error, set the fatal flag, and then return
759 0 : ShowSevereError(
760 : *thisState,
761 0 : fmt::format("Data Exchange API: Problem -- trend history count argument out of range in getPluginTrendVariableMin; received value: {}",
762 : count));
763 0 : ShowContinueError(*thisState,
764 : "The getPluginTrendVariableMin function will return 0 to allow the plugin to finish, then EnergyPlus will abort");
765 0 : thisState->dataPluginManager->apiErrorFlag = true;
766 0 : return 0;
767 : }
768 0 : return EnergyPlus::PluginManagement::PluginManager::getTrendVariableMin(*thisState, handle, count);
769 : }
770 :
771 0 : Real64 getPluginTrendVariableMax(EnergyPlusState state, int handle, int count)
772 : {
773 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
774 0 : if (handle < 0 || handle > thisState->dataPluginManager->pluginManager->maxTrendVariableIndex) {
775 : // need to fatal out once the plugin is done
776 : // throw an error, set the fatal flag, and then return
777 0 : ShowSevereError(*thisState,
778 0 : fmt::format("Data Exchange API: Problem -- index error in getPluginTrendVariableMax; received handle: {}", handle));
779 0 : ShowContinueError(*thisState,
780 : "The getPluginTrendVariableMax function will return 0 to allow the plugin to finish, then EnergyPlus will abort");
781 0 : thisState->dataPluginManager->apiErrorFlag = true;
782 0 : return 0;
783 : }
784 0 : if (count < 2 || count > EnergyPlus::PluginManagement::PluginManager::getTrendVariableHistorySize(*thisState, handle)) {
785 : // need to fatal out once the plugin is done
786 : // throw an error, set the fatal flag, and then return
787 0 : ShowSevereError(
788 : *thisState,
789 0 : fmt::format("Data Exchange API: Problem -- trend history count argument out of range in getPluginTrendVariableMax; received value: {}",
790 : count));
791 0 : ShowContinueError(*thisState,
792 : "The getPluginTrendVariableMax function will return 0 to allow the plugin to finish, then EnergyPlus will abort");
793 0 : thisState->dataPluginManager->apiErrorFlag = true;
794 0 : return 0;
795 : }
796 0 : return EnergyPlus::PluginManagement::PluginManager::getTrendVariableMax(*thisState, handle, count);
797 : }
798 :
799 0 : Real64 getPluginTrendVariableSum(EnergyPlusState state, int handle, int count)
800 : {
801 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
802 0 : if (handle < 0 || handle > thisState->dataPluginManager->pluginManager->maxTrendVariableIndex) {
803 : // need to fatal out once the plugin is done
804 : // throw an error, set the fatal flag, and then return
805 0 : ShowSevereError(*thisState,
806 0 : fmt::format("Data Exchange API: Problem -- index error in getPluginTrendVariableSum; received handle: {}", handle));
807 0 : ShowContinueError(*thisState,
808 : "The getPluginTrendVariableSum function will return 0 to allow the plugin to finish, then EnergyPlus will abort");
809 0 : thisState->dataPluginManager->apiErrorFlag = true;
810 0 : return 0;
811 : }
812 0 : if (count < 2 || count > EnergyPlus::PluginManagement::PluginManager::getTrendVariableHistorySize(*thisState, handle)) {
813 : // need to fatal out once the plugin is done
814 : // throw an error, set the fatal flag, and then return
815 0 : ShowSevereError(
816 : *thisState,
817 0 : fmt::format("Data Exchange API: Problem -- trend history count argument out of range in getPluginTrendVariableSum; received value: {}",
818 : count));
819 0 : ShowContinueError(*thisState,
820 : "The getPluginTrendVariableSum function will return 0 to allow the plugin to finish, then EnergyPlus will abort");
821 0 : thisState->dataPluginManager->apiErrorFlag = true;
822 0 : return 0;
823 : }
824 0 : return EnergyPlus::PluginManagement::PluginManager::getTrendVariableSum(*thisState, handle, count);
825 : }
826 :
827 3173 : Real64 getPluginTrendVariableDirection(EnergyPlusState state, int handle, int count)
828 : {
829 3173 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
830 3173 : if (handle < 0 || handle > thisState->dataPluginManager->pluginManager->maxTrendVariableIndex) {
831 : // need to fatal out once the plugin is done
832 : // throw an error, set the fatal flag, and then return
833 0 : ShowSevereError(*thisState,
834 0 : fmt::format("Data Exchange API: Problem -- index error in getPluginTrendVariableDirection; received handle: {}", handle));
835 0 : ShowContinueError(*thisState,
836 : "The getPluginTrendVariableDirection function will return 0 to allow the plugin to finish, then EnergyPlus will abort");
837 0 : thisState->dataPluginManager->apiErrorFlag = true;
838 0 : return 0;
839 : }
840 3173 : if (count < 2 || count > EnergyPlus::PluginManagement::PluginManager::getTrendVariableHistorySize(*thisState, handle)) {
841 : // need to fatal out once the plugin is done
842 : // throw an error, set the fatal flag, and then return
843 0 : ShowSevereError(
844 : *thisState,
845 0 : fmt::format(
846 : "Data Exchange API: Problem -- trend history count argument out of range in getPluginTrendVariableDirection; received value: {}",
847 : count));
848 0 : ShowContinueError(*thisState,
849 : "The getPluginTrendVariableDirection function will return 0 to allow the plugin to finish, then EnergyPlus will abort");
850 0 : thisState->dataPluginManager->apiErrorFlag = true;
851 0 : return 0;
852 : }
853 3173 : return EnergyPlus::PluginManagement::PluginManager::getTrendVariableDirection(*thisState, handle, count);
854 : }
855 :
856 0 : int year(EnergyPlusState state)
857 : {
858 0 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
859 0 : return thisState->dataEnvrn->Year;
860 : }
861 :
862 0 : int calendarYear(EnergyPlusState state)
863 : {
864 0 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
865 0 : return thisState->dataGlobal->CalendarYear;
866 : }
867 :
868 7355 : int month(EnergyPlusState state)
869 : {
870 7355 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
871 7355 : return thisState->dataEnvrn->Month;
872 : }
873 :
874 4182 : int dayOfMonth(EnergyPlusState state)
875 : {
876 4182 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
877 4182 : return thisState->dataEnvrn->DayOfMonth;
878 : }
879 :
880 8364 : int dayOfWeek(EnergyPlusState state)
881 : {
882 8364 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
883 8364 : return thisState->dataEnvrn->DayOfWeek;
884 : }
885 :
886 4182 : int dayOfYear(EnergyPlusState state)
887 : {
888 4182 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
889 4182 : return thisState->dataEnvrn->DayOfYear;
890 : }
891 :
892 0 : int daylightSavingsTimeIndicator(EnergyPlusState state)
893 : {
894 0 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
895 0 : return thisState->dataEnvrn->DSTIndicator;
896 : }
897 :
898 8364 : int hour(EnergyPlusState state)
899 : {
900 8364 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
901 8364 : return thisState->dataGlobal->HourOfDay - 1;
902 : // no, just stay on 0..23+ DSTadjust ! offset by 1 and daylight savings time
903 : }
904 :
905 0 : Real64 currentTime(EnergyPlusState state)
906 : {
907 0 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
908 0 : if (thisState->dataHVACGlobal->TimeStepSys < thisState->dataGlobal->TimeStepZone) {
909 : // CurrentTime is for end of zone timestep, need to move back to beginning of current zone timestep, then add on system time elapsed already
910 : // plus current system timestep
911 0 : return thisState->dataGlobal->CurrentTime - thisState->dataGlobal->TimeStepZone + thisState->dataHVACGlobal->SysTimeElapsed +
912 0 : thisState->dataHVACGlobal->TimeStepSys;
913 : }
914 0 : return thisState->dataGlobal->CurrentTime;
915 : }
916 :
917 0 : int minutes(EnergyPlusState state)
918 : {
919 : // the -1 is to push us to the right minute, but this should be handled cautiously because if we are inside the HVAC iteration loop,
920 : // currentTime() returns a floating point fractional hour, so truncation could put this a few seconds from the expected minute.
921 0 : const Real64 currentTimeVal = currentTime(state);
922 0 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
923 0 : const Real64 fractionalHoursIntoTheDay = currentTimeVal - static_cast<double>(thisState->dataGlobal->HourOfDay - 1);
924 0 : const Real64 fractionalMinutesIntoTheDay = std::round(fractionalHoursIntoTheDay * 60.0);
925 0 : return static_cast<int>(fractionalMinutesIntoTheDay);
926 : }
927 :
928 0 : int numTimeStepsInHour([[maybe_unused]] EnergyPlusState state)
929 : {
930 0 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
931 0 : return thisState->dataGlobal->NumOfTimeStepInHour;
932 : }
933 :
934 0 : int zoneTimeStepNum([[maybe_unused]] EnergyPlusState state)
935 : {
936 0 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
937 0 : return thisState->dataGlobal->TimeStep;
938 : }
939 :
940 16728 : int holidayIndex(EnergyPlusState state)
941 : {
942 16728 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
943 16728 : return thisState->dataEnvrn->HolidayIndex;
944 : }
945 :
946 0 : int sunIsUp(EnergyPlusState state)
947 : {
948 : // maintain response convention from previous (EMS) implementation
949 0 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
950 0 : return (int)thisState->dataEnvrn->SunIsUp;
951 : }
952 :
953 0 : int isRaining(EnergyPlusState state)
954 : {
955 0 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
956 0 : return (int)thisState->dataEnvrn->IsRain;
957 : }
958 :
959 2160 : int warmupFlag(EnergyPlusState state)
960 : {
961 2160 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
962 2160 : return (int)thisState->dataGlobal->WarmupFlag;
963 : }
964 :
965 0 : Real64 zoneTimeStep(EnergyPlusState state)
966 : {
967 0 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
968 0 : return thisState->dataGlobal->TimeStepZone;
969 : }
970 :
971 44275 : Real64 systemTimeStep(EnergyPlusState state)
972 : {
973 44275 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
974 44275 : return thisState->dataHVACGlobal->TimeStepSys;
975 : }
976 :
977 0 : int currentEnvironmentNum(EnergyPlusState state)
978 : {
979 0 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
980 0 : return thisState->dataEnvrn->CurEnvirNum;
981 : }
982 :
983 2880 : int kindOfSim(EnergyPlusState state)
984 : {
985 2880 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
986 2880 : return static_cast<int>(thisState->dataGlobal->KindOfSim);
987 : }
988 :
989 19 : int getConstructionHandle(EnergyPlusState state, const char *constructionName)
990 : {
991 19 : int handle = 0;
992 19 : std::string const nameUC = EnergyPlus::Util::makeUPPER(constructionName);
993 19 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
994 418 : for (auto const &construct : thisState->dataConstruction->Construct) {
995 418 : handle++;
996 418 : if (nameUC == EnergyPlus::Util::makeUPPER(construct.Name)) {
997 19 : return handle;
998 : }
999 : }
1000 0 : return -1; // return -1 if it wasn't found
1001 19 : }
1002 :
1003 0 : int actualTime(EnergyPlusState)
1004 : {
1005 0 : const std::string datestring;
1006 0 : Array1D_int datevalues(8);
1007 0 : ObjexxFCL::date_and_time(datestring, _, _, datevalues);
1008 0 : return sum(datevalues({5, 8}));
1009 0 : }
1010 :
1011 0 : int actualDateTime(EnergyPlusState)
1012 : {
1013 0 : const std::string datestring;
1014 0 : const Array1D_int datevalues(8);
1015 0 : ObjexxFCL::date_and_time(datestring, _, _, datevalues);
1016 0 : return sum(datevalues);
1017 0 : }
1018 :
1019 0 : int todayWeatherIsRainAtTime(EnergyPlusState state, int hour, int timeStepNum)
1020 : {
1021 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
1022 :
1023 0 : const int iHour = hour + 1;
1024 0 : if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) &&
1025 0 : (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) {
1026 0 : return (int)thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).IsRain;
1027 : }
1028 0 : ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
1029 0 : thisState->dataPluginManager->apiErrorFlag = true;
1030 0 : return 0;
1031 : }
1032 :
1033 0 : int todayWeatherIsSnowAtTime(EnergyPlusState state, int hour, int timeStepNum)
1034 : {
1035 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
1036 :
1037 0 : const int iHour = hour + 1;
1038 0 : if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) &&
1039 0 : (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) {
1040 0 : return (int)thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).IsSnow;
1041 : }
1042 0 : ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
1043 0 : thisState->dataPluginManager->apiErrorFlag = true;
1044 0 : return 0;
1045 : }
1046 :
1047 0 : Real64 todayWeatherOutDryBulbAtTime(EnergyPlusState state, int hour, int timeStepNum)
1048 : {
1049 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
1050 :
1051 0 : const int iHour = hour + 1;
1052 0 : if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) &&
1053 0 : (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) {
1054 0 : return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).OutDryBulbTemp;
1055 : }
1056 0 : ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
1057 0 : thisState->dataPluginManager->apiErrorFlag = true;
1058 0 : return 0.0;
1059 : }
1060 :
1061 0 : Real64 todayWeatherOutDewPointAtTime(EnergyPlusState state, int hour, int timeStepNum)
1062 : {
1063 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
1064 0 : int iHour = hour + 1;
1065 0 : if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) &&
1066 0 : (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) {
1067 0 : return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).OutDewPointTemp;
1068 : }
1069 0 : ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
1070 0 : thisState->dataPluginManager->apiErrorFlag = true;
1071 0 : return 0.0;
1072 : }
1073 :
1074 0 : Real64 todayWeatherOutBarometricPressureAtTime(EnergyPlusState state, int hour, int timeStepNum)
1075 : {
1076 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
1077 0 : int iHour = hour + 1;
1078 0 : if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) &&
1079 0 : (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) {
1080 0 : return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).OutBaroPress;
1081 : }
1082 0 : ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
1083 0 : thisState->dataPluginManager->apiErrorFlag = true;
1084 0 : return 0.0;
1085 : }
1086 :
1087 0 : Real64 todayWeatherOutRelativeHumidityAtTime(EnergyPlusState state, int hour, int timeStepNum)
1088 : {
1089 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
1090 0 : const int iHour = hour + 1;
1091 0 : if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) &&
1092 0 : (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) {
1093 0 : return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).OutRelHum;
1094 : }
1095 0 : ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
1096 0 : thisState->dataPluginManager->apiErrorFlag = true;
1097 0 : return 0.0;
1098 : }
1099 :
1100 0 : Real64 todayWeatherWindSpeedAtTime(EnergyPlusState state, int hour, int timeStepNum)
1101 : {
1102 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
1103 0 : const int iHour = hour + 1;
1104 0 : if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) &&
1105 0 : (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) {
1106 0 : return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).WindSpeed;
1107 : }
1108 0 : ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
1109 0 : thisState->dataPluginManager->apiErrorFlag = true;
1110 0 : return 0.0;
1111 : }
1112 :
1113 0 : Real64 todayWeatherWindDirectionAtTime(EnergyPlusState state, int hour, int timeStepNum)
1114 : {
1115 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
1116 0 : const int iHour = hour + 1;
1117 0 : if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) &&
1118 0 : (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) {
1119 0 : return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).WindDir;
1120 : }
1121 0 : ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
1122 0 : thisState->dataPluginManager->apiErrorFlag = true;
1123 0 : return 0.0;
1124 : }
1125 :
1126 0 : Real64 todayWeatherSkyTemperatureAtTime(EnergyPlusState state, int hour, int timeStepNum)
1127 : {
1128 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
1129 0 : const int iHour = hour + 1;
1130 0 : if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) &&
1131 0 : (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) {
1132 0 : return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).SkyTemp;
1133 : }
1134 0 : ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
1135 0 : thisState->dataPluginManager->apiErrorFlag = true;
1136 0 : return 0.0;
1137 : }
1138 :
1139 0 : Real64 todayWeatherHorizontalIRSkyAtTime(EnergyPlusState state, int hour, int timeStepNum)
1140 : {
1141 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
1142 0 : const int iHour = hour + 1;
1143 0 : if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) &&
1144 0 : (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) {
1145 0 : return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).HorizIRSky;
1146 : }
1147 0 : ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
1148 0 : thisState->dataPluginManager->apiErrorFlag = true;
1149 0 : return 0.0;
1150 : }
1151 :
1152 0 : Real64 todayWeatherBeamSolarRadiationAtTime(EnergyPlusState state, int hour, int timeStepNum)
1153 : {
1154 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
1155 0 : const int iHour = hour + 1;
1156 0 : if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) &&
1157 0 : (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) {
1158 0 : return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).BeamSolarRad;
1159 : }
1160 0 : ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
1161 0 : thisState->dataPluginManager->apiErrorFlag = true;
1162 0 : return 0.0;
1163 : }
1164 :
1165 0 : Real64 todayWeatherDiffuseSolarRadiationAtTime(EnergyPlusState state, int hour, int timeStepNum)
1166 : {
1167 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
1168 0 : const int iHour = hour + 1;
1169 0 : if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) &&
1170 0 : (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) {
1171 0 : return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).DifSolarRad;
1172 : }
1173 0 : ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
1174 0 : thisState->dataPluginManager->apiErrorFlag = true;
1175 0 : return 0.0;
1176 : }
1177 :
1178 0 : Real64 todayWeatherAlbedoAtTime(EnergyPlusState state, int hour, int timeStepNum)
1179 : {
1180 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
1181 0 : const int iHour = hour + 1;
1182 0 : if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) &&
1183 0 : (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) {
1184 0 : return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).Albedo;
1185 : }
1186 0 : ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
1187 0 : thisState->dataPluginManager->apiErrorFlag = true;
1188 0 : return 0.0;
1189 : }
1190 :
1191 0 : Real64 todayWeatherLiquidPrecipitationAtTime(EnergyPlusState state, int hour, int timeStepNum)
1192 : {
1193 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
1194 0 : const int iHour = hour + 1;
1195 0 : if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) &&
1196 0 : (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) {
1197 0 : return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).LiquidPrecip;
1198 : }
1199 0 : ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
1200 0 : thisState->dataPluginManager->apiErrorFlag = true;
1201 0 : return 0.0;
1202 : }
1203 :
1204 0 : int tomorrowWeatherIsRainAtTime(EnergyPlusState state, int hour, int timeStepNum)
1205 : {
1206 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
1207 0 : const int iHour = hour + 1;
1208 0 : if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) &&
1209 0 : (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) {
1210 0 : return (int)thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).IsRain;
1211 : }
1212 0 : ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
1213 0 : thisState->dataPluginManager->apiErrorFlag = true;
1214 0 : return 0;
1215 : }
1216 :
1217 0 : int tomorrowWeatherIsSnowAtTime(EnergyPlusState state, int hour, int timeStepNum)
1218 : {
1219 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
1220 0 : const int iHour = hour + 1;
1221 0 : if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) &&
1222 0 : (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) {
1223 0 : return (int)thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).IsSnow;
1224 : }
1225 0 : ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
1226 0 : thisState->dataPluginManager->apiErrorFlag = true;
1227 0 : return 0;
1228 : }
1229 :
1230 288 : Real64 tomorrowWeatherOutDryBulbAtTime(EnergyPlusState state, int hour, int timeStepNum)
1231 : {
1232 288 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
1233 288 : const int iHour = hour + 1;
1234 576 : if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) &&
1235 288 : (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) {
1236 288 : return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).OutDryBulbTemp;
1237 : }
1238 0 : ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
1239 0 : thisState->dataPluginManager->apiErrorFlag = true;
1240 0 : return 0.0;
1241 : }
1242 :
1243 0 : Real64 tomorrowWeatherOutDewPointAtTime(EnergyPlusState state, int hour, int timeStepNum)
1244 : {
1245 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
1246 0 : const int iHour = hour + 1;
1247 0 : if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) &&
1248 0 : (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) {
1249 0 : return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).OutDewPointTemp;
1250 : }
1251 0 : ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
1252 0 : thisState->dataPluginManager->apiErrorFlag = true;
1253 0 : return 0.0;
1254 : }
1255 :
1256 0 : Real64 tomorrowWeatherOutBarometricPressureAtTime(EnergyPlusState state, int hour, int timeStepNum)
1257 : {
1258 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
1259 0 : const int iHour = hour + 1;
1260 0 : if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) &&
1261 0 : (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) {
1262 0 : return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).OutBaroPress;
1263 : }
1264 0 : ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
1265 0 : thisState->dataPluginManager->apiErrorFlag = true;
1266 0 : return 0.0;
1267 : }
1268 :
1269 0 : Real64 tomorrowWeatherOutRelativeHumidityAtTime(EnergyPlusState state, int hour, int timeStepNum)
1270 : {
1271 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
1272 0 : const int iHour = hour + 1;
1273 0 : if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) &&
1274 0 : (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) {
1275 0 : return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).OutRelHum;
1276 : }
1277 0 : ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
1278 0 : thisState->dataPluginManager->apiErrorFlag = true;
1279 0 : return 0.0;
1280 : }
1281 :
1282 0 : Real64 tomorrowWeatherWindSpeedAtTime(EnergyPlusState state, int hour, int timeStepNum)
1283 : {
1284 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
1285 0 : const int iHour = hour + 1;
1286 0 : if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) &&
1287 0 : (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) {
1288 0 : return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).WindSpeed;
1289 : }
1290 0 : ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
1291 0 : thisState->dataPluginManager->apiErrorFlag = true;
1292 0 : return 0.0;
1293 : }
1294 :
1295 0 : Real64 tomorrowWeatherWindDirectionAtTime(EnergyPlusState state, int hour, int timeStepNum)
1296 : {
1297 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
1298 0 : const int iHour = hour + 1;
1299 0 : if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) &&
1300 0 : (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) {
1301 0 : return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).WindDir;
1302 : }
1303 0 : ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
1304 0 : thisState->dataPluginManager->apiErrorFlag = true;
1305 0 : return 0.0;
1306 : }
1307 :
1308 0 : Real64 tomorrowWeatherSkyTemperatureAtTime(EnergyPlusState state, int hour, int timeStepNum)
1309 : {
1310 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
1311 0 : const int iHour = hour + 1;
1312 0 : if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) &&
1313 0 : (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) {
1314 0 : return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).SkyTemp;
1315 : }
1316 0 : ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
1317 0 : thisState->dataPluginManager->apiErrorFlag = true;
1318 0 : return 0.0;
1319 : }
1320 :
1321 0 : Real64 tomorrowWeatherHorizontalIRSkyAtTime(EnergyPlusState state, int hour, int timeStepNum)
1322 : {
1323 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
1324 0 : const int iHour = hour + 1;
1325 0 : if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) &&
1326 0 : (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) {
1327 0 : return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).HorizIRSky;
1328 : }
1329 0 : ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
1330 0 : thisState->dataPluginManager->apiErrorFlag = true;
1331 0 : return 0.0;
1332 : }
1333 :
1334 0 : Real64 tomorrowWeatherBeamSolarRadiationAtTime(EnergyPlusState state, int hour, int timeStepNum)
1335 : {
1336 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
1337 0 : const int iHour = hour + 1;
1338 0 : if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) &&
1339 0 : (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) {
1340 0 : return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).BeamSolarRad;
1341 : }
1342 0 : ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
1343 0 : thisState->dataPluginManager->apiErrorFlag = true;
1344 0 : return 0.0;
1345 : }
1346 :
1347 0 : Real64 tomorrowWeatherDiffuseSolarRadiationAtTime(EnergyPlusState state, int hour, int timeStepNum)
1348 : {
1349 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
1350 0 : const int iHour = hour + 1;
1351 0 : if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) &&
1352 0 : (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) {
1353 0 : return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).DifSolarRad;
1354 : }
1355 0 : ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
1356 0 : thisState->dataPluginManager->apiErrorFlag = true;
1357 0 : return 0.0;
1358 : }
1359 :
1360 0 : Real64 tomorrowWeatherAlbedoAtTime(EnergyPlusState state, int hour, int timeStepNum)
1361 : {
1362 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
1363 0 : const int iHour = hour + 1;
1364 0 : if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) &&
1365 0 : (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) {
1366 0 : return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).Albedo;
1367 : }
1368 0 : ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
1369 0 : thisState->dataPluginManager->apiErrorFlag = true;
1370 0 : return 0.0;
1371 : }
1372 :
1373 0 : Real64 tomorrowWeatherLiquidPrecipitationAtTime(EnergyPlusState state, const int hour, const int timeStepNum)
1374 : {
1375 0 : auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
1376 0 : const int iHour = hour + 1;
1377 0 : if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) &&
1378 0 : (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) {
1379 0 : return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).LiquidPrecip;
1380 : }
1381 0 : ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
1382 0 : thisState->dataPluginManager->apiErrorFlag = true;
1383 0 : return 0.0;
1384 : }
1385 :
1386 0 : Real64 currentSimTime(EnergyPlusState state)
1387 : {
1388 0 : const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
1389 0 : return (thisState->dataGlobal->DayOfSim - 1) * EnergyPlus::Constant::HoursInDay + currentTime(state);
1390 : }
|