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 : // C++ Headers
49 : #include <cassert>
50 : #include <cmath>
51 : #include <string>
52 :
53 : // ObjexxFCL Headers
54 : #include <ObjexxFCL/Fmath.hh>
55 :
56 : // EnergyPlus Headers
57 : #include "rs0001_factory.h"
58 : #include <EnergyPlus/Autosizing/All_Simple_Sizing.hh>
59 : #include <EnergyPlus/BranchNodeConnections.hh>
60 : #include <EnergyPlus/ChillerElectricASHRAE205.hh>
61 : #include <EnergyPlus/CurveManager.hh>
62 : #include <EnergyPlus/Data/EnergyPlusData.hh>
63 : #include <EnergyPlus/DataBranchAirLoopPlant.hh>
64 : #include <EnergyPlus/DataEnvironment.hh>
65 : #include <EnergyPlus/DataHVACGlobals.hh>
66 : #include <EnergyPlus/DataHeatBalance.hh>
67 : #include <EnergyPlus/DataIPShortCuts.hh>
68 : #include <EnergyPlus/DataLoopNode.hh>
69 : #include <EnergyPlus/DataSizing.hh>
70 : #include <EnergyPlus/DataSystemVariables.hh>
71 : #include <EnergyPlus/EMSManager.hh>
72 : #include <EnergyPlus/EnergyPlusLogger.hh>
73 : #include <EnergyPlus/FaultsManager.hh>
74 : #include <EnergyPlus/FileSystem.hh>
75 : #include <EnergyPlus/FluidProperties.hh>
76 : #include <EnergyPlus/General.hh>
77 : #include <EnergyPlus/GeneralRoutines.hh>
78 : #include <EnergyPlus/GlobalNames.hh>
79 : #include <EnergyPlus/HeatBalanceInternalHeatGains.hh>
80 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
81 : #include <EnergyPlus/NodeInputManager.hh>
82 : #include <EnergyPlus/OutAirNodeManager.hh>
83 : #include <EnergyPlus/OutputProcessor.hh>
84 : #include <EnergyPlus/OutputReportPredefined.hh>
85 : #include <EnergyPlus/Plant/DataPlant.hh>
86 : #include <EnergyPlus/Plant/PlantLocation.hh>
87 : #include <EnergyPlus/PlantUtilities.hh>
88 : #include <EnergyPlus/ScheduleManager.hh>
89 : #include <EnergyPlus/UtilityRoutines.hh>
90 : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
91 :
92 : namespace EnergyPlus::ChillerElectricASHRAE205 {
93 :
94 : constexpr std::array<std::string_view, static_cast<int>(AmbientTempIndicator::Num) - 1> AmbientTempNamesUC{
95 : "SCHEDULE",
96 : "ZONE",
97 : "OUTDOORS",
98 : };
99 :
100 : std::map<std::string, Btwxt::InterpolationMethod> InterpMethods = // NOLINT(cert-err58-cpp)
101 : {{"LINEAR", Btwxt::InterpolationMethod::linear}, {"CUBIC", Btwxt::InterpolationMethod::cubic}};
102 :
103 3 : void getChillerASHRAE205Input(EnergyPlusData &state)
104 : {
105 : static constexpr std::string_view RoutineName("getChillerASHRAE205Input: "); // include trailing blank space
106 : static constexpr std::string_view routineName = "getChillerASHRAE205Input";
107 :
108 : using namespace tk205;
109 9 : RSInstanceFactory::register_factory("RS0001", std::make_shared<RS0001Factory>());
110 :
111 3 : bool ErrorsFound{false};
112 :
113 3 : auto &s_ip = state.dataInputProcessing->inputProcessor;
114 3 : auto &s_ipsc = state.dataIPShortCut;
115 :
116 3 : state.dataIPShortCut->cCurrentModuleObject = ChillerElectricASHRAE205::ASHRAE205ChillerSpecs::ObjectType;
117 3 : int numElectric205Chillers = s_ip->getNumObjectsFound(state, state.dataIPShortCut->cCurrentModuleObject);
118 :
119 3 : if (numElectric205Chillers <= 0) {
120 0 : ShowSevereError(state, format("No {} equipment specified in input file", state.dataIPShortCut->cCurrentModuleObject));
121 0 : ErrorsFound = true;
122 : }
123 :
124 3 : state.dataChillerElectricASHRAE205->Electric205Chiller.allocate(numElectric205Chillers);
125 :
126 3 : auto const &ChillerInstances = s_ip->epJSON.find(state.dataIPShortCut->cCurrentModuleObject).value();
127 3 : int ChillerNum{0};
128 3 : auto const &objectSchemaProps = s_ip->getObjectSchemaProps(state, state.dataIPShortCut->cCurrentModuleObject);
129 :
130 8 : for (auto &instance : ChillerInstances.items()) {
131 5 : auto const &fields = instance.value();
132 5 : std::string const &thisObjectName = instance.key();
133 :
134 5 : ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, thisObjectName};
135 :
136 5 : GlobalNames::VerifyUniqueChillerName(
137 10 : state, state.dataIPShortCut->cCurrentModuleObject, thisObjectName, ErrorsFound, state.dataIPShortCut->cCurrentModuleObject + " Name");
138 :
139 5 : ++ChillerNum;
140 5 : auto &thisChiller = state.dataChillerElectricASHRAE205->Electric205Chiller(ChillerNum);
141 5 : thisChiller.Name = Util::makeUPPER(thisObjectName);
142 :
143 5 : s_ip->markObjectAsUsed(state.dataIPShortCut->cCurrentModuleObject, thisObjectName);
144 :
145 15 : std::string const rep_file_name = s_ip->getAlphaFieldValue(fields, objectSchemaProps, "representation_file_name");
146 5 : fs::path rep_file_path = DataSystemVariables::CheckForActualFilePath(state, fs::path(rep_file_name), std::string(RoutineName));
147 5 : if (rep_file_path.empty()) {
148 0 : ErrorsFound = true;
149 : // Given that several of the following expressions require the representation file to be present, we'll just throw a fatal here.
150 : // The ErrorsFound flag is still set to true here so that in the future, if we defer the fatal until later in this routine, it will still
151 : // be set The CheckForActualFilePath function emits some nice information to the ERR file, so we just need a simple fatal here
152 0 : ShowFatalError(state, "Program terminates due to the missing ASHRAE 205 RS0001 representation file.");
153 : }
154 : // Since logger context must persist across all calls to libtk205/btwxt, it must be a member
155 5 : thisChiller.LoggerContext = {&state, format("{} \"{}\"", state.dataIPShortCut->cCurrentModuleObject, thisObjectName)};
156 10 : thisChiller.Representation = std::dynamic_pointer_cast<tk205::rs0001_ns::RS0001>(
157 25 : RSInstanceFactory::create("RS0001", FileSystem::toString(rep_file_path).c_str(), std::make_shared<EnergyPlusLogger>()));
158 5 : if (nullptr == thisChiller.Representation) {
159 0 : ShowSevereError(state, format("{} is not an instance of an ASHRAE205 Chiller.", rep_file_path));
160 0 : ErrorsFound = true;
161 : }
162 5 : thisChiller.Representation->performance.performance_map_cooling.get_logger()->set_message_context(&thisChiller.LoggerContext);
163 5 : thisChiller.Representation->performance.performance_map_standby.get_logger()->set_message_context(&thisChiller.LoggerContext);
164 5 : thisChiller.InterpolationType =
165 10 : InterpMethods[Util::makeUPPER(s_ip->getAlphaFieldValue(fields, objectSchemaProps, "performance_interpolation_method"))];
166 :
167 5 : const auto &compressorSequence = thisChiller.Representation->performance.performance_map_cooling.grid_variables.compressor_sequence_number;
168 : // minmax_element is sound but perhaps overkill; as sequence numbers are required by A205 to be in ascending order
169 5 : const auto minmaxSequenceNum = std::minmax_element(compressorSequence.begin(), compressorSequence.end());
170 5 : thisChiller.MinSequenceNumber = *(minmaxSequenceNum.first);
171 5 : thisChiller.MaxSequenceNumber = *(minmaxSequenceNum.second);
172 :
173 10 : if (fields.count("rated_capacity")) {
174 0 : ShowWarningError(state, format("{}{}=\"{}\"", std::string{RoutineName}, state.dataIPShortCut->cCurrentModuleObject, thisChiller.Name));
175 0 : ShowContinueError(state, "Rated Capacity field is not yet supported for ASHRAE 205 representations.");
176 : }
177 :
178 5 : thisChiller.RefCap = 0.0; // ip->getRealFieldValue(fields, objectSchemaProps, "rated_capacity");
179 5 : thisChiller.RefCapWasAutoSized = false; // for now
180 :
181 : // if (thisChiller.RefCap == DataSizing::AutoSize) {
182 : // thisChiller.RefCapWasAutoSized = true;
183 : // }
184 : // if (thisChiller.RefCap == 0.0) {
185 : // ShowSevereError(
186 : // state, format("{}{}=\"{}\"",std::string{RoutineName},state.dataIPShortCut->cCurrentModuleObject,thisChiller.Name);
187 : // ShowContinueError(state, format("Invalid {}={:.2R}", "Rated Capacity", thisChiller.RefCap));
188 : // ErrorsFound = true;
189 : // }
190 :
191 10 : std::string const evap_inlet_node_name = s_ip->getAlphaFieldValue(fields, objectSchemaProps, "chilled_water_inlet_node_name");
192 10 : std::string const evap_outlet_node_name = s_ip->getAlphaFieldValue(fields, objectSchemaProps, "chilled_water_outlet_node_name");
193 5 : if (evap_inlet_node_name.empty() || evap_outlet_node_name.empty()) {
194 0 : ShowSevereError(state, format("{}{}=\"{}\"", std::string{RoutineName}, state.dataIPShortCut->cCurrentModuleObject, thisChiller.Name));
195 0 : ShowContinueError(state, "Evaporator Inlet or Outlet Node Name is blank.");
196 0 : ErrorsFound = true;
197 : }
198 5 : thisChiller.EvapInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
199 : evap_inlet_node_name,
200 : ErrorsFound,
201 : DataLoopNode::ConnectionObjectType::ChillerElectricASHRAE205,
202 5 : thisChiller.Name,
203 : DataLoopNode::NodeFluidType::Water,
204 : DataLoopNode::ConnectionType::Inlet,
205 : NodeInputManager::CompFluidStream::Primary,
206 : DataLoopNode::ObjectIsNotParent);
207 10 : thisChiller.EvapOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
208 : evap_outlet_node_name,
209 : ErrorsFound,
210 : DataLoopNode::ConnectionObjectType::ChillerElectricASHRAE205,
211 5 : thisChiller.Name,
212 : DataLoopNode::NodeFluidType::Water,
213 : DataLoopNode::ConnectionType::Outlet,
214 : NodeInputManager::CompFluidStream::Primary,
215 : DataLoopNode::ObjectIsNotParent);
216 10 : BranchNodeConnections::TestCompSet(
217 5 : state, state.dataIPShortCut->cCurrentModuleObject, thisChiller.Name, evap_inlet_node_name, evap_outlet_node_name, "Chilled Water Nodes");
218 :
219 5 : thisChiller.CondenserType = DataPlant::CondenserType::WaterCooled;
220 :
221 10 : std::string const cond_inlet_node_name = s_ip->getAlphaFieldValue(fields, objectSchemaProps, "condenser_inlet_node_name");
222 10 : std::string const cond_outlet_node_name = s_ip->getAlphaFieldValue(fields, objectSchemaProps, "condenser_outlet_node_name");
223 5 : if (cond_inlet_node_name.empty() || cond_outlet_node_name.empty()) {
224 0 : ShowSevereError(state, format("{}{}=\"{}\"", std::string{RoutineName}, state.dataIPShortCut->cCurrentModuleObject, thisChiller.Name));
225 0 : ShowContinueError(state, "Condenser Inlet or Outlet Node Name is blank.");
226 0 : ErrorsFound = true;
227 : }
228 5 : thisChiller.CondInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
229 : cond_inlet_node_name,
230 : ErrorsFound,
231 : DataLoopNode::ConnectionObjectType::ChillerElectricASHRAE205,
232 5 : thisChiller.Name,
233 : DataLoopNode::NodeFluidType::Water,
234 : DataLoopNode::ConnectionType::Inlet,
235 : NodeInputManager::CompFluidStream::Secondary,
236 : DataLoopNode::ObjectIsNotParent);
237 :
238 10 : thisChiller.CondOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
239 : cond_outlet_node_name,
240 : ErrorsFound,
241 : DataLoopNode::ConnectionObjectType::ChillerElectricASHRAE205,
242 5 : thisChiller.Name,
243 : DataLoopNode::NodeFluidType::Water,
244 : DataLoopNode::ConnectionType::Outlet,
245 : NodeInputManager::CompFluidStream::Secondary,
246 : DataLoopNode::ObjectIsNotParent);
247 :
248 10 : BranchNodeConnections::TestCompSet(state,
249 5 : state.dataIPShortCut->cCurrentModuleObject,
250 : thisChiller.Name,
251 : cond_inlet_node_name,
252 : cond_outlet_node_name,
253 : "Condenser Water Nodes");
254 :
255 5 : thisChiller.FlowMode = static_cast<DataPlant::FlowMode>(
256 10 : getEnumValue(DataPlant::FlowModeNamesUC, s_ip->getAlphaFieldValue(fields, objectSchemaProps, "chiller_flow_mode")));
257 :
258 5 : if (thisChiller.FlowMode == DataPlant::FlowMode::Invalid) {
259 0 : ShowSevereError(state, format("{}{}=\"{}\"", std::string{RoutineName}, state.dataIPShortCut->cCurrentModuleObject, thisObjectName));
260 0 : ShowContinueError(state, format("Invalid Chiller Flow Mode = {}", fields.at("chiller_flow_mode").get<std::string>()));
261 0 : ShowContinueError(state, "Available choices are ConstantFlow, NotModulated, or LeavingSetpointModulated");
262 0 : ShowContinueError(state, "Flow mode NotModulated is assumed and the simulation continues.");
263 0 : thisChiller.FlowMode = DataPlant::FlowMode::NotModulated;
264 : };
265 :
266 5 : thisChiller.SizFac = fields.at("sizing_factor").get<Real64>();
267 5 : if (thisChiller.SizFac <= 0.0) {
268 0 : thisChiller.SizFac = 1.0;
269 : }
270 :
271 : {
272 5 : auto &tmpFlowRate = fields.at("chilled_water_maximum_requested_flow_rate");
273 5 : if (tmpFlowRate == "Autosize") {
274 0 : thisChiller.EvapVolFlowRate = DataSizing::AutoSize;
275 0 : thisChiller.EvapVolFlowRateWasAutoSized = true;
276 : } else {
277 5 : thisChiller.EvapVolFlowRate = tmpFlowRate.get<Real64>();
278 : }
279 : }
280 : {
281 5 : auto &tmpFlowRate = fields.at("condenser_maximum_requested_flow_rate");
282 5 : if (tmpFlowRate == "Autosize") {
283 0 : thisChiller.CondVolFlowRate = DataSizing::AutoSize;
284 0 : thisChiller.CondVolFlowRateWasAutoSized = true;
285 : } else {
286 5 : thisChiller.CondVolFlowRate = tmpFlowRate.get<Real64>();
287 : }
288 : }
289 :
290 5 : thisChiller.AmbientTempType = static_cast<AmbientTempIndicator>(
291 10 : getEnumValue(AmbientTempNamesUC, Util::makeUPPER(s_ip->getAlphaFieldValue(fields, objectSchemaProps, "ambient_temperature_indicator"))));
292 5 : switch (thisChiller.AmbientTempType) {
293 0 : case AmbientTempIndicator::Schedule: {
294 0 : std::string const ambient_temp_schedule = s_ip->getAlphaFieldValue(fields, objectSchemaProps, "ambient_temperature_schedule");
295 0 : if ((thisChiller.ambientTempSched = Sched::GetSchedule(state, ambient_temp_schedule)) == nullptr) {
296 0 : ShowSevereItemNotFound(state, eoh, "Ambient Temperature Schedule", ambient_temp_schedule);
297 0 : ErrorsFound = true;
298 : }
299 :
300 0 : break;
301 0 : }
302 5 : case AmbientTempIndicator::TempZone: {
303 10 : std::string const ambient_temp_zone_name = s_ip->getAlphaFieldValue(fields, objectSchemaProps, "ambient_temperature_zone_name");
304 5 : thisChiller.AmbientTempZone = Util::FindItemInList(ambient_temp_zone_name, state.dataHeatBal->Zone);
305 5 : if (thisChiller.AmbientTempZone == 0) {
306 0 : ShowSevereError(state,
307 0 : format("{} = {}: Ambient Temperature Zone not found = {}",
308 0 : state.dataIPShortCut->cCurrentModuleObject,
309 : thisObjectName,
310 : ambient_temp_zone_name));
311 0 : ErrorsFound = true;
312 : } else {
313 5 : SetupZoneInternalGain(state,
314 : thisChiller.AmbientTempZone,
315 : thisChiller.Name,
316 : DataHeatBalance::IntGainType::ElectricEquipment,
317 : &thisChiller.AmbientZoneGain);
318 : }
319 5 : break;
320 5 : }
321 0 : case AmbientTempIndicator::OutsideAir: {
322 : std::string const ambient_temp_outdoor_node =
323 0 : s_ip->getAlphaFieldValue(fields, objectSchemaProps, "ambient_temperature_outdoor_air_node_name");
324 0 : thisChiller.AmbientTempOutsideAirNode = NodeInputManager::GetOnlySingleNode(state,
325 : ambient_temp_outdoor_node,
326 : ErrorsFound,
327 : DataLoopNode::ConnectionObjectType::ChillerElectricASHRAE205,
328 0 : thisChiller.Name,
329 : DataLoopNode::NodeFluidType::Air,
330 : DataLoopNode::ConnectionType::OutsideAirReference,
331 : NodeInputManager::CompFluidStream::Primary,
332 : DataLoopNode::ObjectIsNotParent);
333 0 : if (fields.count("ambient_temperature_outdoor_air_node_name")) {
334 0 : if (!OutAirNodeManager::CheckOutAirNodeNumber(state, thisChiller.AmbientTempOutsideAirNode)) {
335 0 : ShowSevereError(state,
336 0 : format("{} = {}: Outdoor Air Node not on OutdoorAir:NodeList or OutdoorAir:Node",
337 0 : state.dataIPShortCut->cCurrentModuleObject,
338 : thisObjectName));
339 0 : ShowContinueError(state, format("...Referenced Node Name={}", ambient_temp_outdoor_node));
340 0 : ErrorsFound = true;
341 : }
342 : } else {
343 0 : ShowSevereError(state, format("{} = {}", state.dataIPShortCut->cCurrentModuleObject, ambient_temp_outdoor_node));
344 0 : ShowContinueError(state, "An Ambient Outdoor Air Node name must be used when the Ambient Temperature Indicator is Outdoors.");
345 0 : ErrorsFound = true;
346 : }
347 :
348 0 : break;
349 0 : }
350 0 : default: {
351 0 : ShowSevereError(state,
352 0 : format("{} = {}: Invalid Ambient Temperature Indicator entered={}",
353 0 : state.dataIPShortCut->cCurrentModuleObject,
354 : thisObjectName,
355 0 : s_ip->getAlphaFieldValue(fields, objectSchemaProps, "ambient_temperature_indicator")));
356 0 : ShowContinueError(state, " Valid entries are SCHEDULE, ZONE, and OUTDOORS.");
357 0 : ErrorsFound = true;
358 0 : break;
359 : }
360 : }
361 : // end Ambient temperature
362 15 : std::string const oil_cooler_inlet_node = s_ip->getAlphaFieldValue(fields, objectSchemaProps, "oil_cooler_inlet_node_name");
363 15 : std::string const oil_cooler_outlet_node = s_ip->getAlphaFieldValue(fields, objectSchemaProps, "oil_cooler_outlet_node_name");
364 5 : if (!oil_cooler_inlet_node.empty() && !oil_cooler_outlet_node.empty()) {
365 2 : thisChiller.OilCoolerInletNode = NodeInputManager::GetOnlySingleNode(state,
366 : oil_cooler_inlet_node,
367 : ErrorsFound,
368 : DataLoopNode::ConnectionObjectType::ChillerElectricASHRAE205,
369 2 : thisChiller.Name,
370 : DataLoopNode::NodeFluidType::Water,
371 : DataLoopNode::ConnectionType::Inlet,
372 : NodeInputManager::CompFluidStream::Tertiary,
373 : DataLoopNode::ObjectIsNotParent);
374 4 : thisChiller.OilCoolerOutletNode = NodeInputManager::GetOnlySingleNode(state,
375 : oil_cooler_outlet_node,
376 : ErrorsFound,
377 : DataLoopNode::ConnectionObjectType::ChillerElectricASHRAE205,
378 2 : thisChiller.Name,
379 : DataLoopNode::NodeFluidType::Water,
380 : DataLoopNode::ConnectionType::Outlet,
381 : NodeInputManager::CompFluidStream::Tertiary,
382 : DataLoopNode::ObjectIsNotParent);
383 6 : BranchNodeConnections::TestCompSet(state,
384 2 : state.dataIPShortCut->cCurrentModuleObject,
385 : thisChiller.Name,
386 : oil_cooler_inlet_node,
387 : oil_cooler_outlet_node,
388 : "Oil Cooler Water Nodes");
389 : }
390 15 : std::string const aux_heat_inlet_node = s_ip->getAlphaFieldValue(fields, objectSchemaProps, "auxiliary_inlet_node_name");
391 10 : std::string const aux_heat_outlet_node = s_ip->getAlphaFieldValue(fields, objectSchemaProps, "auxiliary_outlet_node_name");
392 5 : if (!aux_heat_inlet_node.empty() && !aux_heat_outlet_node.empty()) {
393 :
394 2 : thisChiller.AuxiliaryHeatInletNode = NodeInputManager::GetOnlySingleNode(state,
395 : aux_heat_inlet_node,
396 : ErrorsFound,
397 : DataLoopNode::ConnectionObjectType::ChillerElectricASHRAE205,
398 2 : thisChiller.Name,
399 : DataLoopNode::NodeFluidType::Water,
400 : DataLoopNode::ConnectionType::Inlet,
401 : NodeInputManager::CompFluidStream::Quaternary,
402 : DataLoopNode::ObjectIsNotParent);
403 4 : thisChiller.AuxiliaryHeatOutletNode = NodeInputManager::GetOnlySingleNode(state,
404 : aux_heat_outlet_node,
405 : ErrorsFound,
406 : DataLoopNode::ConnectionObjectType::ChillerElectricASHRAE205,
407 2 : thisChiller.Name,
408 : DataLoopNode::NodeFluidType::Water,
409 : DataLoopNode::ConnectionType::Outlet,
410 : NodeInputManager::CompFluidStream::Quaternary,
411 : DataLoopNode::ObjectIsNotParent);
412 6 : BranchNodeConnections::TestCompSet(state,
413 2 : state.dataIPShortCut->cCurrentModuleObject,
414 : thisChiller.Name,
415 : aux_heat_inlet_node,
416 : aux_heat_outlet_node,
417 : "Auxiliary Water Nodes");
418 : }
419 :
420 : // TODO: When implemented, add ...WasAutoSized variables
421 10 : if (fields.count("oil_cooler_design_flow_rate")) {
422 4 : thisChiller.OilCoolerVolFlowRate = fields.at("oil_cooler_design_flow_rate").get<Real64>();
423 : }
424 10 : if (fields.count("auxiliary_equipment_design_flow_rate")) {
425 0 : thisChiller.AuxiliaryVolFlowRate = fields.at("auxiliary_equipment_design_flow_rate").get<Real64>();
426 : }
427 :
428 10 : if (fields.count("end_use_subcategory")) {
429 0 : thisChiller.EndUseSubcategory = s_ip->getAlphaFieldValue(fields, objectSchemaProps, "end_use_subcategory");
430 : } else {
431 5 : thisChiller.EndUseSubcategory = "General";
432 : }
433 : // Set reference conditions
434 5 : thisChiller.TempRefCondIn = 29.44;
435 5 : thisChiller.TempRefEvapOut = 6.67;
436 8 : }
437 :
438 3 : if (ErrorsFound) {
439 0 : ShowFatalError(state, format("Errors found in processing input for {}", state.dataIPShortCut->cCurrentModuleObject));
440 : }
441 3 : }
442 :
443 14 : ASHRAE205ChillerSpecs *ASHRAE205ChillerSpecs::factory(EnergyPlusData &state, std::string const &objectName)
444 : {
445 14 : if (state.dataChillerElectricASHRAE205->getInputFlag) {
446 3 : getChillerASHRAE205Input(state);
447 3 : state.dataChillerElectricASHRAE205->getInputFlag = false;
448 : }
449 14 : auto thisObj = std::find_if(state.dataChillerElectricASHRAE205->Electric205Chiller.begin(),
450 14 : state.dataChillerElectricASHRAE205->Electric205Chiller.end(),
451 20 : [&objectName](const ASHRAE205ChillerSpecs &myObj) { return myObj.Name == objectName; });
452 14 : if (thisObj != state.dataChillerElectricASHRAE205->Electric205Chiller.end()) {
453 14 : return thisObj;
454 : }
455 : // If we didn't find it, fatal
456 : ShowFatalError(state, format("ASHRAE205ChillerSpecs::factory: Error getting inputs for object named: {}", objectName)); // LCOV_EXCL_LINE
457 : return nullptr; // LCOV_EXCL_LINE
458 : }
459 :
460 5 : void ASHRAE205ChillerSpecs::oneTimeInit_new(EnergyPlusData &state)
461 : {
462 : // This function is called from GetPlantInput
463 : // Locate the chillers on the plant loops for later usage
464 5 : bool errFlag{false};
465 15 : PlantUtilities::ScanPlantLoopsForObject(
466 10 : state, this->Name, DataPlant::PlantEquipmentType::Chiller_ElectricASHRAE205, this->CWPlantLoc, errFlag, _, _, _, this->EvapInletNodeNum, _);
467 5 : if (this->CondenserType != DataPlant::CondenserType::AirCooled) {
468 15 : PlantUtilities::ScanPlantLoopsForObject(state,
469 : this->Name,
470 : DataPlant::PlantEquipmentType::Chiller_ElectricASHRAE205,
471 5 : this->CDPlantLoc,
472 : errFlag,
473 : _,
474 : _,
475 : _,
476 5 : this->CondInletNodeNum,
477 : _);
478 5 : PlantUtilities::InterConnectTwoPlantLoopSides(
479 5 : state, this->CWPlantLoc, this->CDPlantLoc, DataPlant::PlantEquipmentType::Chiller_ElectricASHRAE205, true);
480 : }
481 5 : if (this->OilCoolerInletNode) {
482 6 : PlantUtilities::ScanPlantLoopsForObject(state,
483 : this->Name,
484 : DataPlant::PlantEquipmentType::Chiller_ElectricASHRAE205,
485 2 : this->OCPlantLoc,
486 : errFlag,
487 : _,
488 : _,
489 : _,
490 2 : this->OilCoolerInletNode,
491 : _);
492 : }
493 5 : if (this->AuxiliaryHeatInletNode) {
494 6 : PlantUtilities::ScanPlantLoopsForObject(state,
495 : this->Name,
496 : DataPlant::PlantEquipmentType::Chiller_ElectricASHRAE205,
497 2 : this->AHPlantLoc,
498 : errFlag,
499 : _,
500 : _,
501 : _,
502 2 : this->AuxiliaryHeatInletNode,
503 : _);
504 : }
505 : // If and when heat recovery is implemented, uncomment
506 : #if 0
507 : if (this->HeatRecActive) {
508 : PlantUtilities::ScanPlantLoopsForObject(state,
509 : this->Name,
510 : DataPlant::PlantEquipmentType::Chiller_ElectricASHRAE205,
511 : this->HRPlantLoc,
512 : errFlag,
513 : _,
514 : _,
515 : _,
516 : this->HeatRecInletNodeNum,
517 : _);
518 : PlantUtilities::InterConnectTwoPlantLoopSides(
519 : state, this->CWPlantLoc, this->HRPlantLoc, DataPlant::PlantEquipmentType::Chiller_ElectricASHRAE205, true);
520 : }
521 :
522 : if ((this->CondenserType != DataPlant::CondenserType::AirCooled) && (this->HeatRecActive)) {
523 : PlantUtilities::InterConnectTwoPlantLoopSides(
524 : state, this->CDPlantLoc, this->HRPlantLoc, DataPlant::PlantEquipmentType::Chiller_ElectricASHRAE205, false);
525 : }
526 : #endif // #if 0
527 :
528 5 : if (errFlag) {
529 0 : ShowFatalError(state, "InitElecASHRAE205Chiller: Program terminated due to previous condition(s).");
530 : }
531 :
532 5 : if (this->FlowMode == DataPlant::FlowMode::Constant) {
533 : // reset flow priority
534 4 : this->CWPlantLoc.comp->FlowPriority = DataPlant::LoopFlowStatus::NeedyIfLoopOn;
535 : }
536 :
537 1 : else if (this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated) {
538 : // reset flow priority
539 0 : this->CWPlantLoc.comp->FlowPriority = DataPlant::LoopFlowStatus::NeedyIfLoopOn;
540 : // check if setpoint on outlet node
541 0 : if ((state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint == DataLoopNode::SensedNodeFlagValue) &&
542 0 : (state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi == DataLoopNode::SensedNodeFlagValue)) {
543 0 : if (!state.dataGlobal->AnyEnergyManagementSystemInModel) {
544 0 : if (!this->ModulatedFlowErrDone) {
545 0 : ShowWarningError(state, format("Missing temperature setpoint for LeavingSetpointModulated mode chiller named {}", this->Name));
546 0 : ShowContinueError(
547 : state, " A temperature setpoint is needed at the outlet node of a chiller in variable flow mode, use a SetpointManager");
548 0 : ShowContinueError(state, " The overall loop setpoint will be assumed for chiller. The simulation continues ... ");
549 0 : this->ModulatedFlowErrDone = true;
550 : }
551 : } else {
552 : // need call to EMS to check node
553 0 : bool fatalError = false; // but not really fatal yet, but should be.
554 0 : EMSManager::CheckIfNodeSetPointManagedByEMS(state, this->EvapOutletNodeNum, HVAC::CtrlVarType::Temp, fatalError);
555 0 : state.dataLoopNodes->NodeSetpointCheck(this->EvapOutletNodeNum).needsSetpointChecking = false;
556 0 : if (fatalError) {
557 0 : if (!this->ModulatedFlowErrDone) {
558 0 : ShowWarningError(state,
559 0 : format("Missing temperature setpoint for LeavingSetpointModulated mode chiller named {}", this->Name));
560 0 : ShowContinueError(state,
561 : " A temperature setpoint is needed at the outlet node of a chiller evaporator in variable flow mode");
562 0 : ShowContinueError(state, " use a Setpoint Manager to establish a setpoint at the chiller evaporator outlet node ");
563 0 : ShowContinueError(state, " or use an EMS actuator to establish a setpoint at the outlet node ");
564 0 : ShowContinueError(state, " The overall loop setpoint will be assumed for chiller. The simulation continues ... ");
565 0 : this->ModulatedFlowErrDone = true;
566 : }
567 : }
568 : }
569 0 : this->ModulatedFlowSetToLoop = true;
570 0 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint =
571 0 : state.dataLoopNodes->Node(this->CWPlantLoc.loop->TempSetPointNodeNum).TempSetPoint;
572 0 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi =
573 0 : state.dataLoopNodes->Node(this->CWPlantLoc.loop->TempSetPointNodeNum).TempSetPointHi;
574 : }
575 : }
576 :
577 5 : this->setOutputVariables(state);
578 5 : }
579 :
580 227411 : void ASHRAE205ChillerSpecs::initialize(EnergyPlusData &state, bool const RunFlag, Real64 const MyLoad)
581 : {
582 : static constexpr std::string_view RoutineName("ASHRAE205ChillerSpecs::initialize");
583 :
584 227411 : switch (this->AmbientTempType) {
585 0 : case AmbientTempIndicator::Schedule: {
586 0 : this->AmbientTemp = this->ambientTempSched->getCurrentVal();
587 0 : break;
588 : }
589 227411 : case AmbientTempIndicator::TempZone: {
590 227411 : this->AmbientTemp = state.dataZoneTempPredictorCorrector->zoneHeatBalance(this->AmbientTempZone).MAT;
591 227411 : break;
592 : }
593 0 : case AmbientTempIndicator::OutsideAir: {
594 0 : this->AmbientTemp = state.dataLoopNodes->Node(this->AmbientTempOutsideAirNode).Temp;
595 0 : break;
596 : }
597 0 : default:
598 0 : break;
599 : }
600 :
601 227411 : this->EquipFlowCtrl = this->CWPlantLoc.comp->FlowCtrl;
602 :
603 227411 : if (this->MyEnvrnFlag && state.dataGlobal->BeginEnvrnFlag && (state.dataPlnt->PlantFirstSizesOkayToFinalize)) {
604 955 : Real64 rho = this->CWPlantLoc.loop->glycol->getDensity(state, Constant::CWInitConvTemp, RoutineName);
605 :
606 955 : this->EvapMassFlowRateMax = rho * this->EvapVolFlowRate;
607 955 : PlantUtilities::InitComponentNodes(state, 0.0, this->EvapMassFlowRateMax, this->EvapInletNodeNum, this->EvapOutletNodeNum);
608 :
609 955 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
610 955 : rho = this->CDPlantLoc.loop->glycol->getDensity(state, this->TempRefCondIn, RoutineName);
611 955 : this->CondMassFlowRateMax = rho * this->CondVolFlowRate;
612 955 : PlantUtilities::InitComponentNodes(state, 0.0, this->CondMassFlowRateMax, this->CondInletNodeNum, this->CondOutletNodeNum);
613 955 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp = this->TempRefCondIn;
614 : }
615 : // Set mass flow rates at Oil Cooler and Aux Equipment nodes
616 955 : if (this->OilCoolerInletNode) {
617 426 : Real64 rho_oil_cooler = this->OCPlantLoc.loop->glycol->getDensity(state, Constant::InitConvTemp, RoutineName);
618 426 : this->OilCoolerMassFlowRate = rho_oil_cooler * this->OilCoolerVolFlowRate;
619 426 : PlantUtilities::InitComponentNodes(state, 0.0, this->OilCoolerMassFlowRate, this->OilCoolerInletNode, this->OilCoolerOutletNode);
620 : }
621 955 : if (this->AuxiliaryHeatInletNode) {
622 426 : Real64 rho_aux = this->AHPlantLoc.loop->glycol->getDensity(state, Constant::InitConvTemp, RoutineName);
623 426 : this->AuxiliaryMassFlowRate = rho_aux * this->AuxiliaryVolFlowRate;
624 426 : PlantUtilities::InitComponentNodes(state, 0.0, this->AuxiliaryMassFlowRate, this->AuxiliaryHeatInletNode, this->AuxiliaryHeatOutletNode);
625 : }
626 : }
627 227411 : if (!state.dataGlobal->BeginEnvrnFlag) {
628 226376 : this->MyEnvrnFlag = true;
629 : }
630 :
631 227411 : if ((this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated) && this->ModulatedFlowSetToLoop) {
632 : // see ReformulatedEIR or EIR Chiller for origin of the following
633 0 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint =
634 0 : state.dataLoopNodes->Node(this->CWPlantLoc.loop->TempSetPointNodeNum).TempSetPoint;
635 0 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi =
636 0 : state.dataLoopNodes->Node(this->CWPlantLoc.loop->TempSetPointNodeNum).TempSetPointHi;
637 : }
638 :
639 227411 : Real64 mdot = ((std::abs(MyLoad) > 0.0) && RunFlag) ? this->EvapMassFlowRateMax : 0.0;
640 227411 : Real64 mdotCond = ((std::abs(MyLoad) > 0.0) && RunFlag) ? this->CondMassFlowRateMax : 0.0;
641 :
642 227411 : PlantUtilities::SetComponentFlowRate(state, mdot, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
643 :
644 227411 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
645 227411 : PlantUtilities::SetComponentFlowRate(state, mdotCond, this->CondInletNodeNum, this->CondOutletNodeNum, this->CDPlantLoc);
646 : }
647 :
648 : // Set component flow rates for Oil Cooler and Aux equipment
649 227411 : if (this->OilCoolerInletNode) {
650 99284 : PlantUtilities::SetComponentFlowRate(
651 99284 : state, this->OilCoolerMassFlowRate, this->OilCoolerInletNode, this->OilCoolerOutletNode, this->OCPlantLoc);
652 : }
653 227411 : if (this->AuxiliaryHeatInletNode) {
654 99284 : PlantUtilities::SetComponentFlowRate(
655 99284 : state, this->AuxiliaryMassFlowRate, this->AuxiliaryHeatInletNode, this->AuxiliaryHeatOutletNode, this->AHPlantLoc);
656 : }
657 : // Recalculate volumetric flow rates from component mass flow rates if necessary
658 :
659 : // Revisit when heat recovery implemented
660 : #if 0
661 : // Initialize heat recovery flow rates at node
662 : if (this->HeatRecActive) {
663 :
664 : // check if inlet limit active and if exceeded.
665 : bool HeatRecRunFlag = RunFlag;
666 : if (this->heatRecInletLimitSched != nullptr) {
667 : Real64 HeatRecHighInletLimit = this->heatRecInletLimitSched->getCurrentVal();
668 : if (state.dataLoopNodes->Node(this->HeatRecInletNodeNum).Temp > HeatRecHighInletLimit) { // shut down heat recovery
669 : HeatRecRunFlag = false;
670 : } else {
671 : HeatRecRunFlag = RunFlag;
672 : }
673 : }
674 :
675 : mdot = HeatRecRunFlag ? this->DesignHeatRecMassFlowRate : 0.0;
676 :
677 : PlantUtilities::SetComponentFlowRate(state, mdot, this->HeatRecInletNodeNum, this->HeatRecOutletNodeNum, this->HRPlantLoc);
678 : }
679 : #endif // if 0
680 227411 : }
681 :
682 25 : void ASHRAE205ChillerSpecs::size([[maybe_unused]] EnergyPlusData &state)
683 : {
684 : static constexpr std::string_view RoutineName("SizeElectricASHRAE205Chiller");
685 :
686 25 : bool ErrorsFound = false;
687 25 : Real64 tmpNomCap{0.0};
688 25 : Real64 tmpEvapVolFlowRate = this->EvapVolFlowRate;
689 25 : Real64 tmpCondVolFlowRate = this->CondVolFlowRate;
690 :
691 : // Size evaporator flow rate
692 : // find the appropriate Plant Sizing object
693 25 : int PltSizNum = this->CWPlantLoc.loop->PlantSizNum;
694 :
695 25 : if (PltSizNum > 0) {
696 20 : if (state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow) {
697 12 : tmpEvapVolFlowRate = state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate * this->SizFac;
698 : } else {
699 8 : if (this->EvapVolFlowRateWasAutoSized) {
700 0 : tmpEvapVolFlowRate = 0.0;
701 : }
702 : }
703 20 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
704 4 : if (this->EvapVolFlowRateWasAutoSized) {
705 0 : this->EvapVolFlowRate = tmpEvapVolFlowRate;
706 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
707 0 : BaseSizer::reportSizerOutput(
708 : state, this->ObjectType, this->Name, "Design Size Chilled Water Maximum Requested Flow Rate [m3/s]", tmpEvapVolFlowRate);
709 : }
710 0 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
711 0 : BaseSizer::reportSizerOutput(state,
712 : this->ObjectType,
713 : this->Name,
714 : "Initial Design Size Chilled Water Maximum Requested Flow Rate [m3/s]",
715 : tmpEvapVolFlowRate);
716 : }
717 : } else { // Hard-size with sizing data
718 4 : if (this->EvapVolFlowRate > 0.0 && tmpEvapVolFlowRate > 0.0) {
719 4 : Real64 EvapVolFlowRateUser = this->EvapVolFlowRate;
720 4 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
721 4 : BaseSizer::reportSizerOutput(state,
722 : this->ObjectType,
723 : this->Name,
724 : "Design Size Chilled Water Maximum Requested Flow Rate [m3/s]",
725 : tmpEvapVolFlowRate,
726 : "User-Specified Chilled Water Maximum Requested Flow Rate [m3/s]",
727 : EvapVolFlowRateUser);
728 4 : if (state.dataGlobal->DisplayExtraWarnings) {
729 0 : if ((std::abs(tmpEvapVolFlowRate - EvapVolFlowRateUser) / EvapVolFlowRateUser) >
730 0 : state.dataSize->AutoVsHardSizingThreshold) {
731 0 : ShowMessage(state, format("{}: Potential issue with equipment sizing for {}", RoutineName, this->Name));
732 0 : ShowContinueError(
733 0 : state, format("User-Specified Chilled Water Maximum Requested Flow Rate of {:.5R} [m3/s]", EvapVolFlowRateUser));
734 0 : ShowContinueError(state,
735 0 : format("differs from Design Size Chilled Water Maximum Requested Flow Rate of {:.5R} [m3/s]",
736 : tmpEvapVolFlowRate));
737 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
738 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
739 : }
740 : }
741 : }
742 4 : tmpEvapVolFlowRate = EvapVolFlowRateUser;
743 : }
744 : }
745 : }
746 : } else {
747 5 : if (this->EvapVolFlowRateWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
748 0 : ShowSevereError(state, "Autosizing of Electric Chiller evap flow rate requires a loop Sizing:Plant object");
749 0 : ShowContinueError(state, format("Occurs in Electric Chiller object={}", this->Name));
750 0 : ErrorsFound = true;
751 : }
752 5 : if (!this->EvapVolFlowRateWasAutoSized && state.dataPlnt->PlantFinalSizesOkayToReport && (this->EvapVolFlowRate > 0.0)) {
753 1 : BaseSizer::reportSizerOutput(
754 : state, this->ObjectType, this->Name, "User-Specified Chilled Water Maximum Requested Flow Rate [m3/s]", this->EvapVolFlowRate);
755 : }
756 : }
757 :
758 25 : PlantUtilities::RegisterPlantCompDesignFlow(state, this->EvapInletNodeNum, tmpEvapVolFlowRate);
759 :
760 : // Size condenser flow rate
761 25 : int PltSizCondNum = this->CDPlantLoc.loop->PlantSizNum; // Change for air-cooled when it's supported
762 25 : if (PltSizCondNum > 0 && PltSizNum > 0) {
763 20 : if (state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow && tmpNomCap > 0.0) {
764 :
765 0 : Real64 rho = this->CDPlantLoc.loop->glycol->getDensity(state, Constant::CWInitConvTemp, RoutineName);
766 0 : Real64 Cp = this->CDPlantLoc.loop->glycol->getSpecificHeat(state, this->TempRefCondIn, RoutineName);
767 0 : tmpCondVolFlowRate = tmpNomCap * (1.0 + (1.0 / this->RefCOP) * this->CompPowerToCondenserFrac) /
768 0 : (state.dataSize->PlantSizData(PltSizCondNum).DeltaT * Cp * rho);
769 :
770 : } else {
771 20 : if (this->CondVolFlowRateWasAutoSized) {
772 0 : tmpCondVolFlowRate = 0.0;
773 : }
774 : }
775 20 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
776 4 : if (this->CondVolFlowRateWasAutoSized) {
777 0 : this->CondVolFlowRate = tmpCondVolFlowRate;
778 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
779 0 : BaseSizer::reportSizerOutput(
780 : state, this->ObjectType, this->Name, "Design Size Condenser Maximum Requested Flow Rate [m3/s]", tmpCondVolFlowRate);
781 : }
782 0 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
783 0 : BaseSizer::reportSizerOutput(
784 : state, this->ObjectType, this->Name, "Initial Design Size Condenser Maximum Requested Flow Rate [m3/s]", tmpCondVolFlowRate);
785 : }
786 : } else {
787 4 : if (this->CondVolFlowRate > 0.0 && tmpCondVolFlowRate > 0.0) {
788 4 : Real64 CondVolFlowRateUser = this->CondVolFlowRate;
789 4 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
790 4 : BaseSizer::reportSizerOutput(state,
791 : this->ObjectType,
792 : this->Name,
793 : "Design Size Condenser Maximum Requested Flow Rate [m3/s]",
794 : tmpCondVolFlowRate,
795 : "User-Specified Condenser Maximum Requested Flow Rate [m3/s]",
796 : CondVolFlowRateUser);
797 4 : if (state.dataGlobal->DisplayExtraWarnings) {
798 0 : if ((std::abs(tmpCondVolFlowRate - CondVolFlowRateUser) / CondVolFlowRateUser) >
799 0 : state.dataSize->AutoVsHardSizingThreshold) {
800 0 : ShowMessage(state, format("{}: Potential issue with equipment sizing for {}", RoutineName, this->Name));
801 0 : ShowContinueError(
802 0 : state, format("User-Specified Condenser Maximum Requested Flow Rate of {:.5R} [m3/s]", CondVolFlowRateUser));
803 0 : ShowContinueError(
804 : state,
805 0 : format("differs from Design Size Condenser Maximum Requested Flow Rate of {:.5R} [m3/s]", tmpCondVolFlowRate));
806 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
807 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
808 : }
809 : }
810 : }
811 4 : tmpCondVolFlowRate = CondVolFlowRateUser;
812 : }
813 : }
814 : }
815 20 : } else {
816 5 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
817 :
818 5 : if (this->CondVolFlowRateWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
819 0 : ShowSevereError(state, "Autosizing of Electric ASHRAE 205 Chiller condenser fluid flow rate requires a condenser");
820 0 : ShowContinueError(state, "loop Sizing:Plant object");
821 0 : ShowContinueError(state, format("Occurs in Electric ASHRAE 205 Chiller object={}", this->Name));
822 0 : ErrorsFound = true;
823 : }
824 5 : if (!this->CondVolFlowRateWasAutoSized && state.dataPlnt->PlantFinalSizesOkayToReport && (this->CondVolFlowRate > 0.0)) {
825 1 : BaseSizer::reportSizerOutput(
826 : state, this->ObjectType, this->Name, "User-Specified Condenser Maximum Requested Flow Rate [m3/s]", this->CondVolFlowRate);
827 : }
828 :
829 : } else {
830 :
831 : // Auto size condenser air flow to Total Capacity * 0.000114 m3/s/w (850 cfm/ton)
832 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
833 0 : std::string_view CompType =
834 : DataPlant::PlantEquipTypeNames[static_cast<int>(DataPlant::PlantEquipmentType::Chiller_ElectricASHRAE205)];
835 0 : state.dataSize->DataConstantUsedForSizing = this->RefCap;
836 0 : state.dataSize->DataFractionUsedForSizing = 0.000114;
837 0 : Real64 TempSize = this->CondVolFlowRate;
838 0 : bool bPRINT = true; // TRUE if sizing is reported to output (eio)
839 0 : AutoCalculateSizer sizerCondAirFlow;
840 0 : std::string stringOverride = "Condenser Maximum Requested Flow Rate [m3/s]";
841 0 : if (state.dataGlobal->isEpJSON) {
842 0 : stringOverride = "condenser_maximum_requested_flow_rate [m3/s]";
843 : }
844 0 : sizerCondAirFlow.overrideSizingString(stringOverride);
845 0 : sizerCondAirFlow.initializeWithinEP(state, CompType, this->Name, bPRINT, RoutineName);
846 0 : this->CondVolFlowRate = sizerCondAirFlow.size(state, TempSize, ErrorsFound);
847 0 : }
848 : }
849 : }
850 :
851 : // save the reference condenser water volumetric flow rate for use by the condenser water loop sizing algorithms
852 25 : PlantUtilities::RegisterPlantCompDesignFlow(state, this->CondInletNodeNum, tmpCondVolFlowRate);
853 :
854 : // Calculate design evaporator capacity (eventually add autosize here too)
855 :
856 : // TODO: Determine actual rated flow rates instead of design flow rates
857 25 : this->RefCap = this->Representation->performance.performance_map_cooling
858 0 : .calculate_performance(this->EvapVolFlowRate,
859 25 : this->TempRefEvapOut + Constant::Kelvin,
860 : this->CondVolFlowRate,
861 25 : this->TempRefCondIn + Constant::Kelvin,
862 25 : this->MaxSequenceNumber,
863 : this->InterpolationType)
864 25 : .net_evaporator_capacity;
865 :
866 25 : if (PltSizNum > 0) {
867 20 : if (state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow) {
868 12 : Real64 Cp = this->CWPlantLoc.loop->glycol->getSpecificHeat(state, Constant::CWInitConvTemp, RoutineName);
869 :
870 12 : Real64 rho = this->CWPlantLoc.loop->glycol->getDensity(state, Constant::CWInitConvTemp, RoutineName);
871 12 : tmpNomCap = Cp * rho * state.dataSize->PlantSizData(PltSizNum).DeltaT * tmpEvapVolFlowRate;
872 : } else {
873 8 : tmpNomCap = 0.0;
874 : }
875 20 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
876 4 : if (this->RefCapWasAutoSized) {
877 0 : this->RefCap = tmpNomCap;
878 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
879 0 : BaseSizer::reportSizerOutput(state, this->ObjectType, this->Name, "Design Size Rated Capacity [W]", tmpNomCap);
880 : }
881 0 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
882 0 : BaseSizer::reportSizerOutput(state, this->ObjectType, this->Name, "Initial Design Size Rated Capacity [W]", tmpNomCap);
883 : }
884 : } else { // Hard-sized with sizing data
885 4 : if (this->RefCap > 0.0 && tmpNomCap > 0.0) {
886 4 : Real64 RefCapUser = this->RefCap;
887 4 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
888 4 : BaseSizer::reportSizerOutput(state,
889 : this->ObjectType,
890 : this->Name,
891 : "Design Size Rated Capacity [W]",
892 : tmpNomCap,
893 : "User-Specified Rated Capacity [W]",
894 : RefCapUser);
895 4 : if (state.dataGlobal->DisplayExtraWarnings) {
896 0 : if ((std::abs(tmpNomCap - RefCapUser) / RefCapUser) > state.dataSize->AutoVsHardSizingThreshold) {
897 0 : ShowMessage(state, format("{}: Potential issue with equipment sizing for {}", RoutineName, this->Name));
898 0 : ShowContinueError(state, format("User-Specified Rated Capacity of {:.2R} [W]", RefCapUser));
899 0 : ShowContinueError(state, format("differs from Design Size Rated Capacity of {:.2R} [W]", tmpNomCap));
900 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
901 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
902 : }
903 : }
904 : }
905 4 : tmpNomCap = RefCapUser;
906 : }
907 : }
908 : }
909 : } else {
910 5 : if (this->RefCapWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
911 0 : ShowSevereError(state, "Autosizing of Electric Chiller reference capacity requires a loop Sizing:Plant object");
912 0 : ShowContinueError(state, format("Occurs in Electric Chiller object={}", this->Name));
913 0 : ErrorsFound = true;
914 : }
915 5 : if (!this->RefCapWasAutoSized && state.dataPlnt->PlantFinalSizesOkayToReport && (this->RefCap > 0.0)) { // Hard-sized with no sizing data
916 1 : BaseSizer::reportSizerOutput(state, this->ObjectType, this->Name, "User-Specified Rated Capacity [W]", this->RefCap);
917 : }
918 : }
919 :
920 25 : if (this->OilCoolerInletNode) {
921 10 : PlantUtilities::RegisterPlantCompDesignFlow(state, this->OilCoolerInletNode, this->OilCoolerVolFlowRate);
922 : }
923 :
924 25 : if (this->AuxiliaryHeatInletNode) {
925 10 : PlantUtilities::RegisterPlantCompDesignFlow(state, this->AuxiliaryHeatInletNode, this->AuxiliaryVolFlowRate);
926 : }
927 :
928 25 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
929 : // create predefined report
930 5 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchMechType, this->Name, this->ObjectType);
931 5 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchMechNomEff, this->Name, this->RefCOP);
932 5 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchMechNomCap, this->Name, this->RefCap);
933 : }
934 :
935 25 : if (ErrorsFound) {
936 0 : ShowFatalError(state, "Preceding sizing errors cause program termination");
937 : }
938 25 : }
939 :
940 5 : void ASHRAE205ChillerSpecs::setOutputVariables(EnergyPlusData &state)
941 : {
942 10 : SetupOutputVariable(state,
943 : "Chiller Part Load Ratio",
944 : Constant::Units::None,
945 5 : this->ChillerPartLoadRatio,
946 : OutputProcessor::TimeStepType::System,
947 : OutputProcessor::StoreType::Average,
948 5 : this->Name);
949 :
950 10 : SetupOutputVariable(state,
951 : "Chiller Cycling Ratio",
952 : Constant::Units::None,
953 5 : this->ChillerCyclingRatio,
954 : OutputProcessor::TimeStepType::System,
955 : OutputProcessor::StoreType::Average,
956 5 : this->Name);
957 :
958 10 : SetupOutputVariable(state,
959 : "Minimum Part Load Ratio",
960 : Constant::Units::None,
961 5 : this->MinPartLoadRat,
962 : OutputProcessor::TimeStepType::System,
963 : OutputProcessor::StoreType::Average,
964 5 : this->Name);
965 :
966 10 : SetupOutputVariable(state,
967 : "Chiller Electricity Rate",
968 : Constant::Units::W,
969 5 : this->Power,
970 : OutputProcessor::TimeStepType::System,
971 : OutputProcessor::StoreType::Average,
972 5 : this->Name);
973 :
974 10 : SetupOutputVariable(state,
975 : "Chiller Electricity Energy",
976 : Constant::Units::J,
977 5 : this->Energy,
978 : OutputProcessor::TimeStepType::System,
979 : OutputProcessor::StoreType::Sum,
980 5 : this->Name,
981 : Constant::eResource::Electricity,
982 : OutputProcessor::Group::Plant,
983 : OutputProcessor::EndUseCat::Cooling,
984 : this->EndUseSubcategory);
985 :
986 10 : SetupOutputVariable(state,
987 : "Chiller Evaporator Cooling Rate",
988 : Constant::Units::W,
989 5 : this->QEvaporator,
990 : OutputProcessor::TimeStepType::System,
991 : OutputProcessor::StoreType::Average,
992 5 : this->Name);
993 :
994 10 : SetupOutputVariable(state,
995 : "Chiller Evaporator Cooling Energy",
996 : Constant::Units::J,
997 5 : this->EvapEnergy,
998 : OutputProcessor::TimeStepType::System,
999 : OutputProcessor::StoreType::Sum,
1000 5 : this->Name,
1001 : Constant::eResource::EnergyTransfer,
1002 : OutputProcessor::Group::Plant,
1003 : OutputProcessor::EndUseCat::Chillers);
1004 :
1005 10 : SetupOutputVariable(state,
1006 : "Chiller Evaporator Inlet Temperature",
1007 : Constant::Units::C,
1008 5 : this->EvapInletTemp,
1009 : OutputProcessor::TimeStepType::System,
1010 : OutputProcessor::StoreType::Average,
1011 5 : this->Name);
1012 :
1013 10 : SetupOutputVariable(state,
1014 : "Chiller Evaporator Outlet Temperature",
1015 : Constant::Units::C,
1016 5 : this->EvapOutletTemp,
1017 : OutputProcessor::TimeStepType::System,
1018 : OutputProcessor::StoreType::Average,
1019 5 : this->Name);
1020 :
1021 10 : SetupOutputVariable(state,
1022 : "Chiller Evaporator Mass Flow Rate",
1023 : Constant::Units::kg_s,
1024 5 : this->EvapMassFlowRate,
1025 : OutputProcessor::TimeStepType::System,
1026 : OutputProcessor::StoreType::Average,
1027 5 : this->Name);
1028 :
1029 10 : SetupOutputVariable(state,
1030 : "Chiller Condenser Heat Transfer Rate",
1031 : Constant::Units::W,
1032 5 : this->QCondenser,
1033 : OutputProcessor::TimeStepType::System,
1034 : OutputProcessor::StoreType::Average,
1035 5 : this->Name);
1036 :
1037 10 : SetupOutputVariable(state,
1038 : "Chiller Condenser Heat Transfer Energy",
1039 : Constant::Units::J,
1040 5 : this->CondEnergy,
1041 : OutputProcessor::TimeStepType::System,
1042 : OutputProcessor::StoreType::Sum,
1043 5 : this->Name,
1044 : Constant::eResource::EnergyTransfer,
1045 : OutputProcessor::Group::Plant,
1046 : OutputProcessor::EndUseCat::HeatRejection);
1047 :
1048 10 : SetupOutputVariable(state,
1049 : "Chiller COP",
1050 : Constant::Units::W_W,
1051 5 : this->ActualCOP,
1052 : OutputProcessor::TimeStepType::System,
1053 : OutputProcessor::StoreType::Average,
1054 5 : this->Name);
1055 :
1056 10 : SetupOutputVariable(state,
1057 : "Chiller Condenser Inlet Temperature",
1058 : Constant::Units::C,
1059 5 : this->CondInletTemp,
1060 : OutputProcessor::TimeStepType::System,
1061 : OutputProcessor::StoreType::Average,
1062 5 : this->Name);
1063 :
1064 10 : SetupOutputVariable(state,
1065 : "Chiller Condenser Outlet Temperature",
1066 : Constant::Units::C,
1067 5 : this->CondOutletTemp,
1068 : OutputProcessor::TimeStepType::System,
1069 : OutputProcessor::StoreType::Average,
1070 5 : this->Name);
1071 :
1072 10 : SetupOutputVariable(state,
1073 : "Chiller Condenser Mass Flow Rate",
1074 : Constant::Units::kg_s,
1075 5 : this->CondMassFlowRate,
1076 : OutputProcessor::TimeStepType::System,
1077 : OutputProcessor::StoreType::Average,
1078 5 : this->Name);
1079 :
1080 10 : SetupOutputVariable(state,
1081 : "Chiller Effective Heat Rejection Temperature",
1082 : Constant::Units::C,
1083 5 : this->ChillerCondAvgTemp,
1084 : OutputProcessor::TimeStepType::System,
1085 : OutputProcessor::StoreType::Average,
1086 5 : this->Name);
1087 :
1088 10 : SetupOutputVariable(state,
1089 : "Chiller Zone Heat Gain Rate",
1090 : Constant::Units::W,
1091 5 : this->AmbientZoneGain,
1092 : OutputProcessor::TimeStepType::System,
1093 : OutputProcessor::StoreType::Average,
1094 5 : this->Name);
1095 :
1096 10 : SetupOutputVariable(state,
1097 : "Chiller Zone Heat Gain Energy",
1098 : Constant::Units::J,
1099 5 : this->AmbientZoneGainEnergy,
1100 : OutputProcessor::TimeStepType::System,
1101 : OutputProcessor::StoreType::Sum,
1102 5 : this->Name);
1103 :
1104 10 : SetupOutputVariable(state,
1105 : "Oil Cooler Heat Transfer Rate",
1106 : Constant::Units::W,
1107 5 : this->QOilCooler,
1108 : OutputProcessor::TimeStepType::System,
1109 : OutputProcessor::StoreType::Average,
1110 5 : this->Name);
1111 :
1112 10 : SetupOutputVariable(state,
1113 : "Oil Cooler Heat Transfer Energy",
1114 : Constant::Units::J,
1115 5 : this->OilCoolerEnergy,
1116 : OutputProcessor::TimeStepType::System,
1117 : OutputProcessor::StoreType::Sum,
1118 5 : this->Name);
1119 :
1120 10 : SetupOutputVariable(state,
1121 : "Auxiliary Heat Transfer Rate",
1122 : Constant::Units::W,
1123 5 : this->QAuxiliary,
1124 : OutputProcessor::TimeStepType::System,
1125 : OutputProcessor::StoreType::Average,
1126 5 : this->Name);
1127 :
1128 10 : SetupOutputVariable(state,
1129 : "Auxiliary Heat Transfer Energy",
1130 : Constant::Units::J,
1131 5 : this->AuxiliaryEnergy,
1132 : OutputProcessor::TimeStepType::System,
1133 : OutputProcessor::StoreType::Sum,
1134 5 : this->Name);
1135 5 : }
1136 :
1137 74752 : void ASHRAE205ChillerSpecs::findEvaporatorMassFlowRate(EnergyPlusData &state, Real64 &load, Real64 Cp)
1138 : {
1139 : static constexpr std::string_view RoutineName("ASHRAE205ChillerSpecs::findEvaporatorMassFlowRate");
1140 :
1141 : // If FlowLock is False (0), the chiller sets the plant loop mdot
1142 : // If FlowLock is True (1), the new resolved plant loop mdot is used
1143 74752 : if (this->CWPlantLoc.side->FlowLock == DataPlant::FlowLock::Unlocked) {
1144 37352 : this->PossibleSubcooling = !(this->CWPlantLoc.comp->CurOpSchemeType == DataPlant::OpScheme::CompSetPtBased);
1145 :
1146 37352 : Real64 evapDeltaTemp(0.0); // Evaporator temperature difference [C]
1147 :
1148 : // Either set the flow to the Constant value or calculate the flow for the variable volume case
1149 37352 : if ((this->FlowMode == DataPlant::FlowMode::Constant) || (this->FlowMode == DataPlant::FlowMode::NotModulated)) {
1150 : // Set the evaporator mass flow rate to design
1151 : // Start by assuming max (design) flow
1152 37352 : this->EvapMassFlowRate = this->EvapMassFlowRateMax;
1153 : // Use PlantUtilities::SetComponentFlowRate to decide actual flow
1154 37352 : PlantUtilities::SetComponentFlowRate(state, this->EvapMassFlowRate, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
1155 37352 : if (this->EvapMassFlowRate != 0.0) {
1156 37352 : evapDeltaTemp = std::abs(load) / this->EvapMassFlowRate / Cp; // MyLoad = net evaporator capacity, QEvaporator
1157 : } else {
1158 0 : evapDeltaTemp = 0.0;
1159 : }
1160 37352 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - evapDeltaTemp;
1161 0 : } else if (this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated) {
1162 0 : switch (this->CWPlantLoc.loop->LoopDemandCalcScheme) {
1163 0 : case DataPlant::LoopDemandCalcScheme::SingleSetPoint: {
1164 : // Calculate the Delta Temp from the inlet temp to the chiller outlet setpoint
1165 0 : evapDeltaTemp =
1166 0 : state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint;
1167 0 : } break;
1168 0 : case DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand: {
1169 0 : evapDeltaTemp =
1170 0 : state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi;
1171 0 : } break;
1172 0 : default: {
1173 0 : assert(false);
1174 : } break;
1175 : }
1176 :
1177 0 : if (evapDeltaTemp != 0) {
1178 0 : this->EvapMassFlowRate = max(0.0, (std::abs(load) / Cp / evapDeltaTemp));
1179 0 : if ((this->EvapMassFlowRate - this->EvapMassFlowRateMax) > DataBranchAirLoopPlant::MassFlowTolerance) {
1180 0 : this->PossibleSubcooling = true;
1181 : }
1182 : // Check to see if the Maximum is exceeded, if so set to maximum
1183 0 : this->EvapMassFlowRate = min(this->EvapMassFlowRateMax, this->EvapMassFlowRate);
1184 : // Use PlantUtilities::SetComponentFlowRate to decide actual flow
1185 0 : PlantUtilities::SetComponentFlowRate(
1186 0 : state, this->EvapMassFlowRate, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
1187 : // Should we recalculate this with the corrected setpoint?
1188 0 : switch (this->CWPlantLoc.loop->LoopDemandCalcScheme) {
1189 0 : case DataPlant::LoopDemandCalcScheme::SingleSetPoint: {
1190 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint;
1191 0 : } break;
1192 0 : case DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand: {
1193 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi;
1194 0 : } break;
1195 0 : default:
1196 0 : break;
1197 : }
1198 : } else {
1199 : // Try to request zero flow
1200 0 : this->EvapMassFlowRate = 0.0;
1201 : // Use PlantUtilities::SetComponentFlowRate to decide actual flow
1202 0 : PlantUtilities::SetComponentFlowRate(
1203 0 : state, this->EvapMassFlowRate, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
1204 : // No deltaT since component is not running
1205 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
1206 0 : this->QEvaporator = 0.0;
1207 : // PartLoadRat = 0.0;
1208 0 : this->ChillerPartLoadRatio = 0.0;
1209 :
1210 0 : if (this->DeltaTErrCount < 1 && !state.dataGlobal->WarmupFlag) {
1211 0 : ++this->DeltaTErrCount;
1212 0 : ShowWarningError(state, "Evaporator DeltaTemp = 0 in mass flow calculation (Tevapin = Tevapout setpoint temp).");
1213 0 : ShowContinueErrorTimeStamp(state, "");
1214 0 : } else if (!state.dataGlobal->WarmupFlag) {
1215 0 : ++this->ChillerCapFTError;
1216 0 : ShowRecurringWarningErrorAtEnd(
1217 : state,
1218 0 : format("{} \"{}\": Evaporator DeltaTemp = 0 in mass flow calculation warning continues...", this->ObjectType, this->Name),
1219 0 : this->DeltaTErrCountIndex,
1220 : evapDeltaTemp,
1221 : evapDeltaTemp);
1222 : }
1223 : }
1224 : }
1225 : } else { // If FlowLock is True
1226 37400 : this->EvapMassFlowRate = state.dataLoopNodes->Node(this->EvapInletNodeNum).MassFlowRate;
1227 37400 : PlantUtilities::SetComponentFlowRate(state, this->EvapMassFlowRate, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
1228 : // Some other component set the flow to 0. No reason to continue with calculations.
1229 37400 : if (this->EvapMassFlowRate == 0.0) {
1230 0 : load = 0.0;
1231 0 : return;
1232 : }
1233 : } // This is the end of the FlowLock Block
1234 :
1235 74752 : const Real64 rho = this->CWPlantLoc.loop->glycol->getDensity(state, Constant::CWInitConvTemp, RoutineName);
1236 :
1237 74752 : this->EvapVolFlowRate = this->EvapMassFlowRate / rho;
1238 : }
1239 :
1240 227341 : void ASHRAE205ChillerSpecs::calculate(EnergyPlusData &state, Real64 &MyLoad, bool const RunFlag)
1241 : {
1242 : static constexpr std::string_view RoutineName("CalcElecASHRAE205ChillerModel");
1243 227341 : this->ChillerPartLoadRatio = 0.0;
1244 227341 : this->ChillerCyclingRatio = 1.0;
1245 227341 : this->ChillerFalseLoadRate = 0.0;
1246 227341 : this->EvapMassFlowRate = 0.0;
1247 227341 : this->CondMassFlowRate = 0.0;
1248 227341 : this->Power = 0.0;
1249 227341 : this->QCondenser = 0.0;
1250 227341 : this->QEvaporator = 0.0;
1251 227341 : this->QOilCooler = 0.0;
1252 227341 : this->QAuxiliary = 0.0;
1253 227341 : int PlantLoopNum = this->CWPlantLoc.loopNum;
1254 227341 : DataPlant::LoopSideLocation LoopSideNum = this->CWPlantLoc.loopSideNum;
1255 227341 : int BranchNum = this->CWPlantLoc.branchNum;
1256 227341 : int CompNum = this->CWPlantLoc.compNum;
1257 :
1258 : // Set module-level chiller evaporator and condenser inlet temperature variables
1259 : // using prior time step's temperature
1260 227341 : Real64 condInletTemp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
1261 227341 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapOutletNodeNum).Temp;
1262 :
1263 : // If no loop demand or chiller OFF, return
1264 : // If chiller load is 0 or chiller is not running then leave the subroutine. Before leaving
1265 : // if the component control is SERIESACTIVE we set the component flow to inlet flow so that
1266 : // flow resolver will not shut down the branch
1267 :
1268 : // Calculate performance for standby (only used when off or cycling)
1269 : Real64 standbyPower =
1270 227341 : this->Representation->performance.performance_map_standby.calculate_performance(this->AmbientTemp, this->InterpolationType).input_power;
1271 227341 : if (MyLoad >= 0 || !RunFlag) {
1272 152097 : if (this->EquipFlowCtrl == DataBranchAirLoopPlant::ControlType::SeriesActive ||
1273 17701 : this->CWPlantLoc.side->FlowLock == DataPlant::FlowLock::Locked) {
1274 143244 : this->EvapMassFlowRate = state.dataLoopNodes->Node(this->EvapInletNodeNum).MassFlowRate;
1275 : }
1276 152097 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
1277 152097 : if (this->CDPlantLoc.comp->FlowCtrl == DataBranchAirLoopPlant::ControlType::SeriesActive) {
1278 0 : this->CondMassFlowRate = state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate;
1279 : }
1280 : }
1281 152097 : this->Power = standbyPower;
1282 152097 : this->AmbientZoneGain = standbyPower;
1283 152621 : return;
1284 : }
1285 :
1286 : // Revisit
1287 : #if 0
1288 : // // If there is a fault of chiller fouling
1289 : // if (this->FaultyChillerFoulingFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
1290 : // (!state.dataGlobal->KickOffSimulation)) {
1291 : // int FaultIndex = this->FaultyChillerFoulingIndex;
1292 : // Real64 NomCap_ff = ChillerRefCap;
1293 : // Real64 ReferenceCOP_ff = ReferenceCOP;
1294 : //
1295 : // // calculate the Faulty Chiller Fouling Factor using fault information
1296 : // this->FaultyChillerFoulingFactor = state.dataFaultsMgr->FaultsChillerFouling(FaultIndex).CalFoulingFactor(state);
1297 : //
1298 : // // update the Chiller nominal capacity and COP at faulty cases
1299 : // ChillerRefCap = NomCap_ff * this->FaultyChillerFoulingFactor;
1300 : // ReferenceCOP = ReferenceCOP_ff * this->FaultyChillerFoulingFactor;
1301 : // }
1302 : #endif // 0
1303 :
1304 : // Set mass flow rates
1305 75244 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
1306 75244 : this->CondMassFlowRate = this->CondMassFlowRateMax;
1307 75244 : PlantUtilities::SetComponentFlowRate(state, this->CondMassFlowRate, this->CondInletNodeNum, this->CondOutletNodeNum, this->CDPlantLoc);
1308 75244 : PlantUtilities::PullCompInterconnectTrigger(
1309 75244 : state, this->CWPlantLoc, this->CondMassFlowIndex, this->CDPlantLoc, DataPlant::CriteriaType::MassFlowRate, this->CondMassFlowRate);
1310 :
1311 75244 : if (this->CondMassFlowRate < DataBranchAirLoopPlant::MassFlowTolerance) {
1312 476 : MyLoad = 0.0;
1313 476 : this->Power = standbyPower;
1314 476 : this->AmbientZoneGain = standbyPower;
1315 476 : this->EvapMassFlowRate = 0.0;
1316 476 : PlantUtilities::SetComponentFlowRate(state, this->EvapMassFlowRate, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
1317 476 : return;
1318 : }
1319 : }
1320 74768 : Real64 EvapOutletTempSetPoint(0.0); // Evaporator outlet temperature setpoint [C]
1321 74768 : switch (this->CWPlantLoc.loop->LoopDemandCalcScheme) {
1322 74768 : case DataPlant::LoopDemandCalcScheme::SingleSetPoint: {
1323 224304 : if ((this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated) ||
1324 149536 : (this->CWPlantLoc.comp->CurOpSchemeType == DataPlant::OpScheme::CompSetPtBased) ||
1325 74768 : (state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint != DataLoopNode::SensedNodeFlagValue)) {
1326 : // there will be a valid setpoint on outlet
1327 0 : EvapOutletTempSetPoint = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint;
1328 : } else { // use plant loop overall setpoint
1329 74768 : EvapOutletTempSetPoint = state.dataLoopNodes->Node(this->CWPlantLoc.loop->TempSetPointNodeNum).TempSetPoint;
1330 : }
1331 74768 : } break;
1332 0 : case DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand: {
1333 0 : if ((this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated) ||
1334 0 : (this->CWPlantLoc.comp->CurOpSchemeType == DataPlant::OpScheme::CompSetPtBased) ||
1335 0 : (state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi != DataLoopNode::SensedNodeFlagValue)) {
1336 : // there will be a valid setpoint on outlet
1337 0 : EvapOutletTempSetPoint = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi;
1338 : } else { // use plant loop overall setpoint
1339 0 : EvapOutletTempSetPoint = state.dataLoopNodes->Node(this->CWPlantLoc.loop->TempSetPointNodeNum).TempSetPointHi;
1340 : }
1341 0 : } break;
1342 0 : default: {
1343 0 : assert(false);
1344 : } break;
1345 : }
1346 : // Revisit
1347 : #if 0
1348 : // // If there is a fault of Chiller SWT Sensor
1349 : // if (this->FaultyChillerSWTFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) && (!state.dataGlobal->KickOffSimulation)) {
1350 : // int FaultIndex = this->FaultyChillerSWTIndex;
1351 : // Real64 EvapOutletTempSetPoint_ff = EvapOutletTempSetPoint;
1352 : //
1353 : // // calculate the sensor offset using fault information
1354 : // this->FaultyChillerSWTOffset = state.dataFaultsMgr->FaultsChillerSWTSensor(FaultIndex).CalFaultOffsetAct(state);
1355 : // // update the EvapOutletTempSetPoint
1356 : // EvapOutletTempSetPoint =
1357 : // max(this->TempLowLimitEvapOut,
1358 : // min(state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp, EvapOutletTempSetPoint_ff - this->FaultyChillerSWTOffset));
1359 : // this->FaultyChillerSWTOffset = EvapOutletTempSetPoint_ff - EvapOutletTempSetPoint;
1360 : // }
1361 : #endif // 0
1362 : // When implemented, TODO: correct temperature if using heat recovery
1363 :
1364 74768 : this->EvapMassFlowRate = state.dataLoopNodes->Node(this->EvapInletNodeNum).MassFlowRate;
1365 : // If some other component set the flow to 0, no reason to continue with calculations.
1366 74768 : if (this->EvapMassFlowRate == 0.0) {
1367 48 : MyLoad = 0.0;
1368 48 : return;
1369 : }
1370 :
1371 74720 : Real64 CpEvap = this->CWPlantLoc.loop->glycol->getSpecificHeat(state, state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp, RoutineName);
1372 :
1373 : // Calculate mass flow rate based on MyLoad (TODO: then adjust it after determining if chiller can meet the load)
1374 74720 : this->findEvaporatorMassFlowRate(state, MyLoad, CpEvap);
1375 :
1376 : // Available chiller capacity is capacity at the highest sequence number; i.e. max chiller capacity
1377 74720 : const Real64 maximumChillerCap = this->Representation->performance.performance_map_cooling
1378 0 : .calculate_performance(this->EvapVolFlowRate,
1379 74720 : this->EvapOutletTemp + Constant::Kelvin,
1380 : this->CondVolFlowRate,
1381 74720 : this->CondInletTemp + Constant::Kelvin,
1382 74720 : this->MaxSequenceNumber,
1383 : this->InterpolationType)
1384 74720 : .net_evaporator_capacity;
1385 74720 : const Real64 minimumChillerCap = this->Representation->performance.performance_map_cooling
1386 0 : .calculate_performance(this->EvapVolFlowRate,
1387 74720 : this->EvapOutletTemp + Constant::Kelvin,
1388 : this->CondVolFlowRate,
1389 74720 : this->CondInletTemp + Constant::Kelvin,
1390 74720 : this->MinSequenceNumber,
1391 : this->InterpolationType)
1392 74720 : .net_evaporator_capacity;
1393 : // Part load ratio based on load and available chiller capacity; cap at max P.L.R. (can be >1)
1394 74720 : this->ChillerPartLoadRatio = (maximumChillerCap > 0) ? max(0.0, std::abs(MyLoad) / maximumChillerCap) : 0.0;
1395 : // Minimum capacity ratio, under which cycling occurs
1396 74720 : this->MinPartLoadRat = (maximumChillerCap > 0) ? minimumChillerCap / maximumChillerCap : 0.0;
1397 74720 : Real64 partLoadSeqNum{0.};
1398 :
1399 : // Chiller may be operating in one of three modes: cycling, modulating, or full capacity
1400 74720 : if (this->ChillerPartLoadRatio < this->MinPartLoadRat) // Cycling
1401 : {
1402 7229 : this->ChillerCyclingRatio = this->ChillerPartLoadRatio / this->MinPartLoadRat;
1403 7229 : partLoadSeqNum = this->MinSequenceNumber;
1404 67491 : } else if (this->ChillerPartLoadRatio < 1.0) // Modulating
1405 : {
1406 : // Use performance map to find the fractional sequence number (which most closely matches our part load)
1407 67459 : Real64 constexpr accuracy{0.0001};
1408 67459 : int constexpr maxIter{500};
1409 67459 : int solFla{0};
1410 269836 : auto f = [MyLoad, this](Real64 partLoadSeqNum) {
1411 202377 : this->QEvaporator = this->Representation->performance.performance_map_cooling
1412 404754 : .calculate_performance(this->EvapVolFlowRate,
1413 202377 : this->EvapOutletTemp + Constant::Kelvin,
1414 202377 : this->CondVolFlowRate,
1415 202377 : this->CondInletTemp + Constant::Kelvin,
1416 : partLoadSeqNum,
1417 202377 : this->InterpolationType)
1418 202377 : .net_evaporator_capacity;
1419 202377 : return std::abs(MyLoad) - this->QEvaporator;
1420 67459 : };
1421 : // Iteratively calculate this->QEvaporator by modulating partLoadSeqNum, ending at Q_Evaporator(partLoadSeqNum)
1422 67459 : General::SolveRoot(state, accuracy, maxIter, solFla, partLoadSeqNum, f, this->MinSequenceNumber, this->MaxSequenceNumber);
1423 : } else // Full capacity: std::abs(MyLoad) > this->QEvaporator
1424 : {
1425 32 : this->QEvaporator = maximumChillerCap;
1426 32 : partLoadSeqNum = this->MaxSequenceNumber;
1427 : // SolveRoot stuff for eventual flow rate (can always calculate Ts if you have MFR and capacity)
1428 : // recursion? Revisit.
1429 32 : findEvaporatorMassFlowRate(state, this->QEvaporator, CpEvap);
1430 : // if MFR changes, recalculate chiller capacity.
1431 : // repeat until load <= capacity
1432 : }
1433 :
1434 : // Use performance map to get the rest of results at new sequence number
1435 : auto lookupVariablesCooling = // This is a struct returned by value, relying on RVO (THIS_AUTO_OK)
1436 74720 : this->Representation->performance.performance_map_cooling.calculate_performance(this->EvapVolFlowRate,
1437 74720 : this->EvapOutletTemp + Constant::Kelvin,
1438 : this->CondVolFlowRate,
1439 74720 : this->CondInletTemp + Constant::Kelvin,
1440 : partLoadSeqNum,
1441 : this->InterpolationType);
1442 74720 : this->QEvaporator = lookupVariablesCooling.net_evaporator_capacity * this->ChillerCyclingRatio;
1443 :
1444 74720 : Real64 evapDeltaTemp = this->QEvaporator / this->EvapMassFlowRate / CpEvap;
1445 74720 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - evapDeltaTemp;
1446 :
1447 : // TODO: Revisit fault
1448 : #if 0
1449 : // If there is a fault of Chiller SWT Sensor
1450 : if (this->FaultyChillerSWTFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
1451 : (!state.dataGlobal->KickOffSimulation) && (this->EvapMassFlowRate > 0)) {
1452 : // calculate directly affected variables at faulty case: EvapOutletTemp, EvapMassFlowRate, QEvaporator
1453 : int FaultIndex = this->FaultyChillerSWTIndex;
1454 : bool VarFlowFlag = false;
1455 : state.dataFaultsMgr->FaultsChillerSWTSensor(FaultIndex)
1456 : .CalFaultChillerSWT(VarFlowFlag,
1457 : this->FaultyChillerSWTOffset,
1458 : Cp,
1459 : state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp,
1460 : this->EvapOutletTemp,
1461 : this->EvapMassFlowRate,
1462 : this->QEvaporator);
1463 : // update corresponding variables at faulty case
1464 : }
1465 : #endif // 0
1466 :
1467 74720 : Real64 cd = this->Representation->performance.cycling_degradation_coefficient;
1468 74720 : Real64 cyclingFactor{(1.0 - cd) + (cd * this->ChillerCyclingRatio)};
1469 74720 : Real64 runtimeFactor{this->ChillerCyclingRatio / cyclingFactor};
1470 74720 : this->Power = lookupVariablesCooling.input_power * runtimeFactor + ((1 - this->ChillerCyclingRatio) * standbyPower);
1471 74720 : this->QCondenser = lookupVariablesCooling.net_condenser_capacity * this->ChillerCyclingRatio;
1472 74720 : this->QOilCooler = lookupVariablesCooling.oil_cooler_heat;
1473 74720 : this->QAuxiliary = lookupVariablesCooling.auxiliary_heat;
1474 74720 : Real64 QExternallyCooled{0.0};
1475 74720 : if (this->OilCoolerInletNode) {
1476 32548 : QExternallyCooled += this->QOilCooler;
1477 : }
1478 74720 : if (this->AuxiliaryHeatInletNode) {
1479 32548 : QExternallyCooled += this->QAuxiliary;
1480 : }
1481 : // Energy balance on the chiller system gives the amount of heat lost to the ambient zone
1482 74720 : this->AmbientZoneGain = this->QEvaporator + this->Power - (this->QCondenser + QExternallyCooled);
1483 :
1484 74720 : Real64 CpCond = this->CDPlantLoc.loop->glycol->getSpecificHeat(state, condInletTemp, RoutineName);
1485 74720 : this->CondOutletTemp = this->QCondenser / this->CondMassFlowRate / CpCond + condInletTemp;
1486 :
1487 : // Oil cooler and Auxiliary Heat delta-T calculations
1488 74720 : if (this->OilCoolerInletNode) {
1489 32548 : Real64 oilCoolerDeltaTemp = 0.0;
1490 32548 : PlantUtilities::SetComponentFlowRate(
1491 32548 : state, this->OilCoolerMassFlowRate, this->OilCoolerInletNode, this->OilCoolerOutletNode, this->OCPlantLoc);
1492 :
1493 : Real64 CpOilCooler =
1494 32548 : this->OCPlantLoc.loop->glycol->getSpecificHeat(state, state.dataLoopNodes->Node(this->OilCoolerInletNode).Temp, RoutineName);
1495 :
1496 32548 : if (this->OilCoolerMassFlowRate != 0.0) {
1497 0 : oilCoolerDeltaTemp = this->QOilCooler / (this->OilCoolerMassFlowRate * CpOilCooler);
1498 : } else {
1499 32548 : oilCoolerDeltaTemp = 0.0;
1500 : }
1501 32548 : state.dataLoopNodes->Node(this->OilCoolerOutletNode).Temp = state.dataLoopNodes->Node(this->OilCoolerInletNode).Temp - oilCoolerDeltaTemp;
1502 : }
1503 74720 : if (this->AuxiliaryHeatInletNode) {
1504 32548 : Real64 auxiliaryDeltaTemp = 0.0;
1505 32548 : PlantUtilities::SetComponentFlowRate(
1506 32548 : state, this->AuxiliaryMassFlowRate, this->AuxiliaryHeatInletNode, this->AuxiliaryHeatOutletNode, this->AHPlantLoc);
1507 :
1508 : Real64 CpAux =
1509 32548 : this->AHPlantLoc.loop->glycol->getSpecificHeat(state, state.dataLoopNodes->Node(this->AuxiliaryHeatInletNode).Temp, RoutineName);
1510 :
1511 32548 : if (this->AuxiliaryMassFlowRate != 0.0) {
1512 0 : auxiliaryDeltaTemp = this->QAuxiliary / (this->AuxiliaryMassFlowRate * CpAux);
1513 : } else {
1514 32548 : auxiliaryDeltaTemp = 0.0;
1515 : }
1516 32548 : state.dataLoopNodes->Node(this->AuxiliaryHeatOutletNode).Temp =
1517 32548 : state.dataLoopNodes->Node(this->AuxiliaryHeatInletNode).Temp - auxiliaryDeltaTemp;
1518 : }
1519 : }
1520 :
1521 227341 : void ASHRAE205ChillerSpecs::update(EnergyPlusData &state, Real64 const MyLoad, bool const RunFlag)
1522 : {
1523 227341 : if (MyLoad >= 0.0 || !RunFlag) { // Chiller not running so pass inlet states to outlet states
1524 : // Set node temperatures
1525 152621 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).Temp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
1526 152621 : state.dataLoopNodes->Node(this->CondOutletNodeNum).Temp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
1527 152621 : if (this->OilCoolerInletNode) {
1528 66696 : state.dataLoopNodes->Node(this->OilCoolerOutletNode).Temp = state.dataLoopNodes->Node(this->OilCoolerInletNode).Temp;
1529 : }
1530 152621 : if (this->AuxiliaryHeatInletNode) {
1531 66696 : state.dataLoopNodes->Node(this->AuxiliaryHeatOutletNode).Temp = state.dataLoopNodes->Node(this->AuxiliaryHeatInletNode).Temp;
1532 : }
1533 :
1534 152621 : this->ChillerPartLoadRatio = 0.0;
1535 152621 : this->ChillerCyclingRatio = 0.0;
1536 152621 : this->ChillerFalseLoadRate = 0.0;
1537 152621 : this->ChillerFalseLoad = 0.0;
1538 152621 : this->QEvaporator = 0.0;
1539 152621 : this->QCondenser = 0.0;
1540 152621 : this->Energy = 0.0;
1541 152621 : this->EvapEnergy = 0.0;
1542 152621 : this->CondEnergy = 0.0;
1543 152621 : this->QOilCooler = 0.0;
1544 152621 : this->QAuxiliary = 0.0;
1545 152621 : this->OilCoolerEnergy = 0.0;
1546 152621 : this->AuxiliaryEnergy = 0.0;
1547 152621 : this->EvapInletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
1548 152621 : this->CondInletTemp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
1549 152621 : this->CondOutletTemp = state.dataLoopNodes->Node(this->CondOutletNodeNum).Temp;
1550 152621 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapOutletNodeNum).Temp;
1551 152621 : this->ActualCOP = 0.0;
1552 :
1553 : } else { // Chiller is running, so pass calculated values
1554 : // Set node temperatures
1555 74720 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).Temp = this->EvapOutletTemp;
1556 74720 : state.dataLoopNodes->Node(this->CondOutletNodeNum).Temp = this->CondOutletTemp;
1557 : // Set node flow rates; for these load based models
1558 : // assume that sufficient evaporator flow rate is available
1559 74720 : this->EvapEnergy = this->QEvaporator * state.dataHVACGlobal->TimeStepSysSec;
1560 74720 : this->CondEnergy = this->QCondenser * state.dataHVACGlobal->TimeStepSysSec;
1561 74720 : this->OilCoolerEnergy = this->QOilCooler * state.dataHVACGlobal->TimeStepSysSec;
1562 74720 : this->AuxiliaryEnergy = this->QAuxiliary * state.dataHVACGlobal->TimeStepSysSec;
1563 74720 : this->EvapInletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
1564 74720 : this->CondInletTemp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
1565 74720 : this->CondOutletTemp = state.dataLoopNodes->Node(this->CondOutletNodeNum).Temp;
1566 74720 : if (this->Power != 0.0) {
1567 74720 : this->ActualCOP = this->QEvaporator / this->Power;
1568 : } else {
1569 0 : this->ActualCOP = 0.0;
1570 : }
1571 : }
1572 :
1573 : // Calculate in case of standby power
1574 227341 : this->AmbientZoneGainEnergy = this->AmbientZoneGain * state.dataHVACGlobal->TimeStepSysSec;
1575 227341 : this->Energy = this->Power * state.dataHVACGlobal->TimeStepSysSec;
1576 227341 : }
1577 :
1578 451610 : void ASHRAE205ChillerSpecs::simulate(
1579 : EnergyPlusData &state, const PlantLocation &calledFromLocation, bool FirstHVACIteration, Real64 &CurLoad, bool RunFlag)
1580 : {
1581 451610 : if (calledFromLocation.loopNum == this->CWPlantLoc.loopNum) {
1582 227341 : this->initialize(state, RunFlag, CurLoad);
1583 227341 : this->calculate(state, CurLoad, RunFlag);
1584 227341 : this->update(state, CurLoad, RunFlag);
1585 224269 : } else if (calledFromLocation.loopNum == this->CDPlantLoc.loopNum) {
1586 125017 : DataPlant::LoopSideLocation LoopSide = this->CDPlantLoc.loopSideNum;
1587 125017 : PlantUtilities::UpdateChillerComponentCondenserSide(state,
1588 125017 : calledFromLocation.loopNum,
1589 : LoopSide,
1590 : DataPlant::PlantEquipmentType::Chiller_ElectricASHRAE205,
1591 : this->CondInletNodeNum,
1592 : this->CondOutletNodeNum,
1593 : this->QCondenser,
1594 : this->CondInletTemp,
1595 : this->CondOutletTemp,
1596 : this->CondMassFlowRate,
1597 : FirstHVACIteration);
1598 : }
1599 451610 : }
1600 :
1601 70 : void ASHRAE205ChillerSpecs::getDesignCapacities(
1602 : [[maybe_unused]] EnergyPlusData &state, const PlantLocation &calledFromLocation, Real64 &MaxLoad, Real64 &MinLoad, Real64 &OptLoad)
1603 : {
1604 70 : if (calledFromLocation.loopNum == this->CWPlantLoc.loopNum) {
1605 25 : MinLoad = this->Representation->performance.performance_map_cooling
1606 50 : .calculate_performance(this->EvapVolFlowRate,
1607 25 : this->TempRefEvapOut + Constant::Kelvin,
1608 : this->CondVolFlowRate,
1609 25 : this->TempRefCondIn + Constant::Kelvin,
1610 25 : this->MinSequenceNumber,
1611 : this->InterpolationType)
1612 25 : .net_evaporator_capacity;
1613 25 : MaxLoad = this->RefCap;
1614 25 : OptLoad = MaxLoad;
1615 : } else {
1616 45 : MinLoad = 0.0;
1617 45 : MaxLoad = 0.0;
1618 45 : OptLoad = 0.0;
1619 : }
1620 70 : }
1621 :
1622 : } // namespace EnergyPlus::ChillerElectricASHRAE205
|