From 8f7ef9a303c30230f37d2065aa28dd2910cbe43c Mon Sep 17 00:00:00 2001 From: Edwin Lee Date: Sun, 27 Sep 2020 21:31:12 -0500 Subject: [PATCH 1/4] Tweaked readme just to get 9.4 release branch moving --- release/readme.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/release/readme.html b/release/readme.html index 4f51453b1f9..e2c6b9779f0 100644 --- a/release/readme.html +++ b/release/readme.html @@ -37,8 +37,8 @@

EnergyPlus Logo EnergyPlus

- Version 9.3.0
- 31 March 2020
+ Version 9.4.0
+ 30 September 2020
EnergyPlus is a trademark of the US Department of Energy.

From 69edc3cc2846863cbfd15322db411b7919bb1caf Mon Sep 17 00:00:00 2001 From: Edwin Lee Date: Mon, 28 Sep 2020 14:20:05 -0500 Subject: [PATCH 2/4] Final Prep for 9.4.0 --- .../src/overview/api-usage.tex | 191 ++++++++---- .../src/overview/group-python-plugins.tex | 72 +++-- release/readme.html | 284 ++++++------------ src/EnergyPlus/CMakeLists.txt | 2 +- src/EnergyPlus/api/docs/c/Doxyfile | 2 +- src/EnergyPlus/api/docs/python/conf.py | 2 +- .../CreateNewIDFUsingRulesV9_4_0.f90 | 2 + 7 files changed, 264 insertions(+), 291 deletions(-) diff --git a/doc/input-output-reference/src/overview/api-usage.tex b/doc/input-output-reference/src/overview/api-usage.tex index 4f79ec73a40..aef9db4c070 100644 --- a/doc/input-output-reference/src/overview/api-usage.tex +++ b/doc/input-output-reference/src/overview/api-usage.tex @@ -10,23 +10,76 @@ \section{Using EnergyPlus as a Library}\label{sec:api-usage} \begin{itemize} \item The Energy Management System, which was the first method to allow reading and writing simulation data while a simulation was running, and allowing user-defined scripts to be executed to alter simulation data. - \item The EnergyPlus unit test structure, which has, as a side-effect, enabled the ability to "reset" the state of a simulation, and re-run another, in the same memory space. + \item The EnergyPlus unit test structure, which has, as a side-effect, enabled the ability to ``reset'' the state of a simulation, and re-run another, in the same memory space. \end{itemize} +As of version 9.4, the API has been improved, as well as the ability to more reliably ``reset'' the simulation state. +After 9.3 was released and users began toying with the API usage, it was revealed that many (most?) files would not actually run well during series runs of EnergyPlus via API in the same thread because the simulation state was not fully ``cleared''. +Although the simulation state is still not guaranteed to be fully cleared, we are now seeing greater than 95% pass rate on our example files when running them serially multiple times. +This situation will make it much more suited for integrating into workflows as the Python thread does not have to be destroyed to get a clean EnergyPlus state for the next run. +Work is continuing to get the state of the simulation completely managed, and will be completed prior to the next release, ensuring this situation continues improving. + +Note that the effort to improve the simulation state for the API resulted in a break in many API functions. +It was expected that in this first release of the API, issues would be identified that would cause breaks in the API. +Moving forward, it is not expected that API endpoints will change, at least not often. +As the API gains more adoption, EnergyPlus may adopt a more semantic versioning approach where the API is only broken in major version number changes. + Interface developers that have been building on top of EnergyPlus have primarily interacted with the simulation in the traditional manner. The interface would create an input file in a directory, copy in weather data and any other supporting data, and then kick off a simulation in that directory. The interface could grab output messages from the simulation, but that was essentially it. The interface just had to wait until EnergyPlus completed, check data in the output files, and decide what to do next. Grabbing any sort of data from the simulation during a run, even just progress, was highly difficult. -As of version 9.3, a new API has been created that will change all that. -A new formal EnergyPlus API is implemented that allows three categories of interaction with the simulation. -Technically speaking, the three categories are not different, as they operate using the same API mechanics. +The EnergyPlus API has been created to change that situation and open new doors into the simulation program and the opportunity to embed EnergyPlus into vastly more workflows and applications. +A new formal EnergyPlus API is implemented that allows interacting with different ``categories'' of the simulation. +Technically speaking, the categories are not different, as they operate using the same API mechanics. The categorization is purely organizational. In the following subsections, the API is laid out with examples in both C and Python. Full API documentation will be provided separate from this document. Check the release notes for your specific release for more information. +\subsection{State API}\label{subsec:state-api} + +The state of an EnergyPlus represents the entire contents of a running simulation. +Everything from the current time step to the water side economizer operating part load ratio is tracked in the state of a running simulation. +Since the birth of EnergyPlus, the state of the simulation was hung on the global program state, with no explicit object owning and managing the data. +This was perfectly acceptable because the only real use of EnergyPlus was to execute the binary (energyplus.exe) and wait for it to finish and inspect the outputs. +However, this has proved to be a burden when trying to push EnergyPlus into new applications, and as such, the team has worked to move much of the global state into a state class which can then manage the data on itself. +From an internal-to-EnergyPlus perspective, this means that functions will access variables on a class that is passed around throughout the program. +From an API-client perspective, this means that the client will need to create a state instance and pass it into the simulation when asking the simulation to do most operations. + +Prior to calling into most of the API functions, the API client must create a new state instance. +This state instance is not to be directly accessed by the client, but instead the client must simply be a courier of this state instance and pass it in and out of the API calls. +Whenever the client is done with that instance, the instance can be reset to be prepped for another run of EnergyPlus, or destroyed if the client is done with it. + +An example of this in C is listed here: + +\begin{lstlisting} +#include + +int main(int argc, const char * argv[]) { + EnergyPlusState state = stateNew(); + stateReset(state); + stateDelete(state); + printf("Wow this was a boring use case\n"); +} +\end{lstlisting} + +That does not do much. +But moving through the rest of the API functions, it will become clear that this is at the core of an EnergyPlus API workflow. + +In Python, that same example is similar: + +\begin{lstlisting} +from pyenergyplus.api import EnergyPlusAPI + +api = EnergyPlusAPI() +state = api.state_manager.new_state() +api.state_manager.reset_state(state) +api.state_manager.delete_state(state) +print("Wow even boring in Python!?") +\end{lstlisting} + \subsection{Functional API}\label{subsec:functional-api} The ``Functional'' API allows for users to call into the EnergyPlus binary and request static information. @@ -37,25 +90,29 @@ \subsection{Functional API}\label{subsec:functional-api} To interact with the refrigerant property data, the user will also create a refrigerant class and access data through methods. For psychrometrics, in C the function calls do not need to create an instance, however, in Python, a small class captures the psychrometric functions for organization. +While some of the functionality in these property routines are stateless from the perspective of the EnergyPlus simulation engine, an instance of the EnergyPlus ``state'' class is required to be passed in. + An example of exercising the functional API in C is listed here: \begin{lstlisting} #include + #include int main(int argc, const char * argv[]) { - initializeFunctionalAPI(); + EnergyPlusState state = stateNew(); + initializeFunctionalAPI(state); Glycol glycol = NULL; - glycol = glycolNew("WatEr"); - Real64 specificHeat = glycolSpecificHeat(glycol, 35.0); - glycolDelete(glycol); + glycol = glycolNew(state, "WatEr"); + Real64 specificHeat = glycolSpecificHeat(state, glycol, 35.0); + glycolDelete(state, glycol); Refrigerant refrig = NULL; - refrig = refrigerantNew("SteaM"); - Real64 satPress = refrigerantSaturationPressure(refrig, 100.0); - refrigerantDelete(refrig); + refrig = refrigerantNew(state, "SteaM"); + Real64 satPress = refrigerantSaturationPressure(state, refrig, 100.0); + refrigerantDelete(state, refrig); - Real64 rh = psyRhFnTdbWPb(24, 0.009, 101325); // psychrometrics are evaluated directly + Real64 rh = psyRhFnTdbWPb(state, 24, 0.009, 101325); // psychrometrics are evaluated directly } \end{lstlisting} @@ -68,16 +125,18 @@ \subsection{Functional API}\label{subsec:functional-api} \begin{lstlisting} from pyenergyplus.api import EnergyPlusAPI + api = EnergyPlusAPI() + state = api.state_manager.new_state() - glycol = api.functional.glycol(u"water") - cp = glycol.specific_heat(35.0) + glycol = api.functional.glycol(state, u"water") + cp = glycol.specific_heat(state, 35.0) - refrigerant = api.functional.refrigerant("steam") - satPress = refrigerant.saturation_pressure(100.0) + refrigerant = api.functional.refrigerant(state, "steam") + satPress = refrigerant.saturation_pressure(state, 100.0) - psychrometrics = api.functional.psychrometrics() - rh = psychrometrics.relative_humidity_b(24, 0.009, 101325) + psychrometrics = api.functional.psychrometrics(state, ) + rh = psychrometrics.relative_humidity_b(state, 24, 0.009, 101325) \end{lstlisting} Some subtle differences are present. @@ -89,7 +148,7 @@ \subsection{Runtime API}\label{subsec:runtime-api} The ``Runtime'' API allows for users to hook into a running simulation. The client creates functions, and using this runtime API, they can register these functions to be called back at specific points in a simulation. -Once registered, this API includes a function to start the simulation, as well as a function to clear the simulation state so that another simulation can be performed. +Once registered, this API includes a function to start the simulation. There are a number of calling points available to hook in a callback function. For information on the different available calling points, see the EMSApplicationGuide documentation packaged with EnergyPlus. For exact naming conventions on the C and Python registration functions, see either the C header or Python API file, or the API documentation that will be made available separate from the installer. @@ -97,28 +156,37 @@ \subsection{Runtime API}\label{subsec:runtime-api} A minimal approach demonstrating the runtime API in C would be the following: +Note that as of EnergyPlus 9.4, due to the change in handling simulation state, the form of the callback function has changed. +While a simulation is running, there is a matched state object that must be passed in and out of the program to perform operations. +This has already been demonstrated in the above functional API example, but in this case, the state change is more pronounced because the callback function must accept a state argument. +The reason the callback must accept the state argument is because while inside a callback, it is expected that the client code will then call into EnergyPlus to read/write data, and the state must be passed back in. +Basically, the client must be a reliable courier of the state object. + \begin{lstlisting} #include + #include - void dummyCallbackFunction() {} + void dummyCallbackFunction(EnergyPlusState state) { + printf("Hmm I could use my state argument to call back into EnergyPlus to do stuff, great!\n"); + } int main(int argc, const char * argv[]) { - callbackAfterNewEnvironmentWarmupComplete(dummyCallbackFunction); - energyplus(argc, argv); - cClearAllStates(); - callbackAfterNewEnvironmentWarmupComplete(dummyCallbackFunction); - energyplus(argc, argv); + callbackAfterNewEnvironmentWarmupComplete(state, dummyCallbackFunction); + energyplus(state, argc, argv); + stateReset(state); // note previously registered callbacks are cleared here + callbackAfterNewEnvironmentWarmupComplete(state, dummyCallbackFunction); + energyplus(state, argc, argv); } \end{lstlisting} The code is straightforward, though excessively minimal. -A blank function is created, which accepts no arguments, and does nothing. +A minimal function is created, which accepts one argument - a state object, and does nothing. This function is then passed to a callback registration function via the runtime API. EnergyPlus is executed, passing along any command line arguments that are received by the test program. This is a convenience because the energyplus function expects arguments just like the EnergyPlus(.exe) program, so the test script would have the same command line capabilities as EnergyPlus itself. For this code, it could be executed with something like: \verb=program.exe -D /path/to/input.idf=. -Once EnergyPlus is complete, the memory state is cleared, the callback is re-registered, and EnergyPlus is run again. -Since the test script is complete at this point, there is no need to clear the memory state again. +Once EnergyPlus is complete, the state object is reset, the callback is re-registered, and EnergyPlus is run again. +Since the test script is complete at this point, there is no need to reset the state again. The code is strikingly similar in Python: @@ -126,18 +194,21 @@ \subsection{Runtime API}\label{subsec:runtime-api} import sys from pyenergyplus.api import EnergyPlusAPI - def dummy_callback_function(): - pass + def dummy_callback_function(state_argument): + print("My argument is called state_argument to avoid duplicating the outer variable below called state") api = EnergyPlusAPI() - api.runtime.callback_begin_new_environment(dummy_callback_function) - api.runtime.run_energyplus(sys.argv[1:]) - api.runtime.clear_all_states() - api.runtime.callback_begin_new_environment(dummy_callback_function) - api.runtime.run_energyplus(sys.argv[1:]) + state = api.state_manager.new_state() + api.runtime.callback_begin_new_environment(state, dummy_callback_function) + api.runtime.run_energyplus(state, sys.argv[1:]) + api.state_manager.reset_state(state) + api.runtime.callback_begin_new_environment(state, dummy_callback_function) + api.runtime.run_energyplus(state, sys.argv[1:]) \end{lstlisting} -Once again, a dummy function is created, then registered, followed by a call to run EnergyPlus (passing along the relevant command line arguments), the state is cleared, then the function is registered again and EnergyPlus is run a second time. For those command line arguments, when calling EnergyPlus as a library, you should just pass the arguments, not the filename itself. In Python, the argv variable will have the filename as the first item in the list, so this syntax trims that off. +Once again, a dummy function is created, then registered, followed by a call to run EnergyPlus (passing along the relevant command line arguments), the state is cleared, then the function is registered again and EnergyPlus is run a second time. +Note that when calling EnergyPlus as a library, you should just pass the arguments, not the filename itself. +In Python, the argv variable will have the filename as the first item in the list, so this example trims that off. \subsection{Data Exchange API}\label{subsec:data-exchange-api} @@ -180,7 +251,7 @@ \subsection{Data Exchange API}\label{subsec:data-exchange-api} Instead, a specific set of items are available to actuate, primarily control functions, flow requests, and environmental boundary conditions. These actuators, when used in conjunction with the runtime API and data exchange variables, allow a user to read data, make decisions and perform calculations, then actuate control strategies for subsequent time steps. - Actuator functions are similar, but not exactly the same as for variables. + Actuator functions are similar, but not exactly the same, as for variables. An actuator handle/ID is still looked up, but it takes the actuator type, component name, and control type, since components may have more than one control type available for actuation. The actuator can then be ``actuated'' by calling a set-value function, which overrides an internal value, and informs EnergyPlus that this value is currently being externally controlled. To allow EnergyPlus to resume controlling that value, there is an actuator reset function as well. @@ -202,33 +273,34 @@ \subsection{Data Exchange API}\label{subsec:data-exchange-api} \begin{lstlisting} #include #include + #include int outdoorDewPointActuator = -1; int outdoorTempSensor = -1; int handlesRetrieved = 0; - void afterZoneTimeStepHandler() + void afterZoneTimeStepHandler(EnergyPlusState state) { if (handlesRetrieved == 0) { - if (!apiDataFullyReady()) return; - outdoorDewPointActuator = getActuatorHandle("Weather Data", "Outdoor Dew Point", "Environment"); - outdoorTempSensor = getVariableHandle("SITE OUTDOOR AIR DRYBULB TEMPERATURE", "ENVIRONMENT"); + if (!apiDataFullyReady(state)) return; + outdoorDewPointActuator = getActuatorHandle(state, "Weather Data", "Outdoor Dew Point", "Environment"); + outdoorTempSensor = getVariableHandle(state, "SITE OUTDOOR AIR DRYBULB TEMPERATURE", "ENVIRONMENT"); handlesRetrieved = 1; } - Real64 oa_temp = getVariableValue(outdoorTempSensor); - setActuatorValue(outdoorDewPointActuator, oa_temp - 4); + Real64 oa_temp = getVariableValue(state, outdoorTempSensor); + setActuatorValue(state, outdoorDewPointActuator, oa_temp - 4); } - int main(int argc, const char * argv[]) { - callbackEndOfZoneTimeStepAfterZoneReporting(afterZoneTimeStepHandler); - requestVariable("SITE OUTDOOR AIR DRYBULB TEMPERATURE", "ENVIRONMENT"); - energyplus(argc, argv); + callbackEndOfZoneTimeStepAfterZoneReporting(state, afterZoneTimeStepHandler); + requestVariable(state, "SITE OUTDOOR AIR DRYBULB TEMPERATURE", "ENVIRONMENT"); + energyplus(state, argc, argv); } \end{lstlisting} The actual operations happening in this example are completely fictional, but nevertheless demonstrate a possible minimal case. Note that the variable to be used is requested, and if the api data is not fully ready in the callback, it simply returns and waits. + And now in Python: \begin{lstlisting} @@ -238,25 +310,26 @@ \subsection{Data Exchange API}\label{subsec:data-exchange-api} outdoor_temp_sensor = 0 outdoor_dew_point_actuator = 0 - def time_step_handler(): + def time_step_handler(state): global one_time, outdoor_temp_sensor, outdoor_dew_point_sensor, outdoor_dew_point_actuator if one_time: - if not api.exchange.api_data_fully_ready(): + if not api.exchange.api_data_fully_ready(state): return outdoor_temp_sensor = api.exchange.get_variable_handle( - u"SITE OUTDOOR AIR DRYBULB TEMPERATURE", u"ENVIRONMENT" + state, u"SITE OUTDOOR AIR DRYBULB TEMPERATURE", u"ENVIRONMENT" ) outdoor_dew_point_actuator = api.exchange.get_actuator_handle( - "Weather Data", "Outdoor Dew Point", "Environment" + state, "Weather Data", "Outdoor Dew Point", "Environment" ) one_time = False - oa_temp = api.exchange.get_variable_value(outdoor_temp_sensor) - api.exchange.set_actuator_value(outdoor_dew_point_actuator, oa_temp-4) + oa_temp = api.exchange.get_variable_value(state, outdoor_temp_sensor) + api.exchange.set_actuator_value(state, outdoor_dew_point_actuator, oa_temp-4) api = EnergyPlusAPI() - api.runtime.callback_end_zone_timestep_after_zone_reporting(time_step_handler) - api.exchange.request_variable("SITE OUTDOOR AIR DRYBULB TEMPERATURE", "ENVIRONMENT") - api.runtime.run_energyplus(sys.argv[1:]) + state = api.state_manager.new_state() + api.runtime.callback_end_zone_timestep_after_zone_reporting(state, time_step_handler) + api.exchange.request_variable(state, "SITE OUTDOOR AIR DRYBULB TEMPERATURE", "ENVIRONMENT") + api.runtime.run_energyplus(state, sys.argv[1:]) \end{lstlisting} Note that when strings are passed through the Python API, they are both case-insensitive, and type-insensitive. @@ -269,6 +342,7 @@ \subsection{Full Examples}\label{subsec:full-examples} For the latest development version, they are at \href{https://github.com/NREL/EnergyPlus/tree/develop/tst/EnergyPlus/api}{this page}. \subsection{Building and Linking}\label{subsec:building-and-linking} + Once you have your C or Python code scripted up, you need to actually link that code to the EnergyPlus library. The EnergyPlus install includes several relevant pieces: @@ -281,14 +355,15 @@ \subsection{Building and Linking}\label{subsec:building-and-linking} - EnergyPlusAPI.h - func.h - runtime.h + - state.h - libenergyplusapi.so - pyenergyplus -    - api.py + - api.py \end{lstlisting} When building C applications, the build should include the EnergyPlusInstallRoot path in your include path, so that when the client has an \verb=#include=, it will be able to find it relative to the EnergyPlus install root path. Once the code is compiled, it should be linked to the EnergyPlus shared library, which also lives in the root of the EnergyPlus install. -The actual command will be different based on your compiler, but for gcc, as example, the command passed to the linker would be \verb=-l/path/to/libenergyplusapi.so=. +The actual command will be different based on your system and compiler, but using gcc on Linux, for example, the command passed to the linker would be \verb=-l/path/to/libenergyplusapi.so=. When building Python applications, the EnergyPlusInstallRoot should be added to the search path prior to trying to import anything else. This can be accomplished through the use of environment variables, but it is also easy to do at the beginning of scripts, for example: diff --git a/doc/input-output-reference/src/overview/group-python-plugins.tex b/doc/input-output-reference/src/overview/group-python-plugins.tex index be5de65e772..a1d9514bd09 100644 --- a/doc/input-output-reference/src/overview/group-python-plugins.tex +++ b/doc/input-output-reference/src/overview/group-python-plugins.tex @@ -23,6 +23,7 @@ \section{Group -- Python Plugins / Python EMS}\label{group-plugins} In plugin mode, EnergyPlus creates a new Python instance internally to allow processing the user-defined scripts. When EnergyPlus is run in an API mode, it cannot create a new Python session internally, as it may be in an existing Python session. Thus, if a plugin object is found in input during an API call, the program will abort. +In the future, this limitation may be lifted, but for most use cases, if you are calling EnergyPlus as a library (API), you can simply register API callbacks to execute user-defined code at runtime, and don't need to worry about also writing Python Plugins. The API section has information about how to access output variable data, meters, internal variable data, simulation parameters, and actuators, so these do not need additional information here. However, plugin objects have additional ways to interact with the simulation, and the plugins themselves need description, which is here. @@ -50,9 +51,8 @@ \subsection{Python Plugin} from pyenergyplus.plugin import EnergyPlusPlugin class DummyPlugin(EnergyPlusPlugin): - -def on_end_of_zone_timestep_before_zone_reporting(self): -return 0 + def on_end_of_zone_timestep_before_zone_reporting(self, state): + return 0 \end{lstlisting} This skeleton captures the use of a plugin to do nothing, but still shows some important features. @@ -63,6 +63,11 @@ \subsection{Python Plugin} \item The custom method returns zero to indicate success. \end{enumerate} +\textbf{NOTE!} The functional form of the plugin methods changed due to an API change between versions 9.3 and 9.4. +Any plugin files created using 9.3 will need to add a second argument to the methods. +This same argument will need to be passed into any EnergyPlus API methods called during the plugin. +Much more information can be found in the API usage section:~\ref{sec:api-usage}. + Several notes can be taken from this list. The name of the function matters, as it determines when the function will be called. The full list of possible names are: @@ -185,34 +190,31 @@ \subsection{PythonPlugin:Variables} \end{itemize} To use a global variable, an input object must be defined in the current input file, which specifies the variable name. -Then, in a plugin, a handle can be looked up for this global variable using the \verb=get_global_handle= function, which accepts the variable name as the only argument. -With the handle, the current value of the global variable can be looked up using the \verb=get_global_value= function, which takes only the handle for the variable. -Finally, to update the value of the global variable, the \verb=set_global_value= function is used, which takes a handle and a new value. +Then, in a plugin, a handle can be looked up for this global variable using the \verb=get_global_handle= function, which accepts the current state and the variable name as arguments. +With the handle, the current value of the global variable can be looked up using the \verb=get_global_value= function, which takes the current state and the handle for the variable as arguments. +Finally, to update the value of the global variable, the \verb=set_global_value= function is used, which takes the current state, the variable handle and a new value. Assuming a global variable is defined on input called ``OutdoorTemperature'', an example of this inside a plugin function follows: \begin{lstlisting} -global_var_handle = self.api.exchange.get_global_handle('OutdoorTemperature') -var_value = self.api.exchange.get_global_value(global_var_handle) -self.api.exchange.set_global_value(global_var_handle, 3.141) +global_var_handle = self.api.exchange.get_global_handle(state, 'OutdoorTemperature') +var_value = self.api.exchange.get_global_value(state, global_var_handle) +self.api.exchange.set_global_value(state, global_var_handle, 3.141) \end{lstlisting} \subsubsection{Inputs} -The inputs required to declare a global variable consist of the unique PythonPlugin:GlobalVariable object, along with a series of names -NOTE: Right now, the number of available variables is limited at five, but a future version will make this an unlimited object. -However, in many cases, using global variables is not necessary to achieve the client needs. -With the capabilities that come with using Python as a language, many of the reasons to declare and share global variables are eliminated. +The inputs required to declare a global variable consist of the unique PythonPlugin:GlobalVariable object, along with a series of names to identify each variable. \paragraph{Field: Name} This field is the name of this variables object, however since this is required to be a unique object, it does not do much. It is purely used for reporting of errors. -\paragraph{Field Variable Name 1-5} +\paragraph{Field Variable Name N} This field is used to declare and identify a plugin variable inside EnergyPlus. -This name is used as the identifier when accessing this value to read/write in user-defind plugins. +This name is used as the identifier when accessing this value to read/write in user-defined plugins. \subsection{PythonPlugin:TrendVariable} @@ -220,33 +222,33 @@ \subsection{PythonPlugin:TrendVariable} Once these are declared, a number of useful worker functions can be employed to process and read data from the trend. Note that trend variables are initially declared with values of zero at each history place, so the first few calls into the simulation could result in unexpected values of the trend. -To use a trend variable, an input object must be defind int he current input file, which specifies the attributes of the trend, including a name and a number of history terms to keep. +To use a trend variable, an input object must be defined int he current input file, which specifies the attributes of the trend, including a name and a number of history terms to keep. Then, in a plugin, a handle can be looked up for this trend variable using the \verb=get_trend_handle= function, which accepts the trend variable name as the only argument. With the handle, a number of aspects can be processed/looked up: \begin{itemize} - \item The trend value at a specific point in history can be retrieved using the \verb=get_trend_value= function, which accepts a trend handle and an index specifying how far back in history to evaluate the lookup. - \item The average trend value over a specific range can be retrieved using the \verb=get_trend_average= function, which accepts a trend handle and a count of how far back in history to evaluate. - \item The minimum trend value over a specific range can be retreived using the \verb=get_trend_min= function, which accepts a trend handle and a count of how far back in history to evaluate. - \item The maximum trend value over a specific range can be retreived using the \verb=get_trend_max= function, which accepts a trend handle and a count of how far back in history to evaluate. - \item The sum of a trend value over a specific range can be retrieved using the \verb=get_trend_sum= function, which accepts a trend handle and a count of how far back in history to evaluate. - \item The trajectory of a trend (slope of a linear regression line) over a specific range can be calculated using the \verb=get_trend_direction= function, which accepts a trend handle and a count of how far back in history to evaluate. + \item The trend value at a specific point in history can be retrieved using the \verb=get_trend_value= function, which accepts the current state, a trend handle and an index specifying how far back in history to evaluate the lookup. + \item The average trend value over a specific range can be retrieved using the \verb=get_trend_average= function, which accepts the current state, a trend handle and a count of how far back in history to evaluate. + \item The minimum trend value over a specific range can be retrieved using the \verb=get_trend_min= function, which accepts the current state, a trend handle and a count of how far back in history to evaluate. + \item The maximum trend value over a specific range can be retrieved using the \verb=get_trend_max= function, which accepts the current state, a trend handle and a count of how far back in history to evaluate. + \item The sum of a trend value over a specific range can be retrieved using the \verb=get_trend_sum= function, which accepts the current state, a trend handle and a count of how far back in history to evaluate. + \item The trajectory of a trend (slope of a linear regression line) over a specific range can be calculated using the \verb=get_trend_direction= function, which accepts the current state, a trend handle and a count of how far back in history to evaluate. \end{itemize} -Assuming a global variable is defind on input called ``CustomTemperature'', and a trend variable is declared called ``TrendVar'' with at least 5 history terms saved, an example usage of this inside a plugin function follows: +Assuming a global variable is defined on input called ``CustomTemperature'', and a trend variable is declared called ``TrendVar'' with at least 5 history terms saved, an example usage of this inside a plugin function follows: \begin{lstlisting} # update the variable throughout the simulation -global_var_handle = self.api.exchange.get_global_handle('CustomTemperature') -self.api.exchange.set_global_value(global_var_handle, 3.141) +global_var_handle = self.api.exchange.get_global_handle(state, 'CustomTemperature') +self.api.exchange.set_global_value(state, global_var_handle, 3.141) # get trend values as needed -trend_var_handle = self.api.exchange.get_trend_handle('TrendVar') -trend_avg = self.api.exchange.get_trend_average(trend_var_handle, 5) -trend_min = self.api.exchange.get_trend_min(trend_var_handle, 5) -trend_max = self.api.exchange.get_trend_max(trend_var_handle, 5) -trend_sum = self.api.exchange.get_trend_sum(trend_var_handle, 5) -trend_dir = self.api.exchange.get_trend_direction(trend_var_handle, 5) +trend_var_handle = self.api.exchange.get_trend_handle(state, 'TrendVar') +trend_avg = self.api.exchange.get_trend_average(state, trend_var_handle, 5) +trend_min = self.api.exchange.get_trend_min(state, trend_var_handle, 5) +trend_max = self.api.exchange.get_trend_max(state, trend_var_handle, 5) +trend_sum = self.api.exchange.get_trend_sum(state, trend_var_handle, 5) +trend_dir = self.api.exchange.get_trend_direction(state, trend_var_handle, 5) \end{lstlisting} \subsubsection{Inputs} @@ -272,7 +274,7 @@ \subsection{Packaging Details} From a user perspective, the only thing that will be noticed likely is the additional size of the installer. At the very onset of this project, it was decided that we would package Python into the installer, and not require a user to install an external version. This has been successful, however, at the cost of a larger install footprint. -The EnergyPlus install now includes a Python binary shared library, along with the core Python standard library of code. +The EnergyPlus install now includes a Python binary shared library, any dependent libraries, along with the core Python standard library of code. This allows users to create user-defined plugins that access all of the standard Python library capabilities. The main question received about this is about installing non-standard Python packages. @@ -291,9 +293,3 @@ \subsection{Packaging Details} \end{itemize} It is hoped that future versions of this will include a package management tool with EnergyPlus itself, so that installing native packages is straightforward. - -One additional note is that we are currently not linking to Python for our 32-bit Windows builds. -Doing this would have taken significant extra effort to develop the build process to handle both 32 and 64 bit options. -We have very few 32-bit users, and the effort was not justified. -If you are in the rare case of needing Python Plugins, yet also being on a 32-bit Windows machine, consult the development team and a custom build could possibly be built manually. - diff --git a/release/readme.html b/release/readme.html index e2c6b9779f0..f62d3c9498a 100644 --- a/release/readme.html +++ b/release/readme.html @@ -51,7 +51,7 @@

