Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // EnergyPlus Headers
49 : #include <EnergyPlus/Boilers.hh>
50 : #include <EnergyPlus/ChillerAbsorption.hh>
51 : #include <EnergyPlus/ChillerElectricEIR.hh>
52 : #include <EnergyPlus/ChillerIndirectAbsorption.hh>
53 : #include <EnergyPlus/ChillerReformulatedEIR.hh>
54 : #include <EnergyPlus/CondenserLoopTowers.hh>
55 : #include <EnergyPlus/CurveManager.hh>
56 : #include <EnergyPlus/Data/EnergyPlusData.hh>
57 : #include <EnergyPlus/DataIPShortCuts.hh>
58 : #include <EnergyPlus/EvaporativeCoolers.hh>
59 : #include <EnergyPlus/Fans.hh>
60 : #include <EnergyPlus/FaultsManager.hh>
61 : #include <EnergyPlus/HVACControllers.hh>
62 : #include <EnergyPlus/HVACDXHeatPumpSystem.hh>
63 : #include <EnergyPlus/HeatingCoils.hh>
64 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
65 : #include <EnergyPlus/PlantChillers.hh>
66 : #include <EnergyPlus/ScheduleManager.hh>
67 : #include <EnergyPlus/SteamCoils.hh>
68 : #include <EnergyPlus/UtilityRoutines.hh>
69 : #include <EnergyPlus/WaterCoils.hh>
70 :
71 : namespace EnergyPlus {
72 :
73 : namespace FaultsManager {
74 :
75 : // MODULE INFORMATION:
76 : // AUTHOR Tianzhen Hong, LBNL
77 : // DATE WRITTEN August 2013
78 : // MODIFIED Sep. 2013, Xiufeng Pang (XP), LBNL. Added Fouling Coil fault
79 : // Feb. 2015, Rongpeng Zhang, LBNL. Added Thermostat/Humidistat Offset faults
80 : // Apr. 2015, Rongpeng Zhang, LBNL. Added Fouling Air Filter fault
81 : // May. 2016, Rongpeng Zhang, LBNL. Added Chiller/Condenser Supply Water Temperature Sensor fault
82 : // Jun. 2016, Rongpeng Zhang, LBNL. Added Tower Scaling fault
83 : // Jul. 2016, Rongpeng Zhang, LBNL. Added Coil Supply Air Temperature Sensor fault
84 : // Oct. 2016, Rongpeng Zhang, LBNL. Added Fouling Boiler fault
85 : // Nov. 2016, Rongpeng Zhang, LBNL. Added Fouling Chiller fault
86 : // Jan. 2017, Rongpeng Zhang, LBNL. Added Fouling Evaporative Cooler fault
87 :
88 : // PURPOSE OF THIS MODULE:
89 : // This module manages operational faults of buildings and systems.
90 :
91 : // METHODOLOGY EMPLOYED:
92 : // Various methods are employed depending types of faults
93 :
94 : namespace {
95 : // These were static variables within different functions. They were pulled out into the namespace
96 : // to facilitate easier unit testing of those functions.
97 : // These are purposefully not in the header file as an extern variable. No one outside of this module should
98 : // use these. They are cleared by clear_state() for use by unit tests, but normal simulations should be unaffected.
99 : // This is purposefully in an anonymous namespace so nothing outside this implementation file can use it.
100 :
101 : } // namespace
102 :
103 : // FaultTypeEnum
104 :
105 : // Types of faults under Group Operational Faults in IDD
106 : // 1. Temperature sensor offset (FY14)
107 : // 2. Humidity sensor offset (FY14)
108 : // 3. Enthalpy sensor offset (FY14)
109 : // 4. Fouling coils (FY14)
110 : // 5. Thermostat offset (FY15)
111 : // 6. Humidistat offset (FY15)
112 : // 7. Fouling air filter (FY15)
113 : // 8. Chiller Supply Water Temperature Sensor Offset (FY16)
114 : // 9. Condenser Supply Water Temperature Sensor Offset (FY16)
115 : // 10. Cooling Tower Scaling (FY16)
116 : // 11. Coil Supply Air Temperature Sensor Offset (FY16)
117 : // coming ...
118 : // Fouling: chillers, boilers, cooling towers
119 : // Damper leakage: return air, outdoor air
120 : // Blockage: pipe
121 : // Meter: air flow, water flow
122 : // CO2 sensor
123 : // Pressure sensor offset
124 : // more
125 :
126 : Array1D_string const cFaults({0, 15},
127 : {"FaultModel:TemperatureSensorOffset:OutdoorAir",
128 : "FaultModel:HumiditySensorOffset:OutdoorAir",
129 : "FaultModel:EnthalpySensorOffset:OutdoorAir",
130 : "FaultModel:TemperatureSensorOffset:ReturnAir",
131 : "FaultModel:EnthalpySensorOffset:ReturnAir",
132 : "FaultModel:Fouling:Coil",
133 : "FaultModel:ThermostatOffset",
134 : "FaultModel:HumidistatOffset",
135 : "FaultModel:Fouling:AirFilter",
136 : "FaultModel:TemperatureSensorOffset:ChillerSupplyWater",
137 : "FaultModel:TemperatureSensorOffset:CondenserSupplyWater",
138 : "FaultModel:Fouling:CoolingTower",
139 : "FaultModel:TemperatureSensorOffset:CoilSupplyAir",
140 : "FaultModel:Fouling:Boiler",
141 : "FaultModel:Fouling:Chiller",
142 : "FaultModel:Fouling:EvaporativeCooler"});
143 : // 'FaultModel:PressureSensorOffset:OutdoorAir ', &
144 : // 'FaultModel:TemperatureSensorOffset:SupplyAir ', &
145 : // 'FaultModel:TemperatureSensorOffset:ZoneAir ', &
146 : // 'FaultModel:Blockage:Branch ', &
147 : // 'FaultModel:Fouling:Chiller ', &
148 : // 'FaultModel:Fouling:Boiler ', &
149 : // 'FaultModel:DamperLeakage:ReturnAir ', &
150 : // 'FaultModel:DamperLeakage:OutdoorAir ' /)
151 :
152 : enum class ChillerType
153 : {
154 : Invalid = -1,
155 : ChillerElectric,
156 : ChillerElectricEIR,
157 : ChillerElectricReformulatedEIR,
158 : ChillerConstantCOP,
159 : ChillerEngineDriven,
160 : ChillerCombustionTurbine,
161 : ChillerAbsorption,
162 : ChillerAbsorptionIndirect,
163 : Num
164 : };
165 :
166 : enum class CoilType
167 : {
168 : Invalid = -1,
169 : CoilHeatingElectric,
170 : CoilHeatingFuel,
171 : CoilHeatingDesuperheater,
172 : CoilHeatingSteam,
173 : CoilHeatingWater,
174 : CoilCoolingWater,
175 : CoilCoolingWaterDetailedgeometry,
176 : CoilSystemCoolingDX,
177 : CoilSystemHeatingDX,
178 : AirLoopHVACUnitarySystem,
179 : Num
180 : };
181 :
182 : constexpr std::array<std::string_view, static_cast<int>(ChillerType::Num)> ChillerTypeNamesUC{"CHILLER:ELECTRIC",
183 : "CHILLER:ELECTRIC:EIR",
184 : "CHILLER:ELECTRIC:REFORMULATEDEIR",
185 : "CHILLER:CONSTANTCOP",
186 : "CHILLER:ENGINEDRIVEN",
187 : "CHILLER:COMBUSTIONTURBINE",
188 : "CHILLER:ABSORPTION",
189 : "CHILLER:ABSORPTION:INDIRECT"};
190 :
191 : constexpr std::array<std::string_view, static_cast<int>(CoilType::Num)> CoilTypeNamesUC{"COIL:HEATING:ELECTRIC",
192 : "COIL:HEATING:FUEL",
193 : "COIL:HEATING:DESUPERHEATER",
194 : "COIL:HEATING:STEAM",
195 : "COIL:HEATING:WATER",
196 : "COIL:COOLING:WATER",
197 : "COIL:COOLING:WATER:DETAILEDGEOMETRY",
198 : "COILSYSTEM:COOLING:DX",
199 : "COILSYSTEM:HEATING:DX",
200 : "AIRLOOPHVAC:UNITARYSYSTEM"};
201 :
202 : constexpr std::array<std::string_view, static_cast<int>(FouledCoil::Num)> FouledCoilNamesUC{"FOULEDUARATED", "FOULINGFACTOR"};
203 :
204 1213 : void CheckAndReadFaults(EnergyPlusData &state)
205 : {
206 :
207 : // SUBROUTINE INFORMATION:
208 : // AUTHOR Tianzhen Hong, LBNL
209 : // DATE WRITTEN August 2013
210 : // MODIFIED Sep. 2013, Xiufeng Pang (XP), LBNL. Added Fouling Coil fault
211 : // Feb. 2015, Rongpeng Zhang, LBNL. Added Thermostat/Humidistat Offset faults
212 : // Apr. 2015, Rongpeng Zhang, LBNL. Added Fouling Air Filter fault
213 : // May. 2016, Rongpeng Zhang, LBNL. Added Chiller/Condenser Supply Water Temperature Sensor fault
214 : // Jun. 2016, Rongpeng Zhang, LBNL. Added Tower Scaling fault
215 : // Jul. 2016, Rongpeng Zhang, LBNL. Added Coil Supply Air Temperature Sensor fault
216 : // Oct. 2016, Rongpeng Zhang, LBNL. Added Fouling Boiler fault
217 : // Nov. 2016, Rongpeng Zhang, LBNL. Added Fouling Chiller fault
218 : // Jan. 2017, Rongpeng Zhang, LBNL. Added Fouling Evaporative Cooler fault
219 :
220 : // PURPOSE OF THIS SUBROUTINE:
221 : // 1. Determine if any operational faults are present in a model and set flags
222 : // 2. Read faults input
223 :
224 : // METHODOLOGY EMPLOYED:
225 : // Get number of faults-related input objects and assign faults input to data structure
226 : static constexpr std::string_view routineName = "CheckAndReadFaults";
227 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
228 : int NumAlphas; // Number of Alphas for each GetobjectItem call
229 : int NumNumbers; // Number of Numbers for each GetobjectItem call
230 : int IOStatus;
231 1213 : Array1D_string cAlphaArgs(10); // Alpha input items for object
232 1213 : Array1D_bool lAlphaFieldBlanks(10, false);
233 1213 : Array1D_bool lNumericFieldBlanks(10, false);
234 1213 : Array1D_string cAlphaFieldNames(10);
235 1213 : Array1D_string cNumericFieldNames(10);
236 1213 : Array1D<Real64> rNumericArgs(10); // Numeric input items for object
237 1213 : std::string cFaultCurrentObject;
238 :
239 1213 : if (state.dataFaultsMgr->RunFaultMgrOnceFlag) {
240 413 : return;
241 : }
242 :
243 : // check number of faults
244 800 : state.dataFaultsMgr->NumFaults = 0;
245 800 : state.dataFaultsMgr->NumFaultyEconomizer = 0;
246 13600 : for (int NumFaultsTemp = 0, i = 0; i <= 15; ++i) {
247 12800 : NumFaultsTemp = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cFaults(i));
248 12800 : state.dataFaultsMgr->NumFaults += NumFaultsTemp;
249 :
250 12800 : if (i <= 4) {
251 : // 1st-5th fault: economizer sensor offset
252 4000 : state.dataFaultsMgr->NumFaultyEconomizer += NumFaultsTemp;
253 8800 : } else if (i == 5) {
254 : // 6th fault: Coil fouling
255 800 : state.dataFaultsMgr->NumFouledCoil = NumFaultsTemp;
256 8000 : } else if (i == 6) {
257 : // 7th fault: Faulty thermostat
258 800 : state.dataFaultsMgr->NumFaultyThermostat = NumFaultsTemp;
259 7200 : } else if (i == 7) {
260 : // 8th fault: Faulty humidistat
261 800 : state.dataFaultsMgr->NumFaultyHumidistat = NumFaultsTemp;
262 6400 : } else if (i == 8) {
263 : // 9th fault: Fouled air filter
264 800 : state.dataFaultsMgr->NumFaultyAirFilter = NumFaultsTemp;
265 5600 : } else if (i == 9) {
266 : // 10th fault: Faulty Chillers Supply Water Temperature Sensor
267 800 : state.dataFaultsMgr->NumFaultyChillerSWTSensor = NumFaultsTemp;
268 4800 : } else if (i == 10) {
269 : // 11th fault: Faulty Condenser Supply Water Temperature Sensor
270 800 : state.dataFaultsMgr->NumFaultyCondenserSWTSensor = NumFaultsTemp;
271 4000 : } else if (i == 11) {
272 : // 12th fault: Faulty Towers with Scaling
273 800 : state.dataFaultsMgr->NumFaultyTowerFouling = NumFaultsTemp;
274 3200 : } else if (i == 12) {
275 : // 13th fault: Faulty Coil Supply Air Temperature Sensor
276 800 : state.dataFaultsMgr->NumFaultyCoilSATSensor = NumFaultsTemp;
277 2400 : } else if (i == 13) {
278 : // 14th fault: Faulty Boiler with Fouling
279 800 : state.dataFaultsMgr->NumFaultyBoilerFouling = NumFaultsTemp;
280 1600 : } else if (i == 14) {
281 : // 15th fault: Faulty Chiller with Fouling
282 800 : state.dataFaultsMgr->NumFaultyChillerFouling = NumFaultsTemp;
283 800 : } else if (i == 15) {
284 : // 16th fault: Faulty Evaporative Cooler with Fouling
285 800 : state.dataFaultsMgr->NumFaultyEvapCoolerFouling = NumFaultsTemp;
286 : }
287 : }
288 :
289 800 : if (state.dataFaultsMgr->NumFaults > 0) {
290 12 : state.dataFaultsMgr->AnyFaultsInModel = true;
291 : } else {
292 788 : state.dataFaultsMgr->AnyFaultsInModel = false;
293 : }
294 :
295 800 : if (!state.dataFaultsMgr->AnyFaultsInModel) {
296 788 : state.dataFaultsMgr->RunFaultMgrOnceFlag = true;
297 788 : return;
298 : }
299 :
300 : // allocate fault array
301 12 : if (state.dataFaultsMgr->NumFaultyEconomizer > 0) {
302 1 : state.dataFaultsMgr->FaultsEconomizer.allocate(state.dataFaultsMgr->NumFaultyEconomizer);
303 : }
304 12 : if (state.dataFaultsMgr->NumFouledCoil > 0) {
305 1 : state.dataFaultsMgr->FouledCoils.allocate(state.dataFaultsMgr->NumFouledCoil);
306 : }
307 12 : if (state.dataFaultsMgr->NumFaultyThermostat > 0) {
308 2 : state.dataFaultsMgr->FaultsThermostatOffset.allocate(state.dataFaultsMgr->NumFaultyThermostat);
309 : }
310 12 : if (state.dataFaultsMgr->NumFaultyHumidistat > 0) {
311 2 : state.dataFaultsMgr->FaultsHumidistatOffset.allocate(state.dataFaultsMgr->NumFaultyHumidistat);
312 : }
313 12 : if (state.dataFaultsMgr->NumFaultyAirFilter > 0) {
314 1 : state.dataFaultsMgr->FaultsFouledAirFilters.allocate(state.dataFaultsMgr->NumFaultyAirFilter);
315 : }
316 12 : if (state.dataFaultsMgr->NumFaultyChillerSWTSensor > 0) {
317 1 : state.dataFaultsMgr->FaultsChillerSWTSensor.allocate(state.dataFaultsMgr->NumFaultyChillerSWTSensor);
318 : }
319 12 : if (state.dataFaultsMgr->NumFaultyCondenserSWTSensor > 0) {
320 1 : state.dataFaultsMgr->FaultsCondenserSWTSensor.allocate(state.dataFaultsMgr->NumFaultyCondenserSWTSensor);
321 : }
322 12 : if (state.dataFaultsMgr->NumFaultyTowerFouling > 0) {
323 1 : state.dataFaultsMgr->FaultsTowerFouling.allocate(state.dataFaultsMgr->NumFaultyTowerFouling);
324 : }
325 12 : if (state.dataFaultsMgr->NumFaultyCoilSATSensor > 0) {
326 1 : state.dataFaultsMgr->FaultsCoilSATSensor.allocate(state.dataFaultsMgr->NumFaultyCoilSATSensor);
327 : }
328 12 : if (state.dataFaultsMgr->NumFaultyBoilerFouling > 0) {
329 1 : state.dataFaultsMgr->FaultsBoilerFouling.allocate(state.dataFaultsMgr->NumFaultyBoilerFouling);
330 : }
331 12 : if (state.dataFaultsMgr->NumFaultyChillerFouling > 0) {
332 1 : state.dataFaultsMgr->FaultsChillerFouling.allocate(state.dataFaultsMgr->NumFaultyChillerFouling);
333 : }
334 12 : if (state.dataFaultsMgr->NumFaultyEvapCoolerFouling > 0) {
335 1 : state.dataFaultsMgr->FaultsEvapCoolerFouling.allocate(state.dataFaultsMgr->NumFaultyEvapCoolerFouling);
336 : }
337 :
338 : // read faults input of Evaporative Cooler Fouling
339 14 : for (int jFault_EvapCoolerFouling = 1; jFault_EvapCoolerFouling <= state.dataFaultsMgr->NumFaultyEvapCoolerFouling;
340 : ++jFault_EvapCoolerFouling) {
341 2 : auto &faultsECFouling = state.dataFaultsMgr->FaultsEvapCoolerFouling(jFault_EvapCoolerFouling);
342 :
343 2 : cFaultCurrentObject = cFaults(15); // fault object string
344 2 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
345 : cFaultCurrentObject,
346 : jFault_EvapCoolerFouling,
347 : cAlphaArgs,
348 : NumAlphas,
349 : rNumericArgs,
350 : NumNumbers,
351 : IOStatus,
352 : lNumericFieldBlanks,
353 : lAlphaFieldBlanks,
354 : cAlphaFieldNames,
355 : cNumericFieldNames);
356 :
357 2 : ErrorObjectHeader eoh{routineName, cFaultCurrentObject, cAlphaArgs(1)};
358 2 : faultsECFouling.type = FaultType::Fouling_EvapCooler;
359 2 : faultsECFouling.Name = cAlphaArgs(1);
360 :
361 : // Fault availability schedule
362 2 : if (lAlphaFieldBlanks(2)) {
363 2 : faultsECFouling.availSched = Sched::GetScheduleAlwaysOn(state); // returns schedule value of 1
364 0 : } else if ((faultsECFouling.availSched = Sched::GetSchedule(state, cAlphaArgs(2))) == nullptr) {
365 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(2), cAlphaArgs(2));
366 0 : state.dataFaultsMgr->ErrorsFound = true;
367 : }
368 :
369 : // Fault severity schedule
370 2 : if (lAlphaFieldBlanks(3)) {
371 2 : faultsECFouling.severitySched = Sched::GetScheduleAlwaysOn(state); // not an availability schedule, but defaults to constant-1.0
372 0 : } else if ((faultsECFouling.severitySched = Sched::GetSchedule(state, cAlphaArgs(3))) == nullptr) {
373 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(3), cAlphaArgs(3));
374 0 : state.dataFaultsMgr->ErrorsFound = true;
375 : }
376 :
377 : // CapReductionFactor - degree of fault
378 2 : faultsECFouling.FoulingFactor = rNumericArgs(1);
379 :
380 : // Evaporative cooler type
381 2 : faultsECFouling.EvapCoolerType = cAlphaArgs(4);
382 2 : if (lAlphaFieldBlanks(4)) {
383 0 : ShowSevereError(
384 0 : state, format("{} = \"{}\" invalid {} = \"{}\" blank.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(4), cAlphaArgs(4)));
385 0 : state.dataFaultsMgr->ErrorsFound = true;
386 : }
387 :
388 : // Evaporative cooler name
389 2 : faultsECFouling.EvapCoolerName = cAlphaArgs(5);
390 2 : if (lAlphaFieldBlanks(5)) {
391 0 : ShowSevereError(
392 0 : state, format("{} = \"{}\" invalid {} = \"{}\" blank.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(5), cAlphaArgs(5)));
393 0 : state.dataFaultsMgr->ErrorsFound = true;
394 : }
395 :
396 : // Evaporative cooler check
397 2 : if (Util::SameString(faultsECFouling.EvapCoolerType, "EvaporativeCooler:Indirect:WetCoil")) {
398 : // Read in evaporative cooler is not done yet
399 2 : if (state.dataEvapCoolers->GetInputEvapComponentsFlag) {
400 0 : EvaporativeCoolers::GetEvapInput(state);
401 0 : state.dataEvapCoolers->GetInputEvapComponentsFlag = false;
402 : }
403 :
404 : // Check whether the evaporative cooler name and type match each other;
405 : int EvapCoolerNum =
406 2 : Util::FindItemInList(faultsECFouling.EvapCoolerName, state.dataEvapCoolers->EvapCond, &EvaporativeCoolers::EvapConditions::Name);
407 2 : if (EvapCoolerNum <= 0) {
408 0 : ShowSevereError(
409 : state,
410 0 : format("{} = \"{}\" invalid {} = \"{}\" not found.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(5), cAlphaArgs(5)));
411 0 : state.dataFaultsMgr->ErrorsFound = true;
412 : } else {
413 : // Link the boiler with the fault model
414 2 : state.dataEvapCoolers->EvapCond(EvapCoolerNum).FaultyEvapCoolerFoulingFlag = true;
415 2 : state.dataEvapCoolers->EvapCond(EvapCoolerNum).FaultyEvapCoolerFoulingIndex = jFault_EvapCoolerFouling;
416 : }
417 : }
418 : }
419 :
420 : // read faults input of Chiller Fouling
421 14 : for (int jFault_ChillerFouling = 1; jFault_ChillerFouling <= state.dataFaultsMgr->NumFaultyChillerFouling; ++jFault_ChillerFouling) {
422 2 : auto &faultsChillerFouling = state.dataFaultsMgr->FaultsChillerFouling(jFault_ChillerFouling);
423 :
424 2 : cFaultCurrentObject = cFaults(14); // fault object string
425 2 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
426 : cFaultCurrentObject,
427 : jFault_ChillerFouling,
428 : cAlphaArgs,
429 : NumAlphas,
430 : rNumericArgs,
431 : NumNumbers,
432 : IOStatus,
433 : lNumericFieldBlanks,
434 : lAlphaFieldBlanks,
435 : cAlphaFieldNames,
436 : cNumericFieldNames);
437 :
438 2 : ErrorObjectHeader eoh{routineName, cFaultCurrentObject, cAlphaArgs(1)};
439 2 : faultsChillerFouling.type = FaultType::Fouling_Chiller;
440 2 : faultsChillerFouling.Name = cAlphaArgs(1);
441 :
442 : // Fault availability schedule
443 2 : if (lAlphaFieldBlanks(2)) {
444 2 : faultsChillerFouling.availSched = Sched::GetScheduleAlwaysOn(state); // returns schedule value of 1
445 0 : } else if ((faultsChillerFouling.availSched = Sched::GetSchedule(state, cAlphaArgs(2))) == nullptr) {
446 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(2), cAlphaArgs(2));
447 0 : state.dataFaultsMgr->ErrorsFound = true;
448 : }
449 :
450 : // Fault severity schedule
451 2 : if (lAlphaFieldBlanks(3)) {
452 2 : faultsChillerFouling.severitySched = Sched::GetScheduleAlwaysOn(state); // not an availability schedule, but defaults to constant-1.0
453 0 : } else if ((faultsChillerFouling.severitySched = Sched::GetSchedule(state, cAlphaArgs(3))) == nullptr) {
454 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(3), cAlphaArgs(3));
455 0 : state.dataFaultsMgr->ErrorsFound = true;
456 : }
457 :
458 : // CapReductionFactor - degree of fault
459 2 : faultsChillerFouling.FoulingFactor = rNumericArgs(1);
460 :
461 : // Chiller type
462 2 : faultsChillerFouling.ChillerType = cAlphaArgs(4);
463 2 : if (lAlphaFieldBlanks(4)) {
464 0 : ShowSevereError(
465 0 : state, format("{} = \"{}\" invalid {} = \"{}\" blank.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(4), cAlphaArgs(4)));
466 0 : state.dataFaultsMgr->ErrorsFound = true;
467 : }
468 :
469 : // Chiller name
470 2 : faultsChillerFouling.ChillerName = cAlphaArgs(5);
471 2 : if (lAlphaFieldBlanks(5)) {
472 0 : ShowSevereError(
473 0 : state, format("{} = \"{}\" invalid {} = \"{}\" blank.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(5), cAlphaArgs(5)));
474 0 : state.dataFaultsMgr->ErrorsFound = true;
475 : }
476 :
477 : // Chiller check
478 : int ChillerNum;
479 : ChillerType ChillerTypeCheck =
480 2 : static_cast<ChillerType>(getEnumValue(ChillerTypeNamesUC, Util::makeUPPER(faultsChillerFouling.ChillerType)));
481 2 : switch (ChillerTypeCheck) {
482 0 : case ChillerType::ChillerElectric: {
483 : // Check whether the chiller name and chiller type match each other
484 0 : ChillerNum = 0;
485 0 : int thisChil = 0;
486 0 : for (auto const &ch : state.dataPlantChillers->ElectricChiller) {
487 0 : thisChil++;
488 0 : if (ch.Name == faultsChillerFouling.ChillerName) {
489 0 : ChillerNum = thisChil;
490 : }
491 0 : }
492 0 : if (ChillerNum <= 0) {
493 0 : ShowSevereError(
494 : state,
495 0 : format("{} = \"{}\" invalid {} = \"{}\" not found.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(5), cAlphaArgs(5)));
496 0 : state.dataFaultsMgr->ErrorsFound = true;
497 : } else {
498 :
499 0 : if (state.dataPlantChillers->ElectricChiller(ChillerNum).CondenserType != DataPlant::CondenserType::WaterCooled) {
500 : // The fault model is only applicable to the chillers with water based condensers
501 0 : ShowWarningError(state,
502 0 : format("{} = \"{}\" invalid {} = \"{}\". The specified chiller is not water cooled. The chiller fouling "
503 : "fault model will not be applied.",
504 : cFaultCurrentObject,
505 : cAlphaArgs(1),
506 : cAlphaFieldNames(5),
507 : cAlphaArgs(5)));
508 :
509 : } else {
510 : // Link the chiller with the fault model
511 0 : state.dataPlantChillers->ElectricChiller(ChillerNum).FaultyChillerFoulingFlag = true;
512 0 : state.dataPlantChillers->ElectricChiller(ChillerNum).FaultyChillerFoulingIndex = jFault_ChillerFouling;
513 : }
514 : }
515 0 : } break;
516 0 : case ChillerType::ChillerElectricEIR: {
517 : // Read in chiller if not done yet
518 0 : if (state.dataChillerElectricEIR->getInputFlag) {
519 0 : ChillerElectricEIR::GetElectricEIRChillerInput(state);
520 0 : state.dataChillerElectricEIR->getInputFlag = false;
521 : }
522 :
523 : // Check whether the chiller name and chiller type match each other
524 0 : ChillerNum = Util::FindItemInList(faultsChillerFouling.ChillerName, state.dataChillerElectricEIR->ElectricEIRChiller);
525 0 : if (ChillerNum <= 0) {
526 0 : ShowSevereError(
527 : state,
528 0 : format("{} = \"{}\" invalid {} = \"{}\" not found.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(5), cAlphaArgs(5)));
529 0 : state.dataFaultsMgr->ErrorsFound = true;
530 : } else {
531 :
532 0 : if (state.dataChillerElectricEIR->ElectricEIRChiller(ChillerNum).CondenserType != DataPlant::CondenserType::WaterCooled) {
533 : // The fault model is only applicable to the chillers with water based condensers
534 0 : ShowWarningError(state,
535 0 : format("{} = \"{}\" invalid {} = \"{}\". The specified chiller is not water cooled. The chiller fouling "
536 : "fault model will not be applied.",
537 : cFaultCurrentObject,
538 : cAlphaArgs(1),
539 : cAlphaFieldNames(5),
540 : cAlphaArgs(5)));
541 :
542 : } else {
543 : // Link the chiller with the fault model
544 0 : state.dataChillerElectricEIR->ElectricEIRChiller(ChillerNum).FaultyChillerFoulingFlag = true;
545 0 : state.dataChillerElectricEIR->ElectricEIRChiller(ChillerNum).FaultyChillerFoulingIndex = jFault_ChillerFouling;
546 : }
547 : }
548 0 : } break;
549 2 : case ChillerType::ChillerElectricReformulatedEIR: {
550 : // Read in chiller if not done yet
551 2 : if (state.dataChillerReformulatedEIR->GetInputREIR) {
552 0 : ChillerReformulatedEIR::GetElecReformEIRChillerInput(state);
553 0 : state.dataChillerReformulatedEIR->GetInputREIR = false;
554 : }
555 :
556 : // Check whether the chiller name and chiller type match each other
557 2 : ChillerNum = Util::FindItemInList(faultsChillerFouling.ChillerName, state.dataChillerReformulatedEIR->ElecReformEIRChiller);
558 2 : if (ChillerNum <= 0) {
559 0 : ShowSevereError(
560 : state,
561 0 : format("{} = \"{}\" invalid {} = \"{}\" not found.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(5), cAlphaArgs(5)));
562 0 : state.dataFaultsMgr->ErrorsFound = true;
563 : } else {
564 :
565 2 : if (state.dataChillerReformulatedEIR->ElecReformEIRChiller(ChillerNum).CondenserType != DataPlant::CondenserType::WaterCooled) {
566 : // The fault model is only applicable to the chillers with water based condensers
567 0 : ShowWarningError(state,
568 0 : format("{} = \"{}\" invalid {} = \"{}\". The specified chiller is not water cooled. The chiller fouling "
569 : "fault model will not be applied.",
570 : cFaultCurrentObject,
571 : cAlphaArgs(1),
572 : cAlphaFieldNames(5),
573 : cAlphaArgs(5)));
574 :
575 : } else {
576 : // Link the chiller with the fault model
577 2 : state.dataChillerReformulatedEIR->ElecReformEIRChiller(ChillerNum).FaultyChillerFoulingFlag = true;
578 2 : state.dataChillerReformulatedEIR->ElecReformEIRChiller(ChillerNum).FaultyChillerFoulingIndex = jFault_ChillerFouling;
579 : }
580 : }
581 2 : } break;
582 0 : case ChillerType::ChillerConstantCOP: {
583 : // Check whether the chiller name and chiller type match each other
584 0 : ChillerNum = 0;
585 0 : int thisChil = 0;
586 0 : for (auto const &ch : state.dataPlantChillers->ConstCOPChiller) {
587 0 : thisChil++;
588 0 : if (ch.Name == faultsChillerFouling.ChillerName) {
589 0 : ChillerNum = thisChil;
590 : }
591 0 : }
592 0 : if (ChillerNum <= 0) {
593 0 : ShowSevereError(
594 : state,
595 0 : format("{} = \"{}\" invalid {} = \"{}\" not found.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(5), cAlphaArgs(5)));
596 0 : state.dataFaultsMgr->ErrorsFound = true;
597 : } else {
598 :
599 0 : if (state.dataPlantChillers->ConstCOPChiller(ChillerNum).CondenserType != DataPlant::CondenserType::WaterCooled) {
600 : // The fault model is only applicable to the chillers with water based condensers
601 0 : ShowWarningError(state,
602 0 : format("{} = \"{}\" invalid {} = \"{}\". The specified chiller is not water cooled. The chiller fouling "
603 : "fault model will not be applied.",
604 : cFaultCurrentObject,
605 : cAlphaArgs(1),
606 : cAlphaFieldNames(5),
607 : cAlphaArgs(5)));
608 :
609 : } else {
610 : // Link the chiller with the fault model
611 0 : state.dataPlantChillers->ConstCOPChiller(ChillerNum).FaultyChillerFoulingFlag = true;
612 0 : state.dataPlantChillers->ConstCOPChiller(ChillerNum).FaultyChillerFoulingIndex = jFault_ChillerFouling;
613 : }
614 : }
615 0 : } break;
616 0 : case ChillerType::ChillerEngineDriven: {
617 : // Check whether the chiller name and chiller type match each other
618 0 : ChillerNum = 0;
619 0 : int thisChil = 0;
620 0 : for (auto const &ch : state.dataPlantChillers->EngineDrivenChiller) {
621 0 : thisChil++;
622 0 : if (ch.Name == faultsChillerFouling.ChillerName) {
623 0 : ChillerNum = thisChil;
624 : }
625 0 : }
626 0 : if (ChillerNum <= 0) {
627 0 : ShowSevereError(
628 : state,
629 0 : format("{} = \"{}\" invalid {} = \"{}\" not found.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(5), cAlphaArgs(5)));
630 0 : state.dataFaultsMgr->ErrorsFound = true;
631 : } else {
632 :
633 0 : if (state.dataPlantChillers->EngineDrivenChiller(ChillerNum).CondenserType != DataPlant::CondenserType::WaterCooled) {
634 : // The fault model is only applicable to the chillers with water based condensers
635 0 : ShowWarningError(state,
636 0 : format("{} = \"{}\" invalid {} = \"{}\". The specified chiller is not water cooled. The chiller fouling "
637 : "fault model will not be applied.",
638 : cFaultCurrentObject,
639 : cAlphaArgs(1),
640 : cAlphaFieldNames(5),
641 : cAlphaArgs(5)));
642 :
643 : } else {
644 : // Link the fault model with the water cooled chiller
645 0 : state.dataPlantChillers->EngineDrivenChiller(ChillerNum).FaultyChillerFoulingFlag = true;
646 0 : state.dataPlantChillers->EngineDrivenChiller(ChillerNum).FaultyChillerFoulingIndex = jFault_ChillerFouling;
647 : }
648 : }
649 0 : } break;
650 0 : case ChillerType::ChillerCombustionTurbine: {
651 : // Check whether the chiller name and chiller type match each other
652 0 : ChillerNum = 0;
653 0 : int thisChil = 0;
654 0 : for (auto const &ch : state.dataPlantChillers->GTChiller) {
655 0 : thisChil++;
656 0 : if (ch.Name == faultsChillerFouling.ChillerName) {
657 0 : ChillerNum = thisChil;
658 : }
659 0 : }
660 0 : if (ChillerNum <= 0) {
661 0 : ShowSevereError(
662 : state,
663 0 : format("{} = \"{}\" invalid {} = \"{}\" not found.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(5), cAlphaArgs(5)));
664 0 : state.dataFaultsMgr->ErrorsFound = true;
665 : } else {
666 0 : if (state.dataPlantChillers->GTChiller(ChillerNum).CondenserType != DataPlant::CondenserType::WaterCooled) {
667 : // The fault model is only applicable to the chillers with water based condensers
668 0 : ShowWarningError(state,
669 0 : format("{} = \"{}\" invalid {} = \"{}\". The specified chiller is not water cooled. The chiller fouling "
670 : "fault model will not be applied.",
671 : cFaultCurrentObject,
672 : cAlphaArgs(1),
673 : cAlphaFieldNames(5),
674 : cAlphaArgs(5)));
675 :
676 : } else {
677 : // Link the fault model with the water cooled chiller
678 0 : state.dataPlantChillers->GTChiller(ChillerNum).FaultyChillerFoulingFlag = true;
679 0 : state.dataPlantChillers->GTChiller(ChillerNum).FaultyChillerFoulingIndex = jFault_ChillerFouling;
680 : }
681 : }
682 0 : } break;
683 0 : default:
684 0 : break;
685 : }
686 : }
687 :
688 : // read faults input of Boiler Fouling
689 13 : for (int jFault_BoilerFouling = 1; jFault_BoilerFouling <= state.dataFaultsMgr->NumFaultyBoilerFouling; ++jFault_BoilerFouling) {
690 1 : auto &faultsBoilerFouling = state.dataFaultsMgr->FaultsBoilerFouling(jFault_BoilerFouling);
691 :
692 1 : cFaultCurrentObject = cFaults(13); // fault object string
693 1 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
694 : cFaultCurrentObject,
695 : jFault_BoilerFouling,
696 : cAlphaArgs,
697 : NumAlphas,
698 : rNumericArgs,
699 : NumNumbers,
700 : IOStatus,
701 : lNumericFieldBlanks,
702 : lAlphaFieldBlanks,
703 : cAlphaFieldNames,
704 : cNumericFieldNames);
705 :
706 1 : ErrorObjectHeader eoh{routineName, cFaultCurrentObject, cAlphaArgs(1)};
707 1 : faultsBoilerFouling.type = FaultType::Fouling_Boiler;
708 1 : faultsBoilerFouling.Name = cAlphaArgs(1);
709 :
710 : // Fault availability schedule
711 1 : if (lAlphaFieldBlanks(2)) {
712 1 : faultsBoilerFouling.availSched = Sched::GetScheduleAlwaysOn(state); // returns schedule value of 1
713 0 : } else if ((faultsBoilerFouling.availSched = Sched::GetSchedule(state, cAlphaArgs(2))) == nullptr) {
714 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(2), cAlphaArgs(2));
715 0 : state.dataFaultsMgr->ErrorsFound = true;
716 : }
717 :
718 : // Fault severity schedule
719 1 : if (lAlphaFieldBlanks(3)) {
720 1 : faultsBoilerFouling.severitySched = Sched::GetScheduleAlwaysOn(state); // not an availability schedule, but defaults to constant-1.0
721 0 : } else if ((faultsBoilerFouling.severitySched = Sched::GetSchedule(state, cAlphaArgs(3))) == nullptr) {
722 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(3), cAlphaArgs(3));
723 0 : state.dataFaultsMgr->ErrorsFound = true;
724 : }
725 :
726 : // CapReductionFactor - degree of fault
727 1 : faultsBoilerFouling.FoulingFactor = rNumericArgs(1);
728 :
729 : // Boiler type
730 1 : faultsBoilerFouling.BoilerType = cAlphaArgs(4);
731 1 : if (lAlphaFieldBlanks(4)) {
732 0 : ShowSevereError(
733 0 : state, format("{} = \"{}\" invalid {} = \"{}\" blank.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(4), cAlphaArgs(4)));
734 0 : state.dataFaultsMgr->ErrorsFound = true;
735 : }
736 :
737 : // Boiler name
738 1 : faultsBoilerFouling.BoilerName = cAlphaArgs(5);
739 1 : if (lAlphaFieldBlanks(5)) {
740 0 : ShowSevereError(
741 0 : state, format("{} = \"{}\" invalid {} = \"{}\" blank.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(5), cAlphaArgs(5)));
742 0 : state.dataFaultsMgr->ErrorsFound = true;
743 : }
744 :
745 : // Boiler check and link
746 : {
747 1 : if (state.dataBoilers->getBoilerInputFlag) {
748 0 : Boilers::GetBoilerInput(state);
749 0 : state.dataBoilers->getBoilerInputFlag = false;
750 : }
751 : // Check the boiler name and boiler type
752 1 : int BoilerNum = Util::FindItemInList(faultsBoilerFouling.BoilerName, state.dataBoilers->Boiler);
753 1 : if (BoilerNum <= 0) {
754 0 : ShowSevereError(
755 : state,
756 0 : format("{} = \"{}\" invalid {} = \"{}\" not found.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(5), cAlphaArgs(5)));
757 0 : state.dataFaultsMgr->ErrorsFound = true;
758 : } else {
759 : // Link the boiler with the fault model
760 1 : state.dataBoilers->Boiler(BoilerNum).FaultyBoilerFoulingFlag = true;
761 1 : state.dataBoilers->Boiler(BoilerNum).FaultyBoilerFoulingIndex = jFault_BoilerFouling;
762 : }
763 : }
764 : }
765 :
766 : // read faults input of Coil SAT Sensor Offset
767 13 : for (int jFault_CoilSAT = 1; jFault_CoilSAT <= state.dataFaultsMgr->NumFaultyCoilSATSensor; ++jFault_CoilSAT) {
768 1 : auto &faultsCoilSATFouling = state.dataFaultsMgr->FaultsCoilSATSensor(jFault_CoilSAT);
769 :
770 1 : cFaultCurrentObject = cFaults(12); // fault object string
771 1 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
772 : cFaultCurrentObject,
773 : jFault_CoilSAT,
774 : cAlphaArgs,
775 : NumAlphas,
776 : rNumericArgs,
777 : NumNumbers,
778 : IOStatus,
779 : lNumericFieldBlanks,
780 : lAlphaFieldBlanks,
781 : cAlphaFieldNames,
782 : cNumericFieldNames);
783 :
784 1 : ErrorObjectHeader eoh{routineName, cFaultCurrentObject, cAlphaArgs(1)};
785 1 : faultsCoilSATFouling.type = FaultType::TemperatureSensorOffset_CoilSupplyAir;
786 1 : faultsCoilSATFouling.Name = cAlphaArgs(1);
787 :
788 : // Fault availability schedule
789 1 : if (lAlphaFieldBlanks(2)) {
790 1 : faultsCoilSATFouling.availSched = Sched::GetScheduleAlwaysOn(state); // returns schedule value of 1
791 0 : } else if ((faultsCoilSATFouling.availSched = Sched::GetSchedule(state, cAlphaArgs(2))) == nullptr) {
792 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(2), cAlphaArgs(2));
793 0 : state.dataFaultsMgr->ErrorsFound = true;
794 : }
795 :
796 : // Fault severity schedule
797 1 : if (lAlphaFieldBlanks(3)) {
798 1 : faultsCoilSATFouling.severitySched = Sched::GetScheduleAlwaysOn(state); // not an availability schedule, but defaults to constant-1.0
799 0 : } else if ((faultsCoilSATFouling.severitySched = Sched::GetSchedule(state, cAlphaArgs(3))) == nullptr) {
800 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(3), cAlphaArgs(3));
801 0 : state.dataFaultsMgr->ErrorsFound = true;
802 : }
803 :
804 : // offset - degree of fault
805 1 : faultsCoilSATFouling.Offset = rNumericArgs(1);
806 :
807 : // Coil type
808 1 : faultsCoilSATFouling.CoilType = cAlphaArgs(4);
809 1 : if (lAlphaFieldBlanks(4)) {
810 0 : ShowSevereError(
811 0 : state, format("{} = \"{}\" invalid {} = \"{}\" blank.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(4), cAlphaArgs(4)));
812 0 : state.dataFaultsMgr->ErrorsFound = true;
813 : }
814 :
815 : // Coil name
816 1 : faultsCoilSATFouling.CoilName = cAlphaArgs(5);
817 1 : if (lAlphaFieldBlanks(5)) {
818 0 : ShowSevereError(
819 0 : state, format("{} = \"{}\" invalid {} = \"{}\" blank.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(5), cAlphaArgs(5)));
820 0 : state.dataFaultsMgr->ErrorsFound = true;
821 : }
822 :
823 : // Coil check and link
824 1 : CoilType CoilTypeCheck = static_cast<CoilType>(getEnumValue(CoilTypeNamesUC, Util::makeUPPER(faultsCoilSATFouling.CoilType)));
825 1 : switch (CoilTypeCheck) {
826 0 : case CoilType::CoilHeatingElectric:
827 : case CoilType::CoilHeatingFuel:
828 : case CoilType::CoilHeatingDesuperheater: {
829 : // Read in coil input if not done yet
830 0 : if (state.dataHeatingCoils->GetCoilsInputFlag) {
831 0 : HeatingCoils::GetHeatingCoilInput(state);
832 0 : state.dataHeatingCoils->GetCoilsInputFlag = false;
833 : }
834 : // Check the coil name and coil type
835 0 : int CoilNum = Util::FindItemInList(faultsCoilSATFouling.CoilName, state.dataHeatingCoils->HeatingCoil);
836 0 : if (CoilNum <= 0) {
837 0 : ShowSevereError(
838 : state,
839 0 : format("{} = \"{}\" invalid {} = \"{}\" not found.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(5), cAlphaArgs(5)));
840 0 : state.dataFaultsMgr->ErrorsFound = true;
841 : } else {
842 : // Link the coil with the fault model
843 0 : state.dataHeatingCoils->HeatingCoil(CoilNum).FaultyCoilSATFlag = true;
844 0 : state.dataHeatingCoils->HeatingCoil(CoilNum).FaultyCoilSATIndex = jFault_CoilSAT;
845 : }
846 0 : } break;
847 0 : case CoilType::CoilHeatingSteam: {
848 : // Read in coil input if not done yet
849 0 : if (state.dataSteamCoils->GetSteamCoilsInputFlag) {
850 0 : SteamCoils::GetSteamCoilInput(state);
851 0 : state.dataSteamCoils->GetSteamCoilsInputFlag = false;
852 : }
853 : // Check the coil name and coil type
854 0 : int CoilNum = Util::FindItemInList(faultsCoilSATFouling.CoilName, state.dataSteamCoils->SteamCoil);
855 0 : if (CoilNum <= 0) {
856 0 : ShowSevereError(
857 : state,
858 0 : format("{} = \"{}\" invalid {} = \"{}\" not found.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(5), cAlphaArgs(5)));
859 0 : state.dataFaultsMgr->ErrorsFound = true;
860 : } else {
861 :
862 0 : if (state.dataSteamCoils->SteamCoil(CoilNum).TypeOfCoil != SteamCoils::CoilControlType::TemperatureSetPoint) {
863 : // The fault model is only applicable to the coils controlled on leaving air temperature
864 0 : ShowWarningError(state,
865 0 : format("{} = \"{}\" invalid {} = \"{}\". The specified coil is not controlled on leaving air temperature. "
866 : "The coil SAT sensor fault model will not be applied.",
867 : cFaultCurrentObject,
868 : cAlphaArgs(1),
869 : cAlphaFieldNames(5),
870 : cAlphaArgs(5)));
871 : } else {
872 : // Link the fault model with the coil that is controlled on leaving air temperature
873 0 : state.dataSteamCoils->SteamCoil(CoilNum).FaultyCoilSATFlag = true;
874 0 : state.dataSteamCoils->SteamCoil(CoilNum).FaultyCoilSATIndex = jFault_CoilSAT;
875 : }
876 : }
877 0 : } break;
878 1 : case CoilType::CoilHeatingWater:
879 : case CoilType::CoilCoolingWater:
880 : case CoilType::CoilCoolingWaterDetailedgeometry: {
881 : // Read in coil input if not done yet
882 1 : if (state.dataWaterCoils->GetWaterCoilsInputFlag) {
883 0 : WaterCoils::GetWaterCoilInput(state);
884 0 : state.dataWaterCoils->GetWaterCoilsInputFlag = false;
885 : }
886 : // Check the coil name and coil type
887 1 : int CoilNum = Util::FindItemInList(faultsCoilSATFouling.CoilName, state.dataWaterCoils->WaterCoil);
888 1 : if (CoilNum <= 0) {
889 0 : ShowSevereError(
890 : state,
891 0 : format("{} = \"{}\" invalid {} = \"{}\" not found.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(5), cAlphaArgs(5)));
892 0 : state.dataFaultsMgr->ErrorsFound = true;
893 : }
894 :
895 : // Read in Water Coil Controller Name
896 1 : faultsCoilSATFouling.WaterCoilControllerName = cAlphaArgs(6);
897 1 : if (lAlphaFieldBlanks(6)) {
898 0 : ShowSevereError(
899 : state,
900 0 : format("{} = \"{}\" invalid {} = \"{}\" blank.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(6), cAlphaArgs(6)));
901 0 : state.dataFaultsMgr->ErrorsFound = true;
902 : }
903 : // Read in controller input if not done yet
904 1 : if (state.dataHVACControllers->GetControllerInputFlag) {
905 0 : HVACControllers::GetControllerInput(state);
906 0 : state.dataHVACControllers->GetControllerInputFlag = false;
907 : }
908 : // Check the controller name
909 1 : int ControlNum = Util::FindItemInList(faultsCoilSATFouling.WaterCoilControllerName,
910 1 : state.dataHVACControllers->ControllerProps,
911 : &HVACControllers::ControllerPropsType::ControllerName);
912 1 : if (ControlNum <= 0) {
913 0 : ShowSevereError(
914 : state,
915 0 : format("{} = \"{}\" invalid {} = \"{}\" not found.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(6), cAlphaArgs(6)));
916 0 : state.dataFaultsMgr->ErrorsFound = true;
917 : } else {
918 : // Link the controller with the fault model
919 1 : state.dataHVACControllers->ControllerProps(ControlNum).FaultyCoilSATFlag = true;
920 1 : state.dataHVACControllers->ControllerProps(ControlNum).FaultyCoilSATIndex = jFault_CoilSAT;
921 :
922 : // Check whether the controller match the coil
923 1 : if (state.dataHVACControllers->ControllerProps(ControlNum).SensedNode !=
924 1 : state.dataWaterCoils->WaterCoil(CoilNum).AirOutletNodeNum) {
925 0 : ShowSevereError(state,
926 0 : format("{} = \"{}\" invalid {} = \"{}\" does not match {} = \"{}",
927 : cFaultCurrentObject,
928 : cAlphaArgs(1),
929 : cAlphaFieldNames(6),
930 : cAlphaArgs(6),
931 : cAlphaFieldNames(5),
932 : cAlphaArgs(5)));
933 0 : state.dataFaultsMgr->ErrorsFound = true;
934 : }
935 : }
936 1 : } break;
937 0 : case CoilType::CoilSystemCoolingDX: {
938 : // see case CoilCheck::AirLoopHVACUnitarySystem: below
939 : // UnitarySystem connects a different way. Make sure this works by testing a CoilSystem model.
940 : // Read in DXCoolingSystem input if not done yet
941 : // if (state.dataHVACDXSys->GetInputFlag) {
942 : // HVACDXSystem::GetDXCoolingSystemInput(state);
943 : // state.dataHVACDXSys->GetInputFlag = false;
944 : //}
945 :
946 : //// Check the coil name and coil type
947 : // int CoilSysNum = Util::FindItemInList(faultsCoilSATFouling.CoilName,
948 : // state.dataHVACDXSys->DXCoolingSystem);
949 : // if (CoilSysNum <= 0) {
950 : // ShowSevereError(state, format("{}{} = \"{}\" invalid {} = \"{}{}\" not found.", //, cFaultCurrentObject, cAlphaArgs(1),
951 : // cAlphaFieldNames(5), //, cAlphaArgs(5))); state.dataFaultsMgr->ErrorsFound = true;
952 : //} else {
953 : // // Link the coil system with the fault model
954 : // state.dataHVACDXSys->DXCoolingSystem(CoilSysNum).FaultyCoilSATFlag = true;
955 : // state.dataHVACDXSys->DXCoolingSystem(CoilSysNum).FaultyCoilSATIndex = jFault_CoilSAT;
956 : //}
957 0 : } break;
958 0 : case CoilType::CoilSystemHeatingDX: {
959 : // Read in DXCoolingSystem input if not done yet
960 0 : if (state.dataHVACDXHeatPumpSys->GetInputFlag) {
961 0 : HVACDXHeatPumpSystem::GetDXHeatPumpSystemInput(state);
962 0 : state.dataHVACDXHeatPumpSys->GetInputFlag = false;
963 : }
964 :
965 : // Check the coil name and coil type
966 0 : int CoilSysNum = Util::FindItemInList(faultsCoilSATFouling.CoilName, state.dataHVACDXHeatPumpSys->DXHeatPumpSystem);
967 0 : if (CoilSysNum <= 0) {
968 0 : ShowSevereError(
969 : state,
970 0 : format("{} = \"{}\" invalid {} = \"{}\" not found.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(5), cAlphaArgs(5)));
971 0 : state.dataFaultsMgr->ErrorsFound = true;
972 : } else {
973 : // Link the coil system with the fault model
974 0 : state.dataHVACDXHeatPumpSys->DXHeatPumpSystem(CoilSysNum).FaultyCoilSATFlag = true;
975 0 : state.dataHVACDXHeatPumpSys->DXHeatPumpSystem(CoilSysNum).FaultyCoilSATIndex = jFault_CoilSAT;
976 : }
977 0 : } break;
978 0 : case CoilType::AirLoopHVACUnitarySystem: {
979 : // UnitarySystem model connects to FaultManager via function call to FaultsManager::SetFaultyCoilSATSensor
980 0 : } break;
981 0 : default:
982 0 : break;
983 : }
984 : } // End read faults input of Fault_type 113
985 :
986 : // read faults input of Cooling tower scaling
987 13 : for (int jFault_TowerFouling = 1; jFault_TowerFouling <= state.dataFaultsMgr->NumFaultyTowerFouling; ++jFault_TowerFouling) {
988 1 : auto &faultsTowerFouling = state.dataFaultsMgr->FaultsTowerFouling(jFault_TowerFouling);
989 :
990 1 : cFaultCurrentObject = cFaults(11); // fault object string
991 1 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
992 : cFaultCurrentObject,
993 : jFault_TowerFouling,
994 : cAlphaArgs,
995 : NumAlphas,
996 : rNumericArgs,
997 : NumNumbers,
998 : IOStatus,
999 : lNumericFieldBlanks,
1000 : lAlphaFieldBlanks,
1001 : cAlphaFieldNames,
1002 : cNumericFieldNames);
1003 :
1004 1 : ErrorObjectHeader eoh{routineName, cFaultCurrentObject, cAlphaArgs(1)};
1005 1 : faultsTowerFouling.type = FaultType::Fouling_Tower;
1006 1 : faultsTowerFouling.Name = cAlphaArgs(1);
1007 :
1008 : // Fault availability schedule
1009 1 : if (lAlphaFieldBlanks(2)) {
1010 1 : faultsTowerFouling.availSched = Sched::GetScheduleAlwaysOn(state); // returns schedule value of 1
1011 0 : } else if ((faultsTowerFouling.availSched = Sched::GetSchedule(state, cAlphaArgs(2))) == nullptr) {
1012 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(2), cAlphaArgs(2));
1013 0 : state.dataFaultsMgr->ErrorsFound = true;
1014 : }
1015 :
1016 : // Fault severity schedule
1017 1 : if (lAlphaFieldBlanks(3)) {
1018 1 : faultsTowerFouling.severitySched = Sched::GetScheduleAlwaysOn(state); // not an availability schedule, but defaults to constant-1.0
1019 0 : } else if ((faultsTowerFouling.severitySched = Sched::GetSchedule(state, cAlphaArgs(3))) == nullptr) {
1020 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(3), cAlphaArgs(3));
1021 0 : state.dataFaultsMgr->ErrorsFound = true;
1022 : }
1023 :
1024 : // UAReductionFactor - degree of fault
1025 1 : faultsTowerFouling.UAReductionFactor = rNumericArgs(1);
1026 :
1027 : // Cooling tower type
1028 1 : faultsTowerFouling.TowerType = cAlphaArgs(4);
1029 1 : if (lAlphaFieldBlanks(4)) {
1030 0 : ShowSevereError(
1031 0 : state, format("{} = \"{}\" invalid {} = \"{}\" blank.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(4), cAlphaArgs(4)));
1032 0 : state.dataFaultsMgr->ErrorsFound = true;
1033 : }
1034 :
1035 : // Cooling tower name
1036 1 : faultsTowerFouling.TowerName = cAlphaArgs(5);
1037 1 : if (lAlphaFieldBlanks(5)) {
1038 0 : ShowSevereError(
1039 0 : state, format("{} = \"{}\" invalid {} = \"{}\" blank.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(5), cAlphaArgs(5)));
1040 0 : state.dataFaultsMgr->ErrorsFound = true;
1041 : }
1042 :
1043 : // Tower check and link
1044 : {
1045 : // Read in tower input if not done yet
1046 1 : if (state.dataCondenserLoopTowers->GetInput) {
1047 0 : CondenserLoopTowers::GetTowerInput(state);
1048 0 : state.dataCondenserLoopTowers->GetInput = false;
1049 : }
1050 : // Check the tower name and tower type
1051 1 : int TowerNum = Util::FindItemInList(faultsTowerFouling.TowerName, state.dataCondenserLoopTowers->towers);
1052 1 : if (TowerNum <= 0) {
1053 0 : ShowSevereError(
1054 : state,
1055 0 : format("{} = \"{}\" invalid {} = \"{}\" not found.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(5), cAlphaArgs(5)));
1056 0 : state.dataFaultsMgr->ErrorsFound = true;
1057 : } else {
1058 : // Link the tower with the fault model
1059 1 : state.dataCondenserLoopTowers->towers(TowerNum).FaultyTowerFoulingFlag = true;
1060 1 : state.dataCondenserLoopTowers->towers(TowerNum).FaultyTowerFoulingIndex = jFault_TowerFouling;
1061 :
1062 : // Check the faulty tower type
1063 1 : if (!Util::SameString(DataPlant::PlantEquipTypeNames[static_cast<int>(state.dataCondenserLoopTowers->towers(TowerNum).TowerType)],
1064 : faultsTowerFouling.TowerType)) {
1065 0 : ShowWarningError(
1066 : state,
1067 0 : format("{} = \"{}\" invalid {} = \"{}\" not match the type of {}. Tower type in the fault model is updated. ",
1068 : cFaultCurrentObject,
1069 : cAlphaArgs(1),
1070 : cAlphaFieldNames(4),
1071 : cAlphaArgs(4),
1072 : cAlphaFieldNames(5)));
1073 : faultsTowerFouling.TowerType =
1074 0 : DataPlant::PlantEquipTypeNames[static_cast<int>(state.dataCondenserLoopTowers->towers(TowerNum).TowerType)];
1075 : }
1076 :
1077 : // Check the tower model
1078 : // Performance Input Method should be UFactorTimesAreaAndDesignWaterFlowRate to apply the fault model
1079 1 : if (state.dataCondenserLoopTowers->towers(TowerNum).PerformanceInputMethod_Num != CondenserLoopTowers::PIM::UFactor) {
1080 0 : ShowWarningError(
1081 : state,
1082 0 : format("{} = \"{}\" invalid {} = \"{}. Tower Performance Input Method is not UFactorTimesAreaAndDesignWaterFlowRate. The "
1083 : "tower fouling fault model will not be applied to the tower. ",
1084 : cFaultCurrentObject,
1085 : cAlphaArgs(1),
1086 : cAlphaFieldNames(5),
1087 : cAlphaFieldNames(5)));
1088 0 : state.dataCondenserLoopTowers->towers(TowerNum).FaultyTowerFoulingFlag = false;
1089 : }
1090 : }
1091 : }
1092 : }
1093 :
1094 : // read faults input of Condenser SWT Sensor Offset
1095 13 : for (int jFault_CondenserSWT = 1; jFault_CondenserSWT <= state.dataFaultsMgr->NumFaultyCondenserSWTSensor; ++jFault_CondenserSWT) {
1096 1 : auto &faultsCondSWTFouling = state.dataFaultsMgr->FaultsCondenserSWTSensor(jFault_CondenserSWT);
1097 :
1098 1 : cFaultCurrentObject = cFaults(10); // fault object string
1099 1 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1100 : cFaultCurrentObject,
1101 : jFault_CondenserSWT,
1102 : cAlphaArgs,
1103 : NumAlphas,
1104 : rNumericArgs,
1105 : NumNumbers,
1106 : IOStatus,
1107 : lNumericFieldBlanks,
1108 : lAlphaFieldBlanks,
1109 : cAlphaFieldNames,
1110 : cNumericFieldNames);
1111 :
1112 1 : ErrorObjectHeader eoh{routineName, cFaultCurrentObject, cAlphaArgs(1)};
1113 1 : faultsCondSWTFouling.type = FaultType::TemperatureSensorOffset_CondenserSupplyWater;
1114 1 : faultsCondSWTFouling.Name = cAlphaArgs(1);
1115 :
1116 : // Fault availability schedule
1117 1 : if (lAlphaFieldBlanks(2)) {
1118 1 : faultsCondSWTFouling.availSched = Sched::GetScheduleAlwaysOn(state); // returns schedule value of 1
1119 0 : } else if ((faultsCondSWTFouling.availSched = Sched::GetSchedule(state, cAlphaArgs(2))) == nullptr) {
1120 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(2), cAlphaArgs(2));
1121 0 : state.dataFaultsMgr->ErrorsFound = true;
1122 : }
1123 :
1124 : // Fault severity schedule
1125 1 : if (lAlphaFieldBlanks(3)) {
1126 1 : faultsCondSWTFouling.severitySched = Sched::GetScheduleAlwaysOn(state); // not an availability schedule, but defaults to constant-1.0
1127 0 : } else if ((faultsCondSWTFouling.severitySched = Sched::GetSchedule(state, cAlphaArgs(3))) == nullptr) {
1128 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(3), cAlphaArgs(3));
1129 0 : state.dataFaultsMgr->ErrorsFound = true;
1130 : }
1131 :
1132 : // offset - degree of fault
1133 1 : faultsCondSWTFouling.Offset = rNumericArgs(1);
1134 :
1135 : // Cooling tower type
1136 1 : faultsCondSWTFouling.TowerType = cAlphaArgs(4);
1137 1 : if (lAlphaFieldBlanks(4)) {
1138 0 : ShowSevereError(
1139 0 : state, format("{} = \"{}\" invalid {} = \"{}\" blank.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(4), cAlphaArgs(4)));
1140 0 : state.dataFaultsMgr->ErrorsFound = true;
1141 : }
1142 :
1143 : // Cooling tower name
1144 1 : faultsCondSWTFouling.TowerName = cAlphaArgs(5);
1145 1 : if (lAlphaFieldBlanks(5)) {
1146 0 : ShowSevereError(
1147 0 : state, format("{} = \"{}\" invalid {} = \"{}\" blank.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(5), cAlphaArgs(5)));
1148 0 : state.dataFaultsMgr->ErrorsFound = true;
1149 : }
1150 :
1151 : // Tower check and link
1152 : {
1153 : // Read in tower input if not done yet
1154 1 : if (state.dataCondenserLoopTowers->GetInput) {
1155 0 : CondenserLoopTowers::GetTowerInput(state);
1156 0 : state.dataCondenserLoopTowers->GetInput = false;
1157 : }
1158 : // Check the tower name and tower type
1159 1 : int TowerNum = Util::FindItemInList(faultsCondSWTFouling.TowerName, state.dataCondenserLoopTowers->towers);
1160 1 : if (TowerNum <= 0) {
1161 0 : ShowSevereError(
1162 : state,
1163 0 : format("{} = \"{}\" invalid {} = \"{}\" not found.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(5), cAlphaArgs(5)));
1164 0 : state.dataFaultsMgr->ErrorsFound = true;
1165 : } else {
1166 : // Link the tower with the fault model
1167 1 : state.dataCondenserLoopTowers->towers(TowerNum).FaultyCondenserSWTFlag = true;
1168 1 : state.dataCondenserLoopTowers->towers(TowerNum).FaultyCondenserSWTIndex = jFault_CondenserSWT;
1169 :
1170 : // Check the faulty tower type
1171 1 : if (!Util::SameString(DataPlant::PlantEquipTypeNames[static_cast<int>(state.dataCondenserLoopTowers->towers(TowerNum).TowerType)],
1172 : faultsCondSWTFouling.TowerType)) {
1173 0 : ShowWarningError(state,
1174 0 : format("{} = \"{}\" invalid {} = \"{}\" not match the type of {}. Tower type is updated. ",
1175 : cFaultCurrentObject,
1176 : cAlphaArgs(1),
1177 : cAlphaFieldNames(4),
1178 : cAlphaArgs(4),
1179 : cAlphaFieldNames(5)));
1180 : faultsCondSWTFouling.TowerType =
1181 0 : DataPlant::PlantEquipTypeNames[static_cast<int>(state.dataCondenserLoopTowers->towers(TowerNum).TowerType)];
1182 : }
1183 : }
1184 : }
1185 : }
1186 :
1187 : // read faults input of Chiller SWT Sensor Offset
1188 13 : for (int jFault_ChillerSWT = 1; jFault_ChillerSWT <= state.dataFaultsMgr->NumFaultyChillerSWTSensor; ++jFault_ChillerSWT) {
1189 1 : auto &faultsChillerSWT = state.dataFaultsMgr->FaultsChillerSWTSensor(jFault_ChillerSWT);
1190 :
1191 1 : cFaultCurrentObject = cFaults(9); // fault object string
1192 1 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1193 : cFaultCurrentObject,
1194 : jFault_ChillerSWT,
1195 : cAlphaArgs,
1196 : NumAlphas,
1197 : rNumericArgs,
1198 : NumNumbers,
1199 : IOStatus,
1200 : lNumericFieldBlanks,
1201 : lAlphaFieldBlanks,
1202 : cAlphaFieldNames,
1203 : cNumericFieldNames);
1204 :
1205 1 : ErrorObjectHeader eoh{routineName, cFaultCurrentObject, cAlphaArgs(1)};
1206 1 : faultsChillerSWT.type = FaultType::TemperatureSensorOffset_ChillerSupplyWater;
1207 1 : faultsChillerSWT.Name = cAlphaArgs(1);
1208 :
1209 : // Fault availability schedule
1210 1 : if (lAlphaFieldBlanks(2)) {
1211 1 : faultsChillerSWT.availSched = Sched::GetScheduleAlwaysOn(state); // returns schedule value of 1
1212 0 : } else if ((faultsChillerSWT.availSched = Sched::GetSchedule(state, cAlphaArgs(2))) == nullptr) {
1213 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(2), cAlphaArgs(2));
1214 0 : state.dataFaultsMgr->ErrorsFound = true;
1215 : }
1216 :
1217 : // Fault severity schedule
1218 1 : if (lAlphaFieldBlanks(3)) {
1219 1 : faultsChillerSWT.severitySched = Sched::GetScheduleAlwaysOn(state); // not an availability schedule, but defaults to constant-1.0
1220 0 : } else if ((faultsChillerSWT.severitySched = Sched::GetSchedule(state, cAlphaArgs(3))) == nullptr) {
1221 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(3), cAlphaArgs(3));
1222 0 : state.dataFaultsMgr->ErrorsFound = true;
1223 : }
1224 :
1225 : // offset - degree of fault
1226 1 : faultsChillerSWT.Offset = rNumericArgs(1);
1227 :
1228 : // Chiller type
1229 1 : faultsChillerSWT.ChillerType = cAlphaArgs(4);
1230 1 : if (lAlphaFieldBlanks(4)) {
1231 0 : ShowSevereError(
1232 0 : state, format("{} = \"{}\" invalid {} = \"{}\" blank.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(4), cAlphaArgs(4)));
1233 0 : state.dataFaultsMgr->ErrorsFound = true;
1234 : }
1235 :
1236 : // Chiller name
1237 1 : faultsChillerSWT.ChillerName = cAlphaArgs(5);
1238 1 : if (lAlphaFieldBlanks(5)) {
1239 0 : ShowSevereError(
1240 0 : state, format("{} = \"{}\" invalid {} = \"{}\" blank.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(5), cAlphaArgs(5)));
1241 0 : state.dataFaultsMgr->ErrorsFound = true;
1242 : }
1243 :
1244 : // Chiller check
1245 : int ChillerNum;
1246 1 : ChillerType ChillerTypeCheck = static_cast<ChillerType>(getEnumValue(ChillerTypeNamesUC, Util::makeUPPER(faultsChillerSWT.ChillerType)));
1247 1 : switch (ChillerTypeCheck) {
1248 0 : case ChillerType::ChillerElectric: {
1249 : // Check whether the chiller name and chiller type match each other
1250 0 : ChillerNum = 0;
1251 0 : int thisChil = 0;
1252 0 : for (auto const &ch : state.dataPlantChillers->ElectricChiller) {
1253 0 : thisChil++;
1254 0 : if (ch.Name == faultsChillerSWT.ChillerName) {
1255 0 : ChillerNum = thisChil;
1256 : }
1257 0 : }
1258 0 : if (ChillerNum <= 0) {
1259 0 : ShowSevereError(
1260 : state,
1261 0 : format("{} = \"{}\" invalid {} = \"{}\" not found.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(5), cAlphaArgs(5)));
1262 0 : state.dataFaultsMgr->ErrorsFound = true;
1263 : } else {
1264 : // Link the chiller with the fault model
1265 0 : state.dataPlantChillers->ElectricChiller(ChillerNum).FaultyChillerSWTFlag = true;
1266 0 : state.dataPlantChillers->ElectricChiller(ChillerNum).FaultyChillerSWTIndex = jFault_ChillerSWT;
1267 : }
1268 0 : } break;
1269 0 : case ChillerType::ChillerElectricEIR: {
1270 : // Read in chiller if not done yet
1271 0 : if (state.dataChillerElectricEIR->getInputFlag) {
1272 0 : ChillerElectricEIR::GetElectricEIRChillerInput(state);
1273 0 : state.dataChillerElectricEIR->getInputFlag = false;
1274 : }
1275 : // Check whether the chiller name and chiller type match each other
1276 0 : ChillerNum = Util::FindItemInList(faultsChillerSWT.ChillerName, state.dataChillerElectricEIR->ElectricEIRChiller);
1277 0 : if (ChillerNum <= 0) {
1278 0 : ShowSevereError(
1279 : state,
1280 0 : format("{} = \"{}\" invalid {} = \"{}\" not found.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(5), cAlphaArgs(5)));
1281 0 : state.dataFaultsMgr->ErrorsFound = true;
1282 : } else {
1283 : // Link the chiller with the fault model
1284 0 : state.dataChillerElectricEIR->ElectricEIRChiller(ChillerNum).FaultyChillerSWTFlag = true;
1285 0 : state.dataChillerElectricEIR->ElectricEIRChiller(ChillerNum).FaultyChillerSWTIndex = jFault_ChillerSWT;
1286 : }
1287 0 : } break;
1288 1 : case ChillerType::ChillerElectricReformulatedEIR: {
1289 : // Read in chiller if not done yet
1290 1 : if (state.dataChillerReformulatedEIR->GetInputREIR) {
1291 0 : ChillerReformulatedEIR::GetElecReformEIRChillerInput(state);
1292 0 : state.dataChillerReformulatedEIR->GetInputREIR = false;
1293 : }
1294 : // Check whether the chiller name and chiller type match each other
1295 1 : ChillerNum = Util::FindItemInList(faultsChillerSWT.ChillerName, state.dataChillerReformulatedEIR->ElecReformEIRChiller);
1296 1 : if (ChillerNum <= 0) {
1297 0 : ShowSevereError(
1298 : state,
1299 0 : format("{} = \"{}\" invalid {} = \"{}\" not found.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(5), cAlphaArgs(5)));
1300 0 : state.dataFaultsMgr->ErrorsFound = true;
1301 : } else {
1302 : // Link the chiller with the fault model
1303 1 : state.dataChillerReformulatedEIR->ElecReformEIRChiller(ChillerNum).FaultyChillerSWTFlag = true;
1304 1 : state.dataChillerReformulatedEIR->ElecReformEIRChiller(ChillerNum).FaultyChillerSWTIndex = jFault_ChillerSWT;
1305 : }
1306 1 : } break;
1307 0 : case ChillerType::ChillerEngineDriven: {
1308 : // Check whether the chiller name and chiller type match each other
1309 0 : ChillerNum = 0;
1310 0 : int thisChil = 0;
1311 0 : for (auto const &ch : state.dataPlantChillers->EngineDrivenChiller) {
1312 0 : thisChil++;
1313 0 : if (ch.Name == faultsChillerSWT.ChillerName) {
1314 0 : ChillerNum = thisChil;
1315 : }
1316 0 : }
1317 0 : if (ChillerNum <= 0) {
1318 0 : ShowSevereError(
1319 : state,
1320 0 : format("{} = \"{}\" invalid {} = \"{}\" not found.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(5), cAlphaArgs(5)));
1321 0 : state.dataFaultsMgr->ErrorsFound = true;
1322 : } else {
1323 : // Link the chiller with the fault model
1324 0 : state.dataPlantChillers->EngineDrivenChiller(ChillerNum).FaultyChillerSWTFlag = true;
1325 0 : state.dataPlantChillers->EngineDrivenChiller(ChillerNum).FaultyChillerSWTIndex = jFault_ChillerSWT;
1326 : }
1327 0 : } break;
1328 0 : case ChillerType::ChillerCombustionTurbine: {
1329 0 : ChillerNum = 0;
1330 0 : int thisChil = 0;
1331 0 : for (auto const &ch : state.dataPlantChillers->GTChiller) {
1332 0 : thisChil++;
1333 0 : if (ch.Name == faultsChillerSWT.ChillerName) {
1334 0 : ChillerNum = thisChil;
1335 : }
1336 0 : }
1337 0 : if (ChillerNum <= 0) {
1338 0 : ShowSevereError(
1339 : state,
1340 0 : format("{} = \"{}\" invalid {} = \"{}\" not found.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(5), cAlphaArgs(5)));
1341 0 : state.dataFaultsMgr->ErrorsFound = true;
1342 : } else {
1343 : // Link the chiller with the fault model
1344 0 : state.dataPlantChillers->GTChiller(ChillerNum).FaultyChillerSWTFlag = true;
1345 0 : state.dataPlantChillers->GTChiller(ChillerNum).FaultyChillerSWTIndex = jFault_ChillerSWT;
1346 : }
1347 0 : } break;
1348 0 : case ChillerType::ChillerConstantCOP: {
1349 0 : ChillerNum = 0;
1350 0 : int thisChil = 0;
1351 0 : for (auto const &ch : state.dataPlantChillers->ConstCOPChiller) {
1352 0 : thisChil++;
1353 0 : if (ch.Name == faultsChillerSWT.ChillerName) {
1354 0 : ChillerNum = thisChil;
1355 : }
1356 0 : }
1357 0 : if (ChillerNum <= 0) {
1358 0 : ShowSevereError(
1359 : state,
1360 0 : format("{} = \"{}\" invalid {} = \"{}\" not found.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(5), cAlphaArgs(5)));
1361 0 : state.dataFaultsMgr->ErrorsFound = true;
1362 : } else {
1363 : // Link the chiller with the fault model
1364 0 : state.dataPlantChillers->ConstCOPChiller(ChillerNum).FaultyChillerSWTFlag = true;
1365 0 : state.dataPlantChillers->ConstCOPChiller(ChillerNum).FaultyChillerSWTIndex = jFault_ChillerSWT;
1366 : }
1367 0 : } break;
1368 0 : case ChillerType::ChillerAbsorption: {
1369 : // Read in chiller if not done yet
1370 0 : if (state.dataChillerAbsorber->getInput) {
1371 0 : ChillerAbsorption::GetBLASTAbsorberInput(state);
1372 0 : state.dataChillerAbsorber->getInput = false;
1373 : }
1374 : // Check whether the chiller name and chiller type match each other
1375 0 : ChillerNum = Util::FindItemInList(faultsChillerSWT.ChillerName, state.dataChillerAbsorber->absorptionChillers);
1376 0 : if (ChillerNum <= 0) {
1377 0 : ShowSevereError(
1378 : state,
1379 0 : format("{} = \"{}\" invalid {} = \"{}\" not found.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(5), cAlphaArgs(5)));
1380 0 : state.dataFaultsMgr->ErrorsFound = true;
1381 : } else {
1382 : // Link the chiller with the fault model
1383 0 : state.dataChillerAbsorber->absorptionChillers(ChillerNum).FaultyChillerSWTFlag = true;
1384 0 : state.dataChillerAbsorber->absorptionChillers(ChillerNum).FaultyChillerSWTIndex = jFault_ChillerSWT;
1385 : }
1386 0 : } break;
1387 0 : case ChillerType::ChillerAbsorptionIndirect: {
1388 : // Read in chiller if not done yet
1389 0 : if (state.dataChillerIndirectAbsorption->GetInput) {
1390 0 : ChillerIndirectAbsorption::GetIndirectAbsorberInput(state);
1391 0 : state.dataChillerIndirectAbsorption->GetInput = false;
1392 : }
1393 : // Check whether the chiller name and chiller type match each other
1394 0 : ChillerNum = Util::FindItemInList(faultsChillerSWT.ChillerName, state.dataChillerIndirectAbsorption->IndirectAbsorber);
1395 0 : if (ChillerNum <= 0) {
1396 0 : ShowSevereError(
1397 : state,
1398 0 : format("{} = \"{}\" invalid {} = \"{}\" not found.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(5), cAlphaArgs(5)));
1399 0 : state.dataFaultsMgr->ErrorsFound = true;
1400 : } else {
1401 0 : state.dataChillerIndirectAbsorption->IndirectAbsorber(ChillerNum).FaultyChillerSWTFlag = true;
1402 0 : state.dataChillerIndirectAbsorption->IndirectAbsorber(ChillerNum).FaultyChillerSWTIndex = jFault_ChillerSWT;
1403 : }
1404 0 : } break;
1405 0 : default:
1406 0 : break;
1407 : }
1408 : }
1409 :
1410 : // read faults input of Fouled Air Filters
1411 13 : for (int jFault_AirFilter = 1; jFault_AirFilter <= state.dataFaultsMgr->NumFaultyAirFilter; ++jFault_AirFilter) {
1412 1 : auto &faultsAirFilter = state.dataFaultsMgr->FaultsFouledAirFilters(jFault_AirFilter);
1413 :
1414 : // Read in fan if not done yet
1415 1 : if (state.dataFans->GetFanInputFlag) {
1416 0 : Fans::GetFanInput(state);
1417 : }
1418 :
1419 1 : cFaultCurrentObject = cFaults(8); // fault object string
1420 1 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1421 : cFaultCurrentObject,
1422 : jFault_AirFilter,
1423 : cAlphaArgs,
1424 : NumAlphas,
1425 : rNumericArgs,
1426 : NumNumbers,
1427 : IOStatus,
1428 : lNumericFieldBlanks,
1429 : lAlphaFieldBlanks,
1430 : cAlphaFieldNames,
1431 : cNumericFieldNames);
1432 :
1433 1 : ErrorObjectHeader eoh{routineName, cFaultCurrentObject, cAlphaArgs(1)};
1434 1 : faultsAirFilter.type = FaultType::Fouling_AirFilter;
1435 1 : faultsAirFilter.Name = cAlphaArgs(1);
1436 :
1437 : // Information of the fan associated with the fouling air filter
1438 1 : faultsAirFilter.fanType = static_cast<HVAC::FanType>(getEnumValue(HVAC::fanTypeNamesUC, cAlphaArgs(2)));
1439 1 : if (faultsAirFilter.fanType == HVAC::FanType::SystemModel) {
1440 0 : ShowSevereError(state, "Fault:AirFilter cannot be applied to a Fan:SystemModel object");
1441 0 : state.dataFaultsMgr->ErrorsFound = true;
1442 : }
1443 :
1444 1 : faultsAirFilter.fanName = cAlphaArgs(3);
1445 :
1446 : // Check whether the specified fan exists in the fan list
1447 1 : if ((faultsAirFilter.fanNum = Fans::GetFanIndex(state, cAlphaArgs(3))) == 0) {
1448 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(3), cAlphaArgs(3));
1449 0 : state.dataFaultsMgr->ErrorsFound = true;
1450 : } else {
1451 1 : auto *fanComp = dynamic_cast<Fans::FanComponent *>(state.dataFans->fans(faultsAirFilter.fanNum));
1452 1 : assert(fanComp != nullptr);
1453 :
1454 1 : fanComp->faultyFilterFlag = true;
1455 1 : fanComp->faultyFilterIndex = jFault_AirFilter;
1456 : }
1457 :
1458 : // Fault availability schedule
1459 1 : if (lAlphaFieldBlanks(4)) {
1460 0 : faultsAirFilter.availSched = Sched::GetScheduleAlwaysOn(state); // returns schedule value of 1
1461 1 : } else if ((faultsAirFilter.availSched = Sched::GetSchedule(state, cAlphaArgs(4))) == nullptr) {
1462 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(4), cAlphaArgs(4));
1463 0 : state.dataFaultsMgr->ErrorsFound = true;
1464 : }
1465 :
1466 : // Fan pressure increase fraction schedule
1467 1 : if (lAlphaFieldBlanks(5)) {
1468 0 : faultsAirFilter.pressFracSched = Sched::GetScheduleAlwaysOn(state); // not an availability schedule, but defaults to constant-1.0
1469 1 : } else if ((faultsAirFilter.pressFracSched = Sched::GetSchedule(state, cAlphaArgs(5))) == nullptr) {
1470 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(5), cAlphaArgs(5));
1471 0 : state.dataFaultsMgr->ErrorsFound = true;
1472 : }
1473 :
1474 : // Fan curve describing the relationship between fan pressure rise and air flow rate
1475 :
1476 1 : if ((faultsAirFilter.fanCurveNum = Curve::GetCurveIndex(state, cAlphaArgs(6))) == 0) {
1477 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(6), cAlphaArgs(6));
1478 0 : state.dataFaultsMgr->ErrorsFound = true;
1479 : }
1480 :
1481 : // Checking whether the specified fan curve covers the **design** operational point of the fan cannot be done here
1482 : // as the fan might be autosized and is not sized yet, so we call it in Fan::SizeFan instead
1483 :
1484 : // In the fan object, calculate by each time-step: 1) pressure increase value; 2) air flow rate decrease value.
1485 : }
1486 :
1487 : // read faults input of HumidistatOffset
1488 14 : for (int jFault_Humidistat = 1; jFault_Humidistat <= state.dataFaultsMgr->NumFaultyHumidistat; ++jFault_Humidistat) {
1489 2 : auto &faultsHStat = state.dataFaultsMgr->FaultsHumidistatOffset(jFault_Humidistat);
1490 :
1491 2 : cFaultCurrentObject = cFaults(7); // fault object string
1492 2 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1493 : cFaultCurrentObject,
1494 : jFault_Humidistat,
1495 : cAlphaArgs,
1496 : NumAlphas,
1497 : rNumericArgs,
1498 : NumNumbers,
1499 : IOStatus,
1500 : lNumericFieldBlanks,
1501 : lAlphaFieldBlanks,
1502 : cAlphaFieldNames,
1503 : cNumericFieldNames);
1504 :
1505 2 : ErrorObjectHeader eoh{routineName, cFaultCurrentObject, cAlphaArgs(1)};
1506 2 : faultsHStat.type = FaultType::HumidistatOffset;
1507 2 : faultsHStat.Name = cAlphaArgs(1);
1508 2 : faultsHStat.FaultyHumidistatName = cAlphaArgs(2);
1509 2 : faultsHStat.FaultyHumidistatType = cAlphaArgs(3);
1510 :
1511 2 : if (Util::SameString(faultsHStat.FaultyHumidistatType, "ThermostatOffsetDependent")) {
1512 : // For Humidistat Offset Type: ThermostatOffsetDependent
1513 :
1514 : // Related Thermostat Offset Fault Name is required for Humidistat Offset Type: ThermostatOffsetDependent
1515 1 : if (lAlphaFieldBlanks(6)) {
1516 0 : ShowSevereError(state,
1517 0 : format("{} = \"{}\": {} cannot be blank for Humidistat Offset Type = \"ThermostatOffsetDependent\".",
1518 : cFaultCurrentObject,
1519 : cAlphaArgs(1),
1520 : cAlphaFieldNames(6)));
1521 0 : state.dataFaultsMgr->ErrorsFound = true;
1522 : } else {
1523 1 : faultsHStat.FaultyThermostatName = cAlphaArgs(6);
1524 : }
1525 :
1526 : } else {
1527 : // For Humidistat Offset Type: ThermostatOffsetIndependent
1528 :
1529 : // Availability schedule
1530 1 : if (lAlphaFieldBlanks(4)) {
1531 1 : faultsHStat.availSched = Sched::GetScheduleAlwaysOn(state); // returns schedule value of 1
1532 0 : } else if ((faultsHStat.availSched = Sched::GetSchedule(state, cAlphaArgs(4))) == nullptr) {
1533 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(4), cAlphaArgs(4));
1534 0 : state.dataFaultsMgr->ErrorsFound = true;
1535 : }
1536 :
1537 : // Severity schedule
1538 1 : if (lAlphaFieldBlanks(5)) {
1539 1 : faultsHStat.severitySched = Sched::GetScheduleAlwaysOn(state); // not an availability schedule, but defaults to constant-1.0
1540 0 : } else if ((faultsHStat.severitySched = Sched::GetSchedule(state, cAlphaArgs(5))) == nullptr) {
1541 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(5), cAlphaArgs(5));
1542 0 : state.dataFaultsMgr->ErrorsFound = true;
1543 : }
1544 :
1545 : // Reference offset value is required for Humidistat Offset Type: ThermostatOffsetIndependent
1546 1 : if (lAlphaFieldBlanks(1)) {
1547 0 : ShowSevereError(state,
1548 0 : format("{} = \"{}\": {} cannot be blank for Humidistat Offset Type = \"ThermostatOffsetIndependent\".",
1549 : cFaultCurrentObject,
1550 : cAlphaArgs(1),
1551 : cNumericFieldNames(1)));
1552 0 : state.dataFaultsMgr->ErrorsFound = true;
1553 : } else {
1554 1 : faultsHStat.Offset = rNumericArgs(1);
1555 : }
1556 : }
1557 : }
1558 :
1559 : // read faults input of ThermostatOffset
1560 28 : for (int jFault_Thermostat = 1; jFault_Thermostat <= state.dataFaultsMgr->NumFaultyThermostat; ++jFault_Thermostat) {
1561 16 : auto &faultsTStat = state.dataFaultsMgr->FaultsThermostatOffset(jFault_Thermostat);
1562 :
1563 16 : cFaultCurrentObject = cFaults(6); // fault object string
1564 16 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1565 : cFaultCurrentObject,
1566 : jFault_Thermostat,
1567 : cAlphaArgs,
1568 : NumAlphas,
1569 : rNumericArgs,
1570 : NumNumbers,
1571 : IOStatus,
1572 : lNumericFieldBlanks,
1573 : lAlphaFieldBlanks,
1574 : cAlphaFieldNames,
1575 : cNumericFieldNames);
1576 :
1577 16 : ErrorObjectHeader eoh{routineName, cFaultCurrentObject, cAlphaArgs(1)};
1578 16 : faultsTStat.type = FaultType::ThermostatOffset;
1579 16 : faultsTStat.Name = cAlphaArgs(1);
1580 16 : faultsTStat.FaultyThermostatName = cAlphaArgs(2);
1581 :
1582 : // Availability schedule
1583 16 : if (lAlphaFieldBlanks(3)) {
1584 16 : faultsTStat.availSched = Sched::GetScheduleAlwaysOn(state); // returns schedule value of 1
1585 0 : } else if ((faultsTStat.availSched = Sched::GetSchedule(state, cAlphaArgs(3))) == nullptr) {
1586 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(3), cAlphaArgs(3));
1587 0 : state.dataFaultsMgr->ErrorsFound = true;
1588 : }
1589 :
1590 : // Severity schedule
1591 16 : if (lAlphaFieldBlanks(4)) {
1592 16 : faultsTStat.severitySched = Sched::GetScheduleAlwaysOn(state); // not an availability schedule, but defaults to constant-1.0
1593 0 : } else if ((faultsTStat.severitySched = Sched::GetSchedule(state, cAlphaArgs(4))) == nullptr) {
1594 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(4), cAlphaArgs(4));
1595 0 : state.dataFaultsMgr->ErrorsFound = true;
1596 : }
1597 :
1598 : // Reference offset value is required
1599 16 : if (lAlphaFieldBlanks(1)) {
1600 0 : ShowSevereError(state, format("{} = \"{}\" cannot be blank.", cFaultCurrentObject, cNumericFieldNames(1)));
1601 0 : state.dataFaultsMgr->ErrorsFound = true;
1602 : } else {
1603 16 : faultsTStat.Offset = rNumericArgs(1);
1604 : }
1605 : }
1606 :
1607 : // read faults input of Fouling_Coil
1608 14 : for (int jFault_FoulingCoil = 1; jFault_FoulingCoil <= state.dataFaultsMgr->NumFouledCoil; ++jFault_FoulingCoil) {
1609 2 : auto &faultsFoulCoil = state.dataFaultsMgr->FouledCoils(jFault_FoulingCoil);
1610 :
1611 2 : cFaultCurrentObject = cFaults(5); // fault object string
1612 2 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1613 : cFaultCurrentObject,
1614 : jFault_FoulingCoil,
1615 : cAlphaArgs,
1616 : NumAlphas,
1617 : rNumericArgs,
1618 : NumNumbers,
1619 : IOStatus,
1620 : lNumericFieldBlanks,
1621 : lAlphaFieldBlanks,
1622 : cAlphaFieldNames,
1623 : cNumericFieldNames);
1624 :
1625 2 : ErrorObjectHeader eoh{routineName, cFaultCurrentObject, cAlphaArgs(1)};
1626 2 : faultsFoulCoil.type = FaultType::Fouling_Coil;
1627 2 : faultsFoulCoil.Name = cAlphaArgs(1);
1628 2 : faultsFoulCoil.FouledCoilName = cAlphaArgs(2);
1629 :
1630 : // Availability schedule
1631 2 : if (lAlphaFieldBlanks(3)) {
1632 0 : faultsFoulCoil.availSched = Sched::GetScheduleAlwaysOn(state); // returns schedule value of 1
1633 2 : } else if ((faultsFoulCoil.availSched = Sched::GetSchedule(state, cAlphaArgs(3))) == nullptr) {
1634 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(3), cAlphaArgs(3));
1635 0 : state.dataFaultsMgr->ErrorsFound = true;
1636 : }
1637 :
1638 : // Severity schedule
1639 2 : if (lAlphaFieldBlanks(4)) {
1640 0 : faultsFoulCoil.severitySched = Sched::GetScheduleAlwaysOn(state); // not an availability schedule, but defaults to constant-1.0
1641 2 : } else if ((faultsFoulCoil.severitySched = Sched::GetSchedule(state, cAlphaArgs(4))) == nullptr) {
1642 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(4), cAlphaArgs(4));
1643 0 : state.dataFaultsMgr->ErrorsFound = true;
1644 : }
1645 :
1646 2 : faultsFoulCoil.FoulingInputMethod = static_cast<FouledCoil>(getEnumValue(FouledCoilNamesUC, Util::makeUPPER(cAlphaArgs(5))));
1647 2 : if (faultsFoulCoil.FoulingInputMethod == FouledCoil::Invalid) {
1648 0 : faultsFoulCoil.FoulingInputMethod = FouledCoil::UARated;
1649 : }
1650 :
1651 2 : faultsFoulCoil.UAFouled = rNumericArgs(1);
1652 2 : faultsFoulCoil.Rfw = rNumericArgs(2);
1653 2 : faultsFoulCoil.Rfa = rNumericArgs(3);
1654 2 : faultsFoulCoil.Aout = rNumericArgs(4);
1655 2 : faultsFoulCoil.Aratio = rNumericArgs(5);
1656 :
1657 : // Coil check and link
1658 : {
1659 : // Obtains and Allocates WaterCoil related parameters from input file
1660 2 : if (state.dataWaterCoils->GetWaterCoilsInputFlag) {
1661 0 : WaterCoils::GetWaterCoilInput(state);
1662 0 : state.dataWaterCoils->GetWaterCoilsInputFlag = false;
1663 : }
1664 :
1665 : // Check the coil name and type
1666 2 : int CoilNum = Util::FindItemInList(faultsFoulCoil.FouledCoilName, state.dataWaterCoils->WaterCoil);
1667 2 : if (CoilNum <= 0) {
1668 0 : ShowSevereError(state,
1669 0 : format("{} = \"{}\". Referenced Coil named \"{}\" was not found.",
1670 : cFaultCurrentObject,
1671 : cAlphaArgs(1),
1672 0 : faultsFoulCoil.FouledCoilName));
1673 0 : state.dataFaultsMgr->ErrorsFound = true;
1674 : } else {
1675 : // Coil is found: check if the right type
1676 3 : if ((state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating) ||
1677 1 : (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterCooling)) {
1678 : // Link the Coil with the fault model
1679 2 : state.dataWaterCoils->WaterCoil(CoilNum).FaultyCoilFoulingFlag = true;
1680 2 : state.dataWaterCoils->WaterCoil(CoilNum).FaultyCoilFoulingIndex = jFault_FoulingCoil;
1681 :
1682 2 : faultsFoulCoil.FouledCoilType = state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType;
1683 2 : faultsFoulCoil.FouledCoilNum = CoilNum;
1684 :
1685 4 : SetupOutputVariable(state,
1686 : "Coil Fouling Factor",
1687 : Constant::Units::K_W,
1688 2 : state.dataWaterCoils->WaterCoil(CoilNum).FaultyCoilFoulingFactor,
1689 : OutputProcessor::TimeStepType::System,
1690 : OutputProcessor::StoreType::Average,
1691 2 : state.dataWaterCoils->WaterCoil(CoilNum).Name);
1692 :
1693 : // Coil:Cooling:Water doesn't report UA because it's not variable,
1694 : // but here, it's useful since we do change it via fouling, so report it
1695 2 : if (state.dataWaterCoils->WaterCoil(CoilNum).WaterCoilType == DataPlant::PlantEquipmentType::CoilWaterCooling) {
1696 2 : SetupOutputVariable(state,
1697 : "Cooling Coil Total U Factor Times Area Value",
1698 : Constant::Units::W_K,
1699 1 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilTotal,
1700 : OutputProcessor::TimeStepType::System,
1701 : OutputProcessor::StoreType::Average,
1702 1 : state.dataWaterCoils->WaterCoil(CoilNum).Name);
1703 :
1704 2 : SetupOutputVariable(state,
1705 : "Cooling Coil External U Factor Times Area Value",
1706 : Constant::Units::W_K,
1707 1 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilExternal,
1708 : OutputProcessor::TimeStepType::System,
1709 : OutputProcessor::StoreType::Average,
1710 1 : state.dataWaterCoils->WaterCoil(CoilNum).Name);
1711 :
1712 2 : SetupOutputVariable(state,
1713 : "Cooling Coil Internal U Factor Times Area Value",
1714 : Constant::Units::W_K,
1715 1 : state.dataWaterCoils->WaterCoil(CoilNum).UACoilInternal,
1716 : OutputProcessor::TimeStepType::System,
1717 : OutputProcessor::StoreType::Average,
1718 1 : state.dataWaterCoils->WaterCoil(CoilNum).Name);
1719 :
1720 2 : SetupOutputVariable(state,
1721 : "Cooling Coil Total U Factor Times Area Value Before Fouling",
1722 : Constant::Units::W_K,
1723 1 : state.dataWaterCoils->WaterCoil(CoilNum).OriginalUACoilVariable,
1724 : OutputProcessor::TimeStepType::System,
1725 : OutputProcessor::StoreType::Average,
1726 1 : state.dataWaterCoils->WaterCoil(CoilNum).Name);
1727 :
1728 2 : SetupOutputVariable(state,
1729 : "Cooling Coil External U Factor Times Area Value Before Fouling",
1730 : Constant::Units::W_K,
1731 1 : state.dataWaterCoils->WaterCoil(CoilNum).OriginalUACoilExternal,
1732 : OutputProcessor::TimeStepType::System,
1733 : OutputProcessor::StoreType::Average,
1734 1 : state.dataWaterCoils->WaterCoil(CoilNum).Name);
1735 :
1736 2 : SetupOutputVariable(state,
1737 : "Cooling Coil Internal U Factor Times Area Value Before Fouling",
1738 : Constant::Units::W_K,
1739 1 : state.dataWaterCoils->WaterCoil(CoilNum).OriginalUACoilInternal,
1740 : OutputProcessor::TimeStepType::System,
1741 : OutputProcessor::StoreType::Average,
1742 1 : state.dataWaterCoils->WaterCoil(CoilNum).Name);
1743 :
1744 : } else {
1745 2 : SetupOutputVariable(state,
1746 : "Heating Coil U Factor Times Area Value Before Fouling",
1747 : Constant::Units::W_K,
1748 1 : state.dataWaterCoils->WaterCoil(CoilNum).OriginalUACoilVariable,
1749 : OutputProcessor::TimeStepType::System,
1750 : OutputProcessor::StoreType::Average,
1751 1 : state.dataWaterCoils->WaterCoil(CoilNum).Name);
1752 : }
1753 : } else {
1754 0 : ShowSevereError(
1755 : state,
1756 0 : format("{} = \"{}\" invalid {} = \"{}\".", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(2), cAlphaArgs(2)));
1757 0 : ShowContinueError(
1758 : state, R"(Coil was found but it is not one of the supported types ("Coil:Cooling:Water" or "Coil:Heating:Water").)");
1759 0 : state.dataFaultsMgr->ErrorsFound = true;
1760 : }
1761 : }
1762 : }
1763 : }
1764 :
1765 : // read faults input: Fault_type 0 to 4, which are related with economizer sensors
1766 72 : for (int j = 0, i = 0; i <= 4; ++i) {
1767 60 : cFaultCurrentObject = cFaults(i); // fault object string
1768 60 : int NumFaultsTemp = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cFaultCurrentObject);
1769 :
1770 65 : for (int jj = 1; jj <= NumFaultsTemp; ++jj) {
1771 5 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1772 : cFaultCurrentObject,
1773 : jj,
1774 : cAlphaArgs,
1775 : NumAlphas,
1776 : rNumericArgs,
1777 : NumNumbers,
1778 : IOStatus,
1779 : lNumericFieldBlanks,
1780 : lAlphaFieldBlanks,
1781 : cAlphaFieldNames,
1782 : cNumericFieldNames);
1783 :
1784 5 : ErrorObjectHeader eoh{routineName, cFaultCurrentObject, cAlphaArgs(1)};
1785 :
1786 5 : ++j;
1787 5 : auto &fault = state.dataFaultsMgr->FaultsEconomizer(j);
1788 5 : fault.type = static_cast<FaultType>(i);
1789 :
1790 5 : fault.Name = cAlphaArgs(1);
1791 :
1792 : // check availability schedule
1793 5 : if (lAlphaFieldBlanks(2)) {
1794 2 : fault.availSched = Sched::GetScheduleAlwaysOn(state); // returns schedule value of 1
1795 3 : } else if ((fault.availSched = Sched::GetSchedule(state, cAlphaArgs(2))) == nullptr) {
1796 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(2), cAlphaArgs(2));
1797 0 : state.dataFaultsMgr->ErrorsFound = true;
1798 : }
1799 :
1800 : // check severity schedule
1801 5 : if (lAlphaFieldBlanks(3)) {
1802 4 : fault.severitySched = Sched::GetScheduleAlwaysOn(state); // not an availability schedule, but defaults to constant-1.0
1803 1 : } else if ((fault.severitySched = Sched::GetSchedule(state, cAlphaArgs(3))) == nullptr) {
1804 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(3), cAlphaArgs(3));
1805 0 : state.dataFaultsMgr->ErrorsFound = true;
1806 : }
1807 :
1808 5 : fault.ControllerType = cAlphaArgs(4);
1809 : // check controller type
1810 5 : if (lAlphaFieldBlanks(4)) {
1811 0 : ShowSevereError(
1812 : state,
1813 0 : format("{} = \"{}\" invalid {} = \"{}\" blank.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(4), cAlphaArgs(4)));
1814 0 : state.dataFaultsMgr->ErrorsFound = true;
1815 : } else {
1816 5 : if (Util::makeUPPER(cAlphaArgs(4)) == "CONTROLLER:OUTDOORAIR") {
1817 5 : fault.ControllerTypeEnum = iController_AirEconomizer;
1818 :
1819 : // CASE ...
1820 :
1821 : } else {
1822 : }
1823 : }
1824 :
1825 5 : state.dataFaultsMgr->FaultsEconomizer(j).ControllerName = cAlphaArgs(5);
1826 : // check controller name
1827 5 : if (lAlphaFieldBlanks(5)) {
1828 0 : ShowSevereError(
1829 : state,
1830 0 : format("{} = \"{}\" invalid {} = \"{}\" blank.", cFaultCurrentObject, cAlphaArgs(1), cAlphaFieldNames(5), cAlphaArgs(5)));
1831 0 : state.dataFaultsMgr->ErrorsFound = true;
1832 : }
1833 :
1834 : // offset - degree of fault
1835 5 : state.dataFaultsMgr->FaultsEconomizer(j).Offset = rNumericArgs(1);
1836 : }
1837 : }
1838 :
1839 12 : state.dataFaultsMgr->RunFaultMgrOnceFlag = true;
1840 :
1841 12 : if (state.dataFaultsMgr->ErrorsFound) {
1842 0 : ShowFatalError(state, "CheckAndReadFaults: Errors found in getting FaultModel input data. Preceding condition(s) cause termination.");
1843 : }
1844 8419 : }
1845 :
1846 54077 : Real64 FaultProperties::CalFaultOffsetAct([[maybe_unused]] EnergyPlusData &state)
1847 : {
1848 :
1849 : // SUBROUTINE INFORMATION:
1850 : // AUTHOR Rongpeng Zhang
1851 : // DATE WRITTEN Jun. 2016
1852 :
1853 : // PURPOSE OF THIS SUBROUTINE:
1854 : // To calculate the dynamic fault offset based on the fault availability schedule and severity schedule.
1855 :
1856 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1857 54077 : Real64 FaultFac(0.0); // fault modification factor
1858 :
1859 : // Check fault availability schedules
1860 54077 : if (this->availSched->getCurrentVal() > 0.0) {
1861 :
1862 : // Check fault severity schedules
1863 54077 : FaultFac = (this->severitySched != nullptr) ? this->severitySched->getCurrentVal() : 1.0;
1864 : }
1865 :
1866 54077 : return FaultFac * this->Offset;
1867 : }
1868 :
1869 108269 : Real64 FaultPropertiesFouling::CalFoulingFactor([[maybe_unused]] EnergyPlusData &state)
1870 : {
1871 :
1872 : // SUBROUTINE INFORMATION:
1873 : // AUTHOR Rongpeng Zhang
1874 : // DATE WRITTEN Nov. 2016
1875 :
1876 : // PURPOSE OF THIS SUBROUTINE:
1877 : // To calculate the dynamic Nominal Capacity or Efficiency Reduction due to fouling, based on the fault availability schedule and severity
1878 : // schedule. The factor is the ratio between the nominal capacity or efficiency at fouling case and that at fault free case
1879 :
1880 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1881 108269 : Real64 FaultFac(0.0); // fault modification factor
1882 108269 : Real64 FoulingFactor(
1883 : 1.0); // Actual Nominal Fouling Factor, ratio between the nominal capacity or efficiency at fouling case and that at fault free case
1884 :
1885 : // Check fault availability schedules
1886 108269 : if (this->availSched->getCurrentVal() > 0.0) {
1887 :
1888 : // Check fault severity schedules
1889 108269 : FaultFac = (this->severitySched != nullptr) ? this->severitySched->getCurrentVal() : 1.0;
1890 : }
1891 :
1892 : // The more severe the fouling fault is (i.e., larger FaultFac), the less the FoulingFactor is
1893 108269 : if (FaultFac > 0.0) {
1894 108269 : FoulingFactor = min(this->FoulingFactor / FaultFac, 1.0);
1895 : }
1896 :
1897 108269 : return FoulingFactor;
1898 : }
1899 :
1900 3240 : Real64 FaultPropertiesTowerFouling::CalFaultyTowerFoulingFactor([[maybe_unused]] EnergyPlusData &state)
1901 : {
1902 :
1903 : // SUBROUTINE INFORMATION:
1904 : // AUTHOR Rongpeng Zhang
1905 : // DATE WRITTEN Jul. 2016
1906 :
1907 : // PURPOSE OF THIS SUBROUTINE:
1908 : // To calculate the dynamic tower fouling factor based on the fault availability schedule and severity schedule.
1909 : // Fouling factor is the ratio between the UA value at fouling case and that at fault free case
1910 :
1911 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1912 3240 : Real64 FaultFac(0.0); // fault modification factor
1913 3240 : Real64 UAReductionFactorAct(1.0); // actual UA Reduction Factor, ratio between the UA value at fouling case and that at fault free case
1914 :
1915 : // Check fault availability schedules
1916 3240 : if (this->availSched->getCurrentVal() > 0.0) {
1917 :
1918 : // Check fault severity schedules
1919 3240 : FaultFac = (this->severitySched != nullptr) ? this->severitySched->getCurrentVal() : 1.0;
1920 : }
1921 :
1922 : // The more severe the fouling fault is (i.e., larger FaultFac), the less the UAReductionFactor is
1923 3240 : if (FaultFac > 0.0) {
1924 3240 : UAReductionFactorAct = min(this->UAReductionFactor / FaultFac, 1.0);
1925 : }
1926 :
1927 3240 : return UAReductionFactorAct;
1928 : }
1929 :
1930 2654 : Real64 FaultPropertiesFoulingCoil::FaultFraction([[maybe_unused]] EnergyPlusData &state)
1931 : {
1932 : // SUBROUTINE INFORMATION:
1933 : // AUTHOR Julien Marrec, EffiBEM
1934 : // DATE WRITTEN Feb. 2020
1935 :
1936 : // PURPOSE OF THIS SUBROUTINE:
1937 : // Calculate the Fault Fraction based on Availability and Severity Schedules
1938 :
1939 : // Check fault availability schedules
1940 2654 : if (this->availSched->getCurrentVal() > 0.0) {
1941 :
1942 : // Check fault severity schedules (Ptr initialized to -1, so would return a FaultFrac of 1 if not set)
1943 2654 : return this->severitySched->getCurrentVal();
1944 : }
1945 :
1946 0 : return 0.0;
1947 : }
1948 :
1949 50282 : void FaultPropertiesChillerSWT::CalFaultChillerSWT(bool FlagVariableFlow, // True if chiller is variable flow and false if it is constant flow
1950 : Real64 FaultyChillerSWTOffset, // Faulty chiller SWT sensor offset
1951 : Real64 Cp, // Local fluid specific heat
1952 : Real64 EvapInletTemp, // Chiller evaporator inlet water temperature
1953 : Real64 &EvapOutletTemp, // Chiller evaporator outlet water temperature
1954 : Real64 &EvapMassFlowRate, // Chiller mass flow rate
1955 : Real64 &QEvaporator // Chiller evaporator heat transfer rate
1956 : )
1957 : {
1958 : // SUBROUTINE INFORMATION:
1959 : // AUTHOR Rongpeng Zhang
1960 : // DATE WRITTEN Jun. 2016
1961 :
1962 : // PURPOSE OF THIS SUBROUTINE:
1963 : // To calculate the mass flow rate and supply water temperature of a chiller with faulty SWT sensor.
1964 :
1965 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1966 : // Variables for fault free cases
1967 50282 : Real64 EvapOutletTemp_ff = EvapOutletTemp; // Chiller supply water temperature, fault free [C]
1968 50282 : Real64 EvapMassFlowRate_ff = EvapMassFlowRate; // Chiller mass flow rate, fault free [kg/s]
1969 50282 : Real64 QEvaporator_ff = QEvaporator; // Chiller evaporator heat transfer rate, fault free [W]
1970 :
1971 : // Variables for faulty cases
1972 : Real64 EvapOutletTemp_f; // Chiller supply water temperature, faulty case [C]
1973 50282 : Real64 EvapMassFlowRate_f = EvapMassFlowRate_ff; // Chiller mass flow rate, faulty case [kg/s]
1974 : Real64 QEvaporator_f; // Chiller evaporator heat transfer rate, faulty case [W]
1975 :
1976 50282 : if (!FlagVariableFlow) {
1977 : // Chillers with ConstantFlow mode
1978 :
1979 25059 : EvapOutletTemp_f = EvapOutletTemp_ff - FaultyChillerSWTOffset;
1980 :
1981 25059 : if ((EvapInletTemp > EvapOutletTemp_f) && (EvapMassFlowRate_ff > 0)) {
1982 25059 : QEvaporator_f = EvapMassFlowRate_ff * Cp * (EvapInletTemp - EvapOutletTemp_f);
1983 : } else {
1984 0 : EvapMassFlowRate_f = 0.0;
1985 0 : QEvaporator_f = 0.0;
1986 : }
1987 :
1988 : } else {
1989 : // Chillers with LeavingSetpointModulated mode
1990 :
1991 25223 : EvapOutletTemp_f = EvapOutletTemp_ff - FaultyChillerSWTOffset;
1992 :
1993 25223 : if ((EvapInletTemp > EvapOutletTemp_f) && (Cp > 0) && (EvapMassFlowRate_ff > 0)) {
1994 25223 : EvapMassFlowRate_f = QEvaporator_ff / Cp / (EvapInletTemp - EvapOutletTemp_ff);
1995 25223 : QEvaporator_f = EvapMassFlowRate_f * Cp * (EvapInletTemp - EvapOutletTemp_f);
1996 : } else {
1997 0 : EvapMassFlowRate_f = 0.0;
1998 0 : QEvaporator_f = 0.0;
1999 : }
2000 : }
2001 :
2002 : // Return variables
2003 50282 : EvapOutletTemp = EvapOutletTemp_f;
2004 50282 : EvapMassFlowRate = EvapMassFlowRate_f;
2005 50282 : QEvaporator = QEvaporator_f;
2006 50282 : }
2007 :
2008 1 : bool FaultPropertiesAirFilter::CheckFaultyAirFilterFanCurve(EnergyPlusData &state)
2009 : {
2010 :
2011 : // SUBROUTINE INFORMATION:
2012 : // AUTHOR Rongpeng Zhang
2013 : // DATE WRITTEN Apr. 2015
2014 :
2015 : // PURPOSE OF THIS SUBROUTINE:
2016 : // To check whether the fan curve specified in the FaultModel:Fouling:AirFilter object
2017 : // covers the rated operational point of the corresponding fan
2018 : // Return true if the curve covers the fan rated operational point
2019 1 : auto *fan = state.dataFans->fans(this->fanNum);
2020 1 : Real64 deltaPressCal = Curve::CurveValue(state, this->fanCurveNum, fan->maxAirFlowRate);
2021 1 : return ((deltaPressCal > 0.95 * fan->deltaPress) && (deltaPressCal < 1.05 * fan->deltaPress));
2022 : }
2023 :
2024 758 : void SetFaultyCoilSATSensor(
2025 : EnergyPlusData &state, std::string const &CompType, std::string_view CompName, bool &FaultyCoilSATFlag, int &FaultyCoilSATIndex)
2026 : {
2027 :
2028 758 : FaultyCoilSATFlag = false;
2029 758 : FaultyCoilSATIndex = 0;
2030 758 : if (state.dataFaultsMgr->NumFaultyCoilSATSensor == 0) {
2031 758 : return;
2032 : }
2033 0 : for (int jFault_CoilSAT = 1; jFault_CoilSAT <= state.dataFaultsMgr->NumFaultyCoilSATSensor; ++jFault_CoilSAT) {
2034 0 : if (Util::SameString(state.dataFaultsMgr->FaultsCoilSATSensor(jFault_CoilSAT).CoilType, CompType) &&
2035 0 : Util::SameString(state.dataFaultsMgr->FaultsCoilSATSensor(jFault_CoilSAT).CoilName, CompName)) {
2036 0 : FaultyCoilSATFlag = true;
2037 0 : FaultyCoilSATIndex = jFault_CoilSAT;
2038 0 : break;
2039 : }
2040 : }
2041 : }
2042 :
2043 : } // namespace FaultsManager
2044 :
2045 : } // namespace EnergyPlus
|