LCOV - code coverage report
Current view: top level - EnergyPlus - BoilerSteam.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 247 399 61.9 %
Date: 2023-01-17 19:17:23 Functions: 15 15 100.0 %

          Line data    Source code
       1             : // EnergyPlus, Copyright (c) 1996-2023, 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             : // C++ Headers
      49             : #include <cmath>
      50             : 
      51             : // ObjexxFCL Headers
      52             : #include <ObjexxFCL/Array.functions.hh>
      53             : #include <ObjexxFCL/Fmath.hh>
      54             : 
      55             : // EnergyPlus Headers
      56             : #include <EnergyPlus/Autosizing/Base.hh>
      57             : #include <EnergyPlus/BoilerSteam.hh>
      58             : #include <EnergyPlus/BranchNodeConnections.hh>
      59             : #include <EnergyPlus/Data/EnergyPlusData.hh>
      60             : #include <EnergyPlus/DataBranchAirLoopPlant.hh>
      61             : #include <EnergyPlus/DataHVACGlobals.hh>
      62             : #include <EnergyPlus/DataIPShortCuts.hh>
      63             : #include <EnergyPlus/DataLoopNode.hh>
      64             : #include <EnergyPlus/DataSizing.hh>
      65             : #include <EnergyPlus/EMSManager.hh>
      66             : #include <EnergyPlus/FluidProperties.hh>
      67             : #include <EnergyPlus/GlobalNames.hh>
      68             : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      69             : #include <EnergyPlus/NodeInputManager.hh>
      70             : #include <EnergyPlus/OutputProcessor.hh>
      71             : #include <EnergyPlus/OutputReportPredefined.hh>
      72             : #include <EnergyPlus/Plant/DataPlant.hh>
      73             : #include <EnergyPlus/PlantUtilities.hh>
      74             : #include <EnergyPlus/UtilityRoutines.hh>
      75             : 
      76             : namespace EnergyPlus {
      77             : 
      78             : namespace BoilerSteam {
      79             : 
      80             :     // Module containing the routines dealing with the Boilers
      81             : 
      82             :     // MODULE INFORMATION:
      83             :     //    AUTHOR         Rahul Chillar
      84             :     //    DATE WRITTEN   Dec 2004
      85             :     //    MODIFIED       na
      86             :     //    RE-ENGINEERED  na
      87             :     // PURPOSE OF THIS MODULE:
      88             :     // Performs steam boiler simulation for plant simulation
      89             : 
      90             :     const char *fluidNameSteam = "STEAM";
      91             : 
      92           7 :     BoilerSpecs *BoilerSpecs::factory(EnergyPlusData &state, std::string const &objectName)
      93             :     {
      94             :         // Process the input data for boilers if it hasn't been done already
      95           7 :         if (state.dataBoilerSteam->getSteamBoilerInput) {
      96           7 :             GetBoilerInput(state);
      97           7 :             state.dataBoilerSteam->getSteamBoilerInput = false;
      98             :         }
      99             : 
     100             :         // Now look for this particular pipe in the list
     101           7 :         for (auto &boiler : state.dataBoilerSteam->Boiler) {
     102           7 :             if (boiler.Name == objectName) {
     103           7 :                 return &boiler;
     104             :             }
     105             :         }
     106             :         // If we didn't find it, fatal
     107             :         ShowFatalError(state, "LocalBoilerSteamFactory: Error getting inputs for steam boiler named: " + objectName); // LCOV_EXCL_LINE
     108             :         // Shut up the compiler
     109             :         return nullptr; // LCOV_EXCL_LINE
     110             :     }
     111             : 
     112      104818 :     void BoilerSpecs::simulate(
     113             :         EnergyPlusData &state, [[maybe_unused]] const PlantLocation &calledFromLocation, bool FirstHVACIteration, Real64 &CurLoad, bool RunFlag)
     114             :     {
     115      104818 :         this->initialize(state);
     116      104818 :         auto &sim_component(DataPlant::CompData::getPlantComponent(state, this->plantLoc));
     117      104818 :         this->calculate(state, CurLoad, RunFlag, sim_component.FlowCtrl);
     118      104818 :         this->update(state, CurLoad, RunFlag, FirstHVACIteration);
     119      104818 :     }
     120             : 
     121             :     void
     122          35 :     BoilerSpecs::getDesignCapacities([[maybe_unused]] EnergyPlusData &state, const PlantLocation &, Real64 &MaxLoad, Real64 &MinLoad, Real64 &OptLoad)
     123             :     {
     124          35 :         MinLoad = this->NomCap * this->MinPartLoadRat;
     125          35 :         MaxLoad = this->NomCap * this->MaxPartLoadRat;
     126          35 :         OptLoad = this->NomCap * this->OptPartLoadRat;
     127          35 :     }
     128             : 
     129           7 :     void BoilerSpecs::getSizingFactor(Real64 &sizFac)
     130             :     {
     131           7 :         sizFac = this->SizFac;
     132           7 :     }
     133             : 
     134          35 :     void BoilerSpecs::onInitLoopEquip(EnergyPlusData &state, const PlantLocation &)
     135             :     {
     136          35 :         this->initialize(state);
     137          35 :         this->autosize(state);
     138          35 :     }
     139             : 
     140           7 :     void GetBoilerInput(EnergyPlusData &state)
     141             :     {
     142             :         // SUBROUTINE INFORMATION:
     143             :         //       AUTHOR         Rahul Chillar
     144             :         //       DATE WRITTEN   Dec 2004
     145             :         //       MODIFIED       na
     146             :         //       RE-ENGINEERED  na
     147             : 
     148             :         // PURPOSE OF THIS SUBROUTINE:
     149             :         // Get all boiler data from input file
     150             : 
     151             :         // Locals
     152             :         static constexpr std::string_view RoutineName("GetBoilerInput: ");
     153             : 
     154             :         // LOCAL VARIABLES
     155             :         int BoilerNum;       // boiler identifier
     156             :         int NumAlphas;       // Number of elements in the alpha array
     157             :         int NumNums;         // Number of elements in the numeric array
     158             :         int IOStat;          // IO Status when calling get input subroutine
     159             :         int SteamFluidIndex; // Fluid Index for Steam
     160           7 :         bool ErrorsFound(false);
     161             : 
     162           7 :         SteamFluidIndex = 0;
     163           7 :         state.dataIPShortCut->cCurrentModuleObject = "Boiler:Steam";
     164           7 :         int numBoilers = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataIPShortCut->cCurrentModuleObject);
     165             : 
     166           7 :         if (numBoilers <= 0) {
     167           0 :             ShowSevereError(state, "No " + state.dataIPShortCut->cCurrentModuleObject + " equipment specified in input file");
     168           0 :             ErrorsFound = true;
     169             :         }
     170             : 
     171             :         // See if load distribution manager has already gotten the input
     172           7 :         if (allocated(state.dataBoilerSteam->Boiler)) return;
     173             : 
     174             :         // Boiler will have fuel input to it , that is it !
     175           7 :         state.dataBoilerSteam->Boiler.allocate(numBoilers);
     176             : 
     177             :         // LOAD ARRAYS WITH CURVE FIT Boiler DATA
     178          14 :         for (BoilerNum = 1; BoilerNum <= numBoilers; ++BoilerNum) {
     179          42 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     180           7 :                                                                      state.dataIPShortCut->cCurrentModuleObject,
     181             :                                                                      BoilerNum,
     182           7 :                                                                      state.dataIPShortCut->cAlphaArgs,
     183             :                                                                      NumAlphas,
     184           7 :                                                                      state.dataIPShortCut->rNumericArgs,
     185             :                                                                      NumNums,
     186             :                                                                      IOStat,
     187             :                                                                      _,
     188             :                                                                      _,
     189           7 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     190           7 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     191           7 :             UtilityRoutines::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), state.dataIPShortCut->cCurrentModuleObject, ErrorsFound);
     192             :             // ErrorsFound will be set to True if problem was found, left untouched otherwise
     193           7 :             GlobalNames::VerifyUniqueBoilerName(state,
     194           7 :                                                 state.dataIPShortCut->cCurrentModuleObject,
     195           7 :                                                 state.dataIPShortCut->cAlphaArgs(1),
     196             :                                                 ErrorsFound,
     197          14 :                                                 state.dataIPShortCut->cCurrentModuleObject + " Name");
     198           7 :             auto &thisBoiler = state.dataBoilerSteam->Boiler(BoilerNum);
     199           7 :             thisBoiler.Name = state.dataIPShortCut->cAlphaArgs(1);
     200             : 
     201             :             // Validate fuel type input
     202           7 :             bool FuelTypeError(false);
     203          14 :             UtilityRoutines::ValidateFuelTypeWithAssignResourceTypeNum(
     204           7 :                 state.dataIPShortCut->cAlphaArgs(2), thisBoiler.BoilerFuelTypeForOutputVariable, thisBoiler.FuelType, FuelTypeError);
     205           7 :             if (FuelTypeError) {
     206           0 :                 ShowSevereError(state,
     207           0 :                                 std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
     208             :                                     "\",");
     209           0 :                 ShowContinueError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(2) + '=' + state.dataIPShortCut->cAlphaArgs(2));
     210             :                 // Set to Electric to avoid errors when setting up output variables
     211           0 :                 thisBoiler.BoilerFuelTypeForOutputVariable = "Electricity";
     212           0 :                 ErrorsFound = true;
     213           0 :                 FuelTypeError = false;
     214             :             }
     215             : 
     216             :             // INPUTS from the IDF file
     217           7 :             thisBoiler.BoilerMaxOperPress = state.dataIPShortCut->rNumericArgs(1);
     218           7 :             if (thisBoiler.BoilerMaxOperPress < 1e5) {
     219           0 :                 ShowWarningMessage(state, state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\"");
     220           0 :                 ShowContinueError(state, "Field: Maximum Operation Pressure units are Pa. Verify units.");
     221             :             }
     222           7 :             thisBoiler.NomEffic = state.dataIPShortCut->rNumericArgs(2);
     223           7 :             thisBoiler.TempUpLimitBoilerOut = state.dataIPShortCut->rNumericArgs(3);
     224           7 :             thisBoiler.NomCap = state.dataIPShortCut->rNumericArgs(4);
     225           7 :             if (thisBoiler.NomCap == DataSizing::AutoSize) {
     226           7 :                 thisBoiler.NomCapWasAutoSized = true;
     227             :             }
     228           7 :             thisBoiler.MinPartLoadRat = state.dataIPShortCut->rNumericArgs(5);
     229           7 :             thisBoiler.MaxPartLoadRat = state.dataIPShortCut->rNumericArgs(6);
     230           7 :             thisBoiler.OptPartLoadRat = state.dataIPShortCut->rNumericArgs(7);
     231           7 :             thisBoiler.FullLoadCoef[0] = state.dataIPShortCut->rNumericArgs(8);
     232           7 :             thisBoiler.FullLoadCoef[1] = state.dataIPShortCut->rNumericArgs(9);
     233           7 :             thisBoiler.FullLoadCoef[2] = state.dataIPShortCut->rNumericArgs(10);
     234           7 :             thisBoiler.SizFac = state.dataIPShortCut->rNumericArgs(11);
     235           7 :             if (thisBoiler.SizFac <= 0.0) thisBoiler.SizFac = 1.0;
     236             : 
     237           7 :             if ((state.dataIPShortCut->rNumericArgs(8) + state.dataIPShortCut->rNumericArgs(9) + state.dataIPShortCut->rNumericArgs(10)) == 0.0) {
     238           0 :                 ShowSevereError(state,
     239           0 :                                 std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
     240             :                                     "\",");
     241           0 :                 ShowContinueError(state, " Sum of fuel use curve coefficients = 0.0");
     242           0 :                 ErrorsFound = true;
     243             :             }
     244             : 
     245           7 :             if (state.dataIPShortCut->rNumericArgs(5) < 0.0) {
     246           0 :                 ShowSevereError(state,
     247           0 :                                 std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
     248             :                                     "\",");
     249           0 :                 ShowContinueError(state,
     250           0 :                                   format("Invalid {}={:.3R}", state.dataIPShortCut->cNumericFieldNames(5), state.dataIPShortCut->rNumericArgs(5)));
     251           0 :                 ErrorsFound = true;
     252             :             }
     253             : 
     254           7 :             if (state.dataIPShortCut->rNumericArgs(3) == 0.0) {
     255           0 :                 ShowSevereError(state,
     256           0 :                                 std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
     257             :                                     "\",");
     258           0 :                 ShowContinueError(state,
     259           0 :                                   format("Invalid {}={:.3R}", state.dataIPShortCut->cNumericFieldNames(3), state.dataIPShortCut->rNumericArgs(3)));
     260           0 :                 ErrorsFound = true;
     261             :             }
     262           7 :             thisBoiler.BoilerInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
     263           7 :                                                                                 state.dataIPShortCut->cAlphaArgs(3),
     264             :                                                                                 ErrorsFound,
     265             :                                                                                 DataLoopNode::ConnectionObjectType::BoilerSteam,
     266           7 :                                                                                 state.dataIPShortCut->cAlphaArgs(1),
     267             :                                                                                 DataLoopNode::NodeFluidType::Steam,
     268             :                                                                                 DataLoopNode::ConnectionType::Inlet,
     269             :                                                                                 NodeInputManager::CompFluidStream::Primary,
     270           7 :                                                                                 DataLoopNode::ObjectIsNotParent);
     271           7 :             thisBoiler.BoilerOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
     272           7 :                                                                                  state.dataIPShortCut->cAlphaArgs(4),
     273             :                                                                                  ErrorsFound,
     274             :                                                                                  DataLoopNode::ConnectionObjectType::BoilerSteam,
     275           7 :                                                                                  state.dataIPShortCut->cAlphaArgs(1),
     276             :                                                                                  DataLoopNode::NodeFluidType::Steam,
     277             :                                                                                  DataLoopNode::ConnectionType::Outlet,
     278             :                                                                                  NodeInputManager::CompFluidStream::Primary,
     279           7 :                                                                                  DataLoopNode::ObjectIsNotParent);
     280          21 :             BranchNodeConnections::TestCompSet(state,
     281           7 :                                                state.dataIPShortCut->cCurrentModuleObject,
     282           7 :                                                state.dataIPShortCut->cAlphaArgs(1),
     283           7 :                                                state.dataIPShortCut->cAlphaArgs(3),
     284           7 :                                                state.dataIPShortCut->cAlphaArgs(4),
     285             :                                                "Hot Steam Nodes");
     286             : 
     287           7 :             if (SteamFluidIndex == 0 && BoilerNum == 1) {
     288           7 :                 SteamFluidIndex = FluidProperties::FindRefrigerant(state, fluidNameSteam);
     289           7 :                 if (SteamFluidIndex == 0) {
     290           0 :                     ShowSevereError(state,
     291           0 :                                     std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" +
     292           0 :                                         state.dataIPShortCut->cAlphaArgs(1) + "\",");
     293           0 :                     ShowContinueError(state, "Steam Properties not found; Steam Fluid Properties must be included in the input file.");
     294           0 :                     ErrorsFound = true;
     295             :                 }
     296             :             }
     297             : 
     298           7 :             thisBoiler.FluidIndex = SteamFluidIndex;
     299             : 
     300           7 :             if (NumAlphas > 4) {
     301           0 :                 thisBoiler.EndUseSubcategory = state.dataIPShortCut->cAlphaArgs(5);
     302             :             } else {
     303           7 :                 thisBoiler.EndUseSubcategory = "General";
     304             :             }
     305             :         }
     306             : 
     307           7 :         if (ErrorsFound) {
     308           0 :             ShowFatalError(state, std::string{RoutineName} + "Errors found in processing " + state.dataIPShortCut->cCurrentModuleObject + " input.");
     309             :         }
     310             :     }
     311             : 
     312           7 :     void BoilerSpecs::oneTimeInit(EnergyPlusData &state)
     313             :     {
     314           7 :         bool errFlag = false;
     315           7 :         PlantUtilities::ScanPlantLoopsForObject(
     316             :             state, this->Name, DataPlant::PlantEquipmentType::Boiler_Steam, this->plantLoc, errFlag, _, _, _, _, _);
     317           7 :         if (errFlag) {
     318           0 :             ShowFatalError(state, "InitBoiler: Program terminated due to previous condition(s).");
     319             :         }
     320           7 :     }
     321             : 
     322          42 :     void BoilerSpecs::initEachEnvironment(EnergyPlusData &state)
     323             :     {
     324             :         static constexpr std::string_view RoutineName("BoilerSpecs::initEachEnvironment");
     325             : 
     326          42 :         int BoilerInletNode = this->BoilerInletNodeNum;
     327             : 
     328             :         Real64 EnthSteamOutDry =
     329          42 :             FluidProperties::GetSatEnthalpyRefrig(state, fluidNameSteam, this->TempUpLimitBoilerOut, 1.0, this->FluidIndex, RoutineName);
     330             :         Real64 EnthSteamOutWet =
     331          42 :             FluidProperties::GetSatEnthalpyRefrig(state, fluidNameSteam, this->TempUpLimitBoilerOut, 0.0, this->FluidIndex, RoutineName);
     332          42 :         Real64 LatentEnthSteam = EnthSteamOutDry - EnthSteamOutWet;
     333             : 
     334             :         Real64 CpWater =
     335          42 :             FluidProperties::GetSatSpecificHeatRefrig(state, fluidNameSteam, this->TempUpLimitBoilerOut, 0.0, this->FluidIndex, RoutineName);
     336             : 
     337          42 :         this->DesMassFlowRate =
     338          42 :             this->NomCap / (LatentEnthSteam + CpWater * (this->TempUpLimitBoilerOut - state.dataLoopNodes->Node(BoilerInletNode).Temp));
     339             : 
     340          42 :         PlantUtilities::InitComponentNodes(state, 0.0, this->DesMassFlowRate, this->BoilerInletNodeNum, this->BoilerOutletNodeNum);
     341             : 
     342          42 :         this->BoilerPressCheck = 0.0;
     343          42 :         this->FuelUsed = 0.0;
     344          42 :         this->BoilerLoad = 0.0;
     345          42 :         this->BoilerEff = 0.0;
     346          42 :         this->BoilerOutletTemp = 0.0;
     347             : 
     348          42 :         if ((state.dataLoopNodes->Node(this->BoilerOutletNodeNum).TempSetPoint == DataLoopNode::SensedNodeFlagValue) &&
     349           0 :             (state.dataLoopNodes->Node(this->BoilerOutletNodeNum).TempSetPointLo == DataLoopNode::SensedNodeFlagValue)) {
     350           0 :             if (!state.dataGlobal->AnyEnergyManagementSystemInModel) {
     351           0 :                 if (!this->MissingSetPointErrDone) {
     352           0 :                     ShowWarningError(state, "Missing temperature setpoint for Boiler:Steam = " + this->Name);
     353           0 :                     ShowContinueError(state, " A temperature setpoint is needed at the outlet node of the boiler, use a SetpointManager");
     354           0 :                     ShowContinueError(state, " The overall loop setpoint will be assumed for this boiler. The simulation continues ...");
     355           0 :                     this->MissingSetPointErrDone = true;
     356             :                 }
     357             :             } else {
     358             :                 // need call to EMS to check node
     359           0 :                 bool FatalError = false; // but not really fatal yet, but should be.
     360           0 :                 EMSManager::CheckIfNodeSetPointManagedByEMS(
     361             :                     state, this->BoilerOutletNodeNum, EMSManager::SPControlType::TemperatureSetPoint, FatalError);
     362           0 :                 state.dataLoopNodes->NodeSetpointCheck(this->BoilerOutletNodeNum).needsSetpointChecking = false;
     363           0 :                 if (FatalError) {
     364           0 :                     if (!this->MissingSetPointErrDone) {
     365           0 :                         ShowWarningError(state, "Missing temperature setpoint for LeavingSetpointModulated mode Boiler named " + this->Name);
     366           0 :                         ShowContinueError(state, " A temperature setpoint is needed at the outlet node of the boiler.");
     367           0 :                         ShowContinueError(state, " Use a Setpoint Manager to establish a setpoint at the boiler outlet node ");
     368           0 :                         ShowContinueError(state, " or use an EMS actuator to establish a setpoint at the boiler outlet node.");
     369           0 :                         ShowContinueError(state, " The overall loop setpoint will be assumed for this boiler. The simulation continues...");
     370           0 :                         this->MissingSetPointErrDone = true;
     371             :                     }
     372             :                 }
     373             :             }
     374           0 :             this->UseLoopSetPoint = true; // this is for backward compatibility and could be removed
     375             :         }
     376          42 :     }
     377             : 
     378      104853 :     void BoilerSpecs::initialize(EnergyPlusData &state) // number of the current electric chiller being simulated
     379             :     {
     380             :         // SUBROUTINE INFORMATION:
     381             :         //       AUTHOR         Rahul Chillar
     382             :         //       DATE WRITTEN   Dec 2004
     383             :         //       MODIFIED       na
     384             :         //       RE-ENGINEERED  D. Shirey, rework for plant upgrade
     385             : 
     386             :         // PURPOSE OF THIS SUBROUTINE:
     387             :         // This subroutine is for initializations of the Boiler components
     388             : 
     389             :         // METHODOLOGY EMPLOYED:
     390             :         // Uses the status flags to trigger initializations.
     391             : 
     392             :         // Init more variables
     393      104853 :         if (this->myFlag) {
     394           7 :             this->setupOutputVars(state);
     395           7 :             this->oneTimeInit(state);
     396           7 :             this->myFlag = false;
     397             :         }
     398             : 
     399      104853 :         if (state.dataGlobal->BeginEnvrnFlag && this->myEnvrnFlag && (state.dataPlnt->PlantFirstSizesOkayToFinalize)) {
     400          42 :             this->initEachEnvironment(state);
     401          42 :             this->myEnvrnFlag = false;
     402             :         }
     403      104853 :         if (!state.dataGlobal->BeginEnvrnFlag) {
     404      103936 :             this->myEnvrnFlag = true;
     405             :         }
     406             : 
     407      104853 :         if (this->UseLoopSetPoint) {
     408             :             //  At some point, need to circle back and get from plant data structure instead of node
     409             :             // fix for clumsy old input that worked because loop setpoint was spread.
     410             :             //  could be removed with transition, testing , model change, period of being obsolete.
     411           0 :             int BoilerOutletNode = this->BoilerOutletNodeNum;
     412           0 :             switch (state.dataPlnt->PlantLoop(this->plantLoc.loopNum).LoopDemandCalcScheme) {
     413             : 
     414           0 :             case DataPlant::LoopDemandCalcScheme::SingleSetPoint:
     415           0 :                 state.dataLoopNodes->Node(BoilerOutletNode).TempSetPoint =
     416           0 :                     state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->plantLoc.loopNum).TempSetPointNodeNum).TempSetPoint;
     417           0 :                 break;
     418           0 :             case DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand:
     419           0 :                 state.dataLoopNodes->Node(BoilerOutletNode).TempSetPointLo =
     420           0 :                     state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->plantLoc.loopNum).TempSetPointNodeNum).TempSetPointLo;
     421           0 :                 break;
     422           0 :             default:
     423           0 :                 break;
     424             :             }
     425             :         }
     426      104853 :     }
     427             : 
     428           7 :     void BoilerSpecs::setupOutputVars(EnergyPlusData &state)
     429             :     {
     430          14 :         SetupOutputVariable(state,
     431             :                             "Boiler Heating Rate",
     432             :                             OutputProcessor::Unit::W,
     433             :                             this->BoilerLoad,
     434             :                             OutputProcessor::SOVTimeStepType::System,
     435             :                             OutputProcessor::SOVStoreType::Average,
     436           7 :                             this->Name);
     437          14 :         SetupOutputVariable(state,
     438             :                             "Boiler Heating Energy",
     439             :                             OutputProcessor::Unit::J,
     440             :                             this->BoilerEnergy,
     441             :                             OutputProcessor::SOVTimeStepType::System,
     442             :                             OutputProcessor::SOVStoreType::Summed,
     443             :                             this->Name,
     444             :                             _,
     445             :                             "ENERGYTRANSFER",
     446             :                             "BOILERS",
     447             :                             _,
     448           7 :                             "Plant");
     449          21 :         SetupOutputVariable(state,
     450          14 :                             "Boiler " + this->BoilerFuelTypeForOutputVariable + " Rate",
     451             :                             OutputProcessor::Unit::W,
     452             :                             this->FuelUsed,
     453             :                             OutputProcessor::SOVTimeStepType::System,
     454             :                             OutputProcessor::SOVStoreType::Average,
     455             :                             this->Name);
     456          21 :         SetupOutputVariable(state,
     457          14 :                             "Boiler " + this->BoilerFuelTypeForOutputVariable + " Energy",
     458             :                             OutputProcessor::Unit::J,
     459             :                             this->FuelConsumed,
     460             :                             OutputProcessor::SOVTimeStepType::System,
     461             :                             OutputProcessor::SOVStoreType::Summed,
     462             :                             this->Name,
     463             :                             _,
     464             :                             this->BoilerFuelTypeForOutputVariable,
     465             :                             "Heating",
     466             :                             this->EndUseSubcategory,
     467             :                             "Plant");
     468          14 :         SetupOutputVariable(state,
     469             :                             "Boiler Steam Efficiency",
     470             :                             OutputProcessor::Unit::None,
     471             :                             this->BoilerEff,
     472             :                             OutputProcessor::SOVTimeStepType::System,
     473             :                             OutputProcessor::SOVStoreType::Average,
     474           7 :                             this->Name);
     475          14 :         SetupOutputVariable(state,
     476             :                             "Boiler Steam Inlet Temperature",
     477             :                             OutputProcessor::Unit::C,
     478             :                             this->BoilerInletTemp,
     479             :                             OutputProcessor::SOVTimeStepType::System,
     480             :                             OutputProcessor::SOVStoreType::Average,
     481           7 :                             this->Name);
     482          14 :         SetupOutputVariable(state,
     483             :                             "Boiler Steam Outlet Temperature",
     484             :                             OutputProcessor::Unit::C,
     485             :                             this->BoilerOutletTemp,
     486             :                             OutputProcessor::SOVTimeStepType::System,
     487             :                             OutputProcessor::SOVStoreType::Average,
     488           7 :                             this->Name);
     489          14 :         SetupOutputVariable(state,
     490             :                             "Boiler Steam Mass Flow Rate",
     491             :                             OutputProcessor::Unit::kg_s,
     492             :                             this->BoilerMassFlowRate,
     493             :                             OutputProcessor::SOVTimeStepType::System,
     494             :                             OutputProcessor::SOVStoreType::Average,
     495           7 :                             this->Name);
     496           7 :     }
     497             : 
     498          35 :     void BoilerSpecs::autosize(EnergyPlusData &state)
     499             :     {
     500             : 
     501             :         // SUBROUTINE INFORMATION:
     502             :         //       AUTHOR         Rahul Chillar
     503             :         //       DATE WRITTEN   Dec 2004
     504             :         //       MODIFIED       November 2013 Daeho Kang, add component sizing table entries
     505             :         //       RE-ENGINEERED  na
     506             : 
     507             :         // PURPOSE OF THIS SUBROUTINE:
     508             :         // This subroutine is for sizing Boiler Components for which capacities and flow rates
     509             :         // have not been specified in the input.
     510             : 
     511             :         // METHODOLOGY EMPLOYED:
     512             :         // Obtains Steam flow rate from the plant sizing array. Calculates nominal capacity from
     513             :         // the hot water flow rate and the hot water loop design delta T.
     514             : 
     515             :         // SUBROUTINE PARAMETER DEFINITIONS:
     516             :         static constexpr std::string_view RoutineName("SizeBoiler");
     517             : 
     518             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     519          35 :         bool ErrorsFound(false); // If errors detected in input
     520          35 :         Real64 tmpNomCap = this->NomCap;
     521          35 :         int PltSizNum = state.dataPlnt->PlantLoop(this->plantLoc.loopNum).PlantSizNum;
     522             : 
     523          35 :         if (PltSizNum > 0) {
     524          35 :             if (state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate >= DataHVACGlobals::SmallWaterVolFlow) {
     525          28 :                 Real64 SizingTemp = this->TempUpLimitBoilerOut;
     526          28 :                 Real64 SteamDensity = FluidProperties::GetSatDensityRefrig(state, fluidNameSteam, SizingTemp, 1.0, this->FluidIndex, RoutineName);
     527          28 :                 Real64 EnthSteamOutDry = FluidProperties::GetSatEnthalpyRefrig(state, fluidNameSteam, SizingTemp, 1.0, this->FluidIndex, RoutineName);
     528          28 :                 Real64 EnthSteamOutWet = FluidProperties::GetSatEnthalpyRefrig(state, fluidNameSteam, SizingTemp, 0.0, this->FluidIndex, RoutineName);
     529          28 :                 Real64 LatentEnthSteam = EnthSteamOutDry - EnthSteamOutWet;
     530          28 :                 Real64 CpWater = FluidProperties::GetSatSpecificHeatRefrig(state, fluidNameSteam, SizingTemp, 0.0, this->FluidIndex, RoutineName);
     531          84 :                 tmpNomCap = (CpWater * SteamDensity * this->SizFac * state.dataSize->PlantSizData(PltSizNum).DeltaT *
     532          56 :                                  state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate +
     533          28 :                              state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate * SteamDensity * LatentEnthSteam);
     534             :             } else {
     535           7 :                 if (this->NomCapWasAutoSized) tmpNomCap = 0.0;
     536             :             }
     537          35 :             if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
     538           7 :                 if (this->NomCapWasAutoSized) {
     539           7 :                     this->NomCap = tmpNomCap;
     540           7 :                     if (state.dataPlnt->PlantFinalSizesOkayToReport) {
     541           7 :                         BaseSizer::reportSizerOutput(state, "Boiler:Steam", this->Name, "Design Size Nominal Capacity [W]", tmpNomCap);
     542             :                     }
     543           7 :                     if (state.dataPlnt->PlantFirstSizesOkayToReport) {
     544           0 :                         BaseSizer::reportSizerOutput(state, "Boiler:Steam", this->Name, "Initial Design Size Nominal Capacity [W]", tmpNomCap);
     545             :                     }
     546             :                 } else { // Hard-sized with sizing data
     547           0 :                     if (this->NomCap > 0.0 && tmpNomCap > 0.0) {
     548           0 :                         Real64 NomCapUser = this->NomCap;
     549           0 :                         if (state.dataPlnt->PlantFinalSizesOkayToReport) {
     550           0 :                             BaseSizer::reportSizerOutput(state,
     551             :                                                          "Boiler:Steam",
     552             :                                                          this->Name,
     553             :                                                          "Design Size Nominal Capacity [W]",
     554             :                                                          tmpNomCap,
     555             :                                                          "User-Specified Nominal Capacity [W]",
     556           0 :                                                          NomCapUser);
     557           0 :                             if (state.dataGlobal->DisplayExtraWarnings) {
     558           0 :                                 if ((std::abs(tmpNomCap - NomCapUser) / NomCapUser) > state.dataSize->AutoVsHardSizingThreshold) {
     559           0 :                                     ShowMessage(state, "SizePump: Potential issue with equipment sizing for " + this->Name);
     560           0 :                                     ShowContinueError(state, format("User-Specified Nominal Capacity of {:.2R} [W]", NomCapUser));
     561           0 :                                     ShowContinueError(state, format("differs from Design Size Nominal Capacity of {:.2R} [W]", tmpNomCap));
     562           0 :                                     ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
     563           0 :                                     ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
     564             :                                 }
     565             :                             }
     566             :                         }
     567             :                     }
     568             :                 }
     569             :             }
     570             :         } else {
     571           0 :             if (this->NomCapWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
     572           0 :                 ShowSevereError(state, "Autosizing of Boiler nominal capacity requires a loop Sizing:Plant object");
     573           0 :                 ShowContinueError(state, "Occurs in Boiler:Steam object=" + this->Name);
     574           0 :                 ErrorsFound = true;
     575             :             }
     576           0 :             if (!this->NomCapWasAutoSized && this->NomCap > 0.0 && state.dataPlnt->PlantFinalSizesOkayToReport) {
     577           0 :                 BaseSizer::reportSizerOutput(state, "Boiler:Steam", this->Name, "User-Specified Nominal Capacity [W]", this->NomCap);
     578             :             }
     579             :         }
     580             : 
     581          35 :         if (state.dataPlnt->PlantFinalSizesOkayToReport) {
     582             :             // create predefined report
     583           7 :             OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchMechType, this->Name, "Boiler:Steam");
     584           7 :             OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchMechNomEff, this->Name, this->NomEffic);
     585           7 :             OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchMechNomCap, this->Name, this->NomCap);
     586             :         }
     587             : 
     588          35 :         if (ErrorsFound) {
     589           0 :             ShowFatalError(state, "Preceding sizing errors cause program termination");
     590             :         }
     591          35 :     }
     592             : 
     593      104818 :     void BoilerSpecs::calculate(EnergyPlusData &state,
     594             :                                 Real64 &MyLoad,                                         // W - hot water demand to be met by boiler
     595             :                                 bool const RunFlag,                                     // TRUE if boiler operating
     596             :                                 DataBranchAirLoopPlant::ControlType const EquipFlowCtrl // Flow control mode for the equipment
     597             :     )
     598             :     {
     599             :         // SUBROUTINE INFORMATION:
     600             :         //       AUTHOR         Rahul Chillar
     601             :         //       DATE WRITTEN   Dec 2004
     602             :         //       MODIFIED       na
     603             :         //       RE-ENGINEERED  na
     604             : 
     605             :         // PURPOSE OF THIS SUBROUTINE:
     606             :         // This subroutine calculates the boiler fuel consumption and the associated
     607             :         // hot water demand met by the boiler
     608             : 
     609             :         // METHODOLOGY EMPLOYED:
     610             :         // The model is based on a single combustion efficiency (=1 for electric)
     611             :         // and a second order polynomial fit of performance data to obtain part
     612             :         // load performance
     613             : 
     614             :         // SUBROUTINE PARAMETER DEFINITIONS:
     615             :         static constexpr std::string_view RoutineName("CalcBoilerModel");
     616             : 
     617             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     618      104818 :         Real64 BoilerDeltaTemp(0.0); // C - boiler inlet to outlet temperature difference
     619             :         Real64 CpWater;              // Heat capacity of condensed steam
     620             : 
     621             :         // Loading the variables derived type in to local variables
     622      104818 :         this->BoilerLoad = 0.0;
     623      104818 :         this->BoilerMassFlowRate = 0.0;
     624             : 
     625      104818 :         switch (state.dataPlnt->PlantLoop(this->plantLoc.loopNum).LoopDemandCalcScheme) {
     626      104818 :         case DataPlant::LoopDemandCalcScheme::SingleSetPoint: {
     627      104818 :             this->BoilerOutletTemp = state.dataLoopNodes->Node(this->BoilerOutletNodeNum).TempSetPoint;
     628      104818 :         } break;
     629           0 :         case DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand: {
     630           0 :             this->BoilerOutletTemp = state.dataLoopNodes->Node(this->BoilerOutletNodeNum).TempSetPointLo;
     631           0 :         } break;
     632           0 :         default:
     633           0 :             break;
     634             :         }
     635             :         // If the specified load is 0.0 or the boiler should not run then we leave this subroutine.Before leaving
     636             :         // if the component control is SERIESACTIVE we set the component flow to inlet flow so that flow resolver
     637             :         // will not shut down the branch
     638      104818 :         if (MyLoad <= 0.0 || !RunFlag) {
     639       77018 :             if (EquipFlowCtrl == DataBranchAirLoopPlant::ControlType::SeriesActive)
     640           0 :                 this->BoilerMassFlowRate = state.dataLoopNodes->Node(this->BoilerInletNodeNum).MassFlowRate;
     641       77018 :             return;
     642             :         }
     643             : 
     644             :         // Set the current load equal to the boiler load
     645       27800 :         this->BoilerLoad = MyLoad;
     646             : 
     647       27800 :         this->BoilerPressCheck = FluidProperties::GetSatPressureRefrig(state, fluidNameSteam, this->BoilerOutletTemp, this->FluidIndex, RoutineName);
     648             : 
     649       27800 :         if ((this->BoilerPressCheck) > this->BoilerMaxOperPress) {
     650           0 :             if (this->PressErrIndex == 0) {
     651           0 :                 ShowSevereError(state, "Boiler:Steam=\"" + this->Name + "\", Saturation Pressure is greater than Maximum Operating Pressure,");
     652           0 :                 ShowContinueError(state, "Lower Input Temperature");
     653           0 :                 ShowContinueError(state, format("Steam temperature=[{:.2R}] C", this->BoilerOutletTemp));
     654           0 :                 ShowContinueError(state, format("Refrigerant Saturation Pressure =[{:.0R}] Pa", this->BoilerPressCheck));
     655             :             }
     656           0 :             ShowRecurringSevereErrorAtEnd(state,
     657           0 :                                           "Boiler:Steam=\"" + this->Name +
     658             :                                               "\", Saturation Pressure is greater than Maximum Operating Pressure..continues",
     659             :                                           this->PressErrIndex,
     660             :                                           this->BoilerPressCheck,
     661             :                                           this->BoilerPressCheck,
     662             :                                           _,
     663             :                                           "[Pa]",
     664             :                                           "[Pa]");
     665             :         }
     666             : 
     667       55600 :         CpWater = FluidProperties::GetSatSpecificHeatRefrig(
     668       27800 :             state, fluidNameSteam, state.dataLoopNodes->Node(this->BoilerInletNodeNum).Temp, 0.0, this->FluidIndex, RoutineName);
     669             : 
     670       27800 :         if (state.dataPlnt->PlantLoop(this->plantLoc.loopNum).LoopSide(this->plantLoc.loopSideNum).FlowLock ==
     671             :             DataPlant::FlowLock::Unlocked) { // TODO: Components shouldn't check FlowLock
     672             :             // Calculate the flow for the boiler
     673             : 
     674       13900 :             switch (state.dataPlnt->PlantLoop(this->plantLoc.loopNum).LoopDemandCalcScheme) {
     675       13900 :             case DataPlant::LoopDemandCalcScheme::SingleSetPoint: {
     676       13900 :                 BoilerDeltaTemp =
     677       13900 :                     state.dataLoopNodes->Node(this->BoilerOutletNodeNum).TempSetPoint - state.dataLoopNodes->Node(this->BoilerInletNodeNum).Temp;
     678       13900 :             } break;
     679           0 :             default: { // DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand
     680           0 :                 BoilerDeltaTemp =
     681           0 :                     state.dataLoopNodes->Node(this->BoilerOutletNodeNum).TempSetPointLo - state.dataLoopNodes->Node(this->BoilerInletNodeNum).Temp;
     682           0 :             } break;
     683             :             }
     684       13900 :             this->BoilerOutletTemp = BoilerDeltaTemp + state.dataLoopNodes->Node(this->BoilerInletNodeNum).Temp;
     685             : 
     686             :             Real64 const EnthSteamOutDry =
     687       13900 :                 FluidProperties::GetSatEnthalpyRefrig(state, fluidNameSteam, this->BoilerOutletTemp, 1.0, this->FluidIndex, RoutineName);
     688             :             Real64 const EnthSteamOutWet =
     689       13900 :                 FluidProperties::GetSatEnthalpyRefrig(state, fluidNameSteam, this->BoilerOutletTemp, 0.0, this->FluidIndex, RoutineName);
     690       13900 :             Real64 const LatentEnthSteam = EnthSteamOutDry - EnthSteamOutWet;
     691       13900 :             this->BoilerMassFlowRate = this->BoilerLoad / (LatentEnthSteam + (CpWater * BoilerDeltaTemp));
     692             : 
     693       13900 :             PlantUtilities::SetComponentFlowRate(
     694             :                 state, this->BoilerMassFlowRate, this->BoilerInletNodeNum, this->BoilerOutletNodeNum, this->plantLoc);
     695             : 
     696             :         } else { // If FlowLock is True
     697             :             // Set the boiler flow rate from inlet node and then check performance
     698       13900 :             this->BoilerMassFlowRate = state.dataLoopNodes->Node(this->BoilerInletNodeNum).MassFlowRate;
     699             :             // Assume that it can meet the setpoint
     700       13900 :             switch (state.dataPlnt->PlantLoop(this->plantLoc.loopNum).LoopDemandCalcScheme) {
     701       13900 :             case DataPlant::LoopDemandCalcScheme::SingleSetPoint: {
     702       13900 :                 BoilerDeltaTemp =
     703       13900 :                     state.dataLoopNodes->Node(this->BoilerOutletNodeNum).TempSetPoint - state.dataLoopNodes->Node(this->BoilerInletNodeNum).Temp;
     704       13900 :             } break;
     705           0 :             case DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand: {
     706           0 :                 BoilerDeltaTemp =
     707           0 :                     state.dataLoopNodes->Node(this->BoilerOutletNodeNum).TempSetPointLo - state.dataLoopNodes->Node(this->BoilerInletNodeNum).Temp;
     708           0 :             } break;
     709           0 :             default:
     710           0 :                 break;
     711             :             }
     712             :             // If boiler outlet temp is already greater than setpoint than it does not need to operate this iteration
     713       13900 :             if (BoilerDeltaTemp < 0.0) {
     714           0 :                 switch (state.dataPlnt->PlantLoop(this->plantLoc.loopNum).LoopDemandCalcScheme) {
     715           0 :                 case DataPlant::LoopDemandCalcScheme::SingleSetPoint: {
     716           0 :                     this->BoilerOutletTemp = state.dataLoopNodes->Node(this->BoilerOutletNodeNum).TempSetPoint;
     717           0 :                 } break;
     718           0 :                 case DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand: {
     719           0 :                     this->BoilerOutletTemp = state.dataLoopNodes->Node(this->BoilerOutletNodeNum).TempSetPointLo;
     720           0 :                 } break;
     721           0 :                 default:
     722           0 :                     break;
     723             :                 }
     724             :                 Real64 const EnthSteamOutDry =
     725           0 :                     FluidProperties::GetSatEnthalpyRefrig(state, fluidNameSteam, this->BoilerOutletTemp, 1.0, this->FluidIndex, RoutineName);
     726             :                 Real64 const EnthSteamOutWet =
     727           0 :                     FluidProperties::GetSatEnthalpyRefrig(state, fluidNameSteam, this->BoilerOutletTemp, 0.0, this->FluidIndex, RoutineName);
     728           0 :                 Real64 const LatentEnthSteam = EnthSteamOutDry - EnthSteamOutWet;
     729           0 :                 this->BoilerLoad = (this->BoilerMassFlowRate * LatentEnthSteam);
     730             : 
     731             :             } else {
     732       13900 :                 switch (state.dataPlnt->PlantLoop(this->plantLoc.loopNum).LoopDemandCalcScheme) {
     733       13900 :                 case DataPlant::LoopDemandCalcScheme::SingleSetPoint: {
     734       13900 :                     this->BoilerOutletTemp = state.dataLoopNodes->Node(this->BoilerOutletNodeNum).TempSetPoint;
     735       13900 :                 } break;
     736           0 :                 case DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand: {
     737           0 :                     this->BoilerOutletTemp = state.dataLoopNodes->Node(this->BoilerOutletNodeNum).TempSetPointLo;
     738           0 :                 } break;
     739           0 :                 default:
     740           0 :                     break;
     741             :                 }
     742             : 
     743             :                 Real64 const EnthSteamOutDry =
     744       13900 :                     FluidProperties::GetSatEnthalpyRefrig(state, fluidNameSteam, this->BoilerOutletTemp, 1.0, this->FluidIndex, RoutineName);
     745             :                 Real64 const EnthSteamOutWet =
     746       13900 :                     FluidProperties::GetSatEnthalpyRefrig(state, fluidNameSteam, this->BoilerOutletTemp, 0.0, this->FluidIndex, RoutineName);
     747       13900 :                 Real64 const LatentEnthSteam = EnthSteamOutDry - EnthSteamOutWet;
     748       13900 :                 this->BoilerLoad =
     749       13900 :                     std::abs(this->BoilerMassFlowRate * LatentEnthSteam) + std::abs(this->BoilerMassFlowRate * CpWater * BoilerDeltaTemp);
     750             :             }
     751             : 
     752             :             // If load exceeds the distributed load set to the distributed load
     753       13900 :             if (this->BoilerLoad > MyLoad) {
     754           0 :                 this->BoilerLoad = MyLoad;
     755             : 
     756             :                 // Reset later , here just for calculating latent heat
     757           0 :                 switch (state.dataPlnt->PlantLoop(this->plantLoc.loopNum).LoopDemandCalcScheme) {
     758           0 :                 case DataPlant::LoopDemandCalcScheme::SingleSetPoint: {
     759           0 :                     this->BoilerOutletTemp = state.dataLoopNodes->Node(this->BoilerOutletNodeNum).TempSetPoint;
     760           0 :                 } break;
     761           0 :                 case DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand: {
     762           0 :                     this->BoilerOutletTemp = state.dataLoopNodes->Node(this->BoilerOutletNodeNum).TempSetPointLo;
     763           0 :                 } break;
     764           0 :                 default:
     765           0 :                     break;
     766             :                 }
     767             : 
     768             :                 Real64 const EnthSteamOutDry =
     769           0 :                     FluidProperties::GetSatEnthalpyRefrig(state, fluidNameSteam, this->BoilerOutletTemp, 1.0, this->FluidIndex, RoutineName);
     770             :                 Real64 const EnthSteamOutWet =
     771           0 :                     FluidProperties::GetSatEnthalpyRefrig(state, fluidNameSteam, this->BoilerOutletTemp, 0.0, this->FluidIndex, RoutineName);
     772           0 :                 Real64 const LatentEnthSteam = EnthSteamOutDry - EnthSteamOutWet;
     773           0 :                 BoilerDeltaTemp = this->BoilerOutletTemp - state.dataLoopNodes->Node(this->BoilerInletNodeNum).Temp;
     774           0 :                 this->BoilerMassFlowRate = this->BoilerLoad / (LatentEnthSteam + CpWater * BoilerDeltaTemp);
     775             : 
     776           0 :                 PlantUtilities::SetComponentFlowRate(
     777             :                     state, this->BoilerMassFlowRate, this->BoilerInletNodeNum, this->BoilerOutletNodeNum, this->plantLoc);
     778             :             }
     779             : 
     780             :             // Checks Boiler Load on the basis of the machine limits.
     781       13900 :             if (this->BoilerLoad > this->NomCap) {
     782           0 :                 if (this->BoilerMassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) {
     783           0 :                     this->BoilerLoad = this->NomCap;
     784             : 
     785             :                     Real64 const EnthSteamOutDry =
     786           0 :                         FluidProperties::GetSatEnthalpyRefrig(state, fluidNameSteam, this->BoilerOutletTemp, 1.0, this->FluidIndex, RoutineName);
     787             :                     Real64 const EnthSteamOutWet =
     788           0 :                         FluidProperties::GetSatEnthalpyRefrig(state, fluidNameSteam, this->BoilerOutletTemp, 0.0, this->FluidIndex, RoutineName);
     789           0 :                     Real64 const LatentEnthSteam = EnthSteamOutDry - EnthSteamOutWet;
     790           0 :                     BoilerDeltaTemp = this->BoilerOutletTemp - state.dataLoopNodes->Node(this->BoilerInletNodeNum).Temp;
     791           0 :                     this->BoilerMassFlowRate = this->BoilerLoad / (LatentEnthSteam + CpWater * BoilerDeltaTemp);
     792             : 
     793           0 :                     PlantUtilities::SetComponentFlowRate(
     794             :                         state, this->BoilerMassFlowRate, this->BoilerInletNodeNum, this->BoilerOutletNodeNum, this->plantLoc);
     795             :                 } else {
     796           0 :                     this->BoilerLoad = 0.0;
     797           0 :                     this->BoilerOutletTemp = state.dataLoopNodes->Node(this->BoilerInletNodeNum).Temp;
     798             :                 }
     799             :             }
     800             : 
     801             :         } // End of the FlowLock If block
     802             : 
     803             :         // Limit BoilerOutletTemp.  If > max temp, trip boiler.
     804       27800 :         if (this->BoilerOutletTemp > this->TempUpLimitBoilerOut) {
     805           0 :             this->BoilerLoad = 0.0;
     806           0 :             this->BoilerOutletTemp = state.dataLoopNodes->Node(this->BoilerInletNodeNum).Temp;
     807             :             //  Does BoilerMassFlowRate need to be set????
     808             :         }
     809             : 
     810       27800 :         Real64 OperPLR = this->BoilerLoad / this->NomCap;
     811       27800 :         OperPLR = min(OperPLR, this->MaxPartLoadRat);
     812       27800 :         OperPLR = max(OperPLR, this->MinPartLoadRat);
     813       27800 :         Real64 TheorFuelUse = this->BoilerLoad / this->NomEffic;
     814             : 
     815             :         // Calculate fuel used
     816       27800 :         this->FuelUsed = TheorFuelUse / (this->FullLoadCoef[0] + this->FullLoadCoef[1] * OperPLR + this->FullLoadCoef[2] * pow_2(OperPLR));
     817             :         // Calculate boiler efficiency
     818       27800 :         this->BoilerEff = this->BoilerLoad / this->FuelUsed;
     819             :     }
     820             : 
     821             :     // Beginning of Record Keeping subroutines for the BOILER:SIMPLE Module
     822             : 
     823      104818 :     void BoilerSpecs::update(EnergyPlusData &state,
     824             :                              Real64 const MyLoad,                           // boiler operating load
     825             :                              bool const RunFlag,                            // boiler on when TRUE
     826             :                              [[maybe_unused]] bool const FirstHVACIteration // TRUE if First iteration of simulation
     827             :     )
     828             :     {
     829             :         // SUBROUTINE INFORMATION:
     830             :         //       AUTHOR         Rahul Chillar
     831             :         //       DATE WRITTEN   Dec 2004
     832             :         //       MODIFIED       na
     833             :         //       RE-ENGINEERED  na
     834             : 
     835             :         // PURPOSE OF THIS SUBROUTINE:
     836             :         // Boiler simulation reporting
     837             : 
     838      104818 :         Real64 ReportingConstant = state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
     839      104818 :         int BoilerInletNode = this->BoilerInletNodeNum;
     840      104818 :         int BoilerOutletNode = this->BoilerOutletNodeNum;
     841             : 
     842      104818 :         if (MyLoad <= 0.0 || !RunFlag) {
     843             :             // set node temperatures
     844       77018 :             PlantUtilities::SafeCopyPlantNode(state, BoilerInletNode, BoilerOutletNode);
     845       77018 :             state.dataLoopNodes->Node(BoilerOutletNode).Temp = state.dataLoopNodes->Node(BoilerInletNode).Temp;
     846       77018 :             this->BoilerOutletTemp = state.dataLoopNodes->Node(BoilerInletNode).Temp;
     847       77018 :             this->BoilerLoad = 0.0;
     848       77018 :             this->FuelUsed = 0.0;
     849       77018 :             this->BoilerEff = 0.0;
     850       77018 :             state.dataLoopNodes->Node(BoilerInletNode).Press = this->BoilerPressCheck;
     851       77018 :             state.dataLoopNodes->Node(BoilerOutletNode).Press = state.dataLoopNodes->Node(BoilerInletNode).Press;
     852       77018 :             state.dataLoopNodes->Node(BoilerInletNode).Quality = 0.0;
     853       77018 :             state.dataLoopNodes->Node(BoilerOutletNode).Quality = state.dataLoopNodes->Node(BoilerInletNode).Quality;
     854             : 
     855             :         } else {
     856             :             // set node temperatures
     857       27800 :             PlantUtilities::SafeCopyPlantNode(state, BoilerInletNode, BoilerOutletNode);
     858       27800 :             state.dataLoopNodes->Node(BoilerOutletNode).Temp = this->BoilerOutletTemp;
     859       27800 :             state.dataLoopNodes->Node(BoilerInletNode).Press = this->BoilerPressCheck; //???
     860       27800 :             state.dataLoopNodes->Node(BoilerOutletNode).Press = state.dataLoopNodes->Node(BoilerInletNode).Press;
     861       27800 :             state.dataLoopNodes->Node(BoilerOutletNode).Quality = 1.0; // Model assumes saturated steam exiting the boiler
     862             :         }
     863             : 
     864      104818 :         this->BoilerInletTemp = state.dataLoopNodes->Node(BoilerInletNode).Temp;
     865      104818 :         this->BoilerMassFlowRate = state.dataLoopNodes->Node(BoilerOutletNode).MassFlowRate;
     866      104818 :         this->BoilerEnergy = this->BoilerLoad * ReportingConstant;
     867      104818 :         this->FuelConsumed = this->FuelUsed * ReportingConstant;
     868      104818 :     }
     869             : 
     870             : } // namespace BoilerSteam
     871             : 
     872        2313 : } // namespace EnergyPlus

Generated by: LCOV version 1.13