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