LCOV - code coverage report
Current view: top level - EnergyPlus - ExternalInterface.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 3.4 % 1305 45
Test Date: 2025-05-22 16:09:37 Functions: 19.0 % 21 4

            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       165881 : 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       165881 :     if (state.dataExternalInterface->GetInputFlag) {
     109           65 :         GetExternalInterfaceInput(state);
     110           65 :         state.dataExternalInterface->GetInputFlag = false;
     111              :     }
     112              : 
     113       165881 :     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       165881 :     if (state.dataExternalInterface->haveExternalInterfaceFMUImport) {
     124            0 :         std::string errorMessage; // Error message
     125            0 :         errorMessage.reserve(100);
     126            0 :         char *errorMessagePtr(errorMessage.data());
     127            0 :         const int retValErrMsg = checkOperatingSystem(errorMessagePtr);
     128            0 :         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            0 :         InitExternalInterfaceFMUImport(state);
     135              :         // No Data exchange during design days
     136              :         // Data Exchange data during warmup and after warmup
     137            0 :         CalcExternalInterfaceFMUImport(state);
     138            0 :     }
     139       165881 : }
     140              : 
     141           65 : 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           65 :     auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
     159           65 :     cCurrentModuleObject = "ExternalInterface";
     160           65 :     state.dataExternalInterface->NumExternalInterfaces = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     161              : 
     162           65 :     for (int Loop = 1; Loop <= state.dataExternalInterface->NumExternalInterfaces;
     163              :          ++Loop) { // This loop determines whether the external interface is for FMU or BCVTB
     164            0 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     165              :                                                                  cCurrentModuleObject,
     166              :                                                                  Loop,
     167            0 :                                                                  state.dataIPShortCut->cAlphaArgs,
     168              :                                                                  NumAlphas,
     169            0 :                                                                  state.dataIPShortCut->rNumericArgs,
     170              :                                                                  NumNumbers,
     171              :                                                                  IOStatus,
     172              :                                                                  _,
     173              :                                                                  _,
     174            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames,
     175            0 :                                                                  state.dataIPShortCut->cNumericFieldNames);
     176            0 :         if (Util::SameString(state.dataIPShortCut->cAlphaArgs(1), "PtolemyServer")) { // The BCVTB interface is activated.
     177            0 :             ++state.dataExternalInterface->NumExternalInterfacesBCVTB;
     178            0 :         } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(1),
     179              :                                     "FunctionalMockupUnitImport")) { // The functional mock up unit import interface is activated.
     180            0 :             ++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           65 :     if (state.dataExternalInterface->NumExternalInterfacesBCVTB == 0) {
     189          130 :         WarnIfExternalInterfaceObjectsAreUsed(state, "ExternalInterface:Schedule");
     190          130 :         WarnIfExternalInterfaceObjectsAreUsed(state, "ExternalInterface:Variable");
     191          130 :         WarnIfExternalInterfaceObjectsAreUsed(state, "ExternalInterface:Actuator");
     192              :     }
     193              : 
     194              :     // Check if objects are used although FMUExport interface is not defined
     195           65 :     if (state.dataExternalInterface->NumExternalInterfacesFMUExport == 0) {
     196          130 :         WarnIfExternalInterfaceObjectsAreUsed(state, "ExternalInterface:FunctionalMockupUnitExport:To:Schedule");
     197          130 :         WarnIfExternalInterfaceObjectsAreUsed(state, "ExternalInterface:FunctionalMockupUnitExport:To:Variable");
     198          130 :         WarnIfExternalInterfaceObjectsAreUsed(state, "ExternalInterface:FunctionalMockupUnitExport:To:Actuator");
     199              :     }
     200              : 
     201              :     // Check if objects are used although FMU Import interface is not defined
     202           65 :     if (state.dataExternalInterface->NumExternalInterfacesFMUImport == 0) {
     203          130 :         WarnIfExternalInterfaceObjectsAreUsed(state, "ExternalInterface:FunctionalMockupUnitImport:To:Schedule");
     204          130 :         WarnIfExternalInterfaceObjectsAreUsed(state, "ExternalInterface:FunctionalMockupUnitImport:To:Variable");
     205          130 :         WarnIfExternalInterfaceObjectsAreUsed(state, "ExternalInterface:FunctionalMockupUnitImport:To:Actuator");
     206              :     }
     207              : 
     208           65 :     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           65 :     } 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           65 :     } 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           65 :     if ((state.dataExternalInterface->NumExternalInterfacesFMUImport == 1) && (state.dataExternalInterface->NumExternalInterfacesFMUExport == 0)) {
     231            0 :         state.dataExternalInterface->haveExternalInterfaceFMUImport = true;
     232            0 :         DisplayString(state, "Instantiating FunctionalMockupUnitImport interface");
     233            0 :         cCurrentModuleObject = "ExternalInterface:FunctionalMockupUnitImport";
     234            0 :         state.dataExternalInterface->NumFMUObjects = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     235            0 :         VerifyExternalInterfaceObject(state);
     236           65 :     } 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           65 :     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           65 :     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           65 :     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           65 :     if (state.dataExternalInterface->ErrorsFound) {
     261            0 :         ShowFatalError(state, "GetExternalInterfaceInput: preceding conditions cause termination.");
     262              :     }
     263              : 
     264           65 :     StopExternalInterfaceIfError(state);
     265           65 : }
     266              : 
     267           65 : 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           65 :     int constexpr flag1(-10);
     280           65 :     int constexpr flag2(-20);
     281              : 
     282           65 :     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           65 :     if (state.dataExternalInterface->NumExternalInterfacesFMUImport != 0) {
     301            0 :         if (state.dataExternalInterface->ErrorsFound) {
     302            0 :             ShowFatalError(state, "ExternalInterface/StopExternalInterfaceIfError: Error in ExternalInterface: Check EnergyPlus *.err file.");
     303              :         }
     304              :     }
     305           65 : }
     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            0 : 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            0 :     for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
     594            0 :         auto &fmu = state.dataExternalInterface->FMU(i);
     595            0 :         auto &fmuTemp = state.dataExternalInterface->FMUTemp(i);
     596              : 
     597            0 :         for (int j = 1; j <= fmu.NumInstances; ++j) {
     598            0 :             auto &fmuInst = fmu.Instance(j);
     599            0 :             auto &fmuTempInst = fmuTemp.Instance(j);
     600              : 
     601            0 :             if (state.dataExternalInterface->FlagReIni) {
     602              :                 // Get from FMUs, values that will be set in EnergyPlus (Schedule)
     603            0 :                 for (int k = 1; k <= fmuTempInst.NumOutputVariablesSchedule; ++k) {
     604            0 :                     fmuInst.fmuOutputVariableSchedule(k).RealVarValue = fmuTempInst.fmuOutputVariableSchedule(k).RealVarValue;
     605              :                 }
     606              : 
     607              :                 // Get from FMUs, values that will be set in EnergyPlus (Variable)
     608            0 :                 for (int k = 1; k <= fmuTempInst.NumOutputVariablesVariable; ++k) {
     609            0 :                     fmuInst.fmuOutputVariableVariable(k).RealVarValue = fmuTempInst.fmuOutputVariableVariable(k).RealVarValue;
     610              :                 }
     611              : 
     612              :                 // Get from FMUs, values that will be set in EnergyPlus (Actuator)
     613            0 :                 for (int k = 1; k <= fmuTempInst.NumOutputVariablesActuator; ++k) {
     614            0 :                     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            0 :                 if (size(fmuInst.fmuOutputVariableSchedule) > 0) {
     620              : 
     621              :                     // generate vectors here first
     622            0 :                     std::vector<unsigned int> valueReferenceVec;
     623            0 :                     std::vector<Real64> realVarValueVec;
     624            0 :                     for (unsigned long x = 1; x <= size(fmuInst.fmuOutputVariableSchedule); ++x) {
     625            0 :                         valueReferenceVec.push_back(fmuInst.fmuOutputVariableSchedule(x).ValueReference);
     626            0 :                         realVarValueVec.push_back(fmuInst.fmuOutputVariableSchedule(x).RealVarValue);
     627              :                     }
     628              : 
     629              :                     // pass in the vectors as pointers to the first member of the vector
     630            0 :                     fmuInst.fmistatus = fmiEPlusGetReal(
     631            0 :                         &fmuInst.fmicomponent, &valueReferenceVec[0], &realVarValueVec[0], &fmuInst.NumOutputVariablesSchedule, &fmuInst.Index);
     632              : 
     633            0 :                     for (unsigned long x = 1; x <= size(fmuInst.fmuOutputVariableSchedule); ++x) {
     634            0 :                         fmuInst.fmuOutputVariableSchedule(x).ValueReference = valueReferenceVec[x - 1];
     635            0 :                         fmuInst.fmuOutputVariableSchedule(x).RealVarValue = realVarValueVec[x - 1];
     636              :                     }
     637              : 
     638            0 :                     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            0 :                 }
     646              : 
     647              :                 // generate vectors here first
     648            0 :                 if (size(fmuInst.fmuOutputVariableVariable) > 0) {
     649              : 
     650            0 :                     std::vector<unsigned int> valueReferenceVec2;
     651            0 :                     std::vector<Real64> realVarValueVec2;
     652            0 :                     for (unsigned long x = 1; x <= size(fmuInst.fmuOutputVariableVariable); ++x) {
     653            0 :                         valueReferenceVec2.push_back(fmuInst.fmuOutputVariableVariable(x).ValueReference);
     654            0 :                         realVarValueVec2.push_back(fmuInst.fmuOutputVariableVariable(x).RealVarValue);
     655              :                     }
     656              : 
     657              :                     // pass in the vectors as pointers to the first member of the vector
     658            0 :                     fmuInst.fmistatus = fmiEPlusGetReal(
     659            0 :                         &fmuInst.fmicomponent, &valueReferenceVec2[0], &realVarValueVec2[0], &fmuInst.NumOutputVariablesVariable, &fmuInst.Index);
     660              : 
     661            0 :                     for (unsigned long x = 1; x <= size(fmuInst.fmuOutputVariableVariable); ++x) {
     662            0 :                         fmuInst.fmuOutputVariableVariable(x).ValueReference = valueReferenceVec2[x - 1];
     663            0 :                         fmuInst.fmuOutputVariableVariable(x).RealVarValue = realVarValueVec2[x - 1];
     664              :                     }
     665              : 
     666            0 :                     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            0 :                 }
     674              : 
     675            0 :                 if (size(fmuInst.fmuOutputVariableActuator) > 0) {
     676              : 
     677              :                     // generate vectors here first
     678            0 :                     std::vector<unsigned int> valueReferenceVec3;
     679            0 :                     std::vector<Real64> realVarValueVec3;
     680            0 :                     for (unsigned long x = 1; x <= size(fmuInst.fmuOutputVariableActuator); ++x) {
     681            0 :                         valueReferenceVec3.push_back(fmuInst.fmuOutputVariableActuator(x).ValueReference);
     682            0 :                         realVarValueVec3.push_back(fmuInst.fmuOutputVariableActuator(x).RealVarValue);
     683              :                     }
     684              : 
     685              :                     // pass in the vectors as pointers to the first member of the vector
     686            0 :                     fmuInst.fmistatus = fmiEPlusGetReal(
     687            0 :                         &fmuInst.fmicomponent, &valueReferenceVec3[0], &realVarValueVec3[0], &fmuInst.NumOutputVariablesActuator, &fmuInst.Index);
     688              : 
     689            0 :                     for (unsigned long x = 1; x <= size(fmuInst.fmuOutputVariableActuator); ++x) {
     690            0 :                         fmuInst.fmuOutputVariableActuator(x).ValueReference = valueReferenceVec3[x - 1];
     691            0 :                         fmuInst.fmuOutputVariableActuator(x).RealVarValue = realVarValueVec3[x - 1];
     692              :                     }
     693              : 
     694            0 :                     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            0 :                 }
     702              :             }
     703              : 
     704              :             // Set in EnergyPlus the values of the schedules
     705            0 :             for (int k = 1; k <= fmuInst.NumOutputVariablesSchedule; ++k) {
     706            0 :                 Sched::ExternalInterfaceSetSchedule(
     707            0 :                     state, fmuInst.eplusInputVariableSchedule(k).VarIndex, fmuInst.fmuOutputVariableSchedule(k).RealVarValue);
     708              :             }
     709              : 
     710              :             // Set in EnergyPlus the values of the variables
     711            0 :             for (int k = 1; k <= fmuInst.NumOutputVariablesVariable; ++k) {
     712            0 :                 RuntimeLanguageProcessor::ExternalInterfaceSetErlVariable(
     713            0 :                     state, fmuInst.eplusInputVariableVariable(k).VarIndex, fmuInst.fmuOutputVariableVariable(k).RealVarValue);
     714              :             }
     715              : 
     716              :             // Set in EnergyPlus the values of the actuators
     717            0 :             for (int k = 1; k <= fmuInst.NumOutputVariablesActuator; ++k) {
     718            0 :                 RuntimeLanguageProcessor::ExternalInterfaceSetErlVariable(
     719            0 :                     state, fmuInst.eplusInputVariableActuator(k).VarIndex, fmuInst.fmuOutputVariableActuator(k).RealVarValue);
     720              :             }
     721              : 
     722            0 :             if (state.dataExternalInterface->FirstCallGetSetDoStep) {
     723              :                 // Get from EnergyPlus, values that will be set in fmus
     724            0 :                 for (int k = 1; k <= fmuInst.NumInputVariablesInIDF; ++k) {
     725              :                     // This make sure that the variables are updated at the Zone Time Step
     726            0 :                     fmuInst.eplusOutputVariable(k).RTSValue =
     727            0 :                         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            0 :                 for (int k = 1; k <= fmuInst.NumInputVariablesInIDF; ++k) {
     732              :                     // This make sure that the variables are updated at the Zone Time Step
     733            0 :                     fmuInst.eplusOutputVariable(k).RTSValue = GetInternalVariableValueExternalInterface(
     734            0 :                         state, fmuInst.eplusOutputVariable(k).VarType, fmuInst.eplusOutputVariable(k).VarIndex);
     735              :                 }
     736              :             }
     737              : 
     738            0 :             if (!state.dataExternalInterface->FlagReIni) {
     739              : 
     740              :                 // generate vectors here first
     741            0 :                 std::vector<unsigned int> valueReferenceVec4;
     742            0 :                 for (unsigned long x = 1; x <= size(fmuInst.fmuInputVariable); ++x) {
     743            0 :                     valueReferenceVec4.push_back(fmuInst.fmuInputVariable(x).ValueReference);
     744              :                 }
     745              : 
     746            0 :                 std::vector<Real64> rtsValueVec4;
     747            0 :                 for (unsigned long x = 1; x <= size(fmuInst.eplusOutputVariable); ++x) {
     748            0 :                     rtsValueVec4.push_back(fmuInst.eplusOutputVariable(x).RTSValue);
     749              :                 }
     750              : 
     751            0 :                 fmuInst.fmistatus =
     752            0 :                     fmiEPlusSetReal(&fmuInst.fmicomponent, &valueReferenceVec4[0], &rtsValueVec4[0], &fmuInst.NumInputVariablesInIDF, &fmuInst.Index);
     753              : 
     754            0 :                 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            0 :             }
     762            0 :             int localfmitrue(fmiTrue);
     763              :             // Call and simulate the FMUs to get values at the corresponding timestep.
     764            0 :             fmuInst.fmistatus = fmiEPlusDoStep(
     765            0 :                 &fmuInst.fmicomponent, &state.dataExternalInterface->tComm, &state.dataExternalInterface->hStep, &localfmitrue, &fmuInst.Index);
     766            0 :             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            0 :     if (state.dataExternalInterface->useEMS) {
     779              :         bool anyRan;
     780            0 :         EMSManager::ManageEMS(state, EMSManager::EMSCallFrom::ExternalInterface, anyRan, ObjexxFCL::Optional_int_const());
     781              :     }
     782              : 
     783            0 :     state.dataExternalInterface->FirstCallGetSetDoStep = false;
     784            0 : }
     785              : 
     786            0 : 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            0 :     for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
     797            0 :         auto &fmu = state.dataExternalInterface->FMU(i);
     798            0 :         for (int j = 1; j <= fmu.NumInstances; ++j) {
     799            0 :             auto &fmuInst = fmu.Instance(j);
     800            0 :             std::string const folderStr = FileSystem::toString(fmuInst.WorkingFolder);
     801            0 :             fmuInst.fmicomponent = fmiEPlusInstantiateSlave(
     802            0 :                 (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            0 :             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            0 :         }
     811              :     }
     812              : 
     813              :     // Initialize FMUs
     814            0 :     int localfmiTrue(fmiTrue);
     815            0 :     for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
     816            0 :         auto &fmu = state.dataExternalInterface->FMU(i);
     817            0 :         for (int j = 1; j <= fmu.NumInstances; ++j) {
     818            0 :             auto &fmuInst = fmu.Instance(j);
     819            0 :             fmuInst.fmistatus = fmiEPlusInitializeSlave(
     820            0 :                 &fmuInst.fmicomponent, &state.dataExternalInterface->tStart, &localfmiTrue, &state.dataExternalInterface->tStop, &fmuInst.Index);
     821            0 :             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            0 : }
     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            0 : 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            0 :     for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
     873            0 :         auto &fmu = state.dataExternalInterface->FMU(i);
     874            0 :         for (int j = 1; j <= fmu.NumInstances; ++j) {
     875            0 :             auto &fmuInst = fmu.Instance(j);
     876            0 :             if (fmuInst.fmistatus != fmiFatal) {
     877              :                 // Cleanup slaves
     878            0 :                 fmuInst.fmistatus = fmiEPlusFreeSlave(&fmuInst.fmicomponent, &fmuInst.Index, &fmiEndSimulation);
     879              :             }
     880              :             // check if fmiComponent has been freed
     881            0 :             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            0 : }
     890              : 
     891            0 : 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            0 :     Array1D_int keyIndexes(1);                          // Array index for
     903            0 :     Array1D<OutputProcessor::VariableType> varTypes(1); // Array index for
     904            0 :     Array1D_string NamesOfKeys(1);                      // Specific key name
     905            0 :     Array1D_string NameListInstances(5);
     906            0 :     fs::path tempFullFilePath;
     907              : 
     908            0 :     Array1D_string strippedFileName; // remove path from entered file name
     909            0 :     Array1D_string fullFileName;     // entered file name/found
     910              : 
     911            0 :     if (state.dataExternalInterface->FirstCallIni) {
     912            0 :         DisplayString(state, "Initializing FunctionalMockupUnitImport interface");
     913              :         // do one time initializations
     914            0 :         ValidateRunControl(state);
     915            0 :         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            0 :         state.dataExternalInterface->FMURootWorkingFolder = fs::path("tmp-fmus"); // getStringFromCharArray( FMUWorkingFolderCharArr );
     923              : 
     924              :         // Get and store the names of all FMUs in EnergyPlus data structure
     925            0 :         strippedFileName.allocate(state.dataExternalInterface->NumFMUObjects);
     926            0 :         fullFileName.allocate(state.dataExternalInterface->NumFMUObjects);
     927              : 
     928            0 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
     929            0 :         cCurrentModuleObject = "ExternalInterface:FunctionalMockupUnitImport";
     930            0 :         int NumAlphas = 0;  // Number of Alphas for each GetObjectItem call
     931            0 :         int NumNumbers = 0; // Number of Numbers for each GetObjectItem call
     932            0 :         int IOStatus = 0;   // Used in GetObjectItem
     933            0 :         for (int Loop = 1; Loop <= state.dataExternalInterface->NumFMUObjects; ++Loop) {
     934            0 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     935              :                                                                      cCurrentModuleObject,
     936              :                                                                      Loop,
     937            0 :                                                                      state.dataIPShortCut->cAlphaArgs,
     938              :                                                                      NumAlphas,
     939            0 :                                                                      state.dataIPShortCut->rNumericArgs,
     940              :                                                                      NumNumbers,
     941              :                                                                      IOStatus,
     942              :                                                                      _,
     943              :                                                                      _,
     944            0 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     945            0 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     946              :             // Get the FMU name
     947            0 :             state.dataExternalInterface->FMU(Loop).Name = state.dataIPShortCut->cAlphaArgs(1);
     948              : 
     949            0 :             fs::path inputPath = FileSystem::makeNativePath(state.dataExternalInterface->FMU(Loop).Name);
     950              : 
     951            0 :             std::string contextString = cCurrentModuleObject + ", " + state.dataIPShortCut->cAlphaFieldNames(1) + ": ";
     952              : 
     953            0 :             tempFullFilePath = DataSystemVariables::CheckForActualFilePath(state, inputPath, contextString);
     954            0 :             if (!tempFullFilePath.empty()) {
     955              : 
     956              :                 // TODO: eliminate this old block once confident
     957            0 :                 std::string::size_type pos = index(state.dataExternalInterface->FMU(Loop).Name, DataStringGlobals::pathChar, true); // look backwards
     958            0 :                 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            0 :                     pos = index(state.dataExternalInterface->FMU(Loop).Name, DataStringGlobals::altpathChar, true); // look backwards
     962            0 :                     if (pos != std::string::npos) {
     963            0 :                         strippedFileName(Loop) = state.dataExternalInterface->FMU(Loop).Name.substr(pos + 1);
     964              :                     } else {
     965            0 :                         strippedFileName(Loop) = state.dataExternalInterface->FMU(Loop).Name;
     966              :                     }
     967              :                 }
     968            0 :                 fullFileName(Loop) = FileSystem::toString(tempFullFilePath);
     969              :             } else {
     970            0 :                 state.dataExternalInterface->ErrorsFound = true;
     971              :             }
     972              :             // Get fmu time out
     973            0 :             state.dataExternalInterface->FMU(Loop).TimeOut = state.dataIPShortCut->rNumericArgs(1);
     974              :             // Get fmu logging on
     975            0 :             state.dataExternalInterface->FMU(Loop).LoggingOn = state.dataIPShortCut->rNumericArgs(2);
     976            0 :         }
     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            0 :         for (int j = 1; j <= state.dataExternalInterface->NumFMUObjects; ++j) {
     982            0 :             for (int k = 2; k <= state.dataExternalInterface->NumFMUObjects; ++k) {
     983            0 :                 if (!Util::SameString(strippedFileName(j), strippedFileName(k))) continue;
     984              :                 // base file names are the same
     985            0 :                 if (Util::SameString(fullFileName(j), fullFileName(k))) continue;
     986            0 :                 ShowSevereError(state, "ExternalInterface/InitExternalInterfaceFMUImport:");
     987            0 :                 ShowContinueError(state, "duplicate file names (but not same file) entered.");
     988            0 :                 ShowContinueError(state, format("...entered file name=\"{}\"", state.dataExternalInterface->FMU(j).Name));
     989            0 :                 ShowContinueError(state, format("...   full file name=\"{}\"", fullFileName(j)));
     990            0 :                 ShowContinueError(state, format("...entered file name=\"{}\"", state.dataExternalInterface->FMU(k).Name));
     991            0 :                 ShowContinueError(state, format("...   full file name=\"{}\"", fullFileName(k)));
     992            0 :                 ShowContinueError(state, "...name collision but not same file name.");
     993            0 :                 state.dataExternalInterface->ErrorsFound = true;
     994              :             }
     995              :         }
     996              : 
     997            0 :         if (state.dataExternalInterface->ErrorsFound) {
     998            0 :             strippedFileName.deallocate();
     999            0 :             fullFileName.deallocate();
    1000            0 :             StopExternalInterfaceIfError(state);
    1001              :         }
    1002              : 
    1003              :         // get the names of the input variables each state.dataExternalInterface->FMU(and the names of the
    1004              :         // corresponding output variables in EnergyPlus --).
    1005            0 :         cCurrentModuleObject = "ExternalInterface:FunctionalMockupUnitImport:From:Variable";
    1006            0 :         int NumFMUInputVariables = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    1007              :         // Determine the number of instances for each FMUs
    1008            0 :         for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1009            0 :             auto &fmu = state.dataExternalInterface->FMU(i);
    1010              : 
    1011            0 :             std::string Name_OLD = "";
    1012            0 :             int j = 1;
    1013            0 :             int k = 1;
    1014            0 :             fmu.Instance.allocate(NumFMUInputVariables);
    1015            0 :             state.dataExternalInterface->checkInstanceName.allocate(NumFMUInputVariables);
    1016            0 :             for (int l = 1; l <= NumFMUInputVariables; ++l) {
    1017            0 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1018              :                                                                          cCurrentModuleObject,
    1019              :                                                                          l,
    1020            0 :                                                                          state.dataIPShortCut->cAlphaArgs,
    1021              :                                                                          NumAlphas,
    1022            0 :                                                                          state.dataIPShortCut->rNumericArgs,
    1023              :                                                                          NumNumbers,
    1024              :                                                                          IOStatus,
    1025              :                                                                          _,
    1026              :                                                                          _,
    1027            0 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    1028            0 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    1029            0 :                 if (Util::SameString(state.dataIPShortCut->cAlphaArgs(3), fmu.Name)) {
    1030            0 :                     std::string Name_NEW = state.dataIPShortCut->cAlphaArgs(4);
    1031            0 :                     if (!Util::SameString(Name_OLD, Name_NEW)) {
    1032            0 :                         int FOUND = Util::FindItem(Name_NEW, state.dataExternalInterface->checkInstanceName);
    1033            0 :                         if (FOUND == 0) {
    1034            0 :                             state.dataExternalInterface->checkInstanceName(l).Name = Name_NEW;
    1035            0 :                             fmu.NumInstances = j;
    1036            0 :                             fmu.Instance(j).Name = Name_NEW;
    1037            0 :                             ++j;
    1038            0 :                             Name_OLD = Name_NEW;
    1039              :                         }
    1040              :                     }
    1041            0 :                     fmu.TotNumInputVariablesInIDF = k;
    1042            0 :                     ++k;
    1043            0 :                 }
    1044              :             }
    1045            0 :             state.dataExternalInterface->checkInstanceName.deallocate();
    1046            0 :         }
    1047              : 
    1048            0 :         for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1049            0 :             auto &fmu = state.dataExternalInterface->FMU(i);
    1050            0 :             if (fmu.NumInstances == 0) {
    1051            0 :                 ShowSevereError(state, format("ExternalInterface/InitExternalInterfaceFMUImport: The FMU \"{}\" does", fmu.Name));
    1052            0 :                 ShowContinueError(state, "not have any instances or any input variable. An FMU should have at least one instance");
    1053            0 :                 ShowContinueError(state, "or one input variable defined in input file. Check FMU object in the input file.");
    1054            0 :                 state.dataExternalInterface->ErrorsFound = true;
    1055            0 :                 StopExternalInterfaceIfError(state);
    1056              :             }
    1057            0 :             if (NumFMUInputVariables > 0 && fmu.TotNumInputVariablesInIDF == 0) {
    1058            0 :                 ShowWarningError(state, format("InitExternalInterfaceFMUImport: The FMU \"{}\"", fmu.Name));
    1059            0 :                 ShowContinueError(state, "is defined but has no input variables.");
    1060            0 :                 ShowContinueError(state, "Check the input field of the corresponding object");
    1061            0 :                 ShowContinueError(state, "ExternalInterface:FunctionalMockupUnitImport:From:Variable.");
    1062              :             }
    1063              :         }
    1064              : 
    1065              :         // write output folder where FMUs will be unpacked later on.
    1066            0 :         for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1067            0 :             auto &fmu = state.dataExternalInterface->FMU(i);
    1068            0 :             for (int j = 1; j <= fmu.NumInstances; ++j) {
    1069            0 :                 auto &fmuInst = fmu.Instance(j);
    1070            0 :                 fmuInst.WorkingFolder = state.dataExternalInterface->FMURootWorkingFolder / fs::path(strippedFileName(i) + '_' + fmuInst.Name);
    1071              :             }
    1072              :         }
    1073              : 
    1074              :         // parse the fmu defined in the idf using the fmuUnpack.
    1075            0 :         for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1076            0 :             auto &fmu = state.dataExternalInterface->FMU(i);
    1077            0 :             for (int j = 1; j <= fmu.NumInstances; ++j) {
    1078            0 :                 auto &fmuInst = fmu.Instance(j);
    1079              :                 // get the length of working folder trimmed
    1080            0 :                 std::string const workingFolderStr = FileSystem::toString(fmuInst.WorkingFolder);
    1081            0 :                 fmuInst.LenWorkingFolder = workingFolderStr.length();
    1082              :                 // unpack fmus
    1083              :                 // preprocess arguments for library call
    1084              :                 {
    1085            0 :                     std::vector<char> fullFileNameArr(getCharArrayFromString(fullFileName(i)));
    1086            0 :                     std::vector<char> workingFolderArr(getCharArrayFromString(workingFolderStr));
    1087            0 :                     int lenFileName(len(fullFileName(i)));
    1088              : 
    1089              :                     // make the library call
    1090            0 :                     int retVal = fmiEPlusUnpack(&fullFileNameArr[0], &workingFolderArr[0], &lenFileName, &fmuInst.LenWorkingFolder);
    1091              : 
    1092            0 :                     if (retVal != 0) {
    1093            0 :                         ShowSevereError(state, "ExternalInterface/InitExternalInterfaceFMUImport: Error when trying to");
    1094            0 :                         ShowContinueError(state, format("unpack the FMU \"{}\".", fmu.Name));
    1095            0 :                         ShowContinueError(state, "Check if the FMU exists. Also check if the FMU folder is not write protected.");
    1096            0 :                         state.dataExternalInterface->ErrorsFound = true;
    1097            0 :                         StopExternalInterfaceIfError(state);
    1098              :                     }
    1099            0 :                 }
    1100              : 
    1101              :                 {
    1102              :                     // determine modelID and modelGUID of all FMU instances
    1103              :                     // preprocess arguments for library call
    1104            0 :                     std::vector<char> workingFolderArr(getCharArrayFromString(workingFolderStr));
    1105              : 
    1106              :                     // make the library call
    1107            0 :                     fmuInst.Index = model_ID_GUID((char *)fmuInst.Name.c_str(),
    1108            0 :                                                   &workingFolderArr[0],
    1109              :                                                   &fmuInst.LenWorkingFolder,
    1110              :                                                   &fmuInst.NumInputVariablesInFMU,
    1111              :                                                   &fmuInst.NumOutputVariablesInFMU);
    1112              : 
    1113            0 :                     if (fmuInst.Index < 0) {
    1114            0 :                         ShowSevereError(state, "ExternalInterface/InitExternalInterfaceFMUImport: Error when trying to");
    1115            0 :                         ShowContinueError(state, "get the model ID and model GUID");
    1116            0 :                         ShowContinueError(state, format("of instance \"{}\" of FMU \"{}\".", fmuInst.Name, fmu.Name));
    1117            0 :                         ShowContinueError(state, "Check if modelDescription.xml exists in the folder where the FMU has been unpacked.");
    1118            0 :                         state.dataExternalInterface->ErrorsFound = true;
    1119            0 :                         StopExternalInterfaceIfError(state);
    1120              :                     }
    1121            0 :                 }
    1122              : 
    1123              :                 {
    1124              :                     // get the path to the binaries
    1125              :                     // preprocess args for library call
    1126            0 :                     std::vector<char> workingFolderArr(getCharArrayFromString(workingFolderStr));
    1127              :                     // Reserve some space in the string, becasue addLibPathCurrentWorkflowFolder doesn't allocate memory for the
    1128              :                     // workingFolderWithLibArr Note: you can't call str.resize(str.length() + 91) because the conversion to std::vector<char> will
    1129              :                     // find the null terminator and so it will have no effect
    1130              :                     std::string reservedString =
    1131            0 :                         workingFolderStr + "                                                                                           ";
    1132            0 :                     std::vector<char> workingFolderWithLibArr(getCharArrayFromString(reservedString));
    1133              : 
    1134              :                     // make the library call
    1135              :                     int retValfmiPathLib =
    1136            0 :                         addLibPathCurrentWorkingFolder(&workingFolderWithLibArr[0], &workingFolderArr[0], &fmuInst.LenWorkingFolder, &fmuInst.Index);
    1137              : 
    1138              :                     // post process args in case they are used later
    1139            0 :                     fmuInst.WorkingFolder_wLib = fs::path(trim(getStringFromCharArray(workingFolderWithLibArr)));
    1140              : 
    1141            0 :                     if (retValfmiPathLib != 0) {
    1142            0 :                         ShowSevereError(state, "ExternalInterface/InitExternalInterfaceFMUImport: Error when trying to");
    1143            0 :                         ShowContinueError(state, "get the path to the binaries of instance");
    1144            0 :                         ShowContinueError(state, format("\"{}\" of FMU \"{}\".", fmuInst.Name, fmu.Name));
    1145            0 :                         ShowContinueError(state, "Check if binaries folder exists where the FMU has been unpacked.");
    1146            0 :                         state.dataExternalInterface->ErrorsFound = true;
    1147            0 :                         StopExternalInterfaceIfError(state);
    1148              :                     }
    1149              : 
    1150              :                     // get the length of the working folder with libraries
    1151            0 :                     fmuInst.LenWorkingFolder_wLib = FileSystem::toString(fmuInst.WorkingFolder_wLib).length();
    1152            0 :                 }
    1153              : 
    1154              :                 {
    1155              :                     // determine the FMI version
    1156              :                     // preprocess args for library call
    1157            0 :                     std::vector<char> workingFolderWithLibArr(getCharArrayFromString(FileSystem::toString(fmuInst.WorkingFolder_wLib)));
    1158              :                     std::vector<char> VersionNumArr(
    1159            0 :                         getCharArrayFromString("    ")); // the version should only be 3 characters long, since for now we only handle "1.0"
    1160              : 
    1161              :                     // make the library call
    1162              :                     int retValfmiVersion =
    1163            0 :                         getfmiEPlusVersion(&workingFolderWithLibArr[0], &fmuInst.LenWorkingFolder_wLib, &VersionNumArr[0], &fmuInst.Index);
    1164              : 
    1165              :                     // post process in case args are used later
    1166            0 :                     fmuInst.fmiVersionNumber = getStringFromCharArray(VersionNumArr);
    1167              : 
    1168            0 :                     if (retValfmiVersion != 0) {
    1169            0 :                         ShowSevereError(state, "ExternalInterface/InitExternalInterfaceFMUImport: Error when trying to");
    1170            0 :                         ShowContinueError(state, "load FMI functions library of instance");
    1171            0 :                         ShowContinueError(state, format("\"{}\" of FMU \"{}\".", fmuInst.Name, fmu.Name));
    1172            0 :                         ShowContinueError(state, format("\"{}\".", fmuInst.fmiVersionNumber));
    1173            0 :                         state.dataExternalInterface->ErrorsFound = true;
    1174            0 :                         StopExternalInterfaceIfError(state);
    1175              :                     }
    1176              : 
    1177            0 :                     if (fmuInst.fmiVersionNumber.substr(0, 3) != "1.0") {
    1178            0 :                         ShowSevereError(state, "ExternalInterface/InitExternalInterfaceFMUImport: Error when getting version");
    1179            0 :                         ShowContinueError(state, format("number of instance \"{}\"", fmuInst.Name));
    1180            0 :                         ShowContinueError(state, format("of FMU \"{}\".", fmu.Name));
    1181            0 :                         ShowContinueError(state, format("The version number found (\"{}\")", fmuInst.fmiVersionNumber.substr(0, 3)));
    1182            0 :                         ShowContinueError(state, "differs from version 1.0 which is currently supported.");
    1183            0 :                         state.dataExternalInterface->ErrorsFound = true;
    1184            0 :                         StopExternalInterfaceIfError(state);
    1185              :                     }
    1186            0 :                 }
    1187            0 :             }
    1188              :         }
    1189              : 
    1190            0 :         strippedFileName.deallocate();
    1191            0 :         fullFileName.deallocate();
    1192              : 
    1193            0 :         state.dataExternalInterface->UniqueFMUInputVarNames.reserve(static_cast<unsigned>(NumFMUInputVariables));
    1194            0 :         for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1195            0 :             auto &fmu = state.dataExternalInterface->FMU(i);
    1196            0 :             for (int j = 1; j <= fmu.NumInstances; ++j) {
    1197            0 :                 auto &fmuInst = fmu.Instance(j);
    1198            0 :                 fmuInst.fmuInputVariable.allocate(NumFMUInputVariables);
    1199            0 :                 fmuInst.checkfmuInputVariable.allocate(NumFMUInputVariables);
    1200            0 :                 state.dataExternalInterface->UniqueFMUInputVarNames.clear();
    1201            0 :                 fmuInst.eplusOutputVariable.allocate(NumFMUInputVariables);
    1202            0 :                 int k = 1;
    1203            0 :                 for (int l = 1; l <= NumFMUInputVariables; ++l) {
    1204            0 :                     state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1205              :                                                                              cCurrentModuleObject,
    1206              :                                                                              l,
    1207            0 :                                                                              state.dataIPShortCut->cAlphaArgs,
    1208              :                                                                              NumAlphas,
    1209            0 :                                                                              state.dataIPShortCut->rNumericArgs,
    1210              :                                                                              NumNumbers,
    1211              :                                                                              IOStatus,
    1212              :                                                                              _,
    1213              :                                                                              _,
    1214            0 :                                                                              state.dataIPShortCut->cAlphaFieldNames,
    1215            0 :                                                                              state.dataIPShortCut->cNumericFieldNames);
    1216            0 :                     if (Util::SameString(state.dataIPShortCut->cAlphaArgs(3), fmu.Name) &&
    1217            0 :                         Util::SameString(state.dataIPShortCut->cAlphaArgs(4), fmuInst.Name)) {
    1218            0 :                         fmuInst.fmuInputVariable(k).Name = state.dataIPShortCut->cAlphaArgs(5);
    1219            0 :                         fmuInst.eplusOutputVariable(k).VarKey = state.dataIPShortCut->cAlphaArgs(1);
    1220            0 :                         fmuInst.eplusOutputVariable(k).Name = state.dataIPShortCut->cAlphaArgs(2);
    1221              :                         // verify whether we have duplicate FMU input variables in the idf
    1222            0 :                         GlobalNames::VerifyUniqueInterObjectName(state,
    1223            0 :                                                                  state.dataExternalInterface->UniqueFMUInputVarNames,
    1224            0 :                                                                  fmuInst.fmuInputVariable(k).Name,
    1225              :                                                                  cCurrentModuleObject,
    1226              :                                                                  fmuInst.Name,
    1227            0 :                                                                  state.dataExternalInterface->ErrorsFound);
    1228              :                         //                            Util::VerifyName( state.dataExternalInterface->FMU( i ).Instance( j
    1229              :                         //                            ).fmuInputVariable(
    1230              :                         // k
    1231              :                         //).Name,  state.dataExternalInterface->FMU(
    1232              :                         // i
    1233              :                         //).Instance(
    1234              :                         // j
    1235              :                         //).checkfmuInputVariable, NumFMUInputVariables, IsNotOK, IsBlank, "The FMU input variable \"" +
    1236              :                         // state.dataExternalInterface->FMU( i ).Instance( j
    1237              :                         //).fmuInputVariable( k ).Name + "\" of instance \"" + state.dataExternalInterface->FMU( i ).Instance( j ).Name + "\" of FMU
    1238              :                         //\"" + state.dataExternalInterface->FMU( i ).Name + "\"
    1239              :                         // has duplicates. Please check the input file again and delete duplicated entries." );
    1240            0 :                         if (state.dataExternalInterface->ErrorsFound) {
    1241            0 :                             StopExternalInterfaceIfError(state);
    1242              :                         } else {
    1243            0 :                             fmuInst.checkfmuInputVariable(k).Name = fmuInst.fmuInputVariable(k).Name;
    1244              :                         }
    1245              : 
    1246              :                         // preprocess args for library call
    1247            0 :                         std::vector<char> inputVarNameArr(getCharArrayFromString(fmuInst.fmuInputVariable(k).Name));
    1248            0 :                         int inputVarNameLen(len(fmuInst.fmuInputVariable(k).Name));
    1249              : 
    1250              :                         // make the library call
    1251            0 :                         fmuInst.fmuInputVariable(k).ValueReference =
    1252            0 :                             getValueReferenceByNameFMUInputVariables(&inputVarNameArr[0], &inputVarNameLen, &fmuInst.Index);
    1253              : 
    1254              :                         // postprocess args in case they are used later
    1255            0 :                         fmuInst.fmuInputVariable(k).Name = getStringFromCharArray(inputVarNameArr);
    1256              : 
    1257            0 :                         if (fmuInst.fmuInputVariable(k).ValueReference == -999) {
    1258            0 :                             ShowSevereError(state, "ExternalInterface/InitExternalInterfaceFMUImport: Error when trying to");
    1259            0 :                             ShowContinueError(state, "get the value reference of FMU input variable");
    1260            0 :                             ShowContinueError(state, format("\"{}\" of instance \"{}\" of FMU", fmuInst.fmuInputVariable(k).Name, fmuInst.Name));
    1261            0 :                             ShowContinueError(state, format("of FMU \"{}\". Please check the name of input variable", fmu.Name));
    1262            0 :                             ShowContinueError(state, "in the input file and in the modelDescription file.");
    1263            0 :                             state.dataExternalInterface->ErrorsFound = true;
    1264            0 :                             StopExternalInterfaceIfError(state);
    1265              :                         }
    1266              : 
    1267            0 :                         if (fmuInst.fmuInputVariable(k).ValueReference == -1) {
    1268            0 :                             ShowSevereError(state, "ExternalInterface/InitExternalInterfaceFMUImport: Error when trying to");
    1269            0 :                             ShowContinueError(state, "get the value reference of FMU input variable");
    1270            0 :                             ShowContinueError(state, format("\"{}\" of instance \"{}\" of FMU", fmuInst.fmuInputVariable(k).Name, fmuInst.Name));
    1271            0 :                             ShowContinueError(state, format("\"{}\". This variable is not an FMU input variable.", fmu.Name));
    1272            0 :                             ShowContinueError(state, "Please check the causality of the variable in the modelDescription file.");
    1273            0 :                             state.dataExternalInterface->ErrorsFound = true;
    1274            0 :                             StopExternalInterfaceIfError(state);
    1275              :                         }
    1276              : 
    1277              :                         // The next call expects an array, but a single item is passed
    1278              :                         // Therefore create a single item array here first
    1279            0 :                         Array1D_string tempSingleStringA(1, fmuInst.eplusOutputVariable(k).VarKey);
    1280            0 :                         Array1D_string tempSingleStringB(1, fmuInst.eplusOutputVariable(k).Name);
    1281              : 
    1282              :                         // Make the call with arrays
    1283            0 :                         GetReportVariableKey(state, tempSingleStringA, 1, tempSingleStringB, keyIndexes, varTypes);
    1284              : 
    1285              :                         // Then postprocess the array items back in case they changed
    1286            0 :                         fmuInst.eplusOutputVariable(k).VarKey = tempSingleStringA(1);
    1287            0 :                         fmuInst.eplusOutputVariable(k).Name = tempSingleStringB(1);
    1288              : 
    1289            0 :                         fmuInst.eplusOutputVariable(k).VarIndex = keyIndexes(1);
    1290            0 :                         fmuInst.eplusOutputVariable(k).VarType = varTypes(1);
    1291            0 :                         fmuInst.NumInputVariablesInIDF = k;
    1292            0 :                         ++k;
    1293            0 :                     }
    1294              :                 }
    1295              : 
    1296            0 :                 if (NumFMUInputVariables > 0 && fmuInst.NumInputVariablesInIDF == 0) {
    1297            0 :                     ShowWarningError(state, format("InitExternalInterfaceFMUImport: The instance \"{}\" of FMU \"{}\"", fmuInst.Name, fmu.Name));
    1298            0 :                     ShowContinueError(state, "is defined but has no input variables. Check the input field of the");
    1299            0 :                     ShowContinueError(state, "corresponding object: ExternalInterface:FunctionalMockupUnitImport:From:Variable.");
    1300              :                 }
    1301              :             }
    1302              :         }
    1303              : 
    1304            0 :         for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1305            0 :             auto &fmu = state.dataExternalInterface->FMU(i);
    1306            0 :             for (int j = 1; j <= fmu.NumInstances; ++j) {
    1307            0 :                 auto &fmuInst = fmu.Instance(j);
    1308              :                 // check whether the number of input variables in fmu is bigger than in the idf
    1309            0 :                 if (fmuInst.NumInputVariablesInFMU > fmuInst.NumInputVariablesInIDF) {
    1310            0 :                     ShowWarningError(state,
    1311            0 :                                      format("InitExternalInterfaceFMUImport: The number of input variables defined in input file ({})",
    1312            0 :                                             fmuInst.NumInputVariablesInIDF));
    1313            0 :                     ShowContinueError(state,
    1314            0 :                                       format("of instance \"{}\" of FMU \"{}\" is less than the number of input variables", fmuInst.Name, fmu.Name));
    1315            0 :                     ShowContinueError(state, format("in the modelDescription file ({}).", fmuInst.NumInputVariablesInFMU));
    1316            0 :                     ShowContinueError(state, "Check the input file and the modelDescription file again.");
    1317              :                 }
    1318              :                 // check whether the number of input variables in fmu is less than in the idf
    1319            0 :                 if (fmuInst.NumInputVariablesInFMU < fmuInst.NumInputVariablesInIDF) {
    1320            0 :                     ShowWarningError(state,
    1321            0 :                                      format("InitExternalInterfaceFMUImport: The number of input variables defined in input file ({})",
    1322            0 :                                             fmuInst.NumInputVariablesInIDF));
    1323            0 :                     ShowContinueError(
    1324            0 :                         state, format("of instance \"{}\" of FMU \"{}\" is bigger than the number of input variables", fmuInst.Name, fmu.Name));
    1325            0 :                     ShowContinueError(state, format("in the modelDescription file ({}).", fmuInst.NumInputVariablesInFMU));
    1326            0 :                     ShowContinueError(state, "Check the input file and the modelDescription file again.");
    1327              :                 }
    1328              :             }
    1329              :         }
    1330              : 
    1331              :         // get the names of the output variables each fmu (and the names of the
    1332              :         // corresponding input variables in EnergyPlus -- schedule).
    1333            0 :         cCurrentModuleObject = "ExternalInterface:FunctionalMockupUnitImport:To:Schedule";
    1334            0 :         NumFMUInputVariables = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    1335              : 
    1336            0 :         for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1337            0 :             auto &fmu = state.dataExternalInterface->FMU(i);
    1338            0 :             int j = 1;
    1339            0 :             for (int k = 1; k <= NumFMUInputVariables; ++k) {
    1340            0 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1341              :                                                                          cCurrentModuleObject,
    1342              :                                                                          k,
    1343            0 :                                                                          state.dataIPShortCut->cAlphaArgs,
    1344              :                                                                          NumAlphas,
    1345            0 :                                                                          state.dataIPShortCut->rNumericArgs,
    1346              :                                                                          NumNumbers,
    1347              :                                                                          IOStatus,
    1348              :                                                                          _,
    1349              :                                                                          _,
    1350            0 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    1351            0 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    1352            0 :                 if (Util::SameString(state.dataIPShortCut->cAlphaArgs(3), fmu.Name)) {
    1353            0 :                     fmu.TotNumOutputVariablesSchedule = j;
    1354            0 :                     ++j;
    1355              :                 }
    1356              :             }
    1357              :         }
    1358              : 
    1359            0 :         for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1360            0 :             auto &fmu = state.dataExternalInterface->FMU(i);
    1361            0 :             for (int j = 1; j <= fmu.NumInstances; ++j) {
    1362            0 :                 auto &fmuInst = fmu.Instance(j);
    1363            0 :                 fmuInst.fmuOutputVariableSchedule.allocate(NumFMUInputVariables);
    1364            0 :                 fmuInst.eplusInputVariableSchedule.allocate(NumFMUInputVariables);
    1365            0 :                 int k = 1;
    1366            0 :                 for (int l = 1; l <= NumFMUInputVariables; ++l) {
    1367            0 :                     state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1368              :                                                                              cCurrentModuleObject,
    1369              :                                                                              l,
    1370            0 :                                                                              state.dataIPShortCut->cAlphaArgs,
    1371              :                                                                              NumAlphas,
    1372            0 :                                                                              state.dataIPShortCut->rNumericArgs,
    1373              :                                                                              NumNumbers,
    1374              :                                                                              IOStatus,
    1375              :                                                                              _,
    1376              :                                                                              _,
    1377            0 :                                                                              state.dataIPShortCut->cAlphaFieldNames,
    1378            0 :                                                                              state.dataIPShortCut->cNumericFieldNames);
    1379            0 :                     if (Util::SameString(state.dataIPShortCut->cAlphaArgs(3), fmu.Name) &&
    1380            0 :                         Util::SameString(state.dataIPShortCut->cAlphaArgs(4), fmuInst.Name)) {
    1381            0 :                         fmuInst.fmuOutputVariableSchedule(k).Name = state.dataIPShortCut->cAlphaArgs(5);
    1382            0 :                         fmuInst.eplusInputVariableSchedule(k).Name = state.dataIPShortCut->cAlphaArgs(1);
    1383            0 :                         fmuInst.eplusInputVariableSchedule(k).InitialValue = state.dataIPShortCut->rNumericArgs(1);
    1384              : 
    1385              :                         // get the value reference by using the FMU name and the variable name.
    1386              : 
    1387              :                         // preprocess the arguments before the following library call
    1388            0 :                         std::vector<char> NameCharArr(getCharArrayFromString(fmuInst.fmuOutputVariableSchedule(k).Name));
    1389            0 :                         int lengthVar(len(fmuInst.fmuOutputVariableSchedule(k).Name));
    1390              : 
    1391              :                         // make the library call
    1392            0 :                         fmuInst.fmuOutputVariableSchedule(k).ValueReference =
    1393            0 :                             getValueReferenceByNameFMUOutputVariables(&NameCharArr[0], &lengthVar, &fmuInst.Index);
    1394              : 
    1395              :                         // postprocess the arguments after the library call in case they are changed and used later
    1396            0 :                         fmuInst.fmuOutputVariableSchedule(k).Name = getStringFromCharArray(NameCharArr);
    1397              : 
    1398            0 :                         if (fmuInst.fmuOutputVariableSchedule(k).ValueReference == -999) {
    1399            0 :                             ShowSevereError(state,
    1400              :                                             "ExternalInterface/InitExternalInterfaceFMUImport: Error when trying to get the value reference of "
    1401              :                                             "the FMU output variable");
    1402            0 :                             ShowContinueError(state, format("\"{}\" of instance \"{}\"", fmuInst.fmuOutputVariableSchedule(k).Name, fmuInst.Name));
    1403            0 :                             ShowContinueError(state, format("of FMU \"{}\" that will be mapped to a schedule.", fmu.Name));
    1404            0 :                             ShowContinueError(state, "Please check the name of output variables in the input file and");
    1405            0 :                             ShowContinueError(state, "in the modelDescription file.");
    1406            0 :                             state.dataExternalInterface->ErrorsFound = true;
    1407            0 :                             StopExternalInterfaceIfError(state);
    1408              :                         }
    1409              : 
    1410            0 :                         if (fmuInst.fmuOutputVariableSchedule(k).ValueReference == -1) {
    1411            0 :                             ShowSevereError(state,
    1412              :                                             "ExternalInterface/InitExternalInterfaceFMUImport: Error when trying to get the value reference of "
    1413              :                                             "the FMU output variable");
    1414            0 :                             ShowContinueError(state, format("\"{}\" of instance \"{}\"", fmuInst.fmuOutputVariableSchedule(k).Name, fmuInst.Name));
    1415            0 :                             ShowContinueError(state, format("of FMU \"{}\" that will be mapped to a schedule.", fmu.Name));
    1416            0 :                             ShowContinueError(state, "This variable is not an FMU output variable.");
    1417            0 :                             ShowContinueError(state, "Please check the causality of the variable in the modelDescription file.");
    1418            0 :                             state.dataExternalInterface->ErrorsFound = true;
    1419            0 :                             StopExternalInterfaceIfError(state);
    1420              :                         }
    1421              : 
    1422            0 :                         fmuInst.eplusInputVariableSchedule(k).VarIndex = Sched::GetScheduleNum(state, fmuInst.eplusInputVariableSchedule(k).Name);
    1423            0 :                         fmuInst.NumOutputVariablesSchedule = k;
    1424            0 :                         if (fmuInst.eplusInputVariableSchedule(k).VarIndex <= 0) {
    1425            0 :                             ShowSevereError(state,
    1426            0 :                                             format("ExternalInterface/InitExternalInterfaceFMUImport:declares variable \"{}\",",
    1427            0 :                                                    fmuInst.eplusInputVariableSchedule(k).Name));
    1428            0 :                             ShowContinueError(state, "but variable is not a schedule variable.");
    1429            0 :                             state.dataExternalInterface->ErrorsFound = true;
    1430            0 :                             StopExternalInterfaceIfError(state);
    1431              :                         }
    1432            0 :                         ++k;
    1433            0 :                     }
    1434              :                 }
    1435              :             }
    1436              :         }
    1437              : 
    1438              :         // get the names of the output variables each fmu (and the names of the
    1439              :         // corresponding input variables in EnergyPlus -- variable).
    1440            0 :         cCurrentModuleObject = "ExternalInterface:FunctionalMockupUnitImport:To:Variable";
    1441            0 :         NumFMUInputVariables = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    1442              : 
    1443            0 :         for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1444            0 :             auto &fmu = state.dataExternalInterface->FMU(i);
    1445            0 :             int j = 1;
    1446            0 :             for (int k = 1; k <= NumFMUInputVariables; ++k) {
    1447            0 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1448              :                                                                          cCurrentModuleObject,
    1449              :                                                                          k,
    1450            0 :                                                                          state.dataIPShortCut->cAlphaArgs,
    1451              :                                                                          NumAlphas,
    1452            0 :                                                                          state.dataIPShortCut->rNumericArgs,
    1453              :                                                                          NumNumbers,
    1454              :                                                                          IOStatus,
    1455              :                                                                          _,
    1456              :                                                                          _,
    1457            0 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    1458            0 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    1459            0 :                 if (Util::SameString(state.dataIPShortCut->cAlphaArgs(2), fmu.Name)) {
    1460            0 :                     fmu.TotNumOutputVariablesVariable = j;
    1461            0 :                     ++j;
    1462              :                 }
    1463              :             }
    1464              :         }
    1465              : 
    1466            0 :         for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1467            0 :             auto &fmu = state.dataExternalInterface->FMU(i);
    1468            0 :             for (int j = 1; j <= fmu.NumInstances; ++j) {
    1469            0 :                 auto &fmuInst = fmu.Instance(j);
    1470            0 :                 fmuInst.fmuOutputVariableVariable.allocate(NumFMUInputVariables);
    1471            0 :                 fmuInst.eplusInputVariableVariable.allocate(NumFMUInputVariables);
    1472            0 :                 int k = 1;
    1473            0 :                 for (int l = 1; l <= NumFMUInputVariables; ++l) {
    1474            0 :                     state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1475              :                                                                              cCurrentModuleObject,
    1476              :                                                                              l,
    1477            0 :                                                                              state.dataIPShortCut->cAlphaArgs,
    1478              :                                                                              NumAlphas,
    1479            0 :                                                                              state.dataIPShortCut->rNumericArgs,
    1480              :                                                                              NumNumbers,
    1481              :                                                                              IOStatus,
    1482              :                                                                              _,
    1483              :                                                                              _,
    1484            0 :                                                                              state.dataIPShortCut->cAlphaFieldNames,
    1485            0 :                                                                              state.dataIPShortCut->cNumericFieldNames);
    1486            0 :                     if (Util::SameString(state.dataIPShortCut->cAlphaArgs(2), fmu.Name) &&
    1487            0 :                         Util::SameString(state.dataIPShortCut->cAlphaArgs(3), fmuInst.Name)) {
    1488            0 :                         fmuInst.fmuOutputVariableVariable(k).Name = state.dataIPShortCut->cAlphaArgs(4);
    1489            0 :                         fmuInst.eplusInputVariableVariable(k).Name = state.dataIPShortCut->cAlphaArgs(1);
    1490              : 
    1491              :                         // get the value reference by using the FMU name and the variable name.
    1492            0 :                         std::vector<char> NameCharArr(getCharArrayFromString(fmuInst.fmuOutputVariableVariable(k).Name));
    1493            0 :                         int tempLength(len(fmuInst.fmuOutputVariableVariable(k).Name));
    1494            0 :                         fmuInst.fmuOutputVariableVariable(k).ValueReference =
    1495            0 :                             getValueReferenceByNameFMUOutputVariables(&NameCharArr[0], &tempLength, &fmuInst.Index);
    1496              :                         // state.dataExternalInterface->FMU( i ).Instance( j ).fmuOutputVariableVariable( k ).Name = getStringFromCharArray(
    1497              :                         // NameCharArr );
    1498              : 
    1499            0 :                         if (fmuInst.fmuOutputVariableVariable(k).ValueReference == -999) {
    1500            0 :                             ShowSevereError(state,
    1501              :                                             "ExternalInterface/InitExternalInterfaceFMUImport: Error when trying to get the value reference of "
    1502              :                                             "the FMU output variable");
    1503            0 :                             ShowContinueError(state, format("\"{}\" of instance \"{}\"", fmuInst.fmuOutputVariableVariable(k).Name, fmuInst.Name));
    1504            0 :                             ShowContinueError(state, format("of FMU \"{}\" that will be mapped to a variable.", fmu.Name));
    1505            0 :                             ShowContinueError(state, "Please check the name of output variables in the input file and in the modelDescription file.");
    1506            0 :                             state.dataExternalInterface->ErrorsFound = true;
    1507            0 :                             StopExternalInterfaceIfError(state);
    1508              :                         }
    1509              : 
    1510            0 :                         if (fmuInst.fmuOutputVariableVariable(k).ValueReference == -1) {
    1511            0 :                             ShowSevereError(state,
    1512              :                                             "ExternalInterface/InitExternalInterfaceFMUImport: Error when trying to get the value reference of "
    1513              :                                             "the FMU output variable");
    1514            0 :                             ShowContinueError(state, format("\"{}\" of instance \"{}\"", fmuInst.fmuOutputVariableVariable(k).Name, fmuInst.Name));
    1515            0 :                             ShowContinueError(state, format("of FMU \"{}\" that will be mapped to a variable.", fmu.Name));
    1516            0 :                             ShowContinueError(state,
    1517              :                                               "This variable is not an FMU output variable. Please check the causality of the variable in the "
    1518              :                                               "modelDescription file.");
    1519            0 :                             state.dataExternalInterface->ErrorsFound = true;
    1520            0 :                             StopExternalInterfaceIfError(state);
    1521              :                         }
    1522              : 
    1523            0 :                         fmuInst.eplusInputVariableVariable(k).VarIndex =
    1524            0 :                             RuntimeLanguageProcessor::FindEMSVariable(state, fmuInst.eplusInputVariableVariable(k).Name, 0);
    1525            0 :                         fmuInst.NumOutputVariablesVariable = k;
    1526            0 :                         if (fmuInst.eplusInputVariableVariable(k).VarIndex <= 0) {
    1527            0 :                             ShowSevereError(state,
    1528            0 :                                             format("ExternalInterface/InitExternalInterfaceFMUImport:declares variable \"{}\",",
    1529            0 :                                                    fmuInst.eplusInputVariableVariable(k).Name));
    1530            0 :                             ShowContinueError(state, "but variable is not an EMS variable.");
    1531            0 :                             state.dataExternalInterface->ErrorsFound = true;
    1532            0 :                             StopExternalInterfaceIfError(state);
    1533              :                         }
    1534            0 :                         ++k;
    1535            0 :                     }
    1536              :                 }
    1537            0 :                 if (fmuInst.NumOutputVariablesVariable >= 1) {
    1538            0 :                     state.dataExternalInterface->useEMS = true;
    1539              :                 }
    1540              :             }
    1541              :         }
    1542              : 
    1543              :         // get the names of the output variables each fmu (and the names of the
    1544              :         // corresponding input variables in EnergyPlus -- actuator).
    1545            0 :         cCurrentModuleObject = "ExternalInterface:FunctionalMockupUnitImport:To:Actuator";
    1546            0 :         NumFMUInputVariables = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    1547              : 
    1548            0 :         for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1549            0 :             auto &fmu = state.dataExternalInterface->FMU(i);
    1550            0 :             int j = 1;
    1551            0 :             for (int k = 1; k <= NumFMUInputVariables; ++k) {
    1552            0 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1553              :                                                                          cCurrentModuleObject,
    1554              :                                                                          k,
    1555            0 :                                                                          state.dataIPShortCut->cAlphaArgs,
    1556              :                                                                          NumAlphas,
    1557            0 :                                                                          state.dataIPShortCut->rNumericArgs,
    1558              :                                                                          NumNumbers,
    1559              :                                                                          IOStatus,
    1560              :                                                                          _,
    1561              :                                                                          _,
    1562            0 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    1563            0 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    1564            0 :                 if (Util::SameString(state.dataIPShortCut->cAlphaArgs(5), fmu.Name)) {
    1565            0 :                     fmu.TotNumOutputVariablesActuator = j;
    1566            0 :                     ++j;
    1567              :                 }
    1568              :             }
    1569              :         }
    1570              : 
    1571            0 :         for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1572            0 :             auto &fmu = state.dataExternalInterface->FMU(i);
    1573            0 :             for (int j = 1; j <= fmu.NumInstances; ++j) {
    1574            0 :                 auto &fmuInst = fmu.Instance(j);
    1575            0 :                 fmuInst.fmuOutputVariableActuator.allocate(NumFMUInputVariables);
    1576            0 :                 fmuInst.eplusInputVariableActuator.allocate(NumFMUInputVariables);
    1577            0 :                 int k = 1;
    1578            0 :                 for (int l = 1; l <= NumFMUInputVariables; ++l) {
    1579            0 :                     state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1580              :                                                                              cCurrentModuleObject,
    1581              :                                                                              l,
    1582            0 :                                                                              state.dataIPShortCut->cAlphaArgs,
    1583              :                                                                              NumAlphas,
    1584            0 :                                                                              state.dataIPShortCut->rNumericArgs,
    1585              :                                                                              NumNumbers,
    1586              :                                                                              IOStatus,
    1587              :                                                                              _,
    1588              :                                                                              _,
    1589            0 :                                                                              state.dataIPShortCut->cAlphaFieldNames,
    1590            0 :                                                                              state.dataIPShortCut->cNumericFieldNames);
    1591            0 :                     if (Util::SameString(state.dataIPShortCut->cAlphaArgs(5), fmu.Name) &&
    1592            0 :                         Util::SameString(state.dataIPShortCut->cAlphaArgs(6), fmuInst.Name)) {
    1593            0 :                         fmuInst.fmuOutputVariableActuator(k).Name = state.dataIPShortCut->cAlphaArgs(7);
    1594            0 :                         fmuInst.eplusInputVariableActuator(k).Name = state.dataIPShortCut->cAlphaArgs(1);
    1595              : 
    1596              :                         // get the value reference by using the FMU name and the variable name.
    1597            0 :                         std::vector<char> tempNameArr(getCharArrayFromString(fmuInst.fmuOutputVariableActuator(k).Name));
    1598            0 :                         int tempLength(len(fmuInst.fmuOutputVariableActuator(k).Name));
    1599            0 :                         fmuInst.fmuOutputVariableActuator(k).ValueReference =
    1600            0 :                             getValueReferenceByNameFMUOutputVariables(&tempNameArr[0], &tempLength, &fmuInst.Index);
    1601              :                         // state.dataExternalInterface->FMU( i ).Instance( j ).fmuOutputVariableActuator( k ).Name = getStringFromCharArray(
    1602              :                         // tempNameArr );
    1603              : 
    1604            0 :                         if (fmuInst.fmuOutputVariableActuator(k).ValueReference == -999) {
    1605            0 :                             ShowSevereError(state,
    1606              :                                             "ExternalInterface/InitExternalInterfaceFMUImport: Error when trying to get the value reference of "
    1607              :                                             "the FMU output variable");
    1608            0 :                             ShowContinueError(state, format("\"{}\" of instance \"{}\"", fmuInst.fmuOutputVariableActuator(k).Name, fmuInst.Name));
    1609            0 :                             ShowContinueError(state, format("of FMU \"{}\" that will be mapped to an actuator.", fmu.Name));
    1610            0 :                             ShowContinueError(state, "Please check the name of output variables in the input file and in the modelDescription file.");
    1611            0 :                             state.dataExternalInterface->ErrorsFound = true;
    1612            0 :                             StopExternalInterfaceIfError(state);
    1613              :                         }
    1614              : 
    1615            0 :                         if (fmuInst.fmuOutputVariableActuator(k).ValueReference == -1) {
    1616            0 :                             ShowSevereError(state,
    1617              :                                             "ExternalInterface/InitExternalInterfaceFMUImport: Error when trying to get the value reference of "
    1618              :                                             "the FMU output variable");
    1619            0 :                             ShowContinueError(state, format("\"{}\" of instance \"{}\"", fmuInst.fmuOutputVariableActuator(k).Name, fmuInst.Name));
    1620            0 :                             ShowContinueError(state, format("of FMU \"{}\" that will be mapped to an actuator.", fmu.Name));
    1621            0 :                             ShowContinueError(state,
    1622              :                                               "This variable is not an FMU output variable. Please check the causality of the variable in the "
    1623              :                                               "modelDescription file.");
    1624            0 :                             state.dataExternalInterface->ErrorsFound = true;
    1625            0 :                             StopExternalInterfaceIfError(state);
    1626              :                         }
    1627              : 
    1628            0 :                         fmuInst.eplusInputVariableActuator(k).VarIndex =
    1629            0 :                             RuntimeLanguageProcessor::FindEMSVariable(state, fmuInst.eplusInputVariableActuator(k).Name, 0);
    1630            0 :                         fmuInst.NumOutputVariablesActuator = k;
    1631            0 :                         if (fmuInst.eplusInputVariableActuator(k).VarIndex <= 0) {
    1632            0 :                             ShowSevereError(state,
    1633            0 :                                             format("ExternalInterface/InitExternalInterfaceFMUImport:declares variable \"{}\",",
    1634            0 :                                                    fmuInst.eplusInputVariableActuator(k).Name));
    1635            0 :                             ShowContinueError(state, "but variable is not an EMS variable.");
    1636            0 :                             state.dataExternalInterface->ErrorsFound = true;
    1637            0 :                             StopExternalInterfaceIfError(state);
    1638              :                         }
    1639            0 :                         ++k;
    1640            0 :                     }
    1641              :                 }
    1642              :                 // set the flag state.dataExternalInterface->useEMS to true. This will be used then to update the erl variables in erl data structure
    1643            0 :                 if (fmuInst.NumOutputVariablesActuator >= 1) {
    1644            0 :                     state.dataExternalInterface->useEMS = true;
    1645              :                 }
    1646              :             }
    1647              :         }
    1648              : 
    1649              :         // parse the fmu defined in the idf using the fmuUnpack with the flag --unpack.
    1650            0 :         for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1651            0 :             auto &fmu = state.dataExternalInterface->FMU(i);
    1652            0 :             for (int j = 1; j <= fmu.NumInstances; ++j) {
    1653            0 :                 auto &fmuInst = fmu.Instance(j);
    1654            0 :                 fmuInst.NumOutputVariablesInIDF =
    1655            0 :                     fmuInst.NumOutputVariablesSchedule + fmuInst.NumOutputVariablesVariable + fmuInst.NumOutputVariablesActuator;
    1656              :                 // check whether the number of output variables in fmu is bigger than in the idf
    1657            0 :                 if (fmuInst.NumOutputVariablesInFMU > fmuInst.NumOutputVariablesInIDF) {
    1658            0 :                     ShowWarningError(state,
    1659            0 :                                      format("InitExternalInterfaceFMUImport: The number of output variables defined in input file ({})",
    1660            0 :                                             fmuInst.NumOutputVariablesInIDF));
    1661            0 :                     ShowContinueError(state,
    1662            0 :                                       format("of instance \"{}\" of FMU \"{}\" is less than the number of output variables", fmuInst.Name, fmu.Name));
    1663            0 :                     ShowContinueError(state, format("in the modelDescription file ({}).", fmuInst.NumOutputVariablesInFMU));
    1664            0 :                     ShowContinueError(state, "Check the input file and the modelDescription file again.");
    1665              :                 }
    1666              :                 // check whether the number of output variables in fmu is less than in the idf
    1667            0 :                 if (fmuInst.NumOutputVariablesInFMU < fmuInst.NumOutputVariablesInIDF) {
    1668            0 :                     ShowWarningError(state,
    1669            0 :                                      format("InitExternalInterfaceFMUImport: The number of output variables defined in input file ({})",
    1670            0 :                                             fmuInst.NumOutputVariablesInIDF));
    1671            0 :                     ShowContinueError(
    1672            0 :                         state, format("of instance \"{}\" of FMU \"{}\" is bigger than the number of output variables", fmuInst.Name, fmu.Name));
    1673            0 :                     ShowContinueError(state, format("in the modelDescription file ({}).", fmuInst.NumOutputVariablesInFMU));
    1674            0 :                     ShowContinueError(state, "Check the input file and the modelDescription file again.");
    1675              :                 }
    1676              : 
    1677            0 :                 DisplayString(
    1678              :                     state,
    1679            0 :                     format("Number of inputs in instance \"{}\" of FMU \"{}\" = \"{}\".", fmuInst.Name, fmu.Name, fmuInst.NumInputVariablesInIDF));
    1680            0 :                 DisplayString(
    1681              :                     state,
    1682            0 :                     format("Number of outputs in instance \"{}\" of FMU \"{}\" = \"{}\".", fmuInst.Name, fmu.Name, fmuInst.NumOutputVariablesInIDF));
    1683              :             }
    1684              :         }
    1685            0 :         StopExternalInterfaceIfError(state);
    1686            0 :         state.dataExternalInterface->FirstCallIni = false;
    1687              :     }
    1688            0 : }
    1689              : 
    1690            0 : std::string trim(std::string const &str)
    1691              : {
    1692            0 :     std::size_t first = str.find_first_not_of(' ');
    1693            0 :     std::size_t last = str.find_last_not_of(' ');
    1694            0 :     return str.substr(first, last - first + 1);
    1695              : }
    1696              : 
    1697            0 : Real64 GetCurSimStartTimeSeconds(const EnergyPlusData &state)
    1698              : {
    1699              :     // FUNCTION INFORMATION:
    1700              :     //       AUTHOR         Thierry S. Nouidui, Michael Wetter, Wangda Zuo
    1701              :     //       DATE WRITTEN   August 2011
    1702              : 
    1703              :     // PURPOSE OF THIS FUNCTION:
    1704              :     //  Get the current month and day in the runperiod and convert
    1705              :     //  it into seconds.
    1706              : 
    1707              :     // Locals
    1708              :     Real64 simtime;
    1709              : 
    1710            0 :     if (!state.dataEnvrn->CurrentYearIsLeapYear) {
    1711            0 :         switch (state.dataEnvrn->Month) {
    1712            0 :         case 1:
    1713            0 :             simtime = 0;
    1714            0 :             break;
    1715            0 :         case 2:
    1716            0 :             simtime = 31;
    1717            0 :             break;
    1718            0 :         case 3:
    1719            0 :             simtime = 59;
    1720            0 :             break;
    1721            0 :         case 4:
    1722            0 :             simtime = 90;
    1723            0 :             break;
    1724            0 :         case 5:
    1725            0 :             simtime = 120;
    1726            0 :             break;
    1727            0 :         case 6:
    1728            0 :             simtime = 151;
    1729            0 :             break;
    1730            0 :         case 7:
    1731            0 :             simtime = 181;
    1732            0 :             break;
    1733            0 :         case 8:
    1734            0 :             simtime = 212;
    1735            0 :             break;
    1736            0 :         case 9:
    1737            0 :             simtime = 243;
    1738            0 :             break;
    1739            0 :         case 10:
    1740            0 :             simtime = 273;
    1741            0 :             break;
    1742            0 :         case 11:
    1743            0 :             simtime = 304;
    1744            0 :             break;
    1745            0 :         case 12:
    1746            0 :             simtime = 334;
    1747            0 :             break;
    1748            0 :         default:
    1749            0 :             simtime = 0;
    1750              :         }
    1751              :     } else {
    1752            0 :         switch (state.dataEnvrn->Month) {
    1753            0 :         case 1:
    1754            0 :             simtime = 0;
    1755            0 :             break;
    1756            0 :         case 2:
    1757            0 :             simtime = 31;
    1758            0 :             break;
    1759            0 :         case 3:
    1760            0 :             simtime = 59 + 1;
    1761            0 :             break;
    1762            0 :         case 4:
    1763            0 :             simtime = 90 + 1;
    1764            0 :             break;
    1765            0 :         case 5:
    1766            0 :             simtime = 120 + 1;
    1767            0 :             break;
    1768            0 :         case 6:
    1769            0 :             simtime = 151 + 1;
    1770            0 :             break;
    1771            0 :         case 7:
    1772            0 :             simtime = 181 + 1;
    1773            0 :             break;
    1774            0 :         case 8:
    1775            0 :             simtime = 212 + 1;
    1776            0 :             break;
    1777            0 :         case 9:
    1778            0 :             simtime = 243 + 1;
    1779            0 :             break;
    1780            0 :         case 10:
    1781            0 :             simtime = 273 + 1;
    1782            0 :             break;
    1783            0 :         case 11:
    1784            0 :             simtime = 304 + 1;
    1785            0 :             break;
    1786            0 :         case 12:
    1787            0 :             simtime = 334 + 1;
    1788            0 :             break;
    1789            0 :         default:
    1790            0 :             simtime = 0;
    1791              :         }
    1792              :     }
    1793              : 
    1794            0 :     simtime = 24 * (simtime + (state.dataEnvrn->DayOfMonth - 1)); // day of month does not need to be stubtracted??
    1795            0 :     simtime = 60 * (simtime + (state.dataGlobal->HourOfDay - 1)); // hours to minutes
    1796            0 :     simtime = 60 * (simtime);                                     // minutes to seconds
    1797              : 
    1798            0 :     return simtime;
    1799              : }
    1800              : 
    1801            0 : void CalcExternalInterfaceFMUImport(EnergyPlusData &state)
    1802              : {
    1803              : 
    1804              :     // SUBROUTINE INFORMATION:
    1805              :     //       AUTHOR         Thierry S. Nouidui, Michael Wetter, Wangda Zuo
    1806              :     //       DATE WRITTEN   08Aug2011
    1807              : 
    1808              :     // PURPOSE OF THIS SUBROUTINE:
    1809              :     // This subroutine organizes the data exchange between FMU and EnergyPlus.
    1810              : 
    1811              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1812            0 :     Array1D_string Alphas(5);
    1813            0 :     Array1D_int keyIndexes(1);     // Array index for
    1814            0 :     Array1D_string NamesOfKeys(1); // Specific key name
    1815              : 
    1816            0 :     if (state.dataGlobal->WarmupFlag &&
    1817            0 :         (state.dataGlobal->KindOfSim != Constant::KindOfSim::RunPeriodWeather)) { // No data exchange during design days
    1818            0 :         if (state.dataExternalInterface->FirstCallDesignDays) {
    1819            0 :             ShowWarningError(state, "ExternalInterface/CalcExternalInterfaceFMUImport: ExternalInterface does not exchange data during design days.");
    1820              :         }
    1821            0 :         state.dataExternalInterface->FirstCallDesignDays = false;
    1822              :     }
    1823            0 :     if (state.dataGlobal->WarmupFlag && (state.dataGlobal->KindOfSim == Constant::KindOfSim::RunPeriodWeather)) { // Data exchange after design days
    1824            0 :         if (state.dataExternalInterface->FirstCallWUp) {
    1825              :             // set the report during warmup to true so that variables are also updated during the warmup
    1826            0 :             state.dataSysVars->UpdateDataDuringWarmupExternalInterface = true;
    1827            0 :             state.dataExternalInterface->hStep = (60.0 * state.dataGlobal->TimeStepZone) * 60.0;
    1828            0 :             state.dataExternalInterface->tStart = GetCurSimStartTimeSeconds(state);
    1829            0 :             state.dataExternalInterface->tStop = state.dataExternalInterface->tStart + 24.0 * 3600.0;
    1830            0 :             state.dataExternalInterface->tComm = state.dataExternalInterface->tStart;
    1831              : 
    1832              :             // instantiate and initialize the unpack fmus
    1833            0 :             InstantiateInitializeFMUImport(state);
    1834              : 
    1835              :             // allocate memory for a temporary FMU that will be used at the end of the warmup
    1836            0 :             state.dataExternalInterface->FMUTemp.allocate(state.dataExternalInterface->NumFMUObjects);
    1837            0 :             for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1838            0 :                 auto const &fmu = state.dataExternalInterface->FMU(i);
    1839            0 :                 auto &fmuTemp = state.dataExternalInterface->FMUTemp(i);
    1840            0 :                 fmuTemp.Instance.allocate(fmu.NumInstances);
    1841              :             }
    1842            0 :             for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1843            0 :                 auto const &fmu = state.dataExternalInterface->FMU(i);
    1844            0 :                 auto &fmuTemp = state.dataExternalInterface->FMUTemp(i);
    1845            0 :                 for (int j = 1; j <= fmu.NumInstances; ++j) {
    1846            0 :                     auto const &fmuInst = fmu.Instance(j);
    1847            0 :                     auto &fmuTempInst = fmuTemp.Instance(j);
    1848              : 
    1849            0 :                     fmuTempInst.fmuInputVariable.allocate(fmuInst.NumInputVariablesInIDF);
    1850            0 :                     fmuTempInst.eplusOutputVariable.allocate(fmuInst.NumInputVariablesInIDF);
    1851            0 :                     fmuTempInst.fmuOutputVariableSchedule.allocate(fmuInst.NumOutputVariablesSchedule);
    1852            0 :                     fmuTempInst.fmuOutputVariableVariable.allocate(fmuInst.NumOutputVariablesVariable);
    1853            0 :                     fmuTempInst.fmuOutputVariableActuator.allocate(fmuInst.NumOutputVariablesActuator);
    1854              :                 }
    1855              :             }
    1856              : 
    1857            0 :             GetSetVariablesAndDoStepFMUImport(state);
    1858            0 :             state.dataExternalInterface->tComm += state.dataExternalInterface->hStep;
    1859            0 :             state.dataExternalInterface->FirstCallWUp = false;
    1860              : 
    1861              :         } else {
    1862            0 :             if (state.dataExternalInterface->tComm < state.dataExternalInterface->tStop) {
    1863            0 :                 GetSetVariablesAndDoStepFMUImport(state);
    1864              :                 // Advance the communication time step
    1865            0 :                 state.dataExternalInterface->tComm += state.dataExternalInterface->hStep;
    1866              :             } else {
    1867            0 :                 for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1868            0 :                     auto const &fmu = state.dataExternalInterface->FMU(i);
    1869            0 :                     auto &fmuTemp = state.dataExternalInterface->FMUTemp(i);
    1870            0 :                     for (int j = 1; j <= fmu.NumInstances; ++j) {
    1871            0 :                         auto const &fmuInst = fmu.Instance(j);
    1872            0 :                         auto &fmuTempInst = fmuTemp.Instance(j);
    1873              : 
    1874            0 :                         fmuTempInst.NumInputVariablesInIDF = fmuInst.NumInputVariablesInIDF;
    1875            0 :                         for (int k = 1; k <= fmuInst.NumInputVariablesInIDF; ++k) {
    1876            0 :                             fmuTempInst.fmuInputVariable(k).ValueReference = fmuInst.fmuInputVariable(k).ValueReference;
    1877            0 :                             fmuTempInst.eplusOutputVariable(k).RTSValue = fmuInst.eplusOutputVariable(k).RTSValue;
    1878            0 :                             fmuTempInst.eplusOutputVariable(k).ITSValue = fmuInst.eplusOutputVariable(k).ITSValue;
    1879            0 :                             fmuTempInst.eplusOutputVariable(k).VarType = fmuInst.eplusOutputVariable(k).VarType;
    1880              :                         }
    1881              : 
    1882              :                         // save values that will be set in EnergyPlus (Schedule)
    1883            0 :                         fmuTempInst.NumOutputVariablesSchedule = fmuInst.NumOutputVariablesSchedule;
    1884            0 :                         for (int k = 1; k <= fmuInst.NumOutputVariablesSchedule; ++k) {
    1885            0 :                             fmuTempInst.fmuOutputVariableSchedule(k).RealVarValue = fmuInst.fmuOutputVariableSchedule(k).RealVarValue;
    1886              :                         }
    1887              : 
    1888              :                         // save values that will be set in EnergyPlus (Variable)
    1889            0 :                         fmuTempInst.NumOutputVariablesVariable = fmuInst.NumOutputVariablesVariable;
    1890            0 :                         for (int k = 1; k <= fmuInst.NumOutputVariablesVariable; ++k) {
    1891            0 :                             fmuTempInst.fmuOutputVariableVariable(k).RealVarValue = fmuInst.fmuOutputVariableVariable(k).RealVarValue;
    1892              :                         }
    1893              : 
    1894              :                         // save values that will be set in EnergyPlus (Actuator)
    1895            0 :                         fmuTempInst.NumOutputVariablesActuator = fmuInst.NumOutputVariablesActuator;
    1896            0 :                         for (int k = 1; k <= fmuInst.NumOutputVariablesActuator; ++k) {
    1897            0 :                             fmuTempInst.fmuOutputVariableActuator(k).RealVarValue = fmuInst.fmuOutputVariableActuator(k).RealVarValue;
    1898              :                         }
    1899              :                     }
    1900              :                 }
    1901              : 
    1902            0 :                 StopExternalInterfaceIfError(state);
    1903              : 
    1904              :                 // Terminate all FMUs
    1905            0 :                 TerminateResetFreeFMUImport(state, state.dataExternalInterface->fmiEndSimulation);
    1906              : 
    1907              :                 // Reset the communication time step
    1908            0 :                 state.dataExternalInterface->tComm = state.dataExternalInterface->tStart;
    1909              : 
    1910              :                 // Reinstantiate and reinitialize the FMUs
    1911            0 :                 InstantiateInitializeFMUImport(state);
    1912              : 
    1913              :                 // Set the values that have been saved in the FMUs-- saveFMUStateVariables ()
    1914            0 :                 for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1915            0 :                     auto &fmu = state.dataExternalInterface->FMU(i);
    1916            0 :                     auto &fmuTemp = state.dataExternalInterface->FMUTemp(i);
    1917            0 :                     for (int j = 1; j <= fmu.NumInstances; ++j) {
    1918            0 :                         auto &fmuInst = fmu.Instance(j);
    1919            0 :                         auto &fmuTempInst = fmuTemp.Instance(j);
    1920              : 
    1921            0 :                         std::vector<unsigned int> valRefVec;
    1922            0 :                         for (unsigned long x = 1; x <= size(fmuInst.fmuInputVariable); ++x) {
    1923            0 :                             valRefVec.push_back(fmuInst.fmuInputVariable(x).ValueReference);
    1924              :                         }
    1925              : 
    1926            0 :                         std::vector<Real64> rtsValVec;
    1927            0 :                         for (unsigned long x = 1; x <= size(fmuInst.eplusOutputVariable); ++x) {
    1928            0 :                             rtsValVec.push_back(fmuInst.eplusOutputVariable(x).RTSValue);
    1929              :                         }
    1930              : 
    1931              :                         // make the library call
    1932            0 :                         fmuInst.fmistatus =
    1933            0 :                             fmiEPlusSetReal(&fmuInst.fmicomponent, &valRefVec[0], &rtsValVec[0], &fmuTempInst.NumInputVariablesInIDF, &fmuInst.Index);
    1934              : 
    1935            0 :                         if (fmuInst.fmistatus != fmiOK) {
    1936            0 :                             ShowSevereError(
    1937              :                                 state,
    1938            0 :                                 format("ExternalInterface/CalcExternalInterfaceFMUImport: Error when trying to set an input value in instance \"{}\"",
    1939            0 :                                        fmuInst.Name));
    1940            0 :                             ShowContinueError(state, format("of FMU \"{}\"; Error Code = \"{}\"", fmu.Name, fmuInst.fmistatus));
    1941            0 :                             state.dataExternalInterface->ErrorsFound = true;
    1942            0 :                             StopExternalInterfaceIfError(state);
    1943              :                         }
    1944            0 :                     }
    1945              :                 }
    1946              :                 // set the flag to reinitialize states to be true
    1947            0 :                 state.dataExternalInterface->FlagReIni = true;
    1948            0 :                 GetSetVariablesAndDoStepFMUImport(state);
    1949            0 :                 state.dataExternalInterface->FlagReIni = false;
    1950              :                 // advance one time step ahead for the next calculation
    1951            0 :                 state.dataExternalInterface->tComm += state.dataExternalInterface->hStep;
    1952              :             }
    1953              :         }
    1954              :     }
    1955              :     // BeginSimulation
    1956            0 :     if (!state.dataGlobal->WarmupFlag && (state.dataGlobal->KindOfSim == Constant::KindOfSim::RunPeriodWeather)) {
    1957              : 
    1958            0 :         if (state.dataExternalInterface->FirstCallTStep) {
    1959              :             // reset the UpdateDataDuringWarmupExternalInterface to be false.
    1960            0 :             state.dataSysVars->UpdateDataDuringWarmupExternalInterface = false;
    1961              :             // The time is computed in seconds for FMU
    1962            0 :             state.dataExternalInterface->tStart = GetCurSimStartTimeSeconds(state);
    1963            0 :             state.dataExternalInterface->tStop =
    1964            0 :                 state.dataExternalInterface->tStart + (state.dataEnvrn->TotalOverallSimDays - state.dataEnvrn->TotDesDays) * 24.0 * 3600.0;
    1965            0 :             state.dataExternalInterface->tComm = state.dataExternalInterface->tStart;
    1966              : 
    1967              :             // Terminate all FMUs
    1968            0 :             TerminateResetFreeFMUImport(state, state.dataExternalInterface->fmiEndSimulation);
    1969              : 
    1970              :             // Reinstantiate and reinitialize the FMUs
    1971            0 :             InstantiateInitializeFMUImport(state);
    1972              : 
    1973              :             // Set the values that have been saved in the FMUs-- saveFMUStateVariables ()
    1974            0 :             for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    1975            0 :                 auto &fmu = state.dataExternalInterface->FMU(i);
    1976            0 :                 auto &fmuTemp = state.dataExternalInterface->FMUTemp(i);
    1977            0 :                 for (int j = 1; j <= fmu.NumInstances; ++j) {
    1978            0 :                     auto &fmuInst = fmu.Instance(j);
    1979            0 :                     auto &fmuTempInst = fmuTemp.Instance(j);
    1980              : 
    1981              :                     // make vectors first
    1982            0 :                     std::vector<unsigned int> valRefVec;
    1983            0 :                     for (unsigned long x = 1; x <= size(fmuTempInst.fmuInputVariable); ++x) {
    1984            0 :                         valRefVec.push_back(fmuTempInst.fmuInputVariable(x).ValueReference);
    1985              :                     }
    1986            0 :                     std::vector<Real64> rtsValVec;
    1987            0 :                     for (unsigned long x = 1; x <= size(fmuTempInst.eplusOutputVariable); ++x) {
    1988            0 :                         rtsValVec.push_back(fmuTempInst.eplusOutputVariable(x).RTSValue);
    1989              :                     }
    1990              : 
    1991              :                     // make the library call
    1992            0 :                     fmuInst.fmistatus =
    1993            0 :                         fmiEPlusSetReal(&fmuInst.fmicomponent, &valRefVec[0], &rtsValVec[0], &fmuTempInst.NumInputVariablesInIDF, &fmuInst.Index);
    1994              : 
    1995            0 :                     if (fmuInst.fmistatus != fmiOK) {
    1996            0 :                         ShowSevereError(state, "ExternalInterface/CalcExternalInterfaceFMUImport: ");
    1997            0 :                         ShowContinueError(state, "Error when trying to set inputs in instance");
    1998            0 :                         ShowContinueError(state, format("\"{}\" of FMU \"{}\"", fmuInst.Name, fmu.Name));
    1999            0 :                         ShowContinueError(state, format("Error Code = \"{}\"", fmuInst.fmistatus));
    2000            0 :                         state.dataExternalInterface->ErrorsFound = true;
    2001            0 :                         StopExternalInterfaceIfError(state);
    2002              :                     }
    2003            0 :                 }
    2004              :             }
    2005              :             // set the flag to reinitialize states to be true
    2006            0 :             state.dataExternalInterface->FlagReIni = true;
    2007            0 :             GetSetVariablesAndDoStepFMUImport(state);
    2008            0 :             state.dataExternalInterface->FlagReIni = false;
    2009              :             // advance one time step ahead for the next calculation
    2010            0 :             state.dataExternalInterface->tComm += state.dataExternalInterface->hStep;
    2011            0 :             state.dataExternalInterface->FirstCallTStep = false;
    2012              :         } else {
    2013            0 :             if (state.dataExternalInterface->tComm != state.dataExternalInterface->tStop) {
    2014            0 :                 GetSetVariablesAndDoStepFMUImport(state);
    2015            0 :                 state.dataExternalInterface->tComm += state.dataExternalInterface->hStep;
    2016              :             } else {
    2017              :                 // Terminate reset and free Slaves
    2018            0 :                 state.dataExternalInterface->fmiEndSimulation = 1;
    2019            0 :                 TerminateResetFreeFMUImport(state, state.dataExternalInterface->fmiEndSimulation);
    2020            0 :                 for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    2021            0 :                     auto &fmu = state.dataExternalInterface->FMU(i);
    2022            0 :                     auto &fmuTemp = state.dataExternalInterface->FMUTemp(i);
    2023            0 :                     for (int j = 1; j <= fmu.NumInstances; ++j) {
    2024            0 :                         auto &fmuTempInst = fmuTemp.Instance(j);
    2025              :                         // Deallocate used objects
    2026            0 :                         fmuTempInst.fmuInputVariable.deallocate();
    2027            0 :                         fmuTempInst.eplusOutputVariable.deallocate();
    2028            0 :                         fmuTempInst.fmuOutputVariableSchedule.deallocate();
    2029            0 :                         fmuTempInst.fmuOutputVariableVariable.deallocate();
    2030            0 :                         fmuTempInst.fmuOutputVariableActuator.deallocate();
    2031              :                     }
    2032              :                 }
    2033              : 
    2034            0 :                 for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    2035            0 :                     auto &fmuTemp = state.dataExternalInterface->FMUTemp(i);
    2036            0 :                     fmuTemp.Instance.deallocate();
    2037              :                 }
    2038              : 
    2039            0 :                 state.dataExternalInterface->FMUTemp.deallocate();
    2040              : 
    2041            0 :                 for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    2042            0 :                     auto &fmu = state.dataExternalInterface->FMU(i);
    2043            0 :                     for (int j = 1; j <= fmu.NumInstances; ++j) {
    2044            0 :                         auto &fmuInst = fmu.Instance(j);
    2045            0 :                         fmuInst.eplusInputVariableSchedule.deallocate();
    2046            0 :                         fmuInst.fmuOutputVariableSchedule.deallocate();
    2047            0 :                         fmuInst.eplusInputVariableVariable.deallocate();
    2048            0 :                         fmuInst.fmuOutputVariableVariable.deallocate();
    2049            0 :                         fmuInst.eplusInputVariableActuator.deallocate();
    2050            0 :                         fmuInst.fmuOutputVariableActuator.deallocate();
    2051            0 :                         fmuInst.fmuInputVariable.deallocate();
    2052            0 :                         fmuInst.checkfmuInputVariable.deallocate();
    2053              :                     }
    2054              :                 }
    2055              : 
    2056            0 :                 for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) {
    2057            0 :                     auto &fmu = state.dataExternalInterface->FMU(i);
    2058            0 :                     fmu.Instance.deallocate();
    2059              :                 }
    2060            0 :                 state.dataExternalInterface->FMU.deallocate();
    2061              :             }
    2062              :         }
    2063              :     }
    2064            0 : }
    2065              : 
    2066            0 : void ValidateRunControl(EnergyPlusData &state)
    2067              : {
    2068              :     // SUBROUTINE INFORMATION:
    2069              :     //       AUTHOR         Michael Wetter
    2070              :     //       DATE WRITTEN   December 2009
    2071              : 
    2072              :     // PURPOSE OF THIS SUBROUTINE:
    2073              :     // This subroutine ensures that the RunControl object is valid.
    2074              : 
    2075              :     // METHODOLOGY EMPLOYED:
    2076              :     // Use GetObjectItem from the Input Processor
    2077              : 
    2078              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2079            0 :     auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    2080              : 
    2081            0 :     cCurrentModuleObject = "SimulationControl";
    2082            0 :     int const NumRunControl = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    2083            0 :     if (NumRunControl > 0) {
    2084            0 :         int NumAlphas = 0;  // Number of Alphas for each GetObjectItem call
    2085            0 :         int NumNumbers = 0; // Number of Numbers for each GetObjectItem call
    2086            0 :         int IOStatus = 0;   // Used in GetObjectItem
    2087            0 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
    2088              :                                                                  cCurrentModuleObject,
    2089              :                                                                  1,
    2090            0 :                                                                  state.dataIPShortCut->cAlphaArgs,
    2091              :                                                                  NumAlphas,
    2092            0 :                                                                  state.dataIPShortCut->rNumericArgs,
    2093              :                                                                  NumNumbers,
    2094              :                                                                  IOStatus,
    2095              :                                                                  _,
    2096              :                                                                  _,
    2097            0 :                                                                  state.dataIPShortCut->cAlphaFieldNames,
    2098            0 :                                                                  state.dataIPShortCut->cNumericFieldNames);
    2099            0 :         if (state.dataIPShortCut->cAlphaArgs(5) == "NO") { // This run does not have a weather file simulation.
    2100            0 :             ShowSevereError(state, "ExternalInterface: Error in idf file, section SimulationControl:");
    2101            0 :             ShowContinueError(state, "When using the ExternalInterface, a run period from the weather file must be specified");
    2102            0 :             ShowContinueError(state, "in the idf file, because the ExternalInterface interface is not active during");
    2103            0 :             ShowContinueError(state, "warm-up and during sizing.");
    2104            0 :             state.dataExternalInterface->ErrorsFound = true;
    2105              :         }
    2106              :     }
    2107            0 : }
    2108              : 
    2109            0 : void CalcExternalInterface(EnergyPlusData &state)
    2110              : {
    2111              :     // SUBROUTINE INFORMATION:
    2112              :     //       AUTHOR         Michael Wetter
    2113              :     //       DATE WRITTEN   2Dec2007
    2114              : 
    2115              :     // SUBROUTINE PARAMETER DEFINITIONS:
    2116            0 :     int constexpr nDblMax(1024); // Maximum number of doubles
    2117              : 
    2118              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2119              :     Real64 curSimTim; // current simulation time
    2120              :     Real64 preSimTim; // previous time step's simulation time
    2121              : 
    2122            0 :     Array1D<Real64> dblValWri(nDblMax);
    2123            0 :     Array1D<Real64> dblValRea(nDblMax);
    2124              : 
    2125            0 :     if (state.dataExternalInterface->firstCall) {
    2126            0 :         DisplayString(state, "ExternalInterface starts first data exchange.");
    2127            0 :         state.dataExternalInterface->simulationStatus = 2;
    2128            0 :         preSimTim = 0; // In the first call, E+ did not reset SimTimeSteps to zero
    2129              :     } else {
    2130            0 :         preSimTim = state.dataGlobal->SimTimeSteps * state.dataGlobal->MinutesInTimeStep * 60.0;
    2131              :     }
    2132              : 
    2133              :     // Socket asked to terminate simulation, but simulation continues
    2134            0 :     if (state.dataExternalInterface->noMoreValues && state.dataExternalInterface->showContinuationWithoutUpdate) {
    2135            0 :         if (state.dataExternalInterface->haveExternalInterfaceBCVTB) {
    2136            0 :             ShowWarningError(
    2137            0 :                 state, format("ExternalInterface: Continue simulation without updated values from server at t ={:.2T} hours", preSimTim / 3600.0));
    2138              :         }
    2139            0 :         state.dataExternalInterface->showContinuationWithoutUpdate = false;
    2140              :     }
    2141              : 
    2142              :     // Usual branch, control is configured and simulation should continue
    2143            0 :     if (state.dataExternalInterface->configuredControlPoints && (!state.dataExternalInterface->noMoreValues)) {
    2144              :         // Data to be exchanged
    2145            0 :         int nDblWri = size(state.dataExternalInterface->varTypes); // number of doubles to write to socket
    2146            0 :         int nDblRea = 0;                                           // number of doubles to read from socket
    2147            0 :         int flaWri = 0;                                            // flag to write to the socket
    2148              : 
    2149              :         // Get EnergyPlus variables
    2150            0 :         if (state.dataExternalInterface->firstCall) { // bug fix causing external interface to send zero at the beginning of sim, Thierry Nouidui
    2151            0 :             for (int i = 1; i <= nDblWri; ++i) {
    2152            0 :                 dblValWri(i) =
    2153            0 :                     GetInternalVariableValue(state, state.dataExternalInterface->varTypes(i), state.dataExternalInterface->keyVarIndexes(i));
    2154              :             }
    2155              :         } else {
    2156            0 :             for (int i = 1; i <= nDblWri; ++i) {
    2157            0 :                 dblValWri(i) = GetInternalVariableValueExternalInterface(
    2158            0 :                     state, state.dataExternalInterface->varTypes(i), state.dataExternalInterface->keyVarIndexes(i));
    2159              :             }
    2160              :         }
    2161              : 
    2162              :         // Exchange data with socket
    2163            0 :         int retVal = 0;
    2164            0 :         int flaRea = 0; // flag read from the socket
    2165            0 :         if (state.dataExternalInterface->haveExternalInterfaceBCVTB) {
    2166            0 :             retVal = exchangedoubleswithsocket(&state.dataExternalInterface->socketFD,
    2167              :                                                &flaWri,
    2168              :                                                &flaRea,
    2169              :                                                &nDblWri,
    2170              :                                                &nDblRea,
    2171              :                                                &preSimTim,
    2172              :                                                dblValWri.data(),
    2173              :                                                &curSimTim,
    2174              :                                                dblValRea.data());
    2175            0 :         } else if (state.dataExternalInterface->haveExternalInterfaceFMUExport) {
    2176            0 :             retVal = exchangedoubleswithsocketFMU(&state.dataExternalInterface->socketFD,
    2177              :                                                   &flaWri,
    2178              :                                                   &flaRea,
    2179              :                                                   &nDblWri,
    2180              :                                                   &nDblRea,
    2181              :                                                   &preSimTim,
    2182              :                                                   dblValWri.data(),
    2183              :                                                   &curSimTim,
    2184              :                                                   dblValRea.data(),
    2185            0 :                                                   &state.dataExternalInterface->FMUExportActivate);
    2186              :         }
    2187            0 :         bool continueSimulation = true;
    2188              : 
    2189              :         // Check for errors, in which case we terminate the simulation loop
    2190              :         // Added a check since the FMUExport is terminated with the flaRea set to 1.
    2191            0 :         if (state.dataExternalInterface->haveExternalInterfaceBCVTB ||
    2192            0 :             (state.dataExternalInterface->haveExternalInterfaceFMUExport && (flaRea == 0))) {
    2193            0 :             if (retVal != 0) {
    2194            0 :                 continueSimulation = false;
    2195            0 :                 ShowSevereError(state,
    2196            0 :                                 format("ExternalInterface: Socket communication received error value \"{:2}\" at time = {:.2T} hours.",
    2197              :                                        retVal,
    2198            0 :                                        preSimTim / 3600));
    2199            0 :                 ShowContinueError(state, format("ExternalInterface: Flag from server \"{:2}\".", flaRea));
    2200            0 :                 state.dataExternalInterface->ErrorsFound = true;
    2201            0 :                 StopExternalInterfaceIfError(state);
    2202              :             }
    2203              :         }
    2204              : 
    2205              :         // Check communication flag
    2206            0 :         if (flaRea != 0) {
    2207              :             // No more values will be received in future steps
    2208              :             // Added a check since the FMUExport  is terminated with the flaRea set to 1.
    2209            0 :             state.dataExternalInterface->noMoreValues = true;
    2210            0 :             if (state.dataExternalInterface->haveExternalInterfaceBCVTB) {
    2211            0 :                 ShowSevereError(state, format("ExternalInterface: Received end of simulation flag at time = {:.2T} hours.", preSimTim / 3600));
    2212            0 :                 StopExternalInterfaceIfError(state);
    2213              :             }
    2214              :         }
    2215              : 
    2216              :         // Make sure we get the right number of double values, unless retVal != 0
    2217            0 :         if ((flaRea == 0) && (!state.dataExternalInterface->ErrorsFound) && continueSimulation &&
    2218            0 :             (nDblRea != isize(state.dataExternalInterface->varInd))) {
    2219            0 :             ShowSevereError(
    2220              :                 state,
    2221            0 :                 format("ExternalInterface: Received \"{}\" double values, expected \"{}\".", nDblRea, size(state.dataExternalInterface->varInd)));
    2222            0 :             state.dataExternalInterface->ErrorsFound = true;
    2223            0 :             StopExternalInterfaceIfError(state);
    2224              :         }
    2225              : 
    2226              :         // No errors found. Assign exchanged variables
    2227            0 :         if ((flaRea == 0) && continueSimulation) {
    2228            0 :             for (int i = 1; i <= isize(state.dataExternalInterface->varInd); ++i) {
    2229            0 :                 if (state.dataExternalInterface->inpVarTypes(i) == indexSchedule) {
    2230            0 :                     Sched::ExternalInterfaceSetSchedule(state, state.dataExternalInterface->varInd(i), dblValRea(i));
    2231            0 :                 } else if ((state.dataExternalInterface->inpVarTypes(i) == indexVariable) ||
    2232            0 :                            (state.dataExternalInterface->inpVarTypes(i) == indexActuator)) {
    2233            0 :                     RuntimeLanguageProcessor::ExternalInterfaceSetErlVariable(state, state.dataExternalInterface->varInd(i), dblValRea(i));
    2234              :                 } else {
    2235            0 :                     ShowContinueError(state, "ExternalInterface: Error in finding the type of the input variable for EnergyPlus");
    2236            0 :                     ShowContinueError(state, format("variable index: {}. Variable will not be updated.", i));
    2237              :                 }
    2238              :             }
    2239              :         }
    2240              :     }
    2241              : 
    2242              :     // If we have Erl variables, we need to call ManageEMS so that they get updated in the Erl data structure
    2243            0 :     if (state.dataExternalInterface->useEMS) {
    2244              :         bool anyRan;
    2245            0 :         EMSManager::ManageEMS(state, EMSManager::EMSCallFrom::ExternalInterface, anyRan, ObjexxFCL::Optional_int_const());
    2246              :     }
    2247              : 
    2248            0 :     state.dataExternalInterface->firstCall = false; // bug fix causing external interface to send zero at the beginning of sim, Thierry Nouidui
    2249            0 : }
    2250              : 
    2251            0 : void GetReportVariableKey(
    2252              :     EnergyPlusData &state,
    2253              :     const Array1D_string &varKeys,                   // Standard variable name
    2254              :     int const numberOfKeys,                          // Number of keys=size(state.dataExternalInterface->varKeys)
    2255              :     const Array1D_string &VarNames,                  // Standard variable name
    2256              :     Array1D_int &keyVarIndexes,                      // Array index
    2257              :     Array1D<OutputProcessor::VariableType> &varTypes // Types of variables in state.dataExternalInterface->keystate.dataExternalInterface->varIndexes
    2258              : )
    2259              : {
    2260              :     // SUBROUTINE INFORMATION:
    2261              :     //       AUTHOR         Michael Wetter
    2262              :     //       DATE WRITTEN   2Dec2007
    2263              : 
    2264              :     // PURPOSE OF THIS SUBROUTINE:
    2265              :     // Gets the sensor key index and type for the specified variable key and name
    2266              : 
    2267              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2268            0 :     OutputProcessor::VariableType varType(OutputProcessor::VariableType::Invalid);  // 0=not found, 1=integer, 2=real, 3=meter
    2269            0 :     int numKeys(0);                                                                 // Number of keys found
    2270            0 :     OutputProcessor::StoreType varAvgSum(OutputProcessor::StoreType::Average);      // Variable  is Averaged=1 or Summed=2
    2271            0 :     OutputProcessor::TimeStepType varStepType(OutputProcessor::TimeStepType::Zone); // Variable time step is Zone=1 or HVAC=2
    2272            0 :     Constant::Units varUnits(Constant::Units::None);                                // Units sting, may be blank
    2273            0 :     Array1D_string keyNames;
    2274            0 :     Array1D_int keyIndexes; // Array index for
    2275              :     int Loop, iKey;         // Loop counters
    2276              : 
    2277              :     // Get pointers for variables to be sent to Ptolemy
    2278            0 :     for (Loop = 1; Loop <= numberOfKeys; ++Loop) {
    2279            0 :         GetVariableKeyCountandType(state, VarNames(Loop), numKeys, varType, varAvgSum, varStepType, varUnits);
    2280            0 :         if (varType != OutputProcessor::VariableType::Invalid) {
    2281            0 :             keyIndexes.allocate(numKeys);
    2282            0 :             keyNames.allocate(numKeys);
    2283            0 :             GetVariableKeys(state, VarNames(Loop), varType, keyNames, keyIndexes);
    2284              :             // Find key index whose keyName is equal to keyNames(Loop)
    2285            0 :             int max(keyIndexes.size());
    2286            0 :             for (iKey = 1; iKey <= max; ++iKey) {
    2287            0 :                 if (keyNames(iKey) == varKeys(Loop)) {
    2288            0 :                     keyVarIndexes(Loop) = keyIndexes(iKey);
    2289            0 :                     varTypes(Loop) = varType;
    2290            0 :                     break;
    2291              :                 }
    2292              :             }
    2293            0 :             keyIndexes.deallocate();
    2294            0 :             keyNames.deallocate();
    2295              :         }
    2296            0 :         if ((varType == OutputProcessor::VariableType::Invalid) || (iKey > numKeys)) {
    2297            0 :             ShowSevereError(state,
    2298            0 :                             format("ExternalInterface: Simulation model has no variable \"{}\" with key \"{}\".", VarNames(Loop), varKeys(Loop)));
    2299            0 :             state.dataExternalInterface->ErrorsFound = true;
    2300              :         }
    2301              :     }
    2302            0 : }
    2303              : 
    2304          585 : void WarnIfExternalInterfaceObjectsAreUsed(EnergyPlusData &state, std::string const &ObjectWord)
    2305              : {
    2306              :     // SUBROUTINE INFORMATION:
    2307              :     //       AUTHOR         Michael Wetter
    2308              :     //       DATE WRITTEN   December 2009
    2309              : 
    2310              :     // PURPOSE OF THIS SUBROUTINE:
    2311              :     // This subroutine writes a warning if ExternalInterface objects are used in the
    2312              :     // idf file, but the ExternalInterface link is not specified.
    2313              : 
    2314          585 :     int const NumObjects = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, ObjectWord);
    2315          585 :     if (NumObjects > 0) {
    2316            0 :         ShowWarningError(state, format("IDF file contains object \"{}\",", ObjectWord));
    2317            0 :         ShowContinueError(state, "but object \"ExternalInterface\" with appropriate key entry is not specified. Values will not be updated.");
    2318              :     }
    2319          585 : }
    2320              : 
    2321            0 : void VerifyExternalInterfaceObject(EnergyPlusData &state)
    2322              : {
    2323              :     // SUBROUTINE INFORMATION:
    2324              :     //       AUTHOR         Michael Wetter
    2325              :     //       DATE WRITTEN   12Dec2009
    2326              : 
    2327              :     // PURPOSE OF THIS SUBROUTINE:
    2328              :     // This subroutine verifies the correctness of the fields of
    2329              :     // the ExternalInterface object in the idf file
    2330              : 
    2331              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2332            0 :     int NumAlphas(0);  // Number of Alphas for each GetObjectItem call
    2333            0 :     int NumNumbers(0); // Number of Numbers for each GetObjectItem call
    2334            0 :     int IOStatus(0);   // Used in GetObjectItem
    2335            0 :     auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    2336              : 
    2337            0 :     cCurrentModuleObject = "ExternalInterface";
    2338            0 :     state.dataInputProcessing->inputProcessor->getObjectItem(state,
    2339              :                                                              cCurrentModuleObject,
    2340              :                                                              1,
    2341            0 :                                                              state.dataIPShortCut->cAlphaArgs,
    2342              :                                                              NumAlphas,
    2343            0 :                                                              state.dataIPShortCut->rNumericArgs,
    2344              :                                                              NumNumbers,
    2345              :                                                              IOStatus,
    2346              :                                                              _,
    2347              :                                                              _,
    2348            0 :                                                              state.dataIPShortCut->cAlphaFieldNames,
    2349            0 :                                                              state.dataIPShortCut->cNumericFieldNames);
    2350            0 :     if ((!Util::SameString(state.dataIPShortCut->cAlphaArgs(1), "PtolemyServer")) &&
    2351            0 :         (!Util::SameString(state.dataIPShortCut->cAlphaArgs(1), "FunctionalMockupUnitImport")) &&
    2352            0 :         (!Util::SameString(state.dataIPShortCut->cAlphaArgs(1), "FunctionalMockupUnitExport"))) {
    2353            0 :         ShowSevereError(state,
    2354            0 :                         format("VerifyExternalInterfaceObject: {}, invalid {}=\"{}\".",
    2355              :                                cCurrentModuleObject,
    2356            0 :                                state.dataIPShortCut->cAlphaFieldNames(1),
    2357            0 :                                state.dataIPShortCut->cAlphaArgs(1)));
    2358            0 :         ShowContinueError(state, "only \"PtolemyServer or FunctionalMockupUnitImport or FunctionalMockupUnitExport\" allowed.");
    2359            0 :         state.dataExternalInterface->ErrorsFound = true;
    2360              :     }
    2361            0 : }
    2362              : 
    2363            0 : std::vector<char> getCharArrayFromString(std::string const &originalString)
    2364              : {
    2365              :     // c_str returns null terminated, so we don't need a +1?
    2366            0 :     return std::vector<char>(originalString.c_str(), originalString.c_str() + originalString.size());
    2367              : }
    2368              : 
    2369            0 : std::string getStringFromCharArray(std::vector<char> originalCharArray)
    2370              : {
    2371            0 :     originalCharArray.push_back('\0');
    2372            0 :     return std::string(&originalCharArray.front());
    2373              : }
    2374              : 
    2375              : } // namespace EnergyPlus::ExternalInterface
        

Generated by: LCOV version 2.0-1