LCOV - code coverage report
Current view: top level - EnergyPlus - ExternalInterface.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 55.1 % 1307 720
Test Date: 2025-06-02 07:23:51 Functions: 76.2 % 21 16

            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              : // FMI-Related Headers
      49              : extern "C" {
      50              : #include <BCVTB/utilSocket.h>
      51              : #include <BCVTB/utilXml.h>
      52              : #include <FMI/main.h>
      53              : }
      54              : 
      55              : // C++ Headers
      56              : #include <string>
      57              : #include <vector>
      58              : 
      59              : // ObjexxFCL Headers
      60              : #include <ObjexxFCL/Array.functions.hh>
      61              : #include <ObjexxFCL/string.functions.hh>
      62              : 
      63              : // EnergyPlus Headers
      64              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      65              : #include <EnergyPlus/DataEnvironment.hh>
      66              : #include <EnergyPlus/DataIPShortCuts.hh>
      67              : #include <EnergyPlus/DataStringGlobals.hh>
      68              : #include <EnergyPlus/DataSystemVariables.hh>
      69              : #include <EnergyPlus/DisplayRoutines.hh>
      70              : #include <EnergyPlus/EMSManager.hh>
      71              : #include <EnergyPlus/ExternalInterface.hh>
      72              : #include <EnergyPlus/FileSystem.hh>
      73              : #include <EnergyPlus/GlobalNames.hh>
      74              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      75              : #include <EnergyPlus/OutputProcessor.hh>
      76              : #include <EnergyPlus/RuntimeLanguageProcessor.hh>
      77              : #include <EnergyPlus/ScheduleManager.hh>
      78              : #include <EnergyPlus/UtilityRoutines.hh>
      79              : 
      80              : namespace EnergyPlus::ExternalInterface {
      81              : 
      82              : // Module containing the routines dealing with the BCVTB interface
      83              : 
      84              : // MODULE INFORMATION:
      85              : //       AUTHOR         Michael Wetter
      86              : //       DATE WRITTEN   2Dec2007
      87              : //       MODIFIED       Rui Zhang July 2009
      88              : //       MODIFIED       Thierry S. Nouidui 2011
      89              : 
      90              : // PURPOSE OF THIS MODULE:
      91              : // To encapsulate the data and routines required to interface
      92              : // the Building Controls Virtual Test Bed (BCVTB) and FunctionalMockupUnits (FMU)
      93              : 
      94              : // REFERENCES:
      95              : // http://simulationresearch.lbl.gov/bcvtb
      96              : // http://www.modelisar.com
      97              : 
      98      1958080 : void ExternalInterfaceExchangeVariables(EnergyPlusData &state)
      99              : {
     100              : 
     101              :     // SUBROUTINE INFORMATION:
     102              :     //       AUTHOR         Michael Wetter
     103              :     //       DATE WRITTEN   2Dec2007
     104              : 
     105              :     // PURPOSE OF THIS SUBROUTINE:
     106              :     // Exchanges variables between EnergyPlus and the BCVTB socket.
     107              : 
     108      1958080 :     if (state.dataExternalInterface->GetInputFlag) {
     109          800 :         GetExternalInterfaceInput(state);
     110          800 :         state.dataExternalInterface->GetInputFlag = false;
     111              :     }
     112              : 
     113      1958080 :     if (state.dataExternalInterface->haveExternalInterfaceBCVTB || state.dataExternalInterface->haveExternalInterfaceFMUExport) {
     114            0 :         InitExternalInterface(state);
     115              :         // Exchange data only after sizing and after warm-up.
     116              :         // Note that checking for ZoneSizingCalc SysSizingCalc does not work here, hence we
     117              :         // use the KindOfSim flag
     118            0 :         if (!state.dataGlobal->WarmupFlag && (state.dataGlobal->KindOfSim == Constant::KindOfSim::RunPeriodWeather)) {
     119            0 :             CalcExternalInterface(state);
     120              :         }
     121              :     }
     122              : 
     123      1958080 :     if (state.dataExternalInterface->haveExternalInterfaceFMUImport) {
     124       143619 :         std::string errorMessage; // Error message
     125       143619 :         errorMessage.reserve(100);
     126       143619 :         char *errorMessagePtr(errorMessage.data());
     127       143619 :         const int retValErrMsg = checkOperatingSystem(errorMessagePtr);
     128       143619 :         if (retValErrMsg != 0) {
     129            0 :             ShowSevereError(state, format("ExternalInterface/ExternalInterfaceExchangeVariables:{}", errorMessagePtr));
     130            0 :             state.dataExternalInterface->ErrorsFound = true;
     131            0 :             StopExternalInterfaceIfError(state);
     132              :         }
     133              :         // initialize the FunctionalMockupUnitImport interface
     134       143619 :         InitExternalInterfaceFMUImport(state);
     135              :         // No Data exchange during design days
     136              :         // Data Exchange data during warmup and after warmup
     137       143619 :         CalcExternalInterfaceFMUImport(state);
     138       143619 :     }
     139      1958080 : }
     140              : 
     141          800 : void GetExternalInterfaceInput(EnergyPlusData &state)
     142              : {
     143              : 
     144              :     // SUBROUTINE INFORMATION:
     145              :     //       AUTHOR         Michael Wetter
     146              :     //       DATE WRITTEN   2Dec2007
     147              : 
     148              :     // PURPOSE OF THIS SUBROUTINE:
     149              :     // Obtains input data for ExternalInterface
     150              : 
     151              :     // METHODOLOGY EMPLOYED:
     152              :     // Uses InputProcessor "Get" routines to obtain data.
     153              : 
     154              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     155              :     int NumAlphas;  // Number of Alphas for each GetObjectItem call
     156              :     int NumNumbers; // Number of Numbers for each GetObjectItem call
     157              :     int IOStatus;   // Used in GetObjectItem
     158          800 :     auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
     159          800 :     cCurrentModuleObject = "ExternalInterface";
     160          800 :     state.dataExternalInterface->NumExternalInterfaces = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     161              : 
     162          803 :     for (int Loop = 1; Loop <= state.dataExternalInterface->NumExternalInterfaces;
     163              :          ++Loop) { // This loop determines whether the external interface is for FMU or BCVTB
     164            9 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     165              :                                                                  cCurrentModuleObject,
     166              :                                                                  Loop,
     167            3 :                                                                  state.dataIPShortCut->cAlphaArgs,
     168              :                                                                  NumAlphas,
     169            3 :                                                                  state.dataIPShortCut->rNumericArgs,
     170              :                                                                  NumNumbers,
     171              :                                                                  IOStatus,
     172              :                                                                  _,
     173              :                                                                  _,
     174            3 :                                                                  state.dataIPShortCut->cAlphaFieldNames,
     175            3 :                                                                  state.dataIPShortCut->cNumericFieldNames);
     176            3 :         if (Util::SameString(state.dataIPShortCut->cAlphaArgs(1), "PtolemyServer")) { // The BCVTB interface is activated.
     177            0 :             ++state.dataExternalInterface->NumExternalInterfacesBCVTB;
     178            3 :         } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(1),
     179              :                                     "FunctionalMockupUnitImport")) { // The functional mock up unit import interface is activated.
     180            3 :             ++state.dataExternalInterface->NumExternalInterfacesFMUImport;
     181            0 :         } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(1),
     182              :                                     "FunctionalMockupUnitExport")) { // The functional mock up unit export interface is activated.
     183            0 :             ++state.dataExternalInterface->NumExternalInterfacesFMUExport;
     184              :         }
     185              :     }
     186              : 
     187              :     // Check if objects are used although BCVTB interface object is not defined
     188          800 :     if (state.dataExternalInterface->NumExternalInterfacesBCVTB == 0) {
     189         1600 :         WarnIfExternalInterfaceObjectsAreUsed(state, "ExternalInterface:Schedule");
     190         1600 :         WarnIfExternalInterfaceObjectsAreUsed(state, "ExternalInterface:Variable");
     191         1600 :         WarnIfExternalInterfaceObjectsAreUsed(state, "ExternalInterface:Actuator");
     192              :     }
     193              : 
     194              :     // Check if objects are used although FMUExport interface is not defined
     195          800 :     if (state.dataExternalInterface->NumExternalInterfacesFMUExport == 0) {
     196         1600 :         WarnIfExternalInterfaceObjectsAreUsed(state, "ExternalInterface:FunctionalMockupUnitExport:To:Schedule");
     197         1600 :         WarnIfExternalInterfaceObjectsAreUsed(state, "ExternalInterface:FunctionalMockupUnitExport:To:Variable");
     198         1600 :         WarnIfExternalInterfaceObjectsAreUsed(state, "ExternalInterface:FunctionalMockupUnitExport:To:Actuator");
     199              :     }
     200              : 
     201              :     // Check if objects are used although FMU Import interface is not defined
     202          800 :     if (state.dataExternalInterface->NumExternalInterfacesFMUImport == 0) {
     203         1594 :         WarnIfExternalInterfaceObjectsAreUsed(state, "ExternalInterface:FunctionalMockupUnitImport:To:Schedule");
     204         1594 :         WarnIfExternalInterfaceObjectsAreUsed(state, "ExternalInterface:FunctionalMockupUnitImport:To:Variable");
     205         1594 :         WarnIfExternalInterfaceObjectsAreUsed(state, "ExternalInterface:FunctionalMockupUnitImport:To:Actuator");
     206              :     }
     207              : 
     208          800 :     if ((state.dataExternalInterface->NumExternalInterfacesBCVTB == 1) && (state.dataExternalInterface->NumExternalInterfacesFMUExport == 0)) {
     209            0 :         state.dataExternalInterface->haveExternalInterfaceBCVTB = true;
     210            0 :         DisplayString(state, "Instantiating Building Controls Virtual Test Bed");
     211            0 :         state.dataExternalInterface->varKeys.allocate(maxVar);         // Keys of report variables used for data exchange
     212            0 :         state.dataExternalInterface->varNames.allocate(maxVar);        // Names of report variables used for data exchange
     213            0 :         state.dataExternalInterface->inpVarTypes.dimension(maxVar, 0); // Names of report variables used for data exchange
     214            0 :         state.dataExternalInterface->inpVarNames.allocate(maxVar);     // Names of report variables used for data exchange
     215            0 :         VerifyExternalInterfaceObject(state);
     216          800 :     } else if ((state.dataExternalInterface->NumExternalInterfacesBCVTB == 0) && (state.dataExternalInterface->NumExternalInterfacesFMUExport == 1)) {
     217            0 :         state.dataExternalInterface->haveExternalInterfaceFMUExport = true;
     218            0 :         state.dataExternalInterface->FMUExportActivate = 1;
     219            0 :         DisplayString(state, "Instantiating FunctionalMockupUnitExport interface");
     220            0 :         state.dataExternalInterface->varKeys.allocate(maxVar);         // Keys of report variables used for data exchange
     221            0 :         state.dataExternalInterface->varNames.allocate(maxVar);        // Names of report variables used for data exchange
     222            0 :         state.dataExternalInterface->inpVarTypes.dimension(maxVar, 0); // Names of report variables used for data exchange
     223            0 :         state.dataExternalInterface->inpVarNames.allocate(maxVar);     // Names of report variables used for data exchange
     224            0 :         VerifyExternalInterfaceObject(state);
     225          800 :     } else if ((state.dataExternalInterface->NumExternalInterfacesBCVTB == 1) && (state.dataExternalInterface->NumExternalInterfacesFMUExport != 0)) {
     226            0 :         ShowSevereError(state, "GetExternalInterfaceInput: Cannot have Ptolemy and FMU-Export interface simultaneously.");
     227            0 :         state.dataExternalInterface->ErrorsFound = true;
     228              :     }
     229              : 
     230          800 :     if ((state.dataExternalInterface->NumExternalInterfacesFMUImport == 1) && (state.dataExternalInterface->NumExternalInterfacesFMUExport == 0)) {
     231            3 :         state.dataExternalInterface->haveExternalInterfaceFMUImport = true;
     232            3 :         DisplayString(state, "Instantiating FunctionalMockupUnitImport interface");
     233            3 :         cCurrentModuleObject = "ExternalInterface:FunctionalMockupUnitImport";
     234            3 :         state.dataExternalInterface->NumFMUObjects = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     235            3 :         VerifyExternalInterfaceObject(state);
     236          797 :     } else if ((state.dataExternalInterface->NumExternalInterfacesFMUImport == 1) &&
     237            0 :                (state.dataExternalInterface->NumExternalInterfacesFMUExport != 0)) {
     238            0 :         ShowSevereError(state, "GetExternalInterfaceInput: Cannot have FMU-Import and FMU-Export interface simultaneously.");
     239            0 :         state.dataExternalInterface->ErrorsFound = true;
     240              :     }
     241              : 
     242          800 :     if (state.dataExternalInterface->NumExternalInterfacesBCVTB > 1) {
     243            0 :         ShowSevereError(state, "GetExternalInterfaceInput: Cannot have more than one Ptolemy interface.");
     244            0 :         ShowContinueError(state, "GetExternalInterfaceInput: Errors found in input.");
     245            0 :         state.dataExternalInterface->ErrorsFound = true;
     246              :     }
     247              : 
     248          800 :     if (state.dataExternalInterface->NumExternalInterfacesFMUExport > 1) {
     249            0 :         ShowSevereError(state, "GetExternalInterfaceInput: Cannot have more than one FMU-Export interface.");
     250            0 :         ShowContinueError(state, "Errors found in input.");
     251            0 :         state.dataExternalInterface->ErrorsFound = true;
     252              :     }
     253              : 
     254          800 :     if (state.dataExternalInterface->NumExternalInterfacesFMUImport > 1) {
     255            0 :         ShowSevereError(state, "GetExternalInterfaceInput: Cannot have more than one FMU-Import interface.");
     256            0 :         ShowContinueError(state, "Errors found in input.");
     257            0 :         state.dataExternalInterface->ErrorsFound = true;
     258              :     }
     259              : 
     260          800 :     if (state.dataExternalInterface->ErrorsFound) {
     261            0 :         ShowFatalError(state, "GetExternalInterfaceInput: preceding conditions cause termination.");
     262              :     }
     263              : 
     264          800 :     StopExternalInterfaceIfError(state);
     265          800 : }
     266              : 
     267          830 : void StopExternalInterfaceIfError(EnergyPlusData &state)
     268              : {
     269              :     // SUBROUTINE INFORMATION:
     270              :     //       AUTHOR         Michael Wetter
     271              :     //       DATE WRITTEN   9Jan2008
     272              : 
     273              :     // PURPOSE OF THIS SUBROUTINE:
     274              :     // This subroutine gracefully stops the ExternalInterface if an error has been found.
     275              :     // It sends an appropriate message to the ExternalInterface
     276              :     // and then calls a fatal error to stop EnergyPlus.
     277              : 
     278              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     279          830 :     int constexpr flag1(-10);
     280          830 :     int constexpr flag2(-20);
     281              : 
     282          830 :     if ((state.dataExternalInterface->NumExternalInterfacesBCVTB != 0) || (state.dataExternalInterface->NumExternalInterfacesFMUExport != 0)) {
     283            0 :         if (state.dataExternalInterface->ErrorsFound) {
     284              :             // Check if the socket is open
     285            0 :             if (state.dataExternalInterface->socketFD >= 0) {
     286              :                 int retVal; // Return value, needed to catch return value of function call
     287              :                 // Socket is open
     288            0 :                 if (state.dataExternalInterface->simulationStatus == 1) {
     289            0 :                     retVal = sendclientmessage(&state.dataExternalInterface->socketFD, &flag1);
     290              :                 } else {
     291            0 :                     retVal = sendclientmessage(&state.dataExternalInterface->socketFD, &flag2);
     292              :                 }
     293            0 :                 if (retVal == 0) {
     294            0 :                     ShowSevereError(state, "External Interface not found.");
     295              :                 }
     296              :             }
     297            0 :             ShowFatalError(state, "Error in ExternalInterface: Check EnergyPlus *.err file.");
     298              :         }
     299              :     }
     300          830 :     if (state.dataExternalInterface->NumExternalInterfacesFMUImport != 0) {
     301           33 :         if (state.dataExternalInterface->ErrorsFound) {
     302            0 :             ShowFatalError(state, "ExternalInterface/StopExternalInterfaceIfError: Error in ExternalInterface: Check EnergyPlus *.err file.");
     303              :         }
     304              :     }
     305          830 : }
     306              : 
     307            0 : void CloseSocket(EnergyPlusData &state, int const FlagToWriteToSocket)
     308              : {
     309              :     // SUBROUTINE INFORMATION:
     310              :     //       AUTHOR         Michael Wetter
     311              :     //       DATE WRITTEN   December 2008
     312              : 
     313              :     // PURPOSE OF THIS SUBROUTINE:
     314              :     // This subroutine tries to write the optional error code to the
     315              :     // socket and then closes the socket
     316              : 
     317              :     // SUBROUTINE ARGUMENT DEFINITIONS:
     318              :     // +1: E+ reached final time
     319              :     // -1: E+ had some error
     320              : 
     321              :     // Try to establish socket connection. This is needed if Ptolemy started E+,
     322              :     //  but E+ had an error before the call to InitExternalInterface.
     323              : 
     324            0 :     bool fileExist = FileSystem::fileExists(state.dataExternalInterface->socCfgFilPath);
     325              : 
     326            0 :     if ((state.dataExternalInterface->socketFD == -1) && fileExist) {
     327            0 :         state.dataExternalInterface->socketFD = establishclientsocket(FileSystem::toString(state.dataExternalInterface->socCfgFilPath).c_str());
     328              :     }
     329              : 
     330            0 :     if (state.dataExternalInterface->socketFD >= 0) {
     331              :         // TODO: use return value from this function?
     332            0 :         sendclientmessage(&state.dataExternalInterface->socketFD, &FlagToWriteToSocket);
     333              :         // Don't close socket as this may give sometimes an IOException in Windows
     334              :         // This problem seems to affect only Windows but not Mac
     335              :         //     close(state.dataExternalInterface->socketFD)
     336              :     }
     337            0 : }
     338              : 
     339            0 : void ParseString(std::string const &str, // The string, with all elements separated by ';'
     340              :                  Array1D_string &ele,    // The elements
     341              :                  int const nEle          // The number of elements
     342              : )
     343              : {
     344              :     // SUBROUTINE INFORMATION:
     345              :     //       AUTHOR         Michael Wetter
     346              :     //       DATE WRITTEN   8Jan2008
     347              : 
     348              :     // PURPOSE OF THIS SUBROUTINE:
     349              :     // This subroutine parses the semicolon separated string xmlStr
     350              :     // and assigns each element to ele
     351              : 
     352              :     // SUBROUTINE VARIABLE DEFINITIONS:
     353              :     std::string::size_type iSta; // Start of substring
     354              :     std::string::size_type iCol; // Index of ;
     355              : 
     356            0 :     std::string::size_type lenStr = len(str);
     357            0 :     std::string::size_type iEnd = 0;
     358            0 :     for (int i = 1; i <= nEle; ++i) {
     359            0 :         iSta = iEnd; // add one to skip ';'
     360            0 :         iCol = str.find(';', iSta);
     361            0 :         if (iCol != std::string::npos) {
     362            0 :             iEnd = iCol + 1;
     363              :         } else { // Use rest of string
     364            0 :             iEnd = lenStr;
     365              :         }
     366            0 :         ele(i) = Util::makeUPPER(str.substr(iSta, iEnd - iSta - 1));
     367              :     }
     368            0 : }
     369              : 
     370            0 : void InitExternalInterface(EnergyPlusData &state)
     371              : {
     372              :     // SUBROUTINE INFORMATION:
     373              :     //       AUTHOR         Michael Wetter
     374              :     //       DATE WRITTEN   2Dec2007
     375              :     //       MODIFIED       Rui Zhang Aug 2009
     376              : 
     377              :     // PURPOSE OF THIS SUBROUTINE:
     378              :     // This subroutine is for initializations of the ExternalInterface
     379              : 
     380              :     // SUBROUTINE PARAMETER DEFINITIONS:
     381              : 
     382            0 :     std::string const simCfgFilNam("variables.cfg");               // Configuration file
     383            0 :     std::string const xmlStrInKey("schedule,variable,actuator\0"); // xml values in string, separated by ','
     384              : 
     385            0 :     if (state.dataExternalInterface->InitExternalInterfacefirstCall) {
     386            0 :         DisplayString(state, "ExternalInterface initializes.");
     387              :         // do one time initializations
     388              : 
     389            0 :         if (state.dataExternalInterface->haveExternalInterfaceBCVTB) {
     390              :             // Check version number
     391            0 :             int mainVersion = getmainversionnumber();
     392            0 :             if (mainVersion < 0) {
     393            0 :                 ShowSevereError(state, "ExternalInterface: BCVTB is not installed in this version.");
     394            0 :                 state.dataExternalInterface->ErrorsFound = true;
     395            0 :                 StopExternalInterfaceIfError(state);
     396              :             }
     397              :         }
     398              : 
     399              :         // Get port number
     400            0 :         if (FileSystem::fileExists(state.dataExternalInterface->socCfgFilPath)) {
     401            0 :             state.dataExternalInterface->socketFD = establishclientsocket(FileSystem::toString(state.dataExternalInterface->socCfgFilPath).c_str());
     402            0 :             if (state.dataExternalInterface->socketFD < 0) {
     403            0 :                 ShowSevereError(state,
     404            0 :                                 format("ExternalInterface: Could not open socket. File descriptor = {}.", state.dataExternalInterface->socketFD));
     405            0 :                 state.dataExternalInterface->ErrorsFound = true;
     406              :             }
     407              :         } else {
     408            0 :             ShowSevereError(state, format("ExternalInterface: Did not find file \"{}\".", state.dataExternalInterface->socCfgFilPath));
     409            0 :             ShowContinueError(state, "This file needs to be in same directory as in.idf.");
     410            0 :             ShowContinueError(state, "Check the documentation for the ExternalInterface.");
     411            0 :             state.dataExternalInterface->ErrorsFound = true;
     412              :         }
     413              : 
     414              :         // Make sure that idf file specified a run period other than
     415              :         // design day and system sizing.
     416            0 :         ValidateRunControl(state);
     417              : 
     418            0 :         StopExternalInterfaceIfError(state);
     419              : 
     420              :         // make a single length here for all strings to be passed to getepvariables
     421            0 :         size_t lenXmlStr(maxVar * Constant::MaxNameLength); // Length of strings being passed to getepvariables
     422              : 
     423              :         // initialize all the strings to this length with blanks
     424            0 :         std::string xmlStrOut = std::string(lenXmlStr, ' ');
     425            0 :         std::string xmlStrOutTyp = std::string(lenXmlStr, ' ');
     426            0 :         std::string xmlStrIn = std::string(lenXmlStr, ' ');
     427              : 
     428              :         // Get input and output variables for EnergyPlus in sequence
     429              :         // Check if simCfgFilNam exists.
     430            0 :         if (FileSystem::fileExists(simCfgFilNam)) {
     431              :             int retVal; // Return value of function call, used for error handling
     432              : 
     433              :             // preprocess the strings into char vectors before making the library call
     434            0 :             std::vector<char> xmlStrOutTypArr(getCharArrayFromString(xmlStrOutTyp));
     435            0 :             std::vector<char> xmlStrOutArr(getCharArrayFromString(xmlStrOut));
     436            0 :             std::vector<char> xmlStrInArr(getCharArrayFromString(xmlStrIn));
     437              : 
     438              :             // now make the library call
     439            0 :             if (state.dataExternalInterface->haveExternalInterfaceBCVTB) {
     440            0 :                 retVal = getepvariables(simCfgFilNam.c_str(),
     441            0 :                                         &xmlStrOutTypArr[0],
     442            0 :                                         &xmlStrOutArr[0],
     443            0 :                                         &state.dataExternalInterface->nOutVal,
     444              :                                         xmlStrInKey.c_str(),
     445            0 :                                         &state.dataExternalInterface->nInKeys,
     446            0 :                                         &xmlStrInArr[0],
     447            0 :                                         &state.dataExternalInterface->nInpVar,
     448            0 :                                         state.dataExternalInterface->inpVarTypes.data(),
     449              :                                         &lenXmlStr);
     450            0 :             } else if (state.dataExternalInterface->haveExternalInterfaceFMUExport) {
     451            0 :                 retVal = getepvariablesFMU(simCfgFilNam.c_str(),
     452            0 :                                            &xmlStrOutTypArr[0],
     453            0 :                                            &xmlStrOutArr[0],
     454            0 :                                            &state.dataExternalInterface->nOutVal,
     455              :                                            xmlStrInKey.c_str(),
     456            0 :                                            &state.dataExternalInterface->nInKeys,
     457            0 :                                            &xmlStrInArr[0],
     458            0 :                                            &state.dataExternalInterface->nInpVar,
     459            0 :                                            state.dataExternalInterface->inpVarTypes.data(),
     460              :                                            &lenXmlStr);
     461              :             } else {
     462              :                 // there should be no else condition at this point, however we'll still assign the error value for completeness
     463            0 :                 retVal = -1;
     464              :             }
     465              : 
     466              :             // then postprocess the char vectors in case they are used after the fact
     467            0 :             xmlStrOutTyp = getStringFromCharArray(xmlStrOutTypArr);
     468            0 :             xmlStrOut = getStringFromCharArray(xmlStrOutArr);
     469            0 :             xmlStrIn = getStringFromCharArray(xmlStrInArr);
     470              : 
     471            0 :             xmlStrOutTypArr.clear();
     472            0 :             xmlStrOutArr.clear();
     473            0 :             xmlStrInArr.clear();
     474              : 
     475              :             // handle errors when reading variables.cfg file
     476            0 :             if (retVal < 0) {
     477            0 :                 ShowSevereError(state, "ExternalInterface: Error when getting input and output variables for EnergyPlus,");
     478            0 :                 ShowContinueError(state, "check simulation.log for error message.");
     479            0 :                 state.dataExternalInterface->ErrorsFound = true;
     480              :             }
     481              : 
     482            0 :         } else {
     483              : 
     484            0 :             ShowSevereError(state, format("ExternalInterface: Did not find file \"{}\".", simCfgFilNam));
     485            0 :             ShowContinueError(state, "This file needs to be in same directory as in.idf.");
     486            0 :             ShowContinueError(state, "Check the documentation for the ExternalInterface.");
     487            0 :             state.dataExternalInterface->ErrorsFound = true;
     488              :         }
     489            0 :         StopExternalInterfaceIfError(state);
     490              : 
     491            0 :         if (state.dataExternalInterface->nOutVal + state.dataExternalInterface->nInpVar > maxVar) {
     492            0 :             ShowSevereError(state, "ExternalInterface: Too many variables to be exchanged.");
     493            0 :             ShowContinueError(state, format("Attempted to exchange {} outputs", state.dataExternalInterface->nOutVal));
     494            0 :             ShowContinueError(state, format("plus {} inputs.", state.dataExternalInterface->nOutVal));
     495            0 :             ShowContinueError(state, format("Maximum allowed is sum is {}.", maxVar));
     496            0 :             ShowContinueError(state, "To fix, increase maxVar in ExternalInterface.cc");
     497            0 :             state.dataExternalInterface->ErrorsFound = true;
     498              :         }
     499            0 :         StopExternalInterfaceIfError(state);
     500              : 
     501            0 :         if (state.dataExternalInterface->nOutVal < 0) {
     502            0 :             ShowSevereError(state, "ExternalInterface: Error when getting number of xml values for outputs.");
     503            0 :             state.dataExternalInterface->ErrorsFound = true;
     504              :         } else {
     505            0 :             ParseString(xmlStrOut, state.dataExternalInterface->varNames, state.dataExternalInterface->nOutVal);
     506            0 :             ParseString(xmlStrOutTyp, state.dataExternalInterface->varKeys, state.dataExternalInterface->nOutVal);
     507              :         }
     508            0 :         StopExternalInterfaceIfError(state);
     509              : 
     510            0 :         if (state.dataExternalInterface->nInpVar < 0) {
     511            0 :             ShowSevereError(state, "ExternalInterface: Error when getting number of xml values for inputs.");
     512            0 :             state.dataExternalInterface->ErrorsFound = true;
     513              :         } else {
     514            0 :             ParseString(xmlStrIn, state.dataExternalInterface->inpVarNames, state.dataExternalInterface->nInpVar);
     515              :         }
     516            0 :         StopExternalInterfaceIfError(state);
     517              : 
     518            0 :         DisplayString(state, format("Number of outputs in ExternalInterface = {}", state.dataExternalInterface->nOutVal));
     519            0 :         DisplayString(state, format("Number of inputs  in ExternalInterface = {}", state.dataExternalInterface->nInpVar));
     520              : 
     521            0 :         state.dataExternalInterface->InitExternalInterfacefirstCall = false;
     522              : 
     523            0 :     } else if (!state.dataExternalInterface->configuredControlPoints) {
     524            0 :         state.dataExternalInterface->keyVarIndexes.allocate(state.dataExternalInterface->nOutVal);
     525            0 :         state.dataExternalInterface->varTypes.allocate(state.dataExternalInterface->nOutVal);
     526            0 :         GetReportVariableKey(state,
     527            0 :                              state.dataExternalInterface->varKeys,
     528            0 :                              state.dataExternalInterface->nOutVal,
     529            0 :                              state.dataExternalInterface->varNames,
     530            0 :                              state.dataExternalInterface->keyVarIndexes,
     531            0 :                              state.dataExternalInterface->varTypes);
     532            0 :         state.dataExternalInterface->varInd.allocate(state.dataExternalInterface->nInpVar);
     533            0 :         for (int i = 1; i <= state.dataExternalInterface->nInpVar; ++i) {
     534            0 :             if (state.dataExternalInterface->inpVarTypes(i) == indexSchedule) {
     535            0 :                 state.dataExternalInterface->varInd(i) = Sched::GetDayScheduleNum(state, state.dataExternalInterface->inpVarNames(i));
     536            0 :             } else if (state.dataExternalInterface->inpVarTypes(i) == indexVariable) {
     537            0 :                 state.dataExternalInterface->varInd(i) =
     538            0 :                     RuntimeLanguageProcessor::FindEMSVariable(state, state.dataExternalInterface->inpVarNames(i), 0);
     539            0 :             } else if (state.dataExternalInterface->inpVarTypes(i) == indexActuator) {
     540            0 :                 state.dataExternalInterface->varInd(i) =
     541            0 :                     RuntimeLanguageProcessor::FindEMSVariable(state, state.dataExternalInterface->inpVarNames(i), 0);
     542              :             }
     543            0 :             if (state.dataExternalInterface->varInd(i) <= 0) {
     544            0 :                 ShowSevereError(state,
     545            0 :                                 format("ExternalInterface: Error, xml file \"{}\" declares variable \"{}\",",
     546              :                                        simCfgFilNam,
     547            0 :                                        state.dataExternalInterface->inpVarNames(i)));
     548            0 :                 ShowContinueError(state, "but variable was not found in idf file.");
     549            0 :                 state.dataExternalInterface->ErrorsFound = true;
     550              :             }
     551              :         }
     552            0 :         StopExternalInterfaceIfError(state);
     553              :         // Configure Erl variables
     554            0 :         for (int i = 1; i <= state.dataExternalInterface->nInpVar; ++i) {
     555            0 :             if (state.dataExternalInterface->inpVarTypes(i) == indexVariable) { // ems-globalvariable
     556            0 :                 state.dataExternalInterface->useEMS = true;
     557            0 :                 if (!RuntimeLanguageProcessor::isExternalInterfaceErlVariable(state, state.dataExternalInterface->varInd(i))) {
     558            0 :                     ShowSevereError(state,
     559            0 :                                     format("ExternalInterface: Error, xml file \"{}\" declares variable \"{}\",",
     560              :                                            simCfgFilNam,
     561            0 :                                            state.dataExternalInterface->inpVarNames(i)));
     562            0 :                     ShowContinueError(state, "But this variable is an ordinary Erl variable, not an ExternalInterface variable.");
     563            0 :                     ShowContinueError(state, "You must specify a variable of type \"ExternalInterface:Variable\".");
     564            0 :                     state.dataExternalInterface->ErrorsFound = true;
     565              :                 }
     566            0 :             } else if (state.dataExternalInterface->inpVarTypes(i) == indexActuator) { // ems-actuator
     567            0 :                 state.dataExternalInterface->useEMS = true;
     568            0 :                 if (!RuntimeLanguageProcessor::isExternalInterfaceErlVariable(state, state.dataExternalInterface->varInd(i))) {
     569            0 :                     ShowSevereError(state,
     570            0 :                                     format("ExternalInterface: Error, xml file \"{}\" declares variable \"{}\",",
     571              :                                            simCfgFilNam,
     572            0 :                                            state.dataExternalInterface->inpVarNames(i)));
     573            0 :                     ShowContinueError(state, "But this variable is an ordinary Erl actuator, not an ExternalInterface actuator.");
     574            0 :                     ShowContinueError(state, "You must specify a variable of type \"ExternalInterface:Actuator\".");
     575            0 :                     state.dataExternalInterface->ErrorsFound = true;
     576              :                 }
     577              :             }
     578              :         }
     579            0 :         state.dataExternalInterface->configuredControlPoints = true;
     580              :     }
     581            0 :     StopExternalInterfaceIfError(state);
     582            0 : }
     583              : 
     584       143616 : void GetSetVariablesAndDoStepFMUImport(EnergyPlusData &state)
     585              : {
     586              :     // SUBROUTINE INFORMATION:
     587              :     //       AUTHOR         Thierry S. Nouidui, Michael Wetter, Wangda Zuo
     588              :     //       DATE WRITTEN   08Aug2011
     589              : 
     590              :     // PURPOSE OF THIS SUBROUTINE:
     591              :     // This routine gets, sets and does the time integration in FMUs.
     592              : 
     593       287232 :     for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
     594       143616 :         auto &fmu = state.dataExternalInterface->FMU(i);
     595       143616 :         auto &fmuTemp = state.dataExternalInterface->FMUTemp(i);
     596              : 
     597       287232 :         for (int j = 1; j <= fmu.NumInstances; ++j) {
     598       143616 :             auto &fmuInst = fmu.Instance(j);
     599       143616 :             auto &fmuTempInst = fmuTemp.Instance(j);
     600              : 
     601       143616 :             if (state.dataExternalInterface->FlagReIni) {
     602              :                 // Get from FMUs, values that will be set in EnergyPlus (Schedule)
     603           66 :                 for (int k = 1; k <= fmuTempInst.NumOutputVariablesSchedule; ++k) {
     604           36 :                     fmuInst.fmuOutputVariableSchedule(k).RealVarValue = fmuTempInst.fmuOutputVariableSchedule(k).RealVarValue;
     605              :                 }
     606              : 
     607              :                 // Get from FMUs, values that will be set in EnergyPlus (Variable)
     608           36 :                 for (int k = 1; k <= fmuTempInst.NumOutputVariablesVariable; ++k) {
     609            6 :                     fmuInst.fmuOutputVariableVariable(k).RealVarValue = fmuTempInst.fmuOutputVariableVariable(k).RealVarValue;
     610              :                 }
     611              : 
     612              :                 // Get from FMUs, values that will be set in EnergyPlus (Actuator)
     613           36 :                 for (int k = 1; k <= fmuTempInst.NumOutputVariablesActuator; ++k) {
     614            6 :                     fmuInst.fmuOutputVariableActuator(k).RealVarValue = fmuTempInst.fmuOutputVariableActuator(k).RealVarValue;
     615              :                 }
     616              :             } else {
     617              :                 // Get from FMUs, values that will be set in EnergyPlus (Schedule)
     618              : 
     619       143586 :                 if (size(fmuInst.fmuOutputVariableSchedule) > 0) {
     620              : 
     621              :                     // generate vectors here first
     622        36750 :                     std::vector<unsigned int> valueReferenceVec;
     623        36750 :                     std::vector<Real64> realVarValueVec;
     624       110250 :                     for (unsigned long x = 1; x <= size(fmuInst.fmuOutputVariableSchedule); ++x) {
     625        73500 :                         valueReferenceVec.push_back(fmuInst.fmuOutputVariableSchedule(x).ValueReference);
     626        73500 :                         realVarValueVec.push_back(fmuInst.fmuOutputVariableSchedule(x).RealVarValue);
     627              :                     }
     628              : 
     629              :                     // pass in the vectors as pointers to the first member of the vector
     630        36750 :                     fmuInst.fmistatus = fmiEPlusGetReal(
     631        36750 :                         &fmuInst.fmicomponent, &valueReferenceVec[0], &realVarValueVec[0], &fmuInst.NumOutputVariablesSchedule, &fmuInst.Index);
     632              : 
     633       110250 :                     for (unsigned long x = 1; x <= size(fmuInst.fmuOutputVariableSchedule); ++x) {
     634        73500 :                         fmuInst.fmuOutputVariableSchedule(x).ValueReference = valueReferenceVec[x - 1];
     635        73500 :                         fmuInst.fmuOutputVariableSchedule(x).RealVarValue = realVarValueVec[x - 1];
     636              :                     }
     637              : 
     638        36750 :                     if (fmuInst.fmistatus != fmiOK) {
     639            0 :                         ShowSevereError(state, "ExternalInterface/GetSetVariablesAndDoStepFMUImport: Error when trying to get outputs");
     640            0 :                         ShowContinueError(state, format("in instance \"{}\" of FMU \"{}\"", fmuInst.Name, fmu.Name));
     641            0 :                         ShowContinueError(state, format("Error Code = \"{}\"", fmuInst.fmistatus));
     642            0 :                         state.dataExternalInterface->ErrorsFound = true;
     643            0 :                         StopExternalInterfaceIfError(state);
     644              :                     }
     645        36750 :                 }
     646              : 
     647              :                 // generate vectors here first
     648       143586 :                 if (size(fmuInst.fmuOutputVariableVariable) > 0) {
     649              : 
     650        53418 :                     std::vector<unsigned int> valueReferenceVec2;
     651        53418 :                     std::vector<Real64> realVarValueVec2;
     652       106836 :                     for (unsigned long x = 1; x <= size(fmuInst.fmuOutputVariableVariable); ++x) {
     653        53418 :                         valueReferenceVec2.push_back(fmuInst.fmuOutputVariableVariable(x).ValueReference);
     654        53418 :                         realVarValueVec2.push_back(fmuInst.fmuOutputVariableVariable(x).RealVarValue);
     655              :                     }
     656              : 
     657              :                     // pass in the vectors as pointers to the first member of the vector
     658        53418 :                     fmuInst.fmistatus = fmiEPlusGetReal(
     659        53418 :                         &fmuInst.fmicomponent, &valueReferenceVec2[0], &realVarValueVec2[0], &fmuInst.NumOutputVariablesVariable, &fmuInst.Index);
     660              : 
     661       106836 :                     for (unsigned long x = 1; x <= size(fmuInst.fmuOutputVariableVariable); ++x) {
     662        53418 :                         fmuInst.fmuOutputVariableVariable(x).ValueReference = valueReferenceVec2[x - 1];
     663        53418 :                         fmuInst.fmuOutputVariableVariable(x).RealVarValue = realVarValueVec2[x - 1];
     664              :                     }
     665              : 
     666        53418 :                     if (fmuInst.fmistatus != fmiOK) {
     667            0 :                         ShowSevereError(state, "ExternalInterface/GetSetVariablesAndDoStepFMUImport: Error when trying to get outputs");
     668            0 :                         ShowContinueError(state, format("in instance \"{}\" of FMU \"{}\"", fmuInst.Name, fmu.Name));
     669            0 :                         ShowContinueError(state, format("Error Code = \"{}\"", fmuInst.fmistatus));
     670            0 :                         state.dataExternalInterface->ErrorsFound = true;
     671            0 :                         StopExternalInterfaceIfError(state);
     672              :                     }
     673        53418 :                 }
     674              : 
     675       143586 :                 if (size(fmuInst.fmuOutputVariableActuator) > 0) {
     676              : 
     677              :                     // generate vectors here first
     678        53418 :                     std::vector<unsigned int> valueReferenceVec3;
     679        53418 :                     std::vector<Real64> realVarValueVec3;
     680       106836 :                     for (unsigned long x = 1; x <= size(fmuInst.fmuOutputVariableActuator); ++x) {
     681        53418 :                         valueReferenceVec3.push_back(fmuInst.fmuOutputVariableActuator(x).ValueReference);
     682        53418 :                         realVarValueVec3.push_back(fmuInst.fmuOutputVariableActuator(x).RealVarValue);
     683              :                     }
     684              : 
     685              :                     // pass in the vectors as pointers to the first member of the vector
     686        53418 :                     fmuInst.fmistatus = fmiEPlusGetReal(
     687        53418 :                         &fmuInst.fmicomponent, &valueReferenceVec3[0], &realVarValueVec3[0], &fmuInst.NumOutputVariablesActuator, &fmuInst.Index);
     688              : 
     689       106836 :                     for (unsigned long x = 1; x <= size(fmuInst.fmuOutputVariableActuator); ++x) {
     690        53418 :                         fmuInst.fmuOutputVariableActuator(x).ValueReference = valueReferenceVec3[x - 1];
     691        53418 :                         fmuInst.fmuOutputVariableActuator(x).RealVarValue = realVarValueVec3[x - 1];
     692              :                     }
     693              : 
     694        53418 :                     if (fmuInst.fmistatus != fmiOK) {
     695            0 :                         ShowSevereError(state, "ExternalInterface/GetSetVariablesAndDoStepFMUImport: Error when trying to get outputs");
     696            0 :                         ShowContinueError(state, format("in instance \"{}\" of FMU \"{}\"", fmuInst.Name, fmu.Name));
     697            0 :                         ShowContinueError(state, format("Error Code = \"{}\"", fmuInst.fmistatus));
     698            0 :                         state.dataExternalInterface->ErrorsFound = true;
     699            0 :                         StopExternalInterfaceIfError(state);
     700              :                     }
     701        53418 :                 }
     702              :             }
     703              : 
     704              :             // Set in EnergyPlus the values of the schedules
     705       217152 :             for (int k = 1; k <= fmuInst.NumOutputVariablesSchedule; ++k) {
     706       147072 :                 Sched::ExternalInterfaceSetSchedule(
     707        73536 :                     state, fmuInst.eplusInputVariableSchedule(k).VarIndex, fmuInst.fmuOutputVariableSchedule(k).RealVarValue);
     708              :             }
     709              : 
     710              :             // Set in EnergyPlus the values of the variables
     711       197040 :             for (int k = 1; k <= fmuInst.NumOutputVariablesVariable; ++k) {
     712       106848 :                 RuntimeLanguageProcessor::ExternalInterfaceSetErlVariable(
     713        53424 :                     state, fmuInst.eplusInputVariableVariable(k).VarIndex, fmuInst.fmuOutputVariableVariable(k).RealVarValue);
     714              :             }
     715              : 
     716              :             // Set in EnergyPlus the values of the actuators
     717       197040 :             for (int k = 1; k <= fmuInst.NumOutputVariablesActuator; ++k) {
     718       106848 :                 RuntimeLanguageProcessor::ExternalInterfaceSetErlVariable(
     719        53424 :                     state, fmuInst.eplusInputVariableActuator(k).VarIndex, fmuInst.fmuOutputVariableActuator(k).RealVarValue);
     720              :             }
     721              : 
     722       143616 :             if (state.dataExternalInterface->FirstCallGetSetDoStep) {
     723              :                 // Get from EnergyPlus, values that will be set in fmus
     724           11 :                 for (int k = 1; k <= fmuInst.NumInputVariablesInIDF; ++k) {
     725              :                     // This make sure that the variables are updated at the Zone Time Step
     726            8 :                     fmuInst.eplusOutputVariable(k).RTSValue =
     727            8 :                         GetInternalVariableValue(state, fmuInst.eplusOutputVariable(k).VarType, fmuInst.eplusOutputVariable(k).VarIndex);
     728              :                 }
     729              :             } else {
     730              :                 // Get from EnergyPlus, values that will be set in fmus
     731       504373 :                 for (int k = 1; k <= fmuInst.NumInputVariablesInIDF; ++k) {
     732              :                     // This make sure that the variables are updated at the Zone Time Step
     733       360760 :                     fmuInst.eplusOutputVariable(k).RTSValue = GetInternalVariableValueExternalInterface(
     734       360760 :                         state, fmuInst.eplusOutputVariable(k).VarType, fmuInst.eplusOutputVariable(k).VarIndex);
     735              :                 }
     736              :             }
     737              : 
     738       143616 :             if (!state.dataExternalInterface->FlagReIni) {
     739              : 
     740              :                 // generate vectors here first
     741       143586 :                 std::vector<unsigned int> valueReferenceVec4;
     742       504258 :                 for (unsigned long x = 1; x <= size(fmuInst.fmuInputVariable); ++x) {
     743       360672 :                     valueReferenceVec4.push_back(fmuInst.fmuInputVariable(x).ValueReference);
     744              :                 }
     745              : 
     746       143586 :                 std::vector<Real64> rtsValueVec4;
     747       504258 :                 for (unsigned long x = 1; x <= size(fmuInst.eplusOutputVariable); ++x) {
     748       360672 :                     rtsValueVec4.push_back(fmuInst.eplusOutputVariable(x).RTSValue);
     749              :                 }
     750              : 
     751       143586 :                 fmuInst.fmistatus =
     752       143586 :                     fmiEPlusSetReal(&fmuInst.fmicomponent, &valueReferenceVec4[0], &rtsValueVec4[0], &fmuInst.NumInputVariablesInIDF, &fmuInst.Index);
     753              : 
     754       143586 :                 if (fmuInst.fmistatus != fmiOK) {
     755            0 :                     ShowSevereError(state, "ExternalInterface/GetSetVariablesAndDoStepFMUImport: Error when trying to set inputs");
     756            0 :                     ShowContinueError(state, format("in instance \"{}\" of FMU \"{}\"", fmuInst.Name, fmu.Name));
     757            0 :                     ShowContinueError(state, format("Error Code = \"{}\"", fmuInst.fmistatus));
     758            0 :                     state.dataExternalInterface->ErrorsFound = true;
     759            0 :                     StopExternalInterfaceIfError(state);
     760              :                 }
     761       143586 :             }
     762       143616 :             int localfmitrue(fmiTrue);
     763              :             // Call and simulate the FMUs to get values at the corresponding timestep.
     764       143616 :             fmuInst.fmistatus = fmiEPlusDoStep(
     765       143616 :                 &fmuInst.fmicomponent, &state.dataExternalInterface->tComm, &state.dataExternalInterface->hStep, &localfmitrue, &fmuInst.Index);
     766       143616 :             if (fmuInst.fmistatus != fmiOK) {
     767            0 :                 ShowSevereError(state, "ExternalInterface/GetSetVariablesAndDoStepFMUImport: Error when trying to");
     768            0 :                 ShowContinueError(state, format("do the coSimulation with instance \"{}\"", fmuInst.Name));
     769            0 :                 ShowContinueError(state, format("of FMU \"{}\"", fmu.Name));
     770            0 :                 ShowContinueError(state, format("Error Code = \"{}\"", fmuInst.fmistatus));
     771            0 :                 state.dataExternalInterface->ErrorsFound = true;
     772            0 :                 StopExternalInterfaceIfError(state);
     773              :             }
     774              :         }
     775              :     }
     776              : 
     777              :     // If we have Erl variables, we need to call ManageEMS so that they get updated in the Erl data structure
     778       143616 :     if (state.dataExternalInterface->useEMS) {
     779              :         bool anyRan;
     780       106848 :         EMSManager::ManageEMS(state, EMSManager::EMSCallFrom::ExternalInterface, anyRan, ObjexxFCL::Optional_int_const());
     781              :     }
     782              : 
     783       143616 :     state.dataExternalInterface->FirstCallGetSetDoStep = false;
     784       143616 : }
     785              : 
     786           33 : void InstantiateInitializeFMUImport(EnergyPlusData &state)
     787              : {
     788              :     // SUBROUTINE INFORMATION:
     789              :     //       AUTHOR         Thierry S. Nouidui, Michael Wetter, Wangda Zuo
     790              :     //       DATE WRITTEN   08Aug2011
     791              : 
     792              :     // PURPOSE OF THIS SUBROUTINE:
     793              :     // This routine instantiates and initializes FMUs.
     794              : 
     795              :     // Instantiate FMUs
     796           66 :     for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
     797           33 :         auto &fmu = state.dataExternalInterface->FMU(i);
     798           66 :         for (int j = 1; j <= fmu.NumInstances; ++j) {
     799           33 :             auto &fmuInst = fmu.Instance(j);
     800           33 :             std::string const folderStr = FileSystem::toString(fmuInst.WorkingFolder);
     801           33 :             fmuInst.fmicomponent = fmiEPlusInstantiateSlave(
     802           33 :                 (char *)folderStr.c_str(), &fmuInst.LenWorkingFolder, &fmu.TimeOut, &fmu.Visible, &fmu.Interactive, &fmu.LoggingOn, &fmuInst.Index);
     803              :             // TODO: This is doing a null pointer check; OK?
     804           33 :             if (!fmuInst.fmicomponent) {
     805            0 :                 ShowSevereError(state, "ExternalInterface/CalcExternalInterfaceFMUImport: Error when trying to instantiate");
     806            0 :                 ShowContinueError(state, format("instance \"{}\" of FMU \"{}\"", fmuInst.Name, fmu.Name));
     807            0 :                 state.dataExternalInterface->ErrorsFound = true;
     808            0 :                 StopExternalInterfaceIfError(state);
     809              :             }
     810           33 :         }
     811              :     }
     812              : 
     813              :     // Initialize FMUs
     814           33 :     int localfmiTrue(fmiTrue);
     815           66 :     for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
     816           33 :         auto &fmu = state.dataExternalInterface->FMU(i);
     817           66 :         for (int j = 1; j <= fmu.NumInstances; ++j) {
     818           33 :             auto &fmuInst = fmu.Instance(j);
     819           33 :             fmuInst.fmistatus = fmiEPlusInitializeSlave(
     820           33 :                 &fmuInst.fmicomponent, &state.dataExternalInterface->tStart, &localfmiTrue, &state.dataExternalInterface->tStop, &fmuInst.Index);
     821           33 :             if (fmuInst.fmistatus != fmiOK) {
     822            0 :                 ShowSevereError(state, "ExternalInterface/CalcExternalInterfaceFMUImport: Error when trying to initialize");
     823            0 :                 ShowContinueError(state, format("instance \"{}\" of FMU \"{}\"", fmuInst.Name, fmu.Name));
     824            0 :                 ShowContinueError(state, format("Error Code = \"{}\"", fmuInst.fmistatus));
     825            0 :                 state.dataExternalInterface->ErrorsFound = true;
     826            0 :                 StopExternalInterfaceIfError(state);
     827              :             }
     828              :         }
     829              :     }
     830           33 : }
     831              : 
     832            0 : void InitializeFMU(EnergyPlusData &state)
     833              : {
     834              :     // SUBROUTINE INFORMATION:
     835              :     //       AUTHOR         Thierry S. Nouidui, Michael Wetter, Wangda Zuo
     836              :     //       DATE WRITTEN   08Aug2011
     837              : 
     838              :     // PURPOSE OF THIS SUBROUTINE:
     839              :     // This routine reinitializes FMUs.
     840              : 
     841              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     842            0 :     int localfmiTrue(fmiTrue);
     843              : 
     844              :     // Initialize FMUs
     845            0 :     for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
     846            0 :         auto &fmu = state.dataExternalInterface->FMU(i);
     847            0 :         for (int j = 1; j <= fmu.NumInstances; ++j) {
     848            0 :             auto &fmuInst = fmu.Instance(j);
     849            0 :             fmuInst.fmistatus = fmiEPlusInitializeSlave(
     850            0 :                 &fmuInst.fmicomponent, &state.dataExternalInterface->tStart, &localfmiTrue, &state.dataExternalInterface->tStop, &fmuInst.Index);
     851            0 :             if (fmuInst.fmistatus != fmiOK) {
     852            0 :                 ShowSevereError(state, "ExternalInterface/CalcExternalInterfaceFMUImport: Error when trying to initialize");
     853            0 :                 ShowContinueError(state, format("instance \"{}\" of FMU \"{}\"", fmuInst.Name, fmu.Name));
     854            0 :                 ShowContinueError(state, format("Error Code = \"{}\"", fmuInst.fmistatus));
     855            0 :                 state.dataExternalInterface->ErrorsFound = true;
     856            0 :                 StopExternalInterfaceIfError(state);
     857              :             }
     858              :         }
     859              :     }
     860            0 : }
     861              : 
     862           33 : void TerminateResetFreeFMUImport(EnergyPlusData &state, int fmiEndSimulation)
     863              : {
     864              :     // SUBROUTINE INFORMATION:
     865              :     //       AUTHOR         Thierry S. Nouidui, Michael Wetter, Wangda Zuo
     866              :     //       DATE WRITTEN   08Aug2011
     867              : 
     868              :     // PURPOSE OF THIS SUBROUTINE:
     869              :     // This routine terminates the FMUs instances
     870              : 
     871              :     //----Needs to have function that allows to terminates FMU. Was not defined in version 1.0 -- fixme
     872           66 :     for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
     873           33 :         auto &fmu = state.dataExternalInterface->FMU(i);
     874           66 :         for (int j = 1; j <= fmu.NumInstances; ++j) {
     875           33 :             auto &fmuInst = fmu.Instance(j);
     876           33 :             if (fmuInst.fmistatus != fmiFatal) {
     877              :                 // Cleanup slaves
     878           33 :                 fmuInst.fmistatus = fmiEPlusFreeSlave(&fmuInst.fmicomponent, &fmuInst.Index, &fmiEndSimulation);
     879              :             }
     880              :             // check if fmiComponent has been freed
     881           33 :             if (!fmuInst.fmicomponent) {
     882            0 :                 ShowSevereError(state, "ExternalInterface/TerminateResetFreeFMUImport: Error when trying to terminate");
     883            0 :                 ShowContinueError(state, format("instance \"{}\" of FMU \"{}\"", fmuInst.Name, fmu.Name));
     884            0 :                 state.dataExternalInterface->ErrorsFound = true;
     885            0 :                 StopExternalInterfaceIfError(state);
     886              :             }
     887              :         }
     888              :     }
     889           33 : }
     890              : 
     891       143619 : void InitExternalInterfaceFMUImport(EnergyPlusData &state)
     892              : {
     893              : 
     894              :     // SUBROUTINE INFORMATION:
     895              :     //       AUTHOR         Thierry S. Nouidui, Michael Wetter, Wangda Zuo
     896              :     //       DATE WRITTEN   08Aug2011
     897              : 
     898              :     // PURPOSE OF THIS SUBROUTINE:
     899              :     // This routine initializes the input and outputs variables used for the co-simulation with FMUs.
     900              : 
     901              :     // Locals
     902       143619 :     Array1D_int keyIndexes(1);                          // Array index for
     903       143619 :     Array1D<OutputProcessor::VariableType> varTypes(1); // Array index for
     904       143619 :     Array1D_string NamesOfKeys(1);                      // Specific key name
     905       143619 :     Array1D_string NameListInstances(5);
     906       143619 :     fs::path tempFullFilePath;
     907              : 
     908       143619 :     Array1D_string strippedFileName; // remove path from entered file name
     909       143619 :     Array1D_string fullFileName;     // entered file name/found
     910              : 
     911       143619 :     if (state.dataExternalInterface->FirstCallIni) {
     912            3 :         DisplayString(state, "Initializing FunctionalMockupUnitImport interface");
     913              :         // do one time initializations
     914            3 :         ValidateRunControl(state);
     915            3 :         state.dataExternalInterface->FMU.allocate(state.dataExternalInterface->NumFMUObjects);
     916              : 
     917              :         // there used to be code in here to apply the root working folder to create an absolute path
     918              :         // however, this wasn't working, as the root working folder was coming back empty
     919              :         // in any case, the relative paths work fine here
     920              : 
     921              :         // post process as needed in case these are used later
     922            3 :         state.dataExternalInterface->FMURootWorkingFolder = fs::path("tmp-fmus"); // getStringFromCharArray( FMUWorkingFolderCharArr );
     923              : 
     924              :         // Get and store the names of all FMUs in EnergyPlus data structure
     925            3 :         strippedFileName.allocate(state.dataExternalInterface->NumFMUObjects);
     926            3 :         fullFileName.allocate(state.dataExternalInterface->NumFMUObjects);
     927              : 
     928            3 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
     929            3 :         cCurrentModuleObject = "ExternalInterface:FunctionalMockupUnitImport";
     930            3 :         int NumAlphas = 0;  // Number of Alphas for each GetObjectItem call
     931            3 :         int NumNumbers = 0; // Number of Numbers for each GetObjectItem call
     932            3 :         int IOStatus = 0;   // Used in GetObjectItem
     933            6 :         for (int Loop = 1; Loop <= state.dataExternalInterface->NumFMUObjects; ++Loop) {
     934            9 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     935              :                                                                      cCurrentModuleObject,
     936              :                                                                      Loop,
     937            3 :                                                                      state.dataIPShortCut->cAlphaArgs,
     938              :                                                                      NumAlphas,
     939            3 :                                                                      state.dataIPShortCut->rNumericArgs,
     940              :                                                                      NumNumbers,
     941              :                                                                      IOStatus,
     942              :                                                                      _,
     943              :                                                                      _,
     944            3 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     945            3 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     946              :             // Get the FMU name
     947            3 :             state.dataExternalInterface->FMU(Loop).Name = state.dataIPShortCut->cAlphaArgs(1);
     948              : 
     949            3 :             fs::path inputPath = FileSystem::makeNativePath(state.dataExternalInterface->FMU(Loop).Name);
     950              : 
     951            3 :             std::string contextString = cCurrentModuleObject + ", " + state.dataIPShortCut->cAlphaFieldNames(1) + ": ";
     952              : 
     953            3 :             tempFullFilePath = DataSystemVariables::CheckForActualFilePath(state, inputPath, contextString);
     954            3 :             if (!tempFullFilePath.empty()) {
     955              : 
     956              :                 // TODO: eliminate this old block once confident
     957            3 :                 std::string::size_type pos = index(state.dataExternalInterface->FMU(Loop).Name, DataStringGlobals::pathChar, true); // look backwards
     958            3 :                 if (pos != std::string::npos) {
     959            0 :                     strippedFileName(Loop) = state.dataExternalInterface->FMU(Loop).Name.substr(pos + 1);
     960              :                 } else { // pos == 0, look for alt path char
     961            3 :                     pos = index(state.dataExternalInterface->FMU(Loop).Name, DataStringGlobals::altpathChar, true); // look backwards
     962            3 :                     if (pos != std::string::npos) {
     963            3 :                         strippedFileName(Loop) = state.dataExternalInterface->FMU(Loop).Name.substr(pos + 1);
     964              :                     } else {
     965            0 :                         strippedFileName(Loop) = state.dataExternalInterface->FMU(Loop).Name;
     966              :                     }
     967              :                 }
     968            3 :                 fullFileName(Loop) = FileSystem::toString(tempFullFilePath);
     969              :             } else {
     970            0 :                 state.dataExternalInterface->ErrorsFound = true;
     971              :             }
     972              :             // Get fmu time out
     973            3 :             state.dataExternalInterface->FMU(Loop).TimeOut = state.dataIPShortCut->rNumericArgs(1);
     974              :             // Get fmu logging on
     975            3 :             state.dataExternalInterface->FMU(Loop).LoggingOn = state.dataIPShortCut->rNumericArgs(2);
     976            3 :         }
     977              : 
     978              :         // check for dups that aren't the same file
     979              :         // this is windows code...
     980              :         // So this check that if I entered two different things and get the same end filename, then it's wrong?
     981            6 :         for (int j = 1; j <= state.dataExternalInterface->NumFMUObjects; ++j) {
     982            3 :             for (int k = 2; k <= state.dataExternalInterface->NumFMUObjects; ++k) {
     983            0 :                 if (!Util::SameString(strippedFileName(j), strippedFileName(k))) {
     984            0 :                     continue;
     985              :                 }
     986              :                 // base file names are the same
     987            0 :                 if (Util::SameString(fullFileName(j), fullFileName(k))) {
     988            0 :                     continue;
     989              :                 }
     990            0 :                 ShowSevereError(state, "ExternalInterface/InitExternalInterfaceFMUImport:");
     991            0 :                 ShowContinueError(state, "duplicate file names (but not same file) entered.");
     992            0 :                 ShowContinueError(state, format("...entered file name=\"{}\"", state.dataExternalInterface->FMU(j).Name));
     993            0 :                 ShowContinueError(state, format("...   full file name=\"{}\"", fullFileName(j)));
     994            0 :                 ShowContinueError(state, format("...entered file name=\"{}\"", state.dataExternalInterface->FMU(k).Name));
     995            0 :                 ShowContinueError(state, format("...   full file name=\"{}\"", fullFileName(k)));
     996            0 :                 ShowContinueError(state, "...name collision but not same file name.");
     997            0 :                 state.dataExternalInterface->ErrorsFound = true;
     998              :             }
     999              :         }
    1000              : 
    1001            3 :         if (state.dataExternalInterface->ErrorsFound) {
    1002            0 :             strippedFileName.deallocate();
    1003            0 :             fullFileName.deallocate();
    1004            0 :             StopExternalInterfaceIfError(state);
    1005              :         }
    1006              : 
    1007              :         // get the names of the input variables each state.dataExternalInterface->FMU(and the names of the
    1008              :         // corresponding output variables in EnergyPlus --).
    1009            3 :         cCurrentModuleObject = "ExternalInterface:FunctionalMockupUnitImport:From:Variable";
    1010            3 :         int NumFMUInputVariables = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    1011              :         // Determine the number of instances for each FMUs
    1012            6 :         for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1013            3 :             auto &fmu = state.dataExternalInterface->FMU(i);
    1014              : 
    1015            3 :             std::string Name_OLD = "";
    1016            3 :             int j = 1;
    1017            3 :             int k = 1;
    1018            3 :             fmu.Instance.allocate(NumFMUInputVariables);
    1019            3 :             state.dataExternalInterface->checkInstanceName.allocate(NumFMUInputVariables);
    1020           11 :             for (int l = 1; l <= NumFMUInputVariables; ++l) {
    1021           24 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1022              :                                                                          cCurrentModuleObject,
    1023              :                                                                          l,
    1024            8 :                                                                          state.dataIPShortCut->cAlphaArgs,
    1025              :                                                                          NumAlphas,
    1026            8 :                                                                          state.dataIPShortCut->rNumericArgs,
    1027              :                                                                          NumNumbers,
    1028              :                                                                          IOStatus,
    1029              :                                                                          _,
    1030              :                                                                          _,
    1031            8 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    1032            8 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    1033            8 :                 if (Util::SameString(state.dataIPShortCut->cAlphaArgs(3), fmu.Name)) {
    1034            8 :                     std::string Name_NEW = state.dataIPShortCut->cAlphaArgs(4);
    1035            8 :                     if (!Util::SameString(Name_OLD, Name_NEW)) {
    1036            3 :                         int FOUND = Util::FindItem(Name_NEW, state.dataExternalInterface->checkInstanceName);
    1037            3 :                         if (FOUND == 0) {
    1038            3 :                             state.dataExternalInterface->checkInstanceName(l).Name = Name_NEW;
    1039            3 :                             fmu.NumInstances = j;
    1040            3 :                             fmu.Instance(j).Name = Name_NEW;
    1041            3 :                             ++j;
    1042            3 :                             Name_OLD = Name_NEW;
    1043              :                         }
    1044              :                     }
    1045            8 :                     fmu.TotNumInputVariablesInIDF = k;
    1046            8 :                     ++k;
    1047            8 :                 }
    1048              :             }
    1049            3 :             state.dataExternalInterface->checkInstanceName.deallocate();
    1050            3 :         }
    1051              : 
    1052            6 :         for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1053            3 :             auto &fmu = state.dataExternalInterface->FMU(i);
    1054            3 :             if (fmu.NumInstances == 0) {
    1055            0 :                 ShowSevereError(state, format("ExternalInterface/InitExternalInterfaceFMUImport: The FMU \"{}\" does", fmu.Name));
    1056            0 :                 ShowContinueError(state, "not have any instances or any input variable. An FMU should have at least one instance");
    1057            0 :                 ShowContinueError(state, "or one input variable defined in input file. Check FMU object in the input file.");
    1058            0 :                 state.dataExternalInterface->ErrorsFound = true;
    1059            0 :                 StopExternalInterfaceIfError(state);
    1060              :             }
    1061            3 :             if (NumFMUInputVariables > 0 && fmu.TotNumInputVariablesInIDF == 0) {
    1062            0 :                 ShowWarningError(state, format("InitExternalInterfaceFMUImport: The FMU \"{}\"", fmu.Name));
    1063            0 :                 ShowContinueError(state, "is defined but has no input variables.");
    1064            0 :                 ShowContinueError(state, "Check the input field of the corresponding object");
    1065            0 :                 ShowContinueError(state, "ExternalInterface:FunctionalMockupUnitImport:From:Variable.");
    1066              :             }
    1067              :         }
    1068              : 
    1069              :         // write output folder where FMUs will be unpacked later on.
    1070            6 :         for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1071            3 :             auto &fmu = state.dataExternalInterface->FMU(i);
    1072            6 :             for (int j = 1; j <= fmu.NumInstances; ++j) {
    1073            3 :                 auto &fmuInst = fmu.Instance(j);
    1074            3 :                 fmuInst.WorkingFolder = state.dataExternalInterface->FMURootWorkingFolder / fs::path(strippedFileName(i) + '_' + fmuInst.Name);
    1075              :             }
    1076              :         }
    1077              : 
    1078              :         // parse the fmu defined in the idf using the fmuUnpack.
    1079            6 :         for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1080            3 :             auto &fmu = state.dataExternalInterface->FMU(i);
    1081            6 :             for (int j = 1; j <= fmu.NumInstances; ++j) {
    1082            3 :                 auto &fmuInst = fmu.Instance(j);
    1083              :                 // get the length of working folder trimmed
    1084            3 :                 std::string const workingFolderStr = FileSystem::toString(fmuInst.WorkingFolder);
    1085            3 :                 fmuInst.LenWorkingFolder = workingFolderStr.length();
    1086              :                 // unpack fmus
    1087              :                 // preprocess arguments for library call
    1088              :                 {
    1089            3 :                     std::vector<char> fullFileNameArr(getCharArrayFromString(fullFileName(i)));
    1090            3 :                     std::vector<char> workingFolderArr(getCharArrayFromString(workingFolderStr));
    1091            3 :                     int lenFileName(len(fullFileName(i)));
    1092              : 
    1093              :                     // make the library call
    1094            3 :                     int retVal = fmiEPlusUnpack(&fullFileNameArr[0], &workingFolderArr[0], &lenFileName, &fmuInst.LenWorkingFolder);
    1095              : 
    1096            3 :                     if (retVal != 0) {
    1097            0 :                         ShowSevereError(state, "ExternalInterface/InitExternalInterfaceFMUImport: Error when trying to");
    1098            0 :                         ShowContinueError(state, format("unpack the FMU \"{}\".", fmu.Name));
    1099            0 :                         ShowContinueError(state, "Check if the FMU exists. Also check if the FMU folder is not write protected.");
    1100            0 :                         state.dataExternalInterface->ErrorsFound = true;
    1101            0 :                         StopExternalInterfaceIfError(state);
    1102              :                     }
    1103            3 :                 }
    1104              : 
    1105              :                 {
    1106              :                     // determine modelID and modelGUID of all FMU instances
    1107              :                     // preprocess arguments for library call
    1108            3 :                     std::vector<char> workingFolderArr(getCharArrayFromString(workingFolderStr));
    1109              : 
    1110              :                     // make the library call
    1111            3 :                     fmuInst.Index = model_ID_GUID((char *)fmuInst.Name.c_str(),
    1112            3 :                                                   &workingFolderArr[0],
    1113              :                                                   &fmuInst.LenWorkingFolder,
    1114              :                                                   &fmuInst.NumInputVariablesInFMU,
    1115              :                                                   &fmuInst.NumOutputVariablesInFMU);
    1116              : 
    1117            3 :                     if (fmuInst.Index < 0) {
    1118            0 :                         ShowSevereError(state, "ExternalInterface/InitExternalInterfaceFMUImport: Error when trying to");
    1119            0 :                         ShowContinueError(state, "get the model ID and model GUID");
    1120            0 :                         ShowContinueError(state, format("of instance \"{}\" of FMU \"{}\".", fmuInst.Name, fmu.Name));
    1121            0 :                         ShowContinueError(state, "Check if modelDescription.xml exists in the folder where the FMU has been unpacked.");
    1122            0 :                         state.dataExternalInterface->ErrorsFound = true;
    1123            0 :                         StopExternalInterfaceIfError(state);
    1124              :                     }
    1125            3 :                 }
    1126              : 
    1127              :                 {
    1128              :                     // get the path to the binaries
    1129              :                     // preprocess args for library call
    1130            3 :                     std::vector<char> workingFolderArr(getCharArrayFromString(workingFolderStr));
    1131              :                     // Reserve some space in the string, becasue addLibPathCurrentWorkflowFolder doesn't allocate memory for the
    1132              :                     // workingFolderWithLibArr Note: you can't call str.resize(str.length() + 91) because the conversion to std::vector<char> will
    1133              :                     // find the null terminator and so it will have no effect
    1134              :                     std::string reservedString =
    1135            3 :                         workingFolderStr + "                                                                                           ";
    1136            3 :                     std::vector<char> workingFolderWithLibArr(getCharArrayFromString(reservedString));
    1137              : 
    1138              :                     // make the library call
    1139              :                     int retValfmiPathLib =
    1140            3 :                         addLibPathCurrentWorkingFolder(&workingFolderWithLibArr[0], &workingFolderArr[0], &fmuInst.LenWorkingFolder, &fmuInst.Index);
    1141              : 
    1142              :                     // post process args in case they are used later
    1143            3 :                     fmuInst.WorkingFolder_wLib = fs::path(trim(getStringFromCharArray(workingFolderWithLibArr)));
    1144              : 
    1145            3 :                     if (retValfmiPathLib != 0) {
    1146            0 :                         ShowSevereError(state, "ExternalInterface/InitExternalInterfaceFMUImport: Error when trying to");
    1147            0 :                         ShowContinueError(state, "get the path to the binaries of instance");
    1148            0 :                         ShowContinueError(state, format("\"{}\" of FMU \"{}\".", fmuInst.Name, fmu.Name));
    1149            0 :                         ShowContinueError(state, "Check if binaries folder exists where the FMU has been unpacked.");
    1150            0 :                         state.dataExternalInterface->ErrorsFound = true;
    1151            0 :                         StopExternalInterfaceIfError(state);
    1152              :                     }
    1153              : 
    1154              :                     // get the length of the working folder with libraries
    1155            3 :                     fmuInst.LenWorkingFolder_wLib = FileSystem::toString(fmuInst.WorkingFolder_wLib).length();
    1156            3 :                 }
    1157              : 
    1158              :                 {
    1159              :                     // determine the FMI version
    1160              :                     // preprocess args for library call
    1161            3 :                     std::vector<char> workingFolderWithLibArr(getCharArrayFromString(FileSystem::toString(fmuInst.WorkingFolder_wLib)));
    1162              :                     std::vector<char> VersionNumArr(
    1163            3 :                         getCharArrayFromString("    ")); // the version should only be 3 characters long, since for now we only handle "1.0"
    1164              : 
    1165              :                     // make the library call
    1166              :                     int retValfmiVersion =
    1167            3 :                         getfmiEPlusVersion(&workingFolderWithLibArr[0], &fmuInst.LenWorkingFolder_wLib, &VersionNumArr[0], &fmuInst.Index);
    1168              : 
    1169              :                     // post process in case args are used later
    1170            3 :                     fmuInst.fmiVersionNumber = getStringFromCharArray(VersionNumArr);
    1171              : 
    1172            3 :                     if (retValfmiVersion != 0) {
    1173            0 :                         ShowSevereError(state, "ExternalInterface/InitExternalInterfaceFMUImport: Error when trying to");
    1174            0 :                         ShowContinueError(state, "load FMI functions library of instance");
    1175            0 :                         ShowContinueError(state, format("\"{}\" of FMU \"{}\".", fmuInst.Name, fmu.Name));
    1176            0 :                         ShowContinueError(state, format("\"{}\".", fmuInst.fmiVersionNumber));
    1177            0 :                         state.dataExternalInterface->ErrorsFound = true;
    1178            0 :                         StopExternalInterfaceIfError(state);
    1179              :                     }
    1180              : 
    1181            3 :                     if (fmuInst.fmiVersionNumber.substr(0, 3) != "1.0") {
    1182            0 :                         ShowSevereError(state, "ExternalInterface/InitExternalInterfaceFMUImport: Error when getting version");
    1183            0 :                         ShowContinueError(state, format("number of instance \"{}\"", fmuInst.Name));
    1184            0 :                         ShowContinueError(state, format("of FMU \"{}\".", fmu.Name));
    1185            0 :                         ShowContinueError(state, format("The version number found (\"{}\")", fmuInst.fmiVersionNumber.substr(0, 3)));
    1186            0 :                         ShowContinueError(state, "differs from version 1.0 which is currently supported.");
    1187            0 :                         state.dataExternalInterface->ErrorsFound = true;
    1188            0 :                         StopExternalInterfaceIfError(state);
    1189              :                     }
    1190            3 :                 }
    1191            3 :             }
    1192              :         }
    1193              : 
    1194            3 :         strippedFileName.deallocate();
    1195            3 :         fullFileName.deallocate();
    1196              : 
    1197            3 :         state.dataExternalInterface->UniqueFMUInputVarNames.reserve(static_cast<unsigned>(NumFMUInputVariables));
    1198            6 :         for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1199            3 :             auto &fmu = state.dataExternalInterface->FMU(i);
    1200            6 :             for (int j = 1; j <= fmu.NumInstances; ++j) {
    1201            3 :                 auto &fmuInst = fmu.Instance(j);
    1202            3 :                 fmuInst.fmuInputVariable.allocate(NumFMUInputVariables);
    1203            3 :                 fmuInst.checkfmuInputVariable.allocate(NumFMUInputVariables);
    1204            3 :                 state.dataExternalInterface->UniqueFMUInputVarNames.clear();
    1205            3 :                 fmuInst.eplusOutputVariable.allocate(NumFMUInputVariables);
    1206            3 :                 int k = 1;
    1207           11 :                 for (int l = 1; l <= NumFMUInputVariables; ++l) {
    1208           24 :                     state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1209              :                                                                              cCurrentModuleObject,
    1210              :                                                                              l,
    1211            8 :                                                                              state.dataIPShortCut->cAlphaArgs,
    1212              :                                                                              NumAlphas,
    1213            8 :                                                                              state.dataIPShortCut->rNumericArgs,
    1214              :                                                                              NumNumbers,
    1215              :                                                                              IOStatus,
    1216              :                                                                              _,
    1217              :                                                                              _,
    1218            8 :                                                                              state.dataIPShortCut->cAlphaFieldNames,
    1219            8 :                                                                              state.dataIPShortCut->cNumericFieldNames);
    1220           16 :                     if (Util::SameString(state.dataIPShortCut->cAlphaArgs(3), fmu.Name) &&
    1221            8 :                         Util::SameString(state.dataIPShortCut->cAlphaArgs(4), fmuInst.Name)) {
    1222            8 :                         fmuInst.fmuInputVariable(k).Name = state.dataIPShortCut->cAlphaArgs(5);
    1223            8 :                         fmuInst.eplusOutputVariable(k).VarKey = state.dataIPShortCut->cAlphaArgs(1);
    1224            8 :                         fmuInst.eplusOutputVariable(k).Name = state.dataIPShortCut->cAlphaArgs(2);
    1225              :                         // verify whether we have duplicate FMU input variables in the idf
    1226            8 :                         GlobalNames::VerifyUniqueInterObjectName(state,
    1227            8 :                                                                  state.dataExternalInterface->UniqueFMUInputVarNames,
    1228            8 :                                                                  fmuInst.fmuInputVariable(k).Name,
    1229              :                                                                  cCurrentModuleObject,
    1230              :                                                                  fmuInst.Name,
    1231            8 :                                                                  state.dataExternalInterface->ErrorsFound);
    1232              :                         //                            Util::VerifyName( state.dataExternalInterface->FMU( i ).Instance( j
    1233              :                         //                            ).fmuInputVariable(
    1234              :                         // k
    1235              :                         //).Name,  state.dataExternalInterface->FMU(
    1236              :                         // i
    1237              :                         //).Instance(
    1238              :                         // j
    1239              :                         //).checkfmuInputVariable, NumFMUInputVariables, IsNotOK, IsBlank, "The FMU input variable \"" +
    1240              :                         // state.dataExternalInterface->FMU( i ).Instance( j
    1241              :                         //).fmuInputVariable( k ).Name + "\" of instance \"" + state.dataExternalInterface->FMU( i ).Instance( j ).Name + "\" of FMU
    1242              :                         //\"" + state.dataExternalInterface->FMU( i ).Name + "\"
    1243              :                         // has duplicates. Please check the input file again and delete duplicated entries." );
    1244            8 :                         if (state.dataExternalInterface->ErrorsFound) {
    1245            0 :                             StopExternalInterfaceIfError(state);
    1246              :                         } else {
    1247            8 :                             fmuInst.checkfmuInputVariable(k).Name = fmuInst.fmuInputVariable(k).Name;
    1248              :                         }
    1249              : 
    1250              :                         // preprocess args for library call
    1251            8 :                         std::vector<char> inputVarNameArr(getCharArrayFromString(fmuInst.fmuInputVariable(k).Name));
    1252            8 :                         int inputVarNameLen(len(fmuInst.fmuInputVariable(k).Name));
    1253              : 
    1254              :                         // make the library call
    1255           16 :                         fmuInst.fmuInputVariable(k).ValueReference =
    1256            8 :                             getValueReferenceByNameFMUInputVariables(&inputVarNameArr[0], &inputVarNameLen, &fmuInst.Index);
    1257              : 
    1258              :                         // postprocess args in case they are used later
    1259            8 :                         fmuInst.fmuInputVariable(k).Name = getStringFromCharArray(inputVarNameArr);
    1260              : 
    1261            8 :                         if (fmuInst.fmuInputVariable(k).ValueReference == -999) {
    1262            0 :                             ShowSevereError(state, "ExternalInterface/InitExternalInterfaceFMUImport: Error when trying to");
    1263            0 :                             ShowContinueError(state, "get the value reference of FMU input variable");
    1264            0 :                             ShowContinueError(state, format("\"{}\" of instance \"{}\" of FMU", fmuInst.fmuInputVariable(k).Name, fmuInst.Name));
    1265            0 :                             ShowContinueError(state, format("of FMU \"{}\". Please check the name of input variable", fmu.Name));
    1266            0 :                             ShowContinueError(state, "in the input file and in the modelDescription file.");
    1267            0 :                             state.dataExternalInterface->ErrorsFound = true;
    1268            0 :                             StopExternalInterfaceIfError(state);
    1269              :                         }
    1270              : 
    1271            8 :                         if (fmuInst.fmuInputVariable(k).ValueReference == -1) {
    1272            0 :                             ShowSevereError(state, "ExternalInterface/InitExternalInterfaceFMUImport: Error when trying to");
    1273            0 :                             ShowContinueError(state, "get the value reference of FMU input variable");
    1274            0 :                             ShowContinueError(state, format("\"{}\" of instance \"{}\" of FMU", fmuInst.fmuInputVariable(k).Name, fmuInst.Name));
    1275            0 :                             ShowContinueError(state, format("\"{}\". This variable is not an FMU input variable.", fmu.Name));
    1276            0 :                             ShowContinueError(state, "Please check the causality of the variable in the modelDescription file.");
    1277            0 :                             state.dataExternalInterface->ErrorsFound = true;
    1278            0 :                             StopExternalInterfaceIfError(state);
    1279              :                         }
    1280              : 
    1281              :                         // The next call expects an array, but a single item is passed
    1282              :                         // Therefore create a single item array here first
    1283            8 :                         Array1D_string tempSingleStringA(1, fmuInst.eplusOutputVariable(k).VarKey);
    1284            8 :                         Array1D_string tempSingleStringB(1, fmuInst.eplusOutputVariable(k).Name);
    1285              : 
    1286              :                         // Make the call with arrays
    1287            8 :                         GetReportVariableKey(state, tempSingleStringA, 1, tempSingleStringB, keyIndexes, varTypes);
    1288              : 
    1289              :                         // Then postprocess the array items back in case they changed
    1290            8 :                         fmuInst.eplusOutputVariable(k).VarKey = tempSingleStringA(1);
    1291            8 :                         fmuInst.eplusOutputVariable(k).Name = tempSingleStringB(1);
    1292              : 
    1293            8 :                         fmuInst.eplusOutputVariable(k).VarIndex = keyIndexes(1);
    1294            8 :                         fmuInst.eplusOutputVariable(k).VarType = varTypes(1);
    1295            8 :                         fmuInst.NumInputVariablesInIDF = k;
    1296            8 :                         ++k;
    1297            8 :                     }
    1298              :                 }
    1299              : 
    1300            3 :                 if (NumFMUInputVariables > 0 && fmuInst.NumInputVariablesInIDF == 0) {
    1301            0 :                     ShowWarningError(state, format("InitExternalInterfaceFMUImport: The instance \"{}\" of FMU \"{}\"", fmuInst.Name, fmu.Name));
    1302            0 :                     ShowContinueError(state, "is defined but has no input variables. Check the input field of the");
    1303            0 :                     ShowContinueError(state, "corresponding object: ExternalInterface:FunctionalMockupUnitImport:From:Variable.");
    1304              :                 }
    1305              :             }
    1306              :         }
    1307              : 
    1308            6 :         for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1309            3 :             auto &fmu = state.dataExternalInterface->FMU(i);
    1310            6 :             for (int j = 1; j <= fmu.NumInstances; ++j) {
    1311            3 :                 auto &fmuInst = fmu.Instance(j);
    1312              :                 // check whether the number of input variables in fmu is bigger than in the idf
    1313            3 :                 if (fmuInst.NumInputVariablesInFMU > fmuInst.NumInputVariablesInIDF) {
    1314            0 :                     ShowWarningError(state,
    1315            0 :                                      format("InitExternalInterfaceFMUImport: The number of input variables defined in input file ({})",
    1316            0 :                                             fmuInst.NumInputVariablesInIDF));
    1317            0 :                     ShowContinueError(state,
    1318            0 :                                       format("of instance \"{}\" of FMU \"{}\" is less than the number of input variables", fmuInst.Name, fmu.Name));
    1319            0 :                     ShowContinueError(state, format("in the modelDescription file ({}).", fmuInst.NumInputVariablesInFMU));
    1320            0 :                     ShowContinueError(state, "Check the input file and the modelDescription file again.");
    1321              :                 }
    1322              :                 // check whether the number of input variables in fmu is less than in the idf
    1323            3 :                 if (fmuInst.NumInputVariablesInFMU < fmuInst.NumInputVariablesInIDF) {
    1324            0 :                     ShowWarningError(state,
    1325            0 :                                      format("InitExternalInterfaceFMUImport: The number of input variables defined in input file ({})",
    1326            0 :                                             fmuInst.NumInputVariablesInIDF));
    1327            0 :                     ShowContinueError(
    1328            0 :                         state, format("of instance \"{}\" of FMU \"{}\" is bigger than the number of input variables", fmuInst.Name, fmu.Name));
    1329            0 :                     ShowContinueError(state, format("in the modelDescription file ({}).", fmuInst.NumInputVariablesInFMU));
    1330            0 :                     ShowContinueError(state, "Check the input file and the modelDescription file again.");
    1331              :                 }
    1332              :             }
    1333              :         }
    1334              : 
    1335              :         // get the names of the output variables each fmu (and the names of the
    1336              :         // corresponding input variables in EnergyPlus -- schedule).
    1337            3 :         cCurrentModuleObject = "ExternalInterface:FunctionalMockupUnitImport:To:Schedule";
    1338            3 :         NumFMUInputVariables = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    1339              : 
    1340            6 :         for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1341            3 :             auto &fmu = state.dataExternalInterface->FMU(i);
    1342            3 :             int j = 1;
    1343            5 :             for (int k = 1; k <= NumFMUInputVariables; ++k) {
    1344            6 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1345              :                                                                          cCurrentModuleObject,
    1346              :                                                                          k,
    1347            2 :                                                                          state.dataIPShortCut->cAlphaArgs,
    1348              :                                                                          NumAlphas,
    1349            2 :                                                                          state.dataIPShortCut->rNumericArgs,
    1350              :                                                                          NumNumbers,
    1351              :                                                                          IOStatus,
    1352              :                                                                          _,
    1353              :                                                                          _,
    1354            2 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    1355            2 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    1356            2 :                 if (Util::SameString(state.dataIPShortCut->cAlphaArgs(3), fmu.Name)) {
    1357            2 :                     fmu.TotNumOutputVariablesSchedule = j;
    1358            2 :                     ++j;
    1359              :                 }
    1360              :             }
    1361              :         }
    1362              : 
    1363            6 :         for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1364            3 :             auto &fmu = state.dataExternalInterface->FMU(i);
    1365            6 :             for (int j = 1; j <= fmu.NumInstances; ++j) {
    1366            3 :                 auto &fmuInst = fmu.Instance(j);
    1367            3 :                 fmuInst.fmuOutputVariableSchedule.allocate(NumFMUInputVariables);
    1368            3 :                 fmuInst.eplusInputVariableSchedule.allocate(NumFMUInputVariables);
    1369            3 :                 int k = 1;
    1370            5 :                 for (int l = 1; l <= NumFMUInputVariables; ++l) {
    1371            6 :                     state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1372              :                                                                              cCurrentModuleObject,
    1373              :                                                                              l,
    1374            2 :                                                                              state.dataIPShortCut->cAlphaArgs,
    1375              :                                                                              NumAlphas,
    1376            2 :                                                                              state.dataIPShortCut->rNumericArgs,
    1377              :                                                                              NumNumbers,
    1378              :                                                                              IOStatus,
    1379              :                                                                              _,
    1380              :                                                                              _,
    1381            2 :                                                                              state.dataIPShortCut->cAlphaFieldNames,
    1382            2 :                                                                              state.dataIPShortCut->cNumericFieldNames);
    1383            4 :                     if (Util::SameString(state.dataIPShortCut->cAlphaArgs(3), fmu.Name) &&
    1384            2 :                         Util::SameString(state.dataIPShortCut->cAlphaArgs(4), fmuInst.Name)) {
    1385            2 :                         fmuInst.fmuOutputVariableSchedule(k).Name = state.dataIPShortCut->cAlphaArgs(5);
    1386            2 :                         fmuInst.eplusInputVariableSchedule(k).Name = state.dataIPShortCut->cAlphaArgs(1);
    1387            2 :                         fmuInst.eplusInputVariableSchedule(k).InitialValue = state.dataIPShortCut->rNumericArgs(1);
    1388              : 
    1389              :                         // get the value reference by using the FMU name and the variable name.
    1390              : 
    1391              :                         // preprocess the arguments before the following library call
    1392            2 :                         std::vector<char> NameCharArr(getCharArrayFromString(fmuInst.fmuOutputVariableSchedule(k).Name));
    1393            2 :                         int lengthVar(len(fmuInst.fmuOutputVariableSchedule(k).Name));
    1394              : 
    1395              :                         // make the library call
    1396            4 :                         fmuInst.fmuOutputVariableSchedule(k).ValueReference =
    1397            2 :                             getValueReferenceByNameFMUOutputVariables(&NameCharArr[0], &lengthVar, &fmuInst.Index);
    1398              : 
    1399              :                         // postprocess the arguments after the library call in case they are changed and used later
    1400            2 :                         fmuInst.fmuOutputVariableSchedule(k).Name = getStringFromCharArray(NameCharArr);
    1401              : 
    1402            2 :                         if (fmuInst.fmuOutputVariableSchedule(k).ValueReference == -999) {
    1403            0 :                             ShowSevereError(state,
    1404              :                                             "ExternalInterface/InitExternalInterfaceFMUImport: Error when trying to get the value reference of "
    1405              :                                             "the FMU output variable");
    1406            0 :                             ShowContinueError(state, format("\"{}\" of instance \"{}\"", fmuInst.fmuOutputVariableSchedule(k).Name, fmuInst.Name));
    1407            0 :                             ShowContinueError(state, format("of FMU \"{}\" that will be mapped to a schedule.", fmu.Name));
    1408            0 :                             ShowContinueError(state, "Please check the name of output variables in the input file and");
    1409            0 :                             ShowContinueError(state, "in the modelDescription file.");
    1410            0 :                             state.dataExternalInterface->ErrorsFound = true;
    1411            0 :                             StopExternalInterfaceIfError(state);
    1412              :                         }
    1413              : 
    1414            2 :                         if (fmuInst.fmuOutputVariableSchedule(k).ValueReference == -1) {
    1415            0 :                             ShowSevereError(state,
    1416              :                                             "ExternalInterface/InitExternalInterfaceFMUImport: Error when trying to get the value reference of "
    1417              :                                             "the FMU output variable");
    1418            0 :                             ShowContinueError(state, format("\"{}\" of instance \"{}\"", fmuInst.fmuOutputVariableSchedule(k).Name, fmuInst.Name));
    1419            0 :                             ShowContinueError(state, format("of FMU \"{}\" that will be mapped to a schedule.", fmu.Name));
    1420            0 :                             ShowContinueError(state, "This variable is not an FMU output variable.");
    1421            0 :                             ShowContinueError(state, "Please check the causality of the variable in the modelDescription file.");
    1422            0 :                             state.dataExternalInterface->ErrorsFound = true;
    1423            0 :                             StopExternalInterfaceIfError(state);
    1424              :                         }
    1425              : 
    1426            2 :                         fmuInst.eplusInputVariableSchedule(k).VarIndex = Sched::GetScheduleNum(state, fmuInst.eplusInputVariableSchedule(k).Name);
    1427            2 :                         fmuInst.NumOutputVariablesSchedule = k;
    1428            2 :                         if (fmuInst.eplusInputVariableSchedule(k).VarIndex <= 0) {
    1429            0 :                             ShowSevereError(state,
    1430            0 :                                             format("ExternalInterface/InitExternalInterfaceFMUImport:declares variable \"{}\",",
    1431            0 :                                                    fmuInst.eplusInputVariableSchedule(k).Name));
    1432            0 :                             ShowContinueError(state, "but variable is not a schedule variable.");
    1433            0 :                             state.dataExternalInterface->ErrorsFound = true;
    1434            0 :                             StopExternalInterfaceIfError(state);
    1435              :                         }
    1436            2 :                         ++k;
    1437            2 :                     }
    1438              :                 }
    1439              :             }
    1440              :         }
    1441              : 
    1442              :         // get the names of the output variables each fmu (and the names of the
    1443              :         // corresponding input variables in EnergyPlus -- variable).
    1444            3 :         cCurrentModuleObject = "ExternalInterface:FunctionalMockupUnitImport:To:Variable";
    1445            3 :         NumFMUInputVariables = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    1446              : 
    1447            6 :         for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1448            3 :             auto &fmu = state.dataExternalInterface->FMU(i);
    1449            3 :             int j = 1;
    1450            4 :             for (int k = 1; k <= NumFMUInputVariables; ++k) {
    1451            3 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1452              :                                                                          cCurrentModuleObject,
    1453              :                                                                          k,
    1454            1 :                                                                          state.dataIPShortCut->cAlphaArgs,
    1455              :                                                                          NumAlphas,
    1456            1 :                                                                          state.dataIPShortCut->rNumericArgs,
    1457              :                                                                          NumNumbers,
    1458              :                                                                          IOStatus,
    1459              :                                                                          _,
    1460              :                                                                          _,
    1461            1 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    1462            1 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    1463            1 :                 if (Util::SameString(state.dataIPShortCut->cAlphaArgs(2), fmu.Name)) {
    1464            1 :                     fmu.TotNumOutputVariablesVariable = j;
    1465            1 :                     ++j;
    1466              :                 }
    1467              :             }
    1468              :         }
    1469              : 
    1470            6 :         for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1471            3 :             auto &fmu = state.dataExternalInterface->FMU(i);
    1472            6 :             for (int j = 1; j <= fmu.NumInstances; ++j) {
    1473            3 :                 auto &fmuInst = fmu.Instance(j);
    1474            3 :                 fmuInst.fmuOutputVariableVariable.allocate(NumFMUInputVariables);
    1475            3 :                 fmuInst.eplusInputVariableVariable.allocate(NumFMUInputVariables);
    1476            3 :                 int k = 1;
    1477            4 :                 for (int l = 1; l <= NumFMUInputVariables; ++l) {
    1478            3 :                     state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1479              :                                                                              cCurrentModuleObject,
    1480              :                                                                              l,
    1481            1 :                                                                              state.dataIPShortCut->cAlphaArgs,
    1482              :                                                                              NumAlphas,
    1483            1 :                                                                              state.dataIPShortCut->rNumericArgs,
    1484              :                                                                              NumNumbers,
    1485              :                                                                              IOStatus,
    1486              :                                                                              _,
    1487              :                                                                              _,
    1488            1 :                                                                              state.dataIPShortCut->cAlphaFieldNames,
    1489            1 :                                                                              state.dataIPShortCut->cNumericFieldNames);
    1490            2 :                     if (Util::SameString(state.dataIPShortCut->cAlphaArgs(2), fmu.Name) &&
    1491            1 :                         Util::SameString(state.dataIPShortCut->cAlphaArgs(3), fmuInst.Name)) {
    1492            1 :                         fmuInst.fmuOutputVariableVariable(k).Name = state.dataIPShortCut->cAlphaArgs(4);
    1493            1 :                         fmuInst.eplusInputVariableVariable(k).Name = state.dataIPShortCut->cAlphaArgs(1);
    1494              : 
    1495              :                         // get the value reference by using the FMU name and the variable name.
    1496            1 :                         std::vector<char> NameCharArr(getCharArrayFromString(fmuInst.fmuOutputVariableVariable(k).Name));
    1497            1 :                         int tempLength(len(fmuInst.fmuOutputVariableVariable(k).Name));
    1498            2 :                         fmuInst.fmuOutputVariableVariable(k).ValueReference =
    1499            1 :                             getValueReferenceByNameFMUOutputVariables(&NameCharArr[0], &tempLength, &fmuInst.Index);
    1500              :                         // state.dataExternalInterface->FMU( i ).Instance( j ).fmuOutputVariableVariable( k ).Name = getStringFromCharArray(
    1501              :                         // NameCharArr );
    1502              : 
    1503            1 :                         if (fmuInst.fmuOutputVariableVariable(k).ValueReference == -999) {
    1504            0 :                             ShowSevereError(state,
    1505              :                                             "ExternalInterface/InitExternalInterfaceFMUImport: Error when trying to get the value reference of "
    1506              :                                             "the FMU output variable");
    1507            0 :                             ShowContinueError(state, format("\"{}\" of instance \"{}\"", fmuInst.fmuOutputVariableVariable(k).Name, fmuInst.Name));
    1508            0 :                             ShowContinueError(state, format("of FMU \"{}\" that will be mapped to a variable.", fmu.Name));
    1509            0 :                             ShowContinueError(state, "Please check the name of output variables in the input file and in the modelDescription file.");
    1510            0 :                             state.dataExternalInterface->ErrorsFound = true;
    1511            0 :                             StopExternalInterfaceIfError(state);
    1512              :                         }
    1513              : 
    1514            1 :                         if (fmuInst.fmuOutputVariableVariable(k).ValueReference == -1) {
    1515            0 :                             ShowSevereError(state,
    1516              :                                             "ExternalInterface/InitExternalInterfaceFMUImport: Error when trying to get the value reference of "
    1517              :                                             "the FMU output variable");
    1518            0 :                             ShowContinueError(state, format("\"{}\" of instance \"{}\"", fmuInst.fmuOutputVariableVariable(k).Name, fmuInst.Name));
    1519            0 :                             ShowContinueError(state, format("of FMU \"{}\" that will be mapped to a variable.", fmu.Name));
    1520            0 :                             ShowContinueError(state,
    1521              :                                               "This variable is not an FMU output variable. Please check the causality of the variable in the "
    1522              :                                               "modelDescription file.");
    1523            0 :                             state.dataExternalInterface->ErrorsFound = true;
    1524            0 :                             StopExternalInterfaceIfError(state);
    1525              :                         }
    1526              : 
    1527            2 :                         fmuInst.eplusInputVariableVariable(k).VarIndex =
    1528            1 :                             RuntimeLanguageProcessor::FindEMSVariable(state, fmuInst.eplusInputVariableVariable(k).Name, 0);
    1529            1 :                         fmuInst.NumOutputVariablesVariable = k;
    1530            1 :                         if (fmuInst.eplusInputVariableVariable(k).VarIndex <= 0) {
    1531            0 :                             ShowSevereError(state,
    1532            0 :                                             format("ExternalInterface/InitExternalInterfaceFMUImport:declares variable \"{}\",",
    1533            0 :                                                    fmuInst.eplusInputVariableVariable(k).Name));
    1534            0 :                             ShowContinueError(state, "but variable is not an EMS variable.");
    1535            0 :                             state.dataExternalInterface->ErrorsFound = true;
    1536            0 :                             StopExternalInterfaceIfError(state);
    1537              :                         }
    1538            1 :                         ++k;
    1539            1 :                     }
    1540              :                 }
    1541            3 :                 if (fmuInst.NumOutputVariablesVariable >= 1) {
    1542            1 :                     state.dataExternalInterface->useEMS = true;
    1543              :                 }
    1544              :             }
    1545              :         }
    1546              : 
    1547              :         // get the names of the output variables each fmu (and the names of the
    1548              :         // corresponding input variables in EnergyPlus -- actuator).
    1549            3 :         cCurrentModuleObject = "ExternalInterface:FunctionalMockupUnitImport:To:Actuator";
    1550            3 :         NumFMUInputVariables = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    1551              : 
    1552            6 :         for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1553            3 :             auto &fmu = state.dataExternalInterface->FMU(i);
    1554            3 :             int j = 1;
    1555            4 :             for (int k = 1; k <= NumFMUInputVariables; ++k) {
    1556            3 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1557              :                                                                          cCurrentModuleObject,
    1558              :                                                                          k,
    1559            1 :                                                                          state.dataIPShortCut->cAlphaArgs,
    1560              :                                                                          NumAlphas,
    1561            1 :                                                                          state.dataIPShortCut->rNumericArgs,
    1562              :                                                                          NumNumbers,
    1563              :                                                                          IOStatus,
    1564              :                                                                          _,
    1565              :                                                                          _,
    1566            1 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    1567            1 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    1568            1 :                 if (Util::SameString(state.dataIPShortCut->cAlphaArgs(5), fmu.Name)) {
    1569            1 :                     fmu.TotNumOutputVariablesActuator = j;
    1570            1 :                     ++j;
    1571              :                 }
    1572              :             }
    1573              :         }
    1574              : 
    1575            6 :         for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1576            3 :             auto &fmu = state.dataExternalInterface->FMU(i);
    1577            6 :             for (int j = 1; j <= fmu.NumInstances; ++j) {
    1578            3 :                 auto &fmuInst = fmu.Instance(j);
    1579            3 :                 fmuInst.fmuOutputVariableActuator.allocate(NumFMUInputVariables);
    1580            3 :                 fmuInst.eplusInputVariableActuator.allocate(NumFMUInputVariables);
    1581            3 :                 int k = 1;
    1582            4 :                 for (int l = 1; l <= NumFMUInputVariables; ++l) {
    1583            3 :                     state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1584              :                                                                              cCurrentModuleObject,
    1585              :                                                                              l,
    1586            1 :                                                                              state.dataIPShortCut->cAlphaArgs,
    1587              :                                                                              NumAlphas,
    1588            1 :                                                                              state.dataIPShortCut->rNumericArgs,
    1589              :                                                                              NumNumbers,
    1590              :                                                                              IOStatus,
    1591              :                                                                              _,
    1592              :                                                                              _,
    1593            1 :                                                                              state.dataIPShortCut->cAlphaFieldNames,
    1594            1 :                                                                              state.dataIPShortCut->cNumericFieldNames);
    1595            2 :                     if (Util::SameString(state.dataIPShortCut->cAlphaArgs(5), fmu.Name) &&
    1596            1 :                         Util::SameString(state.dataIPShortCut->cAlphaArgs(6), fmuInst.Name)) {
    1597            1 :                         fmuInst.fmuOutputVariableActuator(k).Name = state.dataIPShortCut->cAlphaArgs(7);
    1598            1 :                         fmuInst.eplusInputVariableActuator(k).Name = state.dataIPShortCut->cAlphaArgs(1);
    1599              : 
    1600              :                         // get the value reference by using the FMU name and the variable name.
    1601            1 :                         std::vector<char> tempNameArr(getCharArrayFromString(fmuInst.fmuOutputVariableActuator(k).Name));
    1602            1 :                         int tempLength(len(fmuInst.fmuOutputVariableActuator(k).Name));
    1603            2 :                         fmuInst.fmuOutputVariableActuator(k).ValueReference =
    1604            1 :                             getValueReferenceByNameFMUOutputVariables(&tempNameArr[0], &tempLength, &fmuInst.Index);
    1605              :                         // state.dataExternalInterface->FMU( i ).Instance( j ).fmuOutputVariableActuator( k ).Name = getStringFromCharArray(
    1606              :                         // tempNameArr );
    1607              : 
    1608            1 :                         if (fmuInst.fmuOutputVariableActuator(k).ValueReference == -999) {
    1609            0 :                             ShowSevereError(state,
    1610              :                                             "ExternalInterface/InitExternalInterfaceFMUImport: Error when trying to get the value reference of "
    1611              :                                             "the FMU output variable");
    1612            0 :                             ShowContinueError(state, format("\"{}\" of instance \"{}\"", fmuInst.fmuOutputVariableActuator(k).Name, fmuInst.Name));
    1613            0 :                             ShowContinueError(state, format("of FMU \"{}\" that will be mapped to an actuator.", fmu.Name));
    1614            0 :                             ShowContinueError(state, "Please check the name of output variables in the input file and in the modelDescription file.");
    1615            0 :                             state.dataExternalInterface->ErrorsFound = true;
    1616            0 :                             StopExternalInterfaceIfError(state);
    1617              :                         }
    1618              : 
    1619            1 :                         if (fmuInst.fmuOutputVariableActuator(k).ValueReference == -1) {
    1620            0 :                             ShowSevereError(state,
    1621              :                                             "ExternalInterface/InitExternalInterfaceFMUImport: Error when trying to get the value reference of "
    1622              :                                             "the FMU output variable");
    1623            0 :                             ShowContinueError(state, format("\"{}\" of instance \"{}\"", fmuInst.fmuOutputVariableActuator(k).Name, fmuInst.Name));
    1624            0 :                             ShowContinueError(state, format("of FMU \"{}\" that will be mapped to an actuator.", fmu.Name));
    1625            0 :                             ShowContinueError(state,
    1626              :                                               "This variable is not an FMU output variable. Please check the causality of the variable in the "
    1627              :                                               "modelDescription file.");
    1628            0 :                             state.dataExternalInterface->ErrorsFound = true;
    1629            0 :                             StopExternalInterfaceIfError(state);
    1630              :                         }
    1631              : 
    1632            2 :                         fmuInst.eplusInputVariableActuator(k).VarIndex =
    1633            1 :                             RuntimeLanguageProcessor::FindEMSVariable(state, fmuInst.eplusInputVariableActuator(k).Name, 0);
    1634            1 :                         fmuInst.NumOutputVariablesActuator = k;
    1635            1 :                         if (fmuInst.eplusInputVariableActuator(k).VarIndex <= 0) {
    1636            0 :                             ShowSevereError(state,
    1637            0 :                                             format("ExternalInterface/InitExternalInterfaceFMUImport:declares variable \"{}\",",
    1638            0 :                                                    fmuInst.eplusInputVariableActuator(k).Name));
    1639            0 :                             ShowContinueError(state, "but variable is not an EMS variable.");
    1640            0 :                             state.dataExternalInterface->ErrorsFound = true;
    1641            0 :                             StopExternalInterfaceIfError(state);
    1642              :                         }
    1643            1 :                         ++k;
    1644            1 :                     }
    1645              :                 }
    1646              :                 // set the flag state.dataExternalInterface->useEMS to true. This will be used then to update the erl variables in erl data structure
    1647            3 :                 if (fmuInst.NumOutputVariablesActuator >= 1) {
    1648            1 :                     state.dataExternalInterface->useEMS = true;
    1649              :                 }
    1650              :             }
    1651              :         }
    1652              : 
    1653              :         // parse the fmu defined in the idf using the fmuUnpack with the flag --unpack.
    1654            6 :         for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1655            3 :             auto &fmu = state.dataExternalInterface->FMU(i);
    1656            6 :             for (int j = 1; j <= fmu.NumInstances; ++j) {
    1657            3 :                 auto &fmuInst = fmu.Instance(j);
    1658            3 :                 fmuInst.NumOutputVariablesInIDF =
    1659            3 :                     fmuInst.NumOutputVariablesSchedule + fmuInst.NumOutputVariablesVariable + fmuInst.NumOutputVariablesActuator;
    1660              :                 // check whether the number of output variables in fmu is bigger than in the idf
    1661            3 :                 if (fmuInst.NumOutputVariablesInFMU > fmuInst.NumOutputVariablesInIDF) {
    1662            0 :                     ShowWarningError(state,
    1663            0 :                                      format("InitExternalInterfaceFMUImport: The number of output variables defined in input file ({})",
    1664            0 :                                             fmuInst.NumOutputVariablesInIDF));
    1665            0 :                     ShowContinueError(state,
    1666            0 :                                       format("of instance \"{}\" of FMU \"{}\" is less than the number of output variables", fmuInst.Name, fmu.Name));
    1667            0 :                     ShowContinueError(state, format("in the modelDescription file ({}).", fmuInst.NumOutputVariablesInFMU));
    1668            0 :                     ShowContinueError(state, "Check the input file and the modelDescription file again.");
    1669              :                 }
    1670              :                 // check whether the number of output variables in fmu is less than in the idf
    1671            3 :                 if (fmuInst.NumOutputVariablesInFMU < fmuInst.NumOutputVariablesInIDF) {
    1672            0 :                     ShowWarningError(state,
    1673            0 :                                      format("InitExternalInterfaceFMUImport: The number of output variables defined in input file ({})",
    1674            0 :                                             fmuInst.NumOutputVariablesInIDF));
    1675            0 :                     ShowContinueError(
    1676            0 :                         state, format("of instance \"{}\" of FMU \"{}\" is bigger than the number of output variables", fmuInst.Name, fmu.Name));
    1677            0 :                     ShowContinueError(state, format("in the modelDescription file ({}).", fmuInst.NumOutputVariablesInFMU));
    1678            0 :                     ShowContinueError(state, "Check the input file and the modelDescription file again.");
    1679              :                 }
    1680              : 
    1681            3 :                 DisplayString(
    1682              :                     state,
    1683            6 :                     format("Number of inputs in instance \"{}\" of FMU \"{}\" = \"{}\".", fmuInst.Name, fmu.Name, fmuInst.NumInputVariablesInIDF));
    1684            3 :                 DisplayString(
    1685              :                     state,
    1686            6 :                     format("Number of outputs in instance \"{}\" of FMU \"{}\" = \"{}\".", fmuInst.Name, fmu.Name, fmuInst.NumOutputVariablesInIDF));
    1687              :             }
    1688              :         }
    1689            3 :         StopExternalInterfaceIfError(state);
    1690            3 :         state.dataExternalInterface->FirstCallIni = false;
    1691              :     }
    1692       143619 : }
    1693              : 
    1694            3 : std::string trim(std::string const &str)
    1695              : {
    1696            3 :     std::size_t first = str.find_first_not_of(' ');
    1697            3 :     std::size_t last = str.find_last_not_of(' ');
    1698            3 :     return str.substr(first, last - first + 1);
    1699              : }
    1700              : 
    1701            6 : Real64 GetCurSimStartTimeSeconds(const EnergyPlusData &state)
    1702              : {
    1703              :     // FUNCTION INFORMATION:
    1704              :     //       AUTHOR         Thierry S. Nouidui, Michael Wetter, Wangda Zuo
    1705              :     //       DATE WRITTEN   August 2011
    1706              : 
    1707              :     // PURPOSE OF THIS FUNCTION:
    1708              :     //  Get the current month and day in the runperiod and convert
    1709              :     //  it into seconds.
    1710              : 
    1711              :     // Locals
    1712              :     Real64 simtime;
    1713              : 
    1714            6 :     if (!state.dataEnvrn->CurrentYearIsLeapYear) {
    1715            6 :         switch (state.dataEnvrn->Month) {
    1716            6 :         case 1:
    1717            6 :             simtime = 0;
    1718            6 :             break;
    1719            0 :         case 2:
    1720            0 :             simtime = 31;
    1721            0 :             break;
    1722            0 :         case 3:
    1723            0 :             simtime = 59;
    1724            0 :             break;
    1725            0 :         case 4:
    1726            0 :             simtime = 90;
    1727            0 :             break;
    1728            0 :         case 5:
    1729            0 :             simtime = 120;
    1730            0 :             break;
    1731            0 :         case 6:
    1732            0 :             simtime = 151;
    1733            0 :             break;
    1734            0 :         case 7:
    1735            0 :             simtime = 181;
    1736            0 :             break;
    1737            0 :         case 8:
    1738            0 :             simtime = 212;
    1739            0 :             break;
    1740            0 :         case 9:
    1741            0 :             simtime = 243;
    1742            0 :             break;
    1743            0 :         case 10:
    1744            0 :             simtime = 273;
    1745            0 :             break;
    1746            0 :         case 11:
    1747            0 :             simtime = 304;
    1748            0 :             break;
    1749            0 :         case 12:
    1750            0 :             simtime = 334;
    1751            0 :             break;
    1752            0 :         default:
    1753            0 :             simtime = 0;
    1754              :         }
    1755              :     } else {
    1756            0 :         switch (state.dataEnvrn->Month) {
    1757            0 :         case 1:
    1758            0 :             simtime = 0;
    1759            0 :             break;
    1760            0 :         case 2:
    1761            0 :             simtime = 31;
    1762            0 :             break;
    1763            0 :         case 3:
    1764            0 :             simtime = 59 + 1;
    1765            0 :             break;
    1766            0 :         case 4:
    1767            0 :             simtime = 90 + 1;
    1768            0 :             break;
    1769            0 :         case 5:
    1770            0 :             simtime = 120 + 1;
    1771            0 :             break;
    1772            0 :         case 6:
    1773            0 :             simtime = 151 + 1;
    1774            0 :             break;
    1775            0 :         case 7:
    1776            0 :             simtime = 181 + 1;
    1777            0 :             break;
    1778            0 :         case 8:
    1779            0 :             simtime = 212 + 1;
    1780            0 :             break;
    1781            0 :         case 9:
    1782            0 :             simtime = 243 + 1;
    1783            0 :             break;
    1784            0 :         case 10:
    1785            0 :             simtime = 273 + 1;
    1786            0 :             break;
    1787            0 :         case 11:
    1788            0 :             simtime = 304 + 1;
    1789            0 :             break;
    1790            0 :         case 12:
    1791            0 :             simtime = 334 + 1;
    1792            0 :             break;
    1793            0 :         default:
    1794            0 :             simtime = 0;
    1795              :         }
    1796              :     }
    1797              : 
    1798            6 :     simtime = 24 * (simtime + (state.dataEnvrn->DayOfMonth - 1)); // day of month does not need to be stubtracted??
    1799            6 :     simtime = 60 * (simtime + (state.dataGlobal->HourOfDay - 1)); // hours to minutes
    1800            6 :     simtime = 60 * (simtime);                                     // minutes to seconds
    1801              : 
    1802            6 :     return simtime;
    1803              : }
    1804              : 
    1805       143619 : void CalcExternalInterfaceFMUImport(EnergyPlusData &state)
    1806              : {
    1807              : 
    1808              :     // SUBROUTINE INFORMATION:
    1809              :     //       AUTHOR         Thierry S. Nouidui, Michael Wetter, Wangda Zuo
    1810              :     //       DATE WRITTEN   08Aug2011
    1811              : 
    1812              :     // PURPOSE OF THIS SUBROUTINE:
    1813              :     // This subroutine organizes the data exchange between FMU and EnergyPlus.
    1814              : 
    1815              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1816       143619 :     Array1D_string Alphas(5);
    1817       143619 :     Array1D_int keyIndexes(1);     // Array index for
    1818       143619 :     Array1D_string NamesOfKeys(1); // Specific key name
    1819              : 
    1820       147075 :     if (state.dataGlobal->WarmupFlag &&
    1821         3456 :         (state.dataGlobal->KindOfSim != Constant::KindOfSim::RunPeriodWeather)) { // No data exchange during design days
    1822            0 :         if (state.dataExternalInterface->FirstCallDesignDays) {
    1823            0 :             ShowWarningError(state, "ExternalInterface/CalcExternalInterfaceFMUImport: ExternalInterface does not exchange data during design days.");
    1824              :         }
    1825            0 :         state.dataExternalInterface->FirstCallDesignDays = false;
    1826              :     }
    1827       143619 :     if (state.dataGlobal->WarmupFlag && (state.dataGlobal->KindOfSim == Constant::KindOfSim::RunPeriodWeather)) { // Data exchange after design days
    1828         3456 :         if (state.dataExternalInterface->FirstCallWUp) {
    1829              :             // set the report during warmup to true so that variables are also updated during the warmup
    1830            3 :             state.dataSysVars->UpdateDataDuringWarmupExternalInterface = true;
    1831            3 :             state.dataExternalInterface->hStep = (60.0 * state.dataGlobal->TimeStepZone) * 60.0;
    1832            3 :             state.dataExternalInterface->tStart = GetCurSimStartTimeSeconds(state);
    1833            3 :             state.dataExternalInterface->tStop = state.dataExternalInterface->tStart + 24.0 * 3600.0;
    1834            3 :             state.dataExternalInterface->tComm = state.dataExternalInterface->tStart;
    1835              : 
    1836              :             // instantiate and initialize the unpack fmus
    1837            3 :             InstantiateInitializeFMUImport(state);
    1838              : 
    1839              :             // allocate memory for a temporary FMU that will be used at the end of the warmup
    1840            3 :             state.dataExternalInterface->FMUTemp.allocate(state.dataExternalInterface->NumFMUObjects);
    1841            6 :             for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1842            3 :                 auto const &fmu = state.dataExternalInterface->FMU(i);
    1843            3 :                 auto &fmuTemp = state.dataExternalInterface->FMUTemp(i);
    1844            3 :                 fmuTemp.Instance.allocate(fmu.NumInstances);
    1845              :             }
    1846            6 :             for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1847            3 :                 auto const &fmu = state.dataExternalInterface->FMU(i);
    1848            3 :                 auto &fmuTemp = state.dataExternalInterface->FMUTemp(i);
    1849            6 :                 for (int j = 1; j <= fmu.NumInstances; ++j) {
    1850            3 :                     auto const &fmuInst = fmu.Instance(j);
    1851            3 :                     auto &fmuTempInst = fmuTemp.Instance(j);
    1852              : 
    1853            3 :                     fmuTempInst.fmuInputVariable.allocate(fmuInst.NumInputVariablesInIDF);
    1854            3 :                     fmuTempInst.eplusOutputVariable.allocate(fmuInst.NumInputVariablesInIDF);
    1855            3 :                     fmuTempInst.fmuOutputVariableSchedule.allocate(fmuInst.NumOutputVariablesSchedule);
    1856            3 :                     fmuTempInst.fmuOutputVariableVariable.allocate(fmuInst.NumOutputVariablesVariable);
    1857            3 :                     fmuTempInst.fmuOutputVariableActuator.allocate(fmuInst.NumOutputVariablesActuator);
    1858              :                 }
    1859              :             }
    1860              : 
    1861            3 :             GetSetVariablesAndDoStepFMUImport(state);
    1862            3 :             state.dataExternalInterface->tComm += state.dataExternalInterface->hStep;
    1863            3 :             state.dataExternalInterface->FirstCallWUp = false;
    1864              : 
    1865              :         } else {
    1866         3453 :             if (state.dataExternalInterface->tComm < state.dataExternalInterface->tStop) {
    1867         3426 :                 GetSetVariablesAndDoStepFMUImport(state);
    1868              :                 // Advance the communication time step
    1869         3426 :                 state.dataExternalInterface->tComm += state.dataExternalInterface->hStep;
    1870              :             } else {
    1871           54 :                 for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1872           27 :                     auto const &fmu = state.dataExternalInterface->FMU(i);
    1873           27 :                     auto &fmuTemp = state.dataExternalInterface->FMUTemp(i);
    1874           54 :                     for (int j = 1; j <= fmu.NumInstances; ++j) {
    1875           27 :                         auto const &fmuInst = fmu.Instance(j);
    1876           27 :                         auto &fmuTempInst = fmuTemp.Instance(j);
    1877              : 
    1878           27 :                         fmuTempInst.NumInputVariablesInIDF = fmuInst.NumInputVariablesInIDF;
    1879          115 :                         for (int k = 1; k <= fmuInst.NumInputVariablesInIDF; ++k) {
    1880           88 :                             fmuTempInst.fmuInputVariable(k).ValueReference = fmuInst.fmuInputVariable(k).ValueReference;
    1881           88 :                             fmuTempInst.eplusOutputVariable(k).RTSValue = fmuInst.eplusOutputVariable(k).RTSValue;
    1882           88 :                             fmuTempInst.eplusOutputVariable(k).ITSValue = fmuInst.eplusOutputVariable(k).ITSValue;
    1883           88 :                             fmuTempInst.eplusOutputVariable(k).VarType = fmuInst.eplusOutputVariable(k).VarType;
    1884              :                         }
    1885              : 
    1886              :                         // save values that will be set in EnergyPlus (Schedule)
    1887           27 :                         fmuTempInst.NumOutputVariablesSchedule = fmuInst.NumOutputVariablesSchedule;
    1888           61 :                         for (int k = 1; k <= fmuInst.NumOutputVariablesSchedule; ++k) {
    1889           34 :                             fmuTempInst.fmuOutputVariableSchedule(k).RealVarValue = fmuInst.fmuOutputVariableSchedule(k).RealVarValue;
    1890              :                         }
    1891              : 
    1892              :                         // save values that will be set in EnergyPlus (Variable)
    1893           27 :                         fmuTempInst.NumOutputVariablesVariable = fmuInst.NumOutputVariablesVariable;
    1894           32 :                         for (int k = 1; k <= fmuInst.NumOutputVariablesVariable; ++k) {
    1895            5 :                             fmuTempInst.fmuOutputVariableVariable(k).RealVarValue = fmuInst.fmuOutputVariableVariable(k).RealVarValue;
    1896              :                         }
    1897              : 
    1898              :                         // save values that will be set in EnergyPlus (Actuator)
    1899           27 :                         fmuTempInst.NumOutputVariablesActuator = fmuInst.NumOutputVariablesActuator;
    1900           32 :                         for (int k = 1; k <= fmuInst.NumOutputVariablesActuator; ++k) {
    1901            5 :                             fmuTempInst.fmuOutputVariableActuator(k).RealVarValue = fmuInst.fmuOutputVariableActuator(k).RealVarValue;
    1902              :                         }
    1903              :                     }
    1904              :                 }
    1905              : 
    1906           27 :                 StopExternalInterfaceIfError(state);
    1907              : 
    1908              :                 // Terminate all FMUs
    1909           27 :                 TerminateResetFreeFMUImport(state, state.dataExternalInterface->fmiEndSimulation);
    1910              : 
    1911              :                 // Reset the communication time step
    1912           27 :                 state.dataExternalInterface->tComm = state.dataExternalInterface->tStart;
    1913              : 
    1914              :                 // Reinstantiate and reinitialize the FMUs
    1915           27 :                 InstantiateInitializeFMUImport(state);
    1916              : 
    1917              :                 // Set the values that have been saved in the FMUs-- saveFMUStateVariables ()
    1918           54 :                 for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1919           27 :                     auto &fmu = state.dataExternalInterface->FMU(i);
    1920           27 :                     auto &fmuTemp = state.dataExternalInterface->FMUTemp(i);
    1921           54 :                     for (int j = 1; j <= fmu.NumInstances; ++j) {
    1922           27 :                         auto &fmuInst = fmu.Instance(j);
    1923           27 :                         auto &fmuTempInst = fmuTemp.Instance(j);
    1924              : 
    1925           27 :                         std::vector<unsigned int> valRefVec;
    1926          115 :                         for (unsigned long x = 1; x <= size(fmuInst.fmuInputVariable); ++x) {
    1927           88 :                             valRefVec.push_back(fmuInst.fmuInputVariable(x).ValueReference);
    1928              :                         }
    1929              : 
    1930           27 :                         std::vector<Real64> rtsValVec;
    1931          115 :                         for (unsigned long x = 1; x <= size(fmuInst.eplusOutputVariable); ++x) {
    1932           88 :                             rtsValVec.push_back(fmuInst.eplusOutputVariable(x).RTSValue);
    1933              :                         }
    1934              : 
    1935              :                         // make the library call
    1936           27 :                         fmuInst.fmistatus =
    1937           27 :                             fmiEPlusSetReal(&fmuInst.fmicomponent, &valRefVec[0], &rtsValVec[0], &fmuTempInst.NumInputVariablesInIDF, &fmuInst.Index);
    1938              : 
    1939           27 :                         if (fmuInst.fmistatus != fmiOK) {
    1940            0 :                             ShowSevereError(
    1941              :                                 state,
    1942            0 :                                 format("ExternalInterface/CalcExternalInterfaceFMUImport: Error when trying to set an input value in instance \"{}\"",
    1943            0 :                                        fmuInst.Name));
    1944            0 :                             ShowContinueError(state, format("of FMU \"{}\"; Error Code = \"{}\"", fmu.Name, fmuInst.fmistatus));
    1945            0 :                             state.dataExternalInterface->ErrorsFound = true;
    1946            0 :                             StopExternalInterfaceIfError(state);
    1947              :                         }
    1948           27 :                     }
    1949              :                 }
    1950              :                 // set the flag to reinitialize states to be true
    1951           27 :                 state.dataExternalInterface->FlagReIni = true;
    1952           27 :                 GetSetVariablesAndDoStepFMUImport(state);
    1953           27 :                 state.dataExternalInterface->FlagReIni = false;
    1954              :                 // advance one time step ahead for the next calculation
    1955           27 :                 state.dataExternalInterface->tComm += state.dataExternalInterface->hStep;
    1956              :             }
    1957              :         }
    1958              :     }
    1959              :     // BeginSimulation
    1960       143619 :     if (!state.dataGlobal->WarmupFlag && (state.dataGlobal->KindOfSim == Constant::KindOfSim::RunPeriodWeather)) {
    1961              : 
    1962       140163 :         if (state.dataExternalInterface->FirstCallTStep) {
    1963              :             // reset the UpdateDataDuringWarmupExternalInterface to be false.
    1964            3 :             state.dataSysVars->UpdateDataDuringWarmupExternalInterface = false;
    1965              :             // The time is computed in seconds for FMU
    1966            3 :             state.dataExternalInterface->tStart = GetCurSimStartTimeSeconds(state);
    1967            6 :             state.dataExternalInterface->tStop =
    1968            3 :                 state.dataExternalInterface->tStart + (state.dataEnvrn->TotalOverallSimDays - state.dataEnvrn->TotDesDays) * 24.0 * 3600.0;
    1969            3 :             state.dataExternalInterface->tComm = state.dataExternalInterface->tStart;
    1970              : 
    1971              :             // Terminate all FMUs
    1972            3 :             TerminateResetFreeFMUImport(state, state.dataExternalInterface->fmiEndSimulation);
    1973              : 
    1974              :             // Reinstantiate and reinitialize the FMUs
    1975            3 :             InstantiateInitializeFMUImport(state);
    1976              : 
    1977              :             // Set the values that have been saved in the FMUs-- saveFMUStateVariables ()
    1978            6 :             for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1979            3 :                 auto &fmu = state.dataExternalInterface->FMU(i);
    1980            3 :                 auto &fmuTemp = state.dataExternalInterface->FMUTemp(i);
    1981            6 :                 for (int j = 1; j <= fmu.NumInstances; ++j) {
    1982            3 :                     auto &fmuInst = fmu.Instance(j);
    1983            3 :                     auto &fmuTempInst = fmuTemp.Instance(j);
    1984              : 
    1985              :                     // make vectors first
    1986            3 :                     std::vector<unsigned int> valRefVec;
    1987           11 :                     for (unsigned long x = 1; x <= size(fmuTempInst.fmuInputVariable); ++x) {
    1988            8 :                         valRefVec.push_back(fmuTempInst.fmuInputVariable(x).ValueReference);
    1989              :                     }
    1990            3 :                     std::vector<Real64> rtsValVec;
    1991           11 :                     for (unsigned long x = 1; x <= size(fmuTempInst.eplusOutputVariable); ++x) {
    1992            8 :                         rtsValVec.push_back(fmuTempInst.eplusOutputVariable(x).RTSValue);
    1993              :                     }
    1994              : 
    1995              :                     // make the library call
    1996            3 :                     fmuInst.fmistatus =
    1997            3 :                         fmiEPlusSetReal(&fmuInst.fmicomponent, &valRefVec[0], &rtsValVec[0], &fmuTempInst.NumInputVariablesInIDF, &fmuInst.Index);
    1998              : 
    1999            3 :                     if (fmuInst.fmistatus != fmiOK) {
    2000            0 :                         ShowSevereError(state, "ExternalInterface/CalcExternalInterfaceFMUImport: ");
    2001            0 :                         ShowContinueError(state, "Error when trying to set inputs in instance");
    2002            0 :                         ShowContinueError(state, format("\"{}\" of FMU \"{}\"", fmuInst.Name, fmu.Name));
    2003            0 :                         ShowContinueError(state, format("Error Code = \"{}\"", fmuInst.fmistatus));
    2004            0 :                         state.dataExternalInterface->ErrorsFound = true;
    2005            0 :                         StopExternalInterfaceIfError(state);
    2006              :                     }
    2007            3 :                 }
    2008              :             }
    2009              :             // set the flag to reinitialize states to be true
    2010            3 :             state.dataExternalInterface->FlagReIni = true;
    2011            3 :             GetSetVariablesAndDoStepFMUImport(state);
    2012            3 :             state.dataExternalInterface->FlagReIni = false;
    2013              :             // advance one time step ahead for the next calculation
    2014            3 :             state.dataExternalInterface->tComm += state.dataExternalInterface->hStep;
    2015            3 :             state.dataExternalInterface->FirstCallTStep = false;
    2016              :         } else {
    2017       140160 :             if (state.dataExternalInterface->tComm != state.dataExternalInterface->tStop) {
    2018       140157 :                 GetSetVariablesAndDoStepFMUImport(state);
    2019       140157 :                 state.dataExternalInterface->tComm += state.dataExternalInterface->hStep;
    2020              :             } else {
    2021              :                 // Terminate reset and free Slaves
    2022            3 :                 state.dataExternalInterface->fmiEndSimulation = 1;
    2023            3 :                 TerminateResetFreeFMUImport(state, state.dataExternalInterface->fmiEndSimulation);
    2024            6 :                 for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    2025            3 :                     auto &fmu = state.dataExternalInterface->FMU(i);
    2026            3 :                     auto &fmuTemp = state.dataExternalInterface->FMUTemp(i);
    2027            6 :                     for (int j = 1; j <= fmu.NumInstances; ++j) {
    2028            3 :                         auto &fmuTempInst = fmuTemp.Instance(j);
    2029              :                         // Deallocate used objects
    2030            3 :                         fmuTempInst.fmuInputVariable.deallocate();
    2031            3 :                         fmuTempInst.eplusOutputVariable.deallocate();
    2032            3 :                         fmuTempInst.fmuOutputVariableSchedule.deallocate();
    2033            3 :                         fmuTempInst.fmuOutputVariableVariable.deallocate();
    2034            3 :                         fmuTempInst.fmuOutputVariableActuator.deallocate();
    2035              :                     }
    2036              :                 }
    2037              : 
    2038            6 :                 for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    2039            3 :                     auto &fmuTemp = state.dataExternalInterface->FMUTemp(i);
    2040            3 :                     fmuTemp.Instance.deallocate();
    2041              :                 }
    2042              : 
    2043            3 :                 state.dataExternalInterface->FMUTemp.deallocate();
    2044              : 
    2045            6 :                 for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    2046            3 :                     auto &fmu = state.dataExternalInterface->FMU(i);
    2047            6 :                     for (int j = 1; j <= fmu.NumInstances; ++j) {
    2048            3 :                         auto &fmuInst = fmu.Instance(j);
    2049            3 :                         fmuInst.eplusInputVariableSchedule.deallocate();
    2050            3 :                         fmuInst.fmuOutputVariableSchedule.deallocate();
    2051            3 :                         fmuInst.eplusInputVariableVariable.deallocate();
    2052            3 :                         fmuInst.fmuOutputVariableVariable.deallocate();
    2053            3 :                         fmuInst.eplusInputVariableActuator.deallocate();
    2054            3 :                         fmuInst.fmuOutputVariableActuator.deallocate();
    2055            3 :                         fmuInst.fmuInputVariable.deallocate();
    2056            3 :                         fmuInst.checkfmuInputVariable.deallocate();
    2057              :                     }
    2058              :                 }
    2059              : 
    2060            6 :                 for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    2061            3 :                     auto &fmu = state.dataExternalInterface->FMU(i);
    2062            3 :                     fmu.Instance.deallocate();
    2063              :                 }
    2064            3 :                 state.dataExternalInterface->FMU.deallocate();
    2065              :             }
    2066              :         }
    2067              :     }
    2068       143619 : }
    2069              : 
    2070            3 : void ValidateRunControl(EnergyPlusData &state)
    2071              : {
    2072              :     // SUBROUTINE INFORMATION:
    2073              :     //       AUTHOR         Michael Wetter
    2074              :     //       DATE WRITTEN   December 2009
    2075              : 
    2076              :     // PURPOSE OF THIS SUBROUTINE:
    2077              :     // This subroutine ensures that the RunControl object is valid.
    2078              : 
    2079              :     // METHODOLOGY EMPLOYED:
    2080              :     // Use GetObjectItem from the Input Processor
    2081              : 
    2082              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2083            3 :     auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    2084              : 
    2085            3 :     cCurrentModuleObject = "SimulationControl";
    2086            3 :     int const NumRunControl = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    2087            3 :     if (NumRunControl > 0) {
    2088            2 :         int NumAlphas = 0;  // Number of Alphas for each GetObjectItem call
    2089            2 :         int NumNumbers = 0; // Number of Numbers for each GetObjectItem call
    2090            2 :         int IOStatus = 0;   // Used in GetObjectItem
    2091            6 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
    2092              :                                                                  cCurrentModuleObject,
    2093              :                                                                  1,
    2094            2 :                                                                  state.dataIPShortCut->cAlphaArgs,
    2095              :                                                                  NumAlphas,
    2096            2 :                                                                  state.dataIPShortCut->rNumericArgs,
    2097              :                                                                  NumNumbers,
    2098              :                                                                  IOStatus,
    2099              :                                                                  _,
    2100              :                                                                  _,
    2101            2 :                                                                  state.dataIPShortCut->cAlphaFieldNames,
    2102            2 :                                                                  state.dataIPShortCut->cNumericFieldNames);
    2103            2 :         if (state.dataIPShortCut->cAlphaArgs(5) == "NO") { // This run does not have a weather file simulation.
    2104            0 :             ShowSevereError(state, "ExternalInterface: Error in idf file, section SimulationControl:");
    2105            0 :             ShowContinueError(state, "When using the ExternalInterface, a run period from the weather file must be specified");
    2106            0 :             ShowContinueError(state, "in the idf file, because the ExternalInterface interface is not active during");
    2107            0 :             ShowContinueError(state, "warm-up and during sizing.");
    2108            0 :             state.dataExternalInterface->ErrorsFound = true;
    2109              :         }
    2110              :     }
    2111            3 : }
    2112              : 
    2113            0 : void CalcExternalInterface(EnergyPlusData &state)
    2114              : {
    2115              :     // SUBROUTINE INFORMATION:
    2116              :     //       AUTHOR         Michael Wetter
    2117              :     //       DATE WRITTEN   2Dec2007
    2118              : 
    2119              :     // SUBROUTINE PARAMETER DEFINITIONS:
    2120            0 :     int constexpr nDblMax(1024); // Maximum number of doubles
    2121              : 
    2122              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2123              :     Real64 curSimTim; // current simulation time
    2124              :     Real64 preSimTim; // previous time step's simulation time
    2125              : 
    2126            0 :     Array1D<Real64> dblValWri(nDblMax);
    2127            0 :     Array1D<Real64> dblValRea(nDblMax);
    2128              : 
    2129            0 :     if (state.dataExternalInterface->firstCall) {
    2130            0 :         DisplayString(state, "ExternalInterface starts first data exchange.");
    2131            0 :         state.dataExternalInterface->simulationStatus = 2;
    2132            0 :         preSimTim = 0; // In the first call, E+ did not reset SimTimeSteps to zero
    2133              :     } else {
    2134            0 :         preSimTim = state.dataGlobal->SimTimeSteps * state.dataGlobal->MinutesInTimeStep * 60.0;
    2135              :     }
    2136              : 
    2137              :     // Socket asked to terminate simulation, but simulation continues
    2138            0 :     if (state.dataExternalInterface->noMoreValues && state.dataExternalInterface->showContinuationWithoutUpdate) {
    2139            0 :         if (state.dataExternalInterface->haveExternalInterfaceBCVTB) {
    2140            0 :             ShowWarningError(
    2141            0 :                 state, format("ExternalInterface: Continue simulation without updated values from server at t ={:.2T} hours", preSimTim / 3600.0));
    2142              :         }
    2143            0 :         state.dataExternalInterface->showContinuationWithoutUpdate = false;
    2144              :     }
    2145              : 
    2146              :     // Usual branch, control is configured and simulation should continue
    2147            0 :     if (state.dataExternalInterface->configuredControlPoints && (!state.dataExternalInterface->noMoreValues)) {
    2148              :         // Data to be exchanged
    2149            0 :         int nDblWri = size(state.dataExternalInterface->varTypes); // number of doubles to write to socket
    2150            0 :         int nDblRea = 0;                                           // number of doubles to read from socket
    2151            0 :         int flaWri = 0;                                            // flag to write to the socket
    2152              : 
    2153              :         // Get EnergyPlus variables
    2154            0 :         if (state.dataExternalInterface->firstCall) { // bug fix causing external interface to send zero at the beginning of sim, Thierry Nouidui
    2155            0 :             for (int i = 1; i <= nDblWri; ++i) {
    2156            0 :                 dblValWri(i) =
    2157            0 :                     GetInternalVariableValue(state, state.dataExternalInterface->varTypes(i), state.dataExternalInterface->keyVarIndexes(i));
    2158              :             }
    2159              :         } else {
    2160            0 :             for (int i = 1; i <= nDblWri; ++i) {
    2161            0 :                 dblValWri(i) = GetInternalVariableValueExternalInterface(
    2162            0 :                     state, state.dataExternalInterface->varTypes(i), state.dataExternalInterface->keyVarIndexes(i));
    2163              :             }
    2164              :         }
    2165              : 
    2166              :         // Exchange data with socket
    2167            0 :         int retVal = 0;
    2168            0 :         int flaRea = 0; // flag read from the socket
    2169            0 :         if (state.dataExternalInterface->haveExternalInterfaceBCVTB) {
    2170            0 :             retVal = exchangedoubleswithsocket(&state.dataExternalInterface->socketFD,
    2171              :                                                &flaWri,
    2172              :                                                &flaRea,
    2173              :                                                &nDblWri,
    2174              :                                                &nDblRea,
    2175              :                                                &preSimTim,
    2176              :                                                dblValWri.data(),
    2177              :                                                &curSimTim,
    2178              :                                                dblValRea.data());
    2179            0 :         } else if (state.dataExternalInterface->haveExternalInterfaceFMUExport) {
    2180            0 :             retVal = exchangedoubleswithsocketFMU(&state.dataExternalInterface->socketFD,
    2181              :                                                   &flaWri,
    2182              :                                                   &flaRea,
    2183              :                                                   &nDblWri,
    2184              :                                                   &nDblRea,
    2185              :                                                   &preSimTim,
    2186              :                                                   dblValWri.data(),
    2187              :                                                   &curSimTim,
    2188              :                                                   dblValRea.data(),
    2189            0 :                                                   &state.dataExternalInterface->FMUExportActivate);
    2190              :         }
    2191            0 :         bool continueSimulation = true;
    2192              : 
    2193              :         // Check for errors, in which case we terminate the simulation loop
    2194              :         // Added a check since the FMUExport is terminated with the flaRea set to 1.
    2195            0 :         if (state.dataExternalInterface->haveExternalInterfaceBCVTB ||
    2196            0 :             (state.dataExternalInterface->haveExternalInterfaceFMUExport && (flaRea == 0))) {
    2197            0 :             if (retVal != 0) {
    2198            0 :                 continueSimulation = false;
    2199            0 :                 ShowSevereError(state,
    2200            0 :                                 format("ExternalInterface: Socket communication received error value \"{:2}\" at time = {:.2T} hours.",
    2201              :                                        retVal,
    2202            0 :                                        preSimTim / 3600));
    2203            0 :                 ShowContinueError(state, format("ExternalInterface: Flag from server \"{:2}\".", flaRea));
    2204            0 :                 state.dataExternalInterface->ErrorsFound = true;
    2205            0 :                 StopExternalInterfaceIfError(state);
    2206              :             }
    2207              :         }
    2208              : 
    2209              :         // Check communication flag
    2210            0 :         if (flaRea != 0) {
    2211              :             // No more values will be received in future steps
    2212              :             // Added a check since the FMUExport  is terminated with the flaRea set to 1.
    2213            0 :             state.dataExternalInterface->noMoreValues = true;
    2214            0 :             if (state.dataExternalInterface->haveExternalInterfaceBCVTB) {
    2215            0 :                 ShowSevereError(state, format("ExternalInterface: Received end of simulation flag at time = {:.2T} hours.", preSimTim / 3600));
    2216            0 :                 StopExternalInterfaceIfError(state);
    2217              :             }
    2218              :         }
    2219              : 
    2220              :         // Make sure we get the right number of double values, unless retVal != 0
    2221            0 :         if ((flaRea == 0) && (!state.dataExternalInterface->ErrorsFound) && continueSimulation &&
    2222            0 :             (nDblRea != isize(state.dataExternalInterface->varInd))) {
    2223            0 :             ShowSevereError(
    2224              :                 state,
    2225            0 :                 format("ExternalInterface: Received \"{}\" double values, expected \"{}\".", nDblRea, size(state.dataExternalInterface->varInd)));
    2226            0 :             state.dataExternalInterface->ErrorsFound = true;
    2227            0 :             StopExternalInterfaceIfError(state);
    2228              :         }
    2229              : 
    2230              :         // No errors found. Assign exchanged variables
    2231            0 :         if ((flaRea == 0) && continueSimulation) {
    2232            0 :             for (int i = 1; i <= isize(state.dataExternalInterface->varInd); ++i) {
    2233            0 :                 if (state.dataExternalInterface->inpVarTypes(i) == indexSchedule) {
    2234            0 :                     Sched::ExternalInterfaceSetSchedule(state, state.dataExternalInterface->varInd(i), dblValRea(i));
    2235            0 :                 } else if ((state.dataExternalInterface->inpVarTypes(i) == indexVariable) ||
    2236            0 :                            (state.dataExternalInterface->inpVarTypes(i) == indexActuator)) {
    2237            0 :                     RuntimeLanguageProcessor::ExternalInterfaceSetErlVariable(state, state.dataExternalInterface->varInd(i), dblValRea(i));
    2238              :                 } else {
    2239            0 :                     ShowContinueError(state, "ExternalInterface: Error in finding the type of the input variable for EnergyPlus");
    2240            0 :                     ShowContinueError(state, format("variable index: {}. Variable will not be updated.", i));
    2241              :                 }
    2242              :             }
    2243              :         }
    2244              :     }
    2245              : 
    2246              :     // If we have Erl variables, we need to call ManageEMS so that they get updated in the Erl data structure
    2247            0 :     if (state.dataExternalInterface->useEMS) {
    2248              :         bool anyRan;
    2249            0 :         EMSManager::ManageEMS(state, EMSManager::EMSCallFrom::ExternalInterface, anyRan, ObjexxFCL::Optional_int_const());
    2250              :     }
    2251              : 
    2252            0 :     state.dataExternalInterface->firstCall = false; // bug fix causing external interface to send zero at the beginning of sim, Thierry Nouidui
    2253            0 : }
    2254              : 
    2255            8 : void GetReportVariableKey(
    2256              :     EnergyPlusData &state,
    2257              :     const Array1D_string &varKeys,                   // Standard variable name
    2258              :     int const numberOfKeys,                          // Number of keys=size(state.dataExternalInterface->varKeys)
    2259              :     const Array1D_string &VarNames,                  // Standard variable name
    2260              :     Array1D_int &keyVarIndexes,                      // Array index
    2261              :     Array1D<OutputProcessor::VariableType> &varTypes // Types of variables in state.dataExternalInterface->keystate.dataExternalInterface->varIndexes
    2262              : )
    2263              : {
    2264              :     // SUBROUTINE INFORMATION:
    2265              :     //       AUTHOR         Michael Wetter
    2266              :     //       DATE WRITTEN   2Dec2007
    2267              : 
    2268              :     // PURPOSE OF THIS SUBROUTINE:
    2269              :     // Gets the sensor key index and type for the specified variable key and name
    2270              : 
    2271              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2272            8 :     OutputProcessor::VariableType varType(OutputProcessor::VariableType::Invalid);  // 0=not found, 1=integer, 2=real, 3=meter
    2273            8 :     int numKeys(0);                                                                 // Number of keys found
    2274            8 :     OutputProcessor::StoreType varAvgSum(OutputProcessor::StoreType::Average);      // Variable  is Averaged=1 or Summed=2
    2275            8 :     OutputProcessor::TimeStepType varStepType(OutputProcessor::TimeStepType::Zone); // Variable time step is Zone=1 or HVAC=2
    2276            8 :     Constant::Units varUnits(Constant::Units::None);                                // Units sting, may be blank
    2277            8 :     Array1D_string keyNames;
    2278            8 :     Array1D_int keyIndexes; // Array index for
    2279              :     int Loop, iKey;         // Loop counters
    2280              : 
    2281              :     // Get pointers for variables to be sent to Ptolemy
    2282           16 :     for (Loop = 1; Loop <= numberOfKeys; ++Loop) {
    2283            8 :         GetVariableKeyCountandType(state, VarNames(Loop), numKeys, varType, varAvgSum, varStepType, varUnits);
    2284            8 :         if (varType != OutputProcessor::VariableType::Invalid) {
    2285            8 :             keyIndexes.allocate(numKeys);
    2286            8 :             keyNames.allocate(numKeys);
    2287            8 :             GetVariableKeys(state, VarNames(Loop), varType, keyNames, keyIndexes);
    2288              :             // Find key index whose keyName is equal to keyNames(Loop)
    2289            8 :             int max(keyIndexes.size());
    2290            8 :             for (iKey = 1; iKey <= max; ++iKey) {
    2291            8 :                 if (keyNames(iKey) == varKeys(Loop)) {
    2292            8 :                     keyVarIndexes(Loop) = keyIndexes(iKey);
    2293            8 :                     varTypes(Loop) = varType;
    2294            8 :                     break;
    2295              :                 }
    2296              :             }
    2297            8 :             keyIndexes.deallocate();
    2298            8 :             keyNames.deallocate();
    2299              :         }
    2300            8 :         if ((varType == OutputProcessor::VariableType::Invalid) || (iKey > numKeys)) {
    2301            0 :             ShowSevereError(state,
    2302            0 :                             format("ExternalInterface: Simulation model has no variable \"{}\" with key \"{}\".", VarNames(Loop), varKeys(Loop)));
    2303            0 :             state.dataExternalInterface->ErrorsFound = true;
    2304              :         }
    2305              :     }
    2306            8 : }
    2307              : 
    2308         7191 : void WarnIfExternalInterfaceObjectsAreUsed(EnergyPlusData &state, std::string const &ObjectWord)
    2309              : {
    2310              :     // SUBROUTINE INFORMATION:
    2311              :     //       AUTHOR         Michael Wetter
    2312              :     //       DATE WRITTEN   December 2009
    2313              : 
    2314              :     // PURPOSE OF THIS SUBROUTINE:
    2315              :     // This subroutine writes a warning if ExternalInterface objects are used in the
    2316              :     // idf file, but the ExternalInterface link is not specified.
    2317              : 
    2318         7191 :     int const NumObjects = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, ObjectWord);
    2319         7191 :     if (NumObjects > 0) {
    2320            0 :         ShowWarningError(state, format("IDF file contains object \"{}\",", ObjectWord));
    2321            0 :         ShowContinueError(state, "but object \"ExternalInterface\" with appropriate key entry is not specified. Values will not be updated.");
    2322              :     }
    2323         7191 : }
    2324              : 
    2325            3 : void VerifyExternalInterfaceObject(EnergyPlusData &state)
    2326              : {
    2327              :     // SUBROUTINE INFORMATION:
    2328              :     //       AUTHOR         Michael Wetter
    2329              :     //       DATE WRITTEN   12Dec2009
    2330              : 
    2331              :     // PURPOSE OF THIS SUBROUTINE:
    2332              :     // This subroutine verifies the correctness of the fields of
    2333              :     // the ExternalInterface object in the idf file
    2334              : 
    2335              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2336            3 :     int NumAlphas(0);  // Number of Alphas for each GetObjectItem call
    2337            3 :     int NumNumbers(0); // Number of Numbers for each GetObjectItem call
    2338            3 :     int IOStatus(0);   // Used in GetObjectItem
    2339            3 :     auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    2340              : 
    2341            3 :     cCurrentModuleObject = "ExternalInterface";
    2342            9 :     state.dataInputProcessing->inputProcessor->getObjectItem(state,
    2343              :                                                              cCurrentModuleObject,
    2344              :                                                              1,
    2345            3 :                                                              state.dataIPShortCut->cAlphaArgs,
    2346              :                                                              NumAlphas,
    2347            3 :                                                              state.dataIPShortCut->rNumericArgs,
    2348              :                                                              NumNumbers,
    2349              :                                                              IOStatus,
    2350              :                                                              _,
    2351              :                                                              _,
    2352            3 :                                                              state.dataIPShortCut->cAlphaFieldNames,
    2353            3 :                                                              state.dataIPShortCut->cNumericFieldNames);
    2354            3 :     if ((!Util::SameString(state.dataIPShortCut->cAlphaArgs(1), "PtolemyServer")) &&
    2355            3 :         (!Util::SameString(state.dataIPShortCut->cAlphaArgs(1), "FunctionalMockupUnitImport")) &&
    2356            3 :         (!Util::SameString(state.dataIPShortCut->cAlphaArgs(1), "FunctionalMockupUnitExport"))) {
    2357            0 :         ShowSevereError(state,
    2358            0 :                         format("VerifyExternalInterfaceObject: {}, invalid {}=\"{}\".",
    2359              :                                cCurrentModuleObject,
    2360            0 :                                state.dataIPShortCut->cAlphaFieldNames(1),
    2361            0 :                                state.dataIPShortCut->cAlphaArgs(1)));
    2362            0 :         ShowContinueError(state, "only \"PtolemyServer or FunctionalMockupUnitImport or FunctionalMockupUnitExport\" allowed.");
    2363            0 :         state.dataExternalInterface->ErrorsFound = true;
    2364              :     }
    2365            3 : }
    2366              : 
    2367           33 : std::vector<char> getCharArrayFromString(std::string const &originalString)
    2368              : {
    2369              :     // c_str returns null terminated, so we don't need a +1?
    2370           66 :     return std::vector<char>(originalString.c_str(), originalString.c_str() + originalString.size());
    2371              : }
    2372              : 
    2373           16 : std::string getStringFromCharArray(std::vector<char> originalCharArray)
    2374              : {
    2375           16 :     originalCharArray.push_back('\0');
    2376           32 :     return std::string(&originalCharArray.front());
    2377              : }
    2378              : 
    2379              : } // namespace EnergyPlus::ExternalInterface
        

Generated by: LCOV version 2.0-1