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