Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <cmath>
50 :
51 : // ObjexxFCL Headers
52 : #include <ObjexxFCL/Array.functions.hh>
53 : #include <ObjexxFCL/Fmath.hh>
54 :
55 : // EnergyPlus Headers
56 : #include <EnergyPlus/Autosizing/Base.hh>
57 : #include <EnergyPlus/BranchNodeConnections.hh>
58 : #include <EnergyPlus/Data/EnergyPlusData.hh>
59 : #include <EnergyPlus/DataHVACGlobals.hh>
60 : #include <EnergyPlus/DataIPShortCuts.hh>
61 : #include <EnergyPlus/DataLoopNode.hh>
62 : #include <EnergyPlus/DataSizing.hh>
63 : #include <EnergyPlus/EMSManager.hh>
64 : #include <EnergyPlus/FluidProperties.hh>
65 : #include <EnergyPlus/General.hh>
66 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
67 : #include <EnergyPlus/NodeInputManager.hh>
68 : #include <EnergyPlus/OutputProcessor.hh>
69 : #include <EnergyPlus/PlantComponentTemperatureSources.hh>
70 : #include <EnergyPlus/PlantUtilities.hh>
71 : #include <EnergyPlus/ScheduleManager.hh>
72 : #include <EnergyPlus/UtilityRoutines.hh>
73 :
74 : namespace EnergyPlus {
75 :
76 : namespace PlantComponentTemperatureSources {
77 :
78 : // MODULE INFORMATION:
79 : // AUTHOR Edwin Lee
80 : // DATE WRITTEN November 2012
81 : // MODIFIED na
82 : // RE-ENGINEERED na
83 :
84 : // PURPOSE OF THIS MODULE:
85 : // This module simulates plant supply components which operate against a
86 : // predefined (but variable) boundary temperature.
87 :
88 : // METHODOLOGY EMPLOYED:
89 : // Called by PlantLoopEquipment, model accepts inputs, and calculates a
90 : // thermal response using new plant routines such as SetComponentFlowRate
91 :
92 0 : PlantComponent *WaterSourceSpecs::factory(EnergyPlusData &state, std::string const &objectName)
93 : {
94 0 : if (state.dataPlantCompTempSrc->getWaterSourceInput) {
95 0 : GetWaterSourceInput(state);
96 0 : state.dataPlantCompTempSrc->getWaterSourceInput = false;
97 : }
98 :
99 : // Now look for this particular pipe in the list
100 0 : for (auto &waterSource : state.dataPlantCompTempSrc->WaterSource) {
101 0 : if (waterSource.Name == objectName) {
102 0 : return &waterSource;
103 : }
104 0 : }
105 : // If we didn't find it, fatal
106 0 : ShowFatalError(state,
107 : format("LocalTemperatureSourceFactory: Error getting inputs for temperature source named: {}", objectName)); // LCOV_EXCL_LINE
108 : // Shut up the compiler
109 : return nullptr; // LCOV_EXCL_LINE
110 : }
111 :
112 2 : void WaterSourceSpecs::initialize(EnergyPlusData &state, Real64 &MyLoad)
113 : {
114 :
115 : // SUBROUTINE INFORMATION:
116 : // AUTHOR Edwin Lee
117 : // DATE WRITTEN November 2012
118 : // MODIFIED na
119 : // RE-ENGINEERED na
120 :
121 : // PURPOSE OF THIS SUBROUTINE:
122 : // This subroutine is for initializations of the water source objects
123 :
124 : // METHODOLOGY EMPLOYED:
125 : // Uses the status flags to trigger initializations.
126 :
127 : // SUBROUTINE PARAMETER DEFINITIONS:
128 : static constexpr std::string_view RoutineName("InitWaterSource");
129 :
130 2 : this->oneTimeInit(state);
131 :
132 : // Initialize critical Demand Side Variables at the beginning of each environment
133 2 : if (this->MyEnvironFlag && state.dataGlobal->BeginEnvrnFlag && (state.dataPlnt->PlantFirstSizesOkayToFinalize)) {
134 :
135 1 : Real64 rho = state.dataPlnt->PlantLoop(this->plantLoc.loopNum).glycol->getDensity(state, Constant::InitConvTemp, RoutineName);
136 1 : this->MassFlowRateMax = this->DesVolFlowRate * rho;
137 1 : PlantUtilities::InitComponentNodes(state, 0.0, this->MassFlowRateMax, this->InletNodeNum, this->OutletNodeNum);
138 :
139 1 : this->MyEnvironFlag = false;
140 : }
141 :
142 2 : if (!state.dataGlobal->BeginEnvrnFlag) {
143 0 : this->MyEnvironFlag = true;
144 : }
145 :
146 : // OK, so we can set up the inlet and boundary temperatures now
147 2 : this->InletTemp = state.dataLoopNodes->Node(this->InletNodeNum).Temp;
148 2 : if (this->tempSpecType == TempSpecType::Schedule) {
149 0 : this->BoundaryTemp = this->tempSpecSched->getCurrentVal();
150 : }
151 :
152 : // Calculate specific heat
153 2 : Real64 cp = state.dataPlnt->PlantLoop(this->plantLoc.loopNum).glycol->getSpecificHeat(state, this->BoundaryTemp, RoutineName);
154 :
155 : // Calculate deltaT
156 2 : Real64 delta_temp = this->BoundaryTemp - this->InletTemp;
157 :
158 : // If deltaT is zero then we cannot calculate a flow request, but we may still want one
159 : // If myload is greater than zero, then lets request full flow at the current temperature as it may still be meeting load
160 : // If myload is zero, we'll then request zero flow
161 : // If deltaT is non-zero then we can use the current load and deltaT to calculate a flow request:
162 : // If MyLoad is > 0 then we want to heat the loop
163 : // If MyLoad is < 0 then we want to cool the loop
164 : // Thus, given a fixed outlet temperature (the boundary temp, Tbnd), the eq is:
165 : // MyLoad = mdot * cp * (Tbnd - Tin)
166 : // re-arranging:
167 : // mdot = MyLoad / [cp * (Tbnd - Tin)]
168 : // If there is a deltaT, but no load, the mass flow request will go to zero anyway
169 2 : if (std::abs(delta_temp) < 0.001) {
170 0 : if (std::abs(MyLoad) < 0.001) {
171 0 : this->MassFlowRate = 0.0;
172 : } else {
173 0 : this->MassFlowRate = this->MassFlowRateMax;
174 : }
175 : } else {
176 2 : this->MassFlowRate = MyLoad / (cp * delta_temp);
177 : }
178 :
179 : // If the mdot is negative it means we can't help the load so we will want to just go to zero.
180 : // If the mdot is already zero, then well, we still want to go to zero
181 : // If the mdot is positive, just make sure we constrain it to the design value
182 2 : if (this->MassFlowRate < 0) {
183 0 : this->MassFlowRate = 0.0;
184 : } else {
185 2 : if (!this->EMSOverrideOnMassFlowRateMax) {
186 2 : this->MassFlowRate = min(this->MassFlowRate, this->MassFlowRateMax);
187 : } else {
188 0 : this->MassFlowRate = min(this->MassFlowRate, this->EMSOverrideValueMassFlowRateMax);
189 : }
190 : }
191 :
192 2 : PlantUtilities::SetComponentFlowRate(state, this->MassFlowRate, this->InletNodeNum, this->OutletNodeNum, this->plantLoc);
193 :
194 : // at this point the mass flow rate, inlet temp, and boundary temp structure vars have been updated
195 : // the calc routine will update the outlet temp and heat transfer rate/energies
196 2 : }
197 :
198 1 : void WaterSourceSpecs::setupOutputVars(EnergyPlusData &state)
199 : {
200 :
201 2 : SetupOutputVariable(state,
202 : "Plant Temperature Source Component Mass Flow Rate",
203 : Constant::Units::kg_s,
204 1 : this->MassFlowRate,
205 : OutputProcessor::TimeStepType::System,
206 : OutputProcessor::StoreType::Average,
207 1 : this->Name);
208 2 : SetupOutputVariable(state,
209 : "Plant Temperature Source Component Inlet Temperature",
210 : Constant::Units::C,
211 1 : this->InletTemp,
212 : OutputProcessor::TimeStepType::System,
213 : OutputProcessor::StoreType::Average,
214 1 : this->Name);
215 2 : SetupOutputVariable(state,
216 : "Plant Temperature Source Component Outlet Temperature",
217 : Constant::Units::C,
218 1 : this->OutletTemp,
219 : OutputProcessor::TimeStepType::System,
220 : OutputProcessor::StoreType::Average,
221 1 : this->Name);
222 2 : SetupOutputVariable(state,
223 : "Plant Temperature Source Component Source Temperature",
224 : Constant::Units::C,
225 1 : this->BoundaryTemp,
226 : OutputProcessor::TimeStepType::System,
227 : OutputProcessor::StoreType::Average,
228 1 : this->Name);
229 2 : SetupOutputVariable(state,
230 : "Plant Temperature Source Component Heat Transfer Rate",
231 : Constant::Units::W,
232 1 : this->HeatRate,
233 : OutputProcessor::TimeStepType::System,
234 : OutputProcessor::StoreType::Average,
235 1 : this->Name);
236 2 : SetupOutputVariable(state,
237 : "Plant Temperature Source Component Heat Transfer Energy",
238 : Constant::Units::J,
239 1 : this->HeatEnergy,
240 : OutputProcessor::TimeStepType::System,
241 : OutputProcessor::StoreType::Sum,
242 1 : this->Name);
243 1 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
244 0 : SetupEMSActuator(state,
245 : "PlantComponent:TemperatureSource",
246 : this->Name,
247 : "Maximum Mass Flow Rate",
248 : "[kg/s]",
249 0 : this->EMSOverrideOnMassFlowRateMax,
250 0 : this->EMSOverrideValueMassFlowRateMax);
251 : }
252 1 : }
253 :
254 0 : void WaterSourceSpecs::autosize(EnergyPlusData &state)
255 : {
256 :
257 : // SUBROUTINE INFORMATION:
258 : // AUTHOR Edwin Lee
259 : // DATE WRITTEN November 2012
260 : // MODIFIED November 2013 Daeho Kang, add component sizing table entries
261 : // RE-ENGINEERED na
262 :
263 : // PURPOSE OF THIS SUBROUTINE:
264 : // This subroutine is for sizing water source design flow rate
265 :
266 : // METHODOLOGY EMPLOYED:
267 : // Obtains flow rate from the plant sizing array.
268 :
269 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
270 0 : bool ErrorsFound(false); // If errors detected in input
271 : Real64 DesVolFlowRateUser; // Hardsized design volume flow rate for reporting
272 0 : Real64 tmpVolFlowRate = this->DesVolFlowRate;
273 0 : int PltSizNum = state.dataPlnt->PlantLoop(this->plantLoc.loopNum).PlantSizNum;
274 :
275 0 : if (PltSizNum > 0) {
276 0 : if (state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow) {
277 0 : tmpVolFlowRate = state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate; //* WaterSource(SourceNum)%SizFac
278 0 : if (!this->DesVolFlowRateWasAutoSized) {
279 0 : tmpVolFlowRate = this->DesVolFlowRate;
280 : }
281 : } else {
282 0 : if (this->DesVolFlowRateWasAutoSized) {
283 0 : tmpVolFlowRate = 0.0;
284 : }
285 : }
286 0 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
287 0 : if (this->DesVolFlowRateWasAutoSized) {
288 0 : this->DesVolFlowRate = tmpVolFlowRate;
289 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
290 0 : BaseSizer::reportSizerOutput(
291 : state, "PlantComponent:TemperatureSource", this->Name, "Design Size Design Fluid Flow Rate [m3/s]", tmpVolFlowRate);
292 : }
293 0 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
294 0 : BaseSizer::reportSizerOutput(state,
295 : "PlantComponent:TemperatureSource",
296 : this->Name,
297 : "Initial Design Size Design Fluid Flow Rate [m3/s]",
298 : tmpVolFlowRate);
299 : }
300 : } else {
301 0 : if (this->DesVolFlowRate > 0.0 && tmpVolFlowRate > 0.0) {
302 0 : DesVolFlowRateUser = this->DesVolFlowRate;
303 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
304 0 : BaseSizer::reportSizerOutput(state,
305 : "PlantComponent:TemperatureSource",
306 : this->Name,
307 : "Design Size Design Fluid Flow Rate [m3/s]",
308 : tmpVolFlowRate,
309 : "User-Specified Design Fluid Flow Rate [m3/s]",
310 : DesVolFlowRateUser);
311 0 : if (state.dataGlobal->DisplayExtraWarnings) {
312 0 : if ((std::abs(tmpVolFlowRate - DesVolFlowRateUser) / DesVolFlowRateUser) >
313 0 : state.dataSize->AutoVsHardSizingThreshold) {
314 0 : ShowMessage(
315 : state,
316 0 : format("SizePlantComponentTemperatureSource: Potential issue with equipment sizing for {}", this->Name));
317 0 : ShowContinueError(state, format("User-Specified Design Fluid Flow Rate of {:.5R} [m3/s]", DesVolFlowRateUser));
318 0 : ShowContinueError(state,
319 0 : format("differs from Design Size Design Fluid Flow Rate of {:.5R} [m3/s]", tmpVolFlowRate));
320 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
321 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
322 : }
323 : }
324 : }
325 0 : tmpVolFlowRate = DesVolFlowRateUser;
326 : }
327 : }
328 : }
329 : } else {
330 0 : if (this->DesVolFlowRateWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
331 0 : ShowSevereError(state, "Autosizing of plant component temperature source flow rate requires a loop Sizing:Plant object");
332 0 : ShowContinueError(state, format("Occurs in PlantComponent:TemperatureSource object={}", this->Name));
333 0 : ErrorsFound = true;
334 : }
335 0 : if (!this->DesVolFlowRateWasAutoSized && state.dataPlnt->PlantFinalSizesOkayToReport) {
336 0 : if (this->DesVolFlowRate > 0.0) {
337 0 : BaseSizer::reportSizerOutput(
338 : state, "PlantComponent:TemperatureSource", this->Name, "User-Specified Design Fluid Flow Rate [m3/s]", this->DesVolFlowRate);
339 : }
340 : }
341 : }
342 :
343 0 : PlantUtilities::RegisterPlantCompDesignFlow(state, this->InletNodeNum, tmpVolFlowRate);
344 :
345 0 : if (ErrorsFound) {
346 0 : ShowFatalError(state, "Preceding sizing errors cause program termination");
347 : }
348 0 : }
349 :
350 2 : void WaterSourceSpecs::calculate(EnergyPlusData &state)
351 : {
352 :
353 : // SUBROUTINE INFORMATION:
354 : // AUTHOR Edwin Lee
355 : // DATE WRITTEN October 2012
356 : // MODIFIED na
357 : // RE-ENGINEERED na
358 :
359 : static constexpr std::string_view RoutineName("CalcWaterSource");
360 :
361 2 : if (this->MassFlowRate > 0.0) {
362 1 : this->OutletTemp = this->BoundaryTemp;
363 1 : Real64 Cp = state.dataPlnt->PlantLoop(this->plantLoc.loopNum).glycol->getSpecificHeat(state, this->BoundaryTemp, RoutineName);
364 1 : this->HeatRate = this->MassFlowRate * Cp * (this->OutletTemp - this->InletTemp);
365 1 : this->HeatEnergy = this->HeatRate * state.dataHVACGlobal->TimeStepSysSec;
366 : } else {
367 1 : this->OutletTemp = this->BoundaryTemp;
368 1 : this->HeatRate = 0.0;
369 1 : this->HeatEnergy = 0.0;
370 : }
371 2 : }
372 :
373 2 : void WaterSourceSpecs::update(EnergyPlusData &state)
374 : {
375 2 : state.dataLoopNodes->Node(this->OutletNodeNum).Temp = this->OutletTemp;
376 2 : }
377 :
378 2 : void WaterSourceSpecs::simulate(EnergyPlusData &state,
379 : [[maybe_unused]] const PlantLocation &calledFromLocation,
380 : [[maybe_unused]] bool FirstHVACIteration,
381 : Real64 &CurLoad,
382 : [[maybe_unused]] bool RunFlag)
383 : {
384 2 : this->initialize(state, CurLoad);
385 2 : this->calculate(state);
386 2 : this->update(state);
387 2 : }
388 :
389 0 : void WaterSourceSpecs::getDesignCapacities(
390 : [[maybe_unused]] EnergyPlusData &state, const EnergyPlus::PlantLocation &, Real64 &MaxLoad, Real64 &MinLoad, Real64 &OptLoad)
391 : {
392 :
393 0 : MaxLoad = Constant::BigNumber;
394 0 : MinLoad = 0.0;
395 0 : OptLoad = Constant::BigNumber;
396 0 : }
397 :
398 0 : void WaterSourceSpecs::getSizingFactor(Real64 &_SizFac)
399 : {
400 0 : _SizFac = this->SizFac;
401 0 : }
402 :
403 0 : void WaterSourceSpecs::onInitLoopEquip(EnergyPlusData &state, const PlantLocation &)
404 : {
405 0 : Real64 myLoad = 0.0;
406 0 : this->initialize(state, myLoad);
407 0 : this->autosize(state);
408 0 : }
409 2 : void WaterSourceSpecs::oneTimeInit(EnergyPlusData &state)
410 : {
411 4 : static std::string const RoutineName("InitWaterSource");
412 :
413 2 : if (this->MyFlag) {
414 : // setup output variables once here
415 1 : this->setupOutputVars(state);
416 : // Locate the component on the plant loops for later usage
417 1 : bool errFlag = false;
418 3 : PlantUtilities::ScanPlantLoopsForObject(
419 2 : state, this->Name, DataPlant::PlantEquipmentType::WaterSource, this->plantLoc, errFlag, _, _, _, this->InletNodeNum, _);
420 1 : if (errFlag) {
421 0 : ShowFatalError(state, format("{}: Program terminated due to previous condition(s).", RoutineName));
422 : }
423 1 : this->MyFlag = false;
424 : }
425 2 : }
426 :
427 1 : void GetWaterSourceInput(EnergyPlusData &state)
428 : {
429 :
430 : // SUBROUTINE INFORMATION:
431 : // AUTHOR: Edwin Lee
432 : // DATE WRITTEN: October 2012
433 :
434 : // PURPOSE OF THIS SUBROUTINE:
435 : // This routine gets the inputs and processes them into local data structures
436 :
437 : // METHODOLOGY EMPLOYED:
438 : // Standard E+ input processor interaction
439 :
440 : // REFERENCES:
441 : // WaterSource,
442 : // A1 , \field Name
443 : // A2 , \field Inlet Node
444 : // A3 , \field Outlet Node
445 : // N1 , \field Design Volume Flow Rate
446 : // A4 , \field Temperature Specification Type
447 : // N2 , \field Boundary Temperature
448 : // A5 ; \field Source Temperature Schedule Name
449 :
450 : static constexpr std::string_view routineName = "GetWaterSourceInput";
451 :
452 : // LOCAL VARIABLES:
453 : int NumAlphas; // Number of elements in the alpha array
454 : int NumNums; // Number of elements in the numeric array
455 : int IOStat; // IO Status when calling get input subroutine
456 1 : bool ErrorsFound(false);
457 1 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
458 :
459 : // GET NUMBER OF ALL EQUIPMENT TYPES
460 1 : cCurrentModuleObject = "PlantComponent:TemperatureSource";
461 1 : state.dataPlantCompTempSrc->NumSources = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
462 :
463 1 : if (state.dataPlantCompTempSrc->NumSources <= 0) {
464 0 : ShowSevereError(state, format("No {} equipment specified in input file", cCurrentModuleObject));
465 0 : ErrorsFound = true;
466 : }
467 :
468 : // See if load distribution manager has already gotten the input
469 1 : if (allocated(state.dataPlantCompTempSrc->WaterSource)) {
470 0 : return; // probably not possible, and probably should throw error
471 : }
472 1 : state.dataPlantCompTempSrc->WaterSource.allocate(state.dataPlantCompTempSrc->NumSources);
473 :
474 : // fill arrays
475 2 : for (int SourceNum = 1; SourceNum <= state.dataPlantCompTempSrc->NumSources; ++SourceNum) {
476 3 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
477 : cCurrentModuleObject,
478 : SourceNum,
479 1 : state.dataIPShortCut->cAlphaArgs,
480 : NumAlphas,
481 1 : state.dataIPShortCut->rNumericArgs,
482 : NumNums,
483 : IOStat,
484 : _,
485 1 : state.dataIPShortCut->lAlphaFieldBlanks,
486 1 : state.dataIPShortCut->cAlphaFieldNames,
487 1 : state.dataIPShortCut->cNumericFieldNames);
488 :
489 1 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)};
490 :
491 1 : Util::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
492 :
493 1 : state.dataPlantCompTempSrc->WaterSource(SourceNum).Name = state.dataIPShortCut->cAlphaArgs(1);
494 :
495 1 : state.dataPlantCompTempSrc->WaterSource(SourceNum).InletNodeNum =
496 2 : NodeInputManager::GetOnlySingleNode(state,
497 1 : state.dataIPShortCut->cAlphaArgs(2),
498 : ErrorsFound,
499 : DataLoopNode::ConnectionObjectType::PlantComponentTemperatureSource,
500 1 : state.dataIPShortCut->cAlphaArgs(1),
501 : DataLoopNode::NodeFluidType::Water,
502 : DataLoopNode::ConnectionType::Inlet,
503 : NodeInputManager::CompFluidStream::Primary,
504 : DataLoopNode::ObjectIsNotParent);
505 1 : state.dataPlantCompTempSrc->WaterSource(SourceNum).OutletNodeNum =
506 3 : NodeInputManager::GetOnlySingleNode(state,
507 1 : state.dataIPShortCut->cAlphaArgs(3),
508 : ErrorsFound,
509 : DataLoopNode::ConnectionObjectType::PlantComponentTemperatureSource,
510 1 : state.dataIPShortCut->cAlphaArgs(1),
511 : DataLoopNode::NodeFluidType::Water,
512 : DataLoopNode::ConnectionType::Outlet,
513 : NodeInputManager::CompFluidStream::Primary,
514 : DataLoopNode::ObjectIsNotParent);
515 2 : BranchNodeConnections::TestCompSet(state,
516 : cCurrentModuleObject,
517 1 : state.dataIPShortCut->cAlphaArgs(1),
518 1 : state.dataIPShortCut->cAlphaArgs(2),
519 1 : state.dataIPShortCut->cAlphaArgs(3),
520 : "Chilled Water Nodes");
521 :
522 1 : state.dataPlantCompTempSrc->WaterSource(SourceNum).DesVolFlowRate = state.dataIPShortCut->rNumericArgs(1);
523 1 : if (state.dataPlantCompTempSrc->WaterSource(SourceNum).DesVolFlowRate == DataSizing::AutoSize) {
524 0 : state.dataPlantCompTempSrc->WaterSource(SourceNum).DesVolFlowRateWasAutoSized = true;
525 : }
526 :
527 1 : if (state.dataIPShortCut->cAlphaArgs(4) == "CONSTANT") {
528 1 : state.dataPlantCompTempSrc->WaterSource(SourceNum).tempSpecType = TempSpecType::Constant;
529 1 : state.dataPlantCompTempSrc->WaterSource(SourceNum).BoundaryTemp = state.dataIPShortCut->rNumericArgs(2);
530 0 : } else if (state.dataIPShortCut->cAlphaArgs(4) == "SCHEDULED") {
531 0 : state.dataPlantCompTempSrc->WaterSource(SourceNum).tempSpecType = TempSpecType::Schedule;
532 0 : if ((state.dataPlantCompTempSrc->WaterSource(SourceNum).tempSpecSched =
533 0 : Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(5))) == nullptr) {
534 0 : ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(5), state.dataIPShortCut->cAlphaArgs(5));
535 0 : ErrorsFound = true;
536 : }
537 : } else {
538 0 : ShowSevereError(state, format("Input error for {}={}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
539 0 : ShowContinueError(state,
540 0 : format(R"(Invalid temperature specification type. Expected either "Constant" or "Scheduled". Encountered {})",
541 0 : state.dataIPShortCut->cAlphaArgs(4)));
542 0 : ErrorsFound = true;
543 : }
544 : }
545 :
546 1 : if (ErrorsFound) {
547 0 : ShowFatalError(state, format("Errors found in processing input for {}", cCurrentModuleObject));
548 : }
549 : }
550 :
551 : } // namespace PlantComponentTemperatureSources
552 :
553 : } // namespace EnergyPlus
|