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