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