EnergyPlus Logo EnergyP heating, cooling, lighting, ventilating, and other energy flows. EnergyPlus is a stand-alone simulation engine without a ‘user friendly’ graphical interface. EnergyPlus reads input and writes output as text files...
- ...although, as of 9.3, EnergyPlus is starting to become a library. + ...although, as of 9.3, EnergyPlus started becoming a library.
@@ -77,27 +77,24 @@

EnergyPlus Logo EnergyP

Using EnergyPlus

Utilities and tools for creating, editing, and running input files that come with EnergyPlus include IDF Editor - and - EP-Launch. Many graphical user interfaces for EnergyPlus are available or under development. For the latest - tools, - please see + and EP-Launch. Many graphical user interfaces for EnergyPlus are available or under development. For the latest + tools, please see this website for third party interfaces. A completely new cross-platform version of EP-Launch has been - developed - and is available separate from the EnergyPlus install; see the documentation for more - information. - Some tools may produce out of date IDF files; you can then use the IDFVersionUpdater program to convert older - files to current EnergyPlus version (you may need to use the Multiple Version Conversions set – see below). + information. Some tools may produce out of date IDF files; you can then use the IDFVersionUpdater program to + convert older files to current EnergyPlus version (you may need to use the Multiple Version Conversions + set – see below).

-

What’s going on in V9.3?

+

What’s going on in V9.4?

@@ -108,13 +105,14 @@
Yes... and no.
improvements. Running EnergyPlus can still be accomplished the same way, by creating an input file in IDF or EpJSON syntax, running the EnergyPlus(.exe) binary, and gathering results of interest. All this power is still available. 👍
- However, for advanced usage, there are two significant changes that should be noted. The first - is that user-defined EMS scripts can now be written as Python "plugins" that are executed by - EnergyPlus at runtime. The second is that EnergyPlus can now be treated as a library, where a + As of EnergyPlus 9.3, EnergyPlus started becoming a bit more flexible thanks to the addition of + a formal C API with Python Bindings, as well as the ability to execute user-defined Python + "plugins" in lieu of writing user-defined Erl code. In the library mode, a client can make function calls to setup and execute a simulation, as well as interact with simulation results during a simulation. 👍 👍 👍
- Details of these major changes along with other significant features for this version (hint: - there are a bunch!) are listed below in this readme. Also, see the full + With version 9.4 the library APIs heavily changed, so scripts will need to be updated. (Don't + worry we won't make a habit of that!). Details of these major changes along with other + significant features for this version are listed below in this readme. Also, see the full ChangeLog for a complete list of new features added in this and previous versions.

@@ -128,13 +126,13 @@
Yes... and no.
No, they are different
-

There are a few key changes in the V9.3 IDD. For best results, use the transition program to - transfer from the earlier V9.2 files. Use the IDFVersionUpdater program for best results.

+

There are a few key changes in the V9.4 IDD. For best results, use the transition program to + transfer from the earlier V9.3 files. Use the IDFVersionUpdater program for best results.

@@ -145,7 +143,7 @@
No, they are different
@@ -153,39 +151,17 @@
Some objects require transition
There have been changes in the following objects which require conversion. Either read and follow the Rules document or use the IDFVersionUpdater utility. The “Rules” document contains information on exact object changes that you can do by hand. The updater program is described more fully in the Auxiliary - Programs document. For the v9.3 release, the following objects require conversion (from V9.2): + Programs document. For the v9.4 release, the following objects require conversion (from V9.3):
    -
  • AirConditioner:VariableRefrigerantFlow
  • -
  • AirTerminal:SingleDuct:Uncontrolled (spoiler...it's gone!)
  • -
  • Boiler:HotWater
  • -
  • Boiler:Steam
  • -
  • Chiller:EngineDriven
  • -
  • Chiller:CombustionTurbine
  • -
  • ChillerHeater:Absorption:DirectFired
  • -
  • Coil:Cooling:DX:MultiSpeed
  • -
  • Coil:Heating:Fuel
  • -
  • Coil:Heating:DX:MultiSpeed
  • -
  • EnergyManagementSystem:Program
  • -
  • EnergyManagementSystem:Subroutine
  • -
  • EnergyManagementSystem:MeteredOutputVariable
  • -
  • Exterior:FuelEquipment
  • -
  • FuelFactors
  • -
  • Generator:CombustionTurbine
  • -
  • Generator:InternalCombustionEngine
  • -
  • Generator:MicroTurbine
  • -
  • GlobalGeometryRules
  • -
  • HeatPump:WaterToWater:EIR:Heating
  • -
  • HeatPump:WaterToWater:EIR:Cooling
  • -
  • HVACTemplate:System:VRF
  • -
  • HVACTemplate:Plant:Boiler
  • -
  • LifeCycleCost:UsePriceEscalation
  • -
  • LifeCycleCost:UseAdjustment
  • -
  • OtherEquipment
  • -
  • Output:Table:SummaryReports
  • -
  • ShadowCalculation
  • -
  • WaterHeater:Mixed
  • -
  • WaterHeater:Stratified
  • +
  • Construction:InternalSource
  • ZoneHVAC:HybridUnitaryHVAC
  • +
  • Output:DebuggingData
  • +
  • Output:Diagnostics
  • +
  • ZoneHVAC:LowTemperatureRadiant:VariableFlow
  • +
  • ZoneHVAC:LowTemperatureRadiant:VariableFlow
  • +
  • ZoneHVAC:LowTemperatureRadiant:Electric
  • +
  • ZoneHVAC:LowTemperatureRadiant:ConstantFlow
  • +
  • Multiple Objects Affected with Fuel type Synonym Unification
@@ -214,7 +190,8 @@

Multiple Version Conversions

The install includes the IDFVersionUpdater program and the necessary programs to convert from the previous version (including .rvi and .mvi files) to the current version. The install also includes the necessary programs - to convert from older versions back to v7.2.0. For versions older than v7.2.0, you will need to visit the + to convert from older versions back to v7.2.0. For versions older than v7.2.0, first we applaud your dedication + to EnergyPlus that stretches for quite some time, and second you will need to visit the helpdesk and download the multiple conversion set of programs. The helpdesk downloads area: Converting Older Files @@ -229,7 +206,6 @@

Documentation

guide called the EnergyPlus Essentials was developed and is available with the installed pdf documentation. Big Ladder Software is also hosting html versions of the EnergyPlus Documentation online. -

There are some other documents of interest available on the EnergyPlus web site including:

@@ -238,6 +214,11 @@

Documentation

Testing and Validation Reports
+

+ In addition, we are working to make our API documentation dynamic and hosted on ReadTheDocs. The + README on our Github Repo will be kept + up to date with links to our documentation sources as we get things settled there. +

Weather Data

A small subset of weather files that are available on the web site are also installed in the WeatherData folder. @@ -247,76 +228,18 @@

Weather Data

about the included (or other) files. Weather data for more than 2100 locations in more than 100 countries can be downloaded on the EnergyPlus Weather Page.

-

Important Changes (OK, back to this library thing...)

-

There are three changes in this release of EnergyPlus which rely on different software dependencies.

-
-
C/Python API
-
- A significant change to this release is the ability to call EnergyPlus as a library. Up until now, the way almost all - users interacted with EnergyPlus has always been to setup an input file, and call the EnergyPlus(.exe) binary to run - the file, then gather results as needed from output files. (ExternalInterface being one exception). - While this traditional method is still available, a new approach has been - added. The simulation code has been refactored to allow a C API to be created, exposing functions that enable users - to register callback functions, call functional methods and interact with the simulation state. Through this C API, - a user may create a small C program that includes a callback function registered for each time step. Then at each - time step, this callback function then evaluates fluid property methods also via the API. The function can also - get access to instantaneous variable and meter data in the running simulation, and modify subsequent time steps - by actuating controls and other aspects. This unlocks the door for a whole new set of possible workflows. - To link against this API, just point builds to the EnergyPlus install directory, which has a new "includes" - directory with headers, and the EnergyPlus DLL right in the install root. - Then, on top of the C API, a matching Python API was built that will allow this same functionality, but through - Python scripts, further reducing the burden needed to create a workflow on top of EnergyPlus. The functional - API that exposes fluid property methods will be expanded over time to allow more and more access to internal - calculations in EnergyPlus. To link against this API, just point scripts into the EnergyPlus install directory - and access API files from the pyenergyplus package in there. More information about the API will be provided in - a supplemental documentation source -- initially a PDF -- posted on the release page on GitHub. - Note that the API is in a preliminary state and is subject to break for the next release. Subsequent - releases will be more stable. -
-
Python Plugins (Python EMS)
-
- The next change is the ability to use Python to write EMS scripts. These scripts are currently nicknamed - "plugins", as they are actually quite similar to the design of plugins for other software tools. In these - scripts, the user will write custom Python classes that override a predefined EnergyPlusPlugin base class. - The user will then declare the plugin in their input file, along with some other plugin-related inputs - (variables that can be shared between plugins, custom output variables, etc.). - Based on which functions the user overrides, the functions will be called at specific points during a - simulation. The calling points are the same as those exposed for regular EMS functions. - Once inside the called function, the plugin can then leverage the Python API discussed in the - previous paragraph to read data, write actuators, and evaluate fluid/refrigerant properties. In order to - execute Python scripts at runtime, this EnergyPlus version includes a Python library with it, which can be seen - if the install package is inspected. Users should not need to mess around with this; this note is merely a tip - for power users or people who do unusual things with the install package, that they need to watch this closer. - Details about this new Python Plugin approach are found in the EMSApplicationGuide, InputOutputReference, and - in the example files named PythonPlugin*.idf. -
-
GPU Calculations
-
- Another high impact change with this release is the ability to leverage GPU calculations to improve runtime - performance of the simulation. The documentation contains plenty of information to let users take - advantage of this new feature, which has the potential to drastically speed up simulation runtime, however, - a few notes provide high level tips for this new capability: -
    -
  • - There is a performance overhead associated with passing calculations between the GPU and the CPU, with the - GPU becoming noticeably more efficient in models with more than around 200 shadow-casting surfaces. The - actual number where the GPU becomes more efficient will depend on the specs of the respective hardware. -
  • -
  • - Some machines (mostly server machines) do not have GPU hardware or the required graphics drivers to utilize - this capability. If this scenario is detected on a computer, EnergyPlus will issue a warning and proceed - with the simulation using the calculations on the CPU. -
  • -
  • - Some computers have multiple GPUs. In this case, the highest performance GPU is not always used by default. - You may want to select which GPU is used when running EnergyPlus by setting the graphics performance - preferences on your computer. -
  • -
-
-
+

An Important Note About the API

+

+ Under normal circumstances, we intend on providing a very stable API for clients to access EnergyPlus. + However, as somewhat expected (see 9.3 README), the first release of the API was always likely to expose + some cases that would require a change in the API. Indeed it did. The change is pretty widespread through the + API, but quite an easy change to make. In summary - a new argument is needed in most functions, including + Python Plugin method overrides and user-defined runtime API callback functions. The client merely needs to + accept this argument in functions and pass it back in to the API methods. More information can be found in the + input-output reference document. +

-

Highlights of this release (V9.3.0)

+

Highlights of this release (V9.4.0)

New Features

@@ -324,36 +247,28 @@

New Features

- - - - - - + + - - + + - - + + - - + + - - + + - - - - - - + +
Description
7489Extend EIR WWHP to Air-source
7562Add Three Alternative Models for Clear Sky Emissivity Calculation8100Resilience Metrics Reporting
7603Input file conversion utility IDF->epJSON and reverse8113Implementation of On-Off Control Capabilities for the Variable Flow and Electric Low Temperature Radiant Systems
7605Allow ZoneHVAC:TerminalUnit:VariableRefrigerantFlow to connect to AirloopHVAC and AirLoopHVAC:OutdoorAirSystem:EquipmentList8170Enhancement of Low Temperature Radiant Models to Allow Multi-Zone Systems
7643New Schedule for Minimum Airflow for VAV Boxes8183Implement Changeover Delay for Hydronic Low Temperature Radiant Systems
7776C API, Python API, and Python Plugins8269Allow Multiple Scheduled Shades to Reference a Single Window
7792DX Cooling Coil Refactor
7834Scheduling min air flow for vav boxes follow up7821Add Report of SEER calculated using the user specified PLF curve and default AHRI curve and C_D

Runtime Performance Enhancing Developments

@@ -363,24 +278,20 @@

Runtime Performance Enhancing DevelopmentsDescription - 7302 - Allow GPU-based shading calculations - - - 7534 - Implement Carroll method for Interior Radiant Heat Exchange + 7904 + Native E+ CSV output and conditional output file selection - 7567 - Sizing speed up related to reducing the number of warmup days for design days + 7963 + Skip interzone diffuse solar exchange factors calculations when no interzone window exists - 7574 - A new algorithm for polygon clipping in solar calculations for rectangular surfaces + 8141 + SurfaceWindow struct refactoring - 7761 - Add Performance Overrides and Reporting + 8182 + Bypass interior solar distribution calculation at night

Targeted Refactoring Efforts

@@ -390,61 +301,50 @@

Targeted Refactoring Efforts

Description - 7479 - Simplify the moist air specific heat capacity psychrometric function - - - 7668 - Begin removing objexx gio (a total of 5 different PRs) + 8157 + WeatherManager clean up - 7734 - Make HeatPump:* Output Variable Names Consistent + 8173 + Fix State confusion around API - 7772 - Redefine Trim* and Round* functions in terms of {fmt} + 8211 + Global Pointer-to-Implementation Redesign - 7813 - Reduce use of Array1S objects - - - 7825 - Make EnergyPlus suitable as a cmake subproject - - - 7840 - Eliminating Reference variables - - - 7841 - Reduce Array1A and Array1 usage - - - - (~30 different PRs) Refactoring plant models into a uniform PlantComponent interface base class + (MANY) + Many refactoring efforts to clean up global variable usage in EnergyPlus
-
-
+
+

- A complete list of addressed issues may be found in the installed changelog. + The changelog is no longer packaged with EnergyPlus, but can be found on the release page.

-
+

Platforms

+

+ Packages changed slightly with 9.4. We are now building our packages on a new system which adds better support + for some platforms. During the change, we are stepping away from some older OS versions. For example, we are + not testing on Windows 7 or 8, only 10. However, both our 32-bit and 64-bit packages now include the new + Python plugin system, rather than just the 64-bit as previously. We have also added packaging and testing + with Ubuntu 20.04 in addition to Ubuntu 18.04. On Mac, we are officially releasing an installer for + OSX 10.15, although we will make an effort to offer a package for an older version. (Though 10.15 has been + out for a while now...) +

    -
  • Windows 7, 8 & 10
  • -
  • Linux (Ubuntu 18.04 and compatible) 64 bit versions
  • -
  • Mac OSX 10.13 64 bit versions
  • -
  • EnergyPlus V9.3 has been tested on all of these platforms
  • +
  • Windows 10
  • +
  • Linux (Ubuntu 18.04 and 20.04) 64 bit versions
  • +
  • Mac OSX 10.15 64 bit versions
  • +
  • EnergyPlus V9.4 has been tested on all of these platforms
  • EnergyPlus does intensive computations, and based on configuration, can write massive amounts of data to disk. For best performance, computers should have a substantial amount of memory and high speed hard @@ -508,7 +408,7 @@

    Additional steps you may want to consider:

    Thanks for downloading EnergyPlus. - Special thanks to our beta testers for this release. + Special thanks to our early testers for this release. If you did not download the previous version, we welcome you. If you are a returning customer, we hope you find the latest release exceeding your expectations. We look forward to serving you! diff --git a/src/EnergyPlus/CMakeLists.txt b/src/EnergyPlus/CMakeLists.txt index e63c9c7f89f..adca6b52e55 100644 --- a/src/EnergyPlus/CMakeLists.txt +++ b/src/EnergyPlus/CMakeLists.txt @@ -4,7 +4,7 @@ if(WIN32) endif() set(PYTHON_API_VERSION_MAJOR 0) -set(PYTHON_API_VERSION_MINOR 1) +set(PYTHON_API_VERSION_MINOR 2) configure_file( DataStringGlobals.in.cc "${CMAKE_CURRENT_BINARY_DIR}/DataStringGlobals.cc" ) configure_file( ConfiguredFunctions.in.cc "${CMAKE_CURRENT_BINARY_DIR}/ConfiguredFunctions.cc" ) file( WRITE "${CMAKE_CURRENT_BINARY_DIR}/EmbeddedEpJSONSchema.cc" "Will be filled in later by GenerateEmbeddedEpJSONSchema" ) diff --git a/src/EnergyPlus/api/docs/c/Doxyfile b/src/EnergyPlus/api/docs/c/Doxyfile index 2f89cfd6c74..d0e51096b97 100755 --- a/src/EnergyPlus/api/docs/c/Doxyfile +++ b/src/EnergyPlus/api/docs/c/Doxyfile @@ -846,7 +846,7 @@ EXCLUDE_SYMLINKS = NO # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* -EXCLUDE_PATTERNS = +EXCLUDE_PATTERNS = *autosizing.h # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the diff --git a/src/EnergyPlus/api/docs/python/conf.py b/src/EnergyPlus/api/docs/python/conf.py index 1e8aebda0dd..9c3842305a7 100644 --- a/src/EnergyPlus/api/docs/python/conf.py +++ b/src/EnergyPlus/api/docs/python/conf.py @@ -27,7 +27,7 @@ # The short X.Y version version = u'' # The full version, including alpha/beta/rc tags -release = u'0.1' +release = u'0.2' extra_nav_links = { 'Blah': 'https://energyplus.net' diff --git a/src/Transition/CreateNewIDFUsingRulesV9_4_0.f90 b/src/Transition/CreateNewIDFUsingRulesV9_4_0.f90 index 0cfda818482..01a8bebf6e7 100644 --- a/src/Transition/CreateNewIDFUsingRulesV9_4_0.f90 +++ b/src/Transition/CreateNewIDFUsingRulesV9_4_0.f90 @@ -515,6 +515,8 @@ SUBROUTINE CreateNewIDFUsingRules(EndOfFile,DiffOnly,InLfn,AskForInput,InputFile OutArgs(3) = 'Mode06' ENDIF + CASE('PYTHONPLUGIN:INSTANCE') + CALL writePreprocessorObject(DifLfn,PrognameConversion, 'Warning', 'PythonPlugin:Instance found -- note the API changed from v9.3 and v9.4 -- check docs and update with new state argument.') ! If your original object starts with R, insert the rules here From 0234969ced35f1b8d33f2c781db3975806a0e816 Mon Sep 17 00:00:00 2001 From: Edwin Lee Date: Mon, 28 Sep 2020 14:33:01 -0500 Subject: [PATCH 3/4] Tiny doc tweaks --- doc/input-output-reference/src/overview/api-usage.tex | 2 +- .../src/overview/group-python-plugins.tex | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/input-output-reference/src/overview/api-usage.tex b/doc/input-output-reference/src/overview/api-usage.tex index aef9db4c070..077cd8a40a6 100644 --- a/doc/input-output-reference/src/overview/api-usage.tex +++ b/doc/input-output-reference/src/overview/api-usage.tex @@ -15,7 +15,7 @@ \section{Using EnergyPlus as a Library}\label{sec:api-usage} As of version 9.4, the API has been improved, as well as the ability to more reliably ``reset'' the simulation state. After 9.3 was released and users began toying with the API usage, it was revealed that many (most?) files would not actually run well during series runs of EnergyPlus via API in the same thread because the simulation state was not fully ``cleared''. -Although the simulation state is still not guaranteed to be fully cleared, we are now seeing greater than 95% pass rate on our example files when running them serially multiple times. +Although the simulation state is still not guaranteed to be fully cleared, we are now seeing greater than 95\% pass rate on our example files when running them serially multiple times. This situation will make it much more suited for integrating into workflows as the Python thread does not have to be destroyed to get a clean EnergyPlus state for the next run. Work is continuing to get the state of the simulation completely managed, and will be completed prior to the next release, ensuring this situation continues improving. diff --git a/doc/input-output-reference/src/overview/group-python-plugins.tex b/doc/input-output-reference/src/overview/group-python-plugins.tex index a1d9514bd09..f7e423cd7b8 100644 --- a/doc/input-output-reference/src/overview/group-python-plugins.tex +++ b/doc/input-output-reference/src/overview/group-python-plugins.tex @@ -126,7 +126,7 @@ \subsubsection{Inputs} In these cases, it may be useful to keep plugin files right next to the input file, regardless of the current working directory. Turning this field to Yes will add the directory where the input file is located to the list of search paths. -\paragraph{Field: Search Path 1-5} +\paragraph{Field: Search Path N} There are also some cases, where a user may keep a specific library of plugin scripts that work with a variety of input files. In this case, they may want to just point EnergyPlus to a custom directory away from any specific input file or working directory. From acc74a92944f93d1601d83e96d7662342f538bf0 Mon Sep 17 00:00:00 2001 From: mjwitte Date: Mon, 28 Sep 2020 19:24:05 -0500 Subject: [PATCH 4/4] Python transition warning tweak --- src/Transition/CreateNewIDFUsingRulesV9_4_0.f90 | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Transition/CreateNewIDFUsingRulesV9_4_0.f90 b/src/Transition/CreateNewIDFUsingRulesV9_4_0.f90 index 71d641a32a6..daf251307df 100644 --- a/src/Transition/CreateNewIDFUsingRulesV9_4_0.f90 +++ b/src/Transition/CreateNewIDFUsingRulesV9_4_0.f90 @@ -134,6 +134,7 @@ SUBROUTINE CreateNewIDFUsingRules(EndOfFile,DiffOnly,InLfn,AskForInput,InputFile INTEGER numMeterCustom CHARACTER(len=MaxNameLength) :: MeterCustomName CHARACTER(len=MaxNameLength), ALLOCATABLE, DIMENSION(:) :: MeterCustomNames + LOGICAL :: throwPythonWarning = .TRUE. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! E N D O F I N S E R T L O C A L V A R I A B L E S H E R E ! @@ -537,7 +538,14 @@ SUBROUTINE CreateNewIDFUsingRules(EndOfFile,DiffOnly,InLfn,AskForInput,InputFile ENDIF CASE('PYTHONPLUGIN:INSTANCE') - CALL writePreprocessorObject(DifLfn,PrognameConversion, 'Warning', 'PythonPlugin:Instance found -- note the API changed from v9.3 and v9.4 -- check docs and update with new state argument.') + IF (throwPythonWarning) THEN + CALL ShowWarningError('PythonPlugin:Instance found -- note the API changed from v9.3 and v9.4 -- check docs and update with new state argument.',Auditf) + CALL writePreprocessorObject(DifLfn,PrognameConversion, 'Warning', 'PythonPlugin:Instance found -- note the API changed from v9.3 and v9.4 -- check docs and update with new state argument.') + throwPythonWarning = .false. + END IF + CALL GetNewObjectDefInIDD(ObjectName,NwNumArgs,NwAorN,NwReqFld,NwObjMinFlds,NwFldNames,NwFldDefaults,NwFldUnits) + OutArgs(1:CurArgs)=InArgs(1:CurArgs) + nodiff=.true. ! If your original object starts with R, insert the rules here