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