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