Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2023, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <string>
50 :
51 : // ObjexxFCL Headers
52 : #include <ObjexxFCL/Array.functions.hh>
53 : #include <ObjexxFCL/string.functions.hh>
54 :
55 : // EnergyPlus Headers
56 : #include <EnergyPlus/BranchNodeConnections.hh>
57 : #include <EnergyPlus/Data/EnergyPlusData.hh>
58 : #include <EnergyPlus/DataContaminantBalance.hh>
59 : #include <EnergyPlus/DataEnvironment.hh>
60 : #include <EnergyPlus/DataErrorTracking.hh>
61 : #include <EnergyPlus/EMSManager.hh>
62 : #include <EnergyPlus/FluidProperties.hh>
63 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
64 : #include <EnergyPlus/NodeInputManager.hh>
65 : #include <EnergyPlus/OutputProcessor.hh>
66 : #include <EnergyPlus/Psychrometrics.hh>
67 : #include <EnergyPlus/ScheduleManager.hh>
68 : #include <EnergyPlus/UtilityRoutines.hh>
69 :
70 : namespace EnergyPlus::NodeInputManager {
71 :
72 : // MODULE INFORMATION:
73 : // AUTHOR Linda K. Lawrie
74 : // DATE WRITTEN September 1999
75 :
76 : // PURPOSE OF THIS MODULE:
77 : // To provide utilities for reading and assigning indices for the
78 : // nodes in the HVAC loops.
79 :
80 : using namespace DataLoopNode;
81 : using namespace BranchNodeConnections;
82 :
83 : constexpr const char *fluidNameSteam("STEAM");
84 :
85 283609 : void GetNodeNums(EnergyPlusData &state,
86 : std::string const &Name, // Name for which to obtain information
87 : int &NumNodes, // Number of nodes accompanying this Name
88 : Array1D_int &NodeNumbers, // Node Numbers accompanying this Name
89 : bool &ErrorsFound, // True when errors are found...
90 : DataLoopNode::NodeFluidType nodeFluidType, // Fluidtype for checking/setting node FluidType
91 : DataLoopNode::ConnectionObjectType const NodeObjectType, // Node Object Type (i.e. "Chiller:Electric")
92 : std::string const &NodeObjectName, // Node Object Name (i.e. "MyChiller")
93 : DataLoopNode::ConnectionType const nodeConnectionType, // Node Connection Type (see DataLoopNode)
94 : CompFluidStream const NodeFluidStream, // Which Fluid Stream (1,2,3,...)
95 : bool const ObjectIsParent, // True/False
96 : bool const IncrementFluidStream, // True/False
97 : std::string_view const InputFieldName // Input Field Name
98 : )
99 : {
100 :
101 : // SUBROUTINE INFORMATION:
102 : // AUTHOR Linda K. Lawrie
103 : // DATE WRITTEN September 1999
104 : // MODIFIED February 2004, Fluid Type checking/setting
105 :
106 : // PURPOSE OF THIS SUBROUTINE:
107 : // This subroutine calls the Node Manager to determine if the
108 : // entered name has already been assigned and if it is a list
109 : // or if it is a single node. If it has not been assigned, then
110 : // it is a single node and will need to be entered in the Node
111 : // data structure.
112 :
113 : // SUBROUTINE PARAMETER DEFINITIONS:
114 : static constexpr std::string_view RoutineName("GetNodeNums: ");
115 :
116 283609 : std::string_view const objTypeStr = BranchNodeConnections::ConnectionObjectTypeNames[static_cast<int>(NodeObjectType)];
117 :
118 283609 : if (state.dataNodeInputMgr->GetNodeInputFlag) {
119 615 : GetNodeListsInput(state, ErrorsFound);
120 615 : state.dataNodeInputMgr->GetNodeInputFlag = false;
121 : }
122 :
123 321503 : if (nodeFluidType != DataLoopNode::NodeFluidType::Air && nodeFluidType != DataLoopNode::NodeFluidType::Water &&
124 113499 : nodeFluidType != DataLoopNode::NodeFluidType::Electric && nodeFluidType != DataLoopNode::NodeFluidType::Steam &&
125 37722 : nodeFluidType != DataLoopNode::NodeFluidType::Blank) {
126 0 : ShowSevereError(state, format("{}{}=\"{}=\", invalid fluid type.", RoutineName, objTypeStr, NodeObjectName));
127 0 : ShowContinueError(state, format("..Invalid FluidType={}", nodeFluidType));
128 0 : ErrorsFound = true;
129 0 : ShowFatalError(state, "Preceding issue causes termination.");
130 : }
131 :
132 283609 : if (!Name.empty()) {
133 274646 : int ThisOne = UtilityRoutines::FindItemInList(Name, state.dataNodeInputMgr->NodeLists);
134 274646 : if (ThisOne != 0) {
135 5870 : NumNodes = state.dataNodeInputMgr->NodeLists(ThisOne).NumOfNodesInList;
136 5870 : NodeNumbers({1, NumNodes}) = state.dataNodeInputMgr->NodeLists(ThisOne).NodeNumbers({1, NumNodes});
137 12555 : for (int Loop = 1; Loop <= NumNodes; ++Loop) {
138 12470 : if (nodeFluidType != DataLoopNode::NodeFluidType::Blank &&
139 5785 : state.dataLoopNodes->Node(NodeNumbers(Loop)).FluidType != DataLoopNode::NodeFluidType::Blank) {
140 728 : if (state.dataLoopNodes->Node(NodeNumbers(Loop)).FluidType != nodeFluidType) {
141 0 : ShowSevereError(state, format("{}{}=\"{}=\", invalid data.", RoutineName, objTypeStr, NodeObjectName));
142 0 : if (!InputFieldName.empty()) {
143 0 : ShowContinueError(state, fmt::format("...Ref field={}", InputFieldName));
144 : }
145 0 : ShowContinueError(
146 0 : state, "Existing Fluid type for node, incorrect for request. Node=" + state.dataLoopNodes->NodeID(NodeNumbers(Loop)));
147 0 : ShowContinueError(
148 : state,
149 0 : "Existing Fluid type=" +
150 0 : format("{}",
151 0 : DataLoopNode::NodeFluidTypeNames[static_cast<int>(state.dataLoopNodes->Node(NodeNumbers(Loop)).FluidType)]) +
152 0 : ", Requested Fluid Type=" + format("{}", DataLoopNode::NodeFluidTypeNames[static_cast<int>(nodeFluidType)]));
153 0 : ErrorsFound = true;
154 : }
155 : }
156 6685 : if (state.dataLoopNodes->Node(NodeNumbers(Loop)).FluidType == DataLoopNode::NodeFluidType::Blank) {
157 5944 : state.dataLoopNodes->Node(NodeNumbers(Loop)).FluidType = nodeFluidType;
158 : }
159 6685 : ++state.dataNodeInputMgr->NodeRef(NodeNumbers(Loop));
160 : }
161 : } else {
162 268776 : ThisOne = AssignNodeNumber(state, Name, nodeFluidType, ErrorsFound);
163 268776 : NumNodes = 1;
164 268776 : NodeNumbers(1) = ThisOne;
165 : }
166 : } else {
167 8963 : NumNodes = 0;
168 8963 : NodeNumbers(1) = 0;
169 : }
170 :
171 : // Most calls to this routine use a fixed fluid stream number for all nodes, this is the default
172 283609 : NodeInputManager::CompFluidStream FluidStreamNum = NodeFluidStream;
173 559070 : for (int Loop = 1; Loop <= NumNodes; ++Loop) {
174 : // If requested, assign NodeFluidStream to the first node and increment the fluid stream number
175 : // for each remaining node in the list
176 275461 : if (IncrementFluidStream) {
177 2323 : FluidStreamNum = static_cast<NodeInputManager::CompFluidStream>(static_cast<int>(NodeFluidStream) + (Loop - 1));
178 : }
179 :
180 826383 : RegisterNodeConnection(state,
181 275461 : NodeNumbers(Loop),
182 275461 : state.dataLoopNodes->NodeID(NodeNumbers(Loop)),
183 : NodeObjectType,
184 : NodeObjectName,
185 : nodeConnectionType,
186 : FluidStreamNum,
187 : ObjectIsParent,
188 : ErrorsFound,
189 : InputFieldName);
190 : }
191 283609 : }
192 :
193 769 : void SetupNodeVarsForReporting(EnergyPlusData &state)
194 : {
195 :
196 : // SUBROUTINE INFORMATION:
197 : // AUTHOR Linda K. Lawrie
198 : // DATE WRITTEN September
199 :
200 : // PURPOSE OF THIS SUBROUTINE:
201 : // This subroutine is called when the indicated number of
202 : // Nodes have been found (TOTAL NODE NUMBER) or when HVAC warmup is
203 : // complete, whichever condition is reached first.
204 :
205 769 : auto &Node(state.dataLoopNodes->Node);
206 769 : auto &NodeID(state.dataLoopNodes->NodeID);
207 :
208 769 : if (!state.dataNodeInputMgr->NodeVarsSetup) {
209 769 : if (!state.dataErrTracking->AbortProcessing) {
210 769 : state.dataLoopNodes->MoreNodeInfo.allocate(state.dataNodeInputMgr->NumOfUniqueNodeNames);
211 60194 : for (int NumNode = 1; NumNode <= state.dataNodeInputMgr->NumOfUniqueNodeNames; ++NumNode) {
212 : // Setup Report variables for the Nodes for HVAC Reporting, CurrentModuleObject='Node Name'
213 237700 : SetupOutputVariable(state,
214 : "System Node Temperature",
215 : OutputProcessor::Unit::C,
216 59425 : state.dataLoopNodes->Node(NumNode).Temp,
217 : OutputProcessor::SOVTimeStepType::System,
218 : OutputProcessor::SOVStoreType::Average,
219 118850 : NodeID(NumNode));
220 237700 : SetupOutputVariable(state,
221 : "System Node Mass Flow Rate",
222 : OutputProcessor::Unit::kg_s,
223 59425 : Node(NumNode).MassFlowRate,
224 : OutputProcessor::SOVTimeStepType::System,
225 : OutputProcessor::SOVStoreType::Average,
226 118850 : NodeID(NumNode));
227 237700 : SetupOutputVariable(state,
228 : "System Node Humidity Ratio",
229 : OutputProcessor::Unit::kgWater_kgDryAir,
230 59425 : Node(NumNode).HumRat,
231 : OutputProcessor::SOVTimeStepType::System,
232 : OutputProcessor::SOVStoreType::Average,
233 118850 : NodeID(NumNode));
234 237700 : SetupOutputVariable(state,
235 : "System Node Setpoint Temperature",
236 : OutputProcessor::Unit::C,
237 59425 : Node(NumNode).TempSetPoint,
238 : OutputProcessor::SOVTimeStepType::System,
239 : OutputProcessor::SOVStoreType::Average,
240 118850 : NodeID(NumNode));
241 237700 : SetupOutputVariable(state,
242 : "System Node Setpoint High Temperature",
243 : OutputProcessor::Unit::C,
244 59425 : Node(NumNode).TempSetPointHi,
245 : OutputProcessor::SOVTimeStepType::System,
246 : OutputProcessor::SOVStoreType::Average,
247 118850 : NodeID(NumNode));
248 237700 : SetupOutputVariable(state,
249 : "System Node Setpoint Low Temperature",
250 : OutputProcessor::Unit::C,
251 59425 : Node(NumNode).TempSetPointLo,
252 : OutputProcessor::SOVTimeStepType::System,
253 : OutputProcessor::SOVStoreType::Average,
254 118850 : NodeID(NumNode));
255 237700 : SetupOutputVariable(state,
256 : "System Node Setpoint Humidity Ratio",
257 : OutputProcessor::Unit::kgWater_kgDryAir,
258 59425 : Node(NumNode).HumRatSetPoint,
259 : OutputProcessor::SOVTimeStepType::System,
260 : OutputProcessor::SOVStoreType::Average,
261 118850 : NodeID(NumNode));
262 237700 : SetupOutputVariable(state,
263 : "System Node Setpoint Minimum Humidity Ratio",
264 : OutputProcessor::Unit::kgWater_kgDryAir,
265 59425 : Node(NumNode).HumRatMin,
266 : OutputProcessor::SOVTimeStepType::System,
267 : OutputProcessor::SOVStoreType::Average,
268 118850 : NodeID(NumNode));
269 237700 : SetupOutputVariable(state,
270 : "System Node Setpoint Maximum Humidity Ratio",
271 : OutputProcessor::Unit::kgWater_kgDryAir,
272 59425 : Node(NumNode).HumRatMax,
273 : OutputProcessor::SOVTimeStepType::System,
274 : OutputProcessor::SOVStoreType::Average,
275 118850 : NodeID(NumNode));
276 237700 : SetupOutputVariable(state,
277 : "System Node Relative Humidity",
278 : OutputProcessor::Unit::Perc,
279 59425 : state.dataLoopNodes->MoreNodeInfo(NumNode).RelHumidity,
280 : OutputProcessor::SOVTimeStepType::System,
281 : OutputProcessor::SOVStoreType::Average,
282 118850 : NodeID(NumNode));
283 237700 : SetupOutputVariable(state,
284 : "System Node Pressure",
285 : OutputProcessor::Unit::Pa,
286 59425 : Node(NumNode).Press,
287 : OutputProcessor::SOVTimeStepType::System,
288 : OutputProcessor::SOVStoreType::Average,
289 118850 : NodeID(NumNode));
290 237700 : SetupOutputVariable(state,
291 : "System Node Standard Density Volume Flow Rate",
292 : OutputProcessor::Unit::m3_s,
293 59425 : state.dataLoopNodes->MoreNodeInfo(NumNode).VolFlowRateStdRho,
294 : OutputProcessor::SOVTimeStepType::System,
295 : OutputProcessor::SOVStoreType::Average,
296 118850 : NodeID(NumNode));
297 85304 : if (Node(NumNode).FluidType == DataLoopNode::NodeFluidType::Air ||
298 25879 : Node(NumNode).FluidType == DataLoopNode::NodeFluidType::Water) { // setup volume flow rate report for actual/current density
299 237076 : SetupOutputVariable(state,
300 : "System Node Current Density Volume Flow Rate",
301 : OutputProcessor::Unit::m3_s,
302 59269 : state.dataLoopNodes->MoreNodeInfo(NumNode).VolFlowRateCrntRho,
303 : OutputProcessor::SOVTimeStepType::System,
304 : OutputProcessor::SOVStoreType::Average,
305 118538 : NodeID(NumNode));
306 237076 : SetupOutputVariable(state,
307 : "System Node Current Density",
308 : OutputProcessor::Unit::kg_m3,
309 59269 : state.dataLoopNodes->MoreNodeInfo(NumNode).Density,
310 : OutputProcessor::SOVTimeStepType::System,
311 : OutputProcessor::SOVStoreType::Average,
312 118538 : NodeID(NumNode));
313 237076 : SetupOutputVariable(state,
314 : "System Node Specific Heat",
315 : OutputProcessor::Unit::J_kgK,
316 59269 : state.dataLoopNodes->MoreNodeInfo(NumNode).SpecificHeat,
317 : OutputProcessor::SOVTimeStepType::System,
318 : OutputProcessor::SOVStoreType::Average,
319 118538 : NodeID(NumNode));
320 : }
321 :
322 237700 : SetupOutputVariable(state,
323 : "System Node Enthalpy",
324 : OutputProcessor::Unit::J_kg,
325 59425 : state.dataLoopNodes->MoreNodeInfo(NumNode).ReportEnthalpy,
326 : OutputProcessor::SOVTimeStepType::System,
327 : OutputProcessor::SOVStoreType::Average,
328 118850 : NodeID(NumNode));
329 237700 : SetupOutputVariable(state,
330 : "System Node Wetbulb Temperature",
331 : OutputProcessor::Unit::C,
332 59425 : state.dataLoopNodes->MoreNodeInfo(NumNode).WetBulbTemp,
333 : OutputProcessor::SOVTimeStepType::System,
334 : OutputProcessor::SOVStoreType::Average,
335 118850 : NodeID(NumNode));
336 237700 : SetupOutputVariable(state,
337 : "System Node Dewpoint Temperature",
338 : OutputProcessor::Unit::C,
339 59425 : state.dataLoopNodes->MoreNodeInfo(NumNode).AirDewPointTemp,
340 : OutputProcessor::SOVTimeStepType::System,
341 : OutputProcessor::SOVStoreType::Average,
342 118850 : NodeID(NumNode));
343 237700 : SetupOutputVariable(state,
344 : "System Node Wind Speed",
345 : OutputProcessor::Unit::m_s,
346 59425 : Node(NumNode).OutAirWindSpeed,
347 : OutputProcessor::SOVTimeStepType::System,
348 : OutputProcessor::SOVStoreType::Average,
349 118850 : NodeID(NumNode));
350 237700 : SetupOutputVariable(state,
351 : "System Node Wind Direction",
352 : OutputProcessor::Unit::deg,
353 59425 : Node(NumNode).OutAirWindDir,
354 : OutputProcessor::SOVTimeStepType::System,
355 : OutputProcessor::SOVStoreType::Average,
356 118850 : NodeID(NumNode));
357 237700 : SetupOutputVariable(state,
358 : "System Node Quality",
359 : OutputProcessor::Unit::None,
360 59425 : Node(NumNode).Quality,
361 : OutputProcessor::SOVTimeStepType::System,
362 : OutputProcessor::SOVStoreType::Average,
363 118850 : NodeID(NumNode));
364 237700 : SetupOutputVariable(state,
365 : "System Node Height",
366 : OutputProcessor::Unit::m,
367 59425 : Node(NumNode).Height,
368 : OutputProcessor::SOVTimeStepType::System,
369 : OutputProcessor::SOVStoreType::Average,
370 118850 : NodeID(NumNode));
371 59425 : if (state.dataGlobal->DisplayAdvancedReportVariables) {
372 1708 : SetupOutputVariable(state,
373 : "System Node Minimum Temperature",
374 : OutputProcessor::Unit::C,
375 427 : Node(NumNode).TempMin,
376 : OutputProcessor::SOVTimeStepType::System,
377 : OutputProcessor::SOVStoreType::Average,
378 854 : NodeID(NumNode));
379 1708 : SetupOutputVariable(state,
380 : "System Node Maximum Temperature",
381 : OutputProcessor::Unit::C,
382 427 : Node(NumNode).TempMax,
383 : OutputProcessor::SOVTimeStepType::System,
384 : OutputProcessor::SOVStoreType::Average,
385 854 : NodeID(NumNode));
386 1708 : SetupOutputVariable(state,
387 : "System Node Minimum Limit Mass Flow Rate",
388 : OutputProcessor::Unit::kg_s,
389 427 : Node(NumNode).MassFlowRateMin,
390 : OutputProcessor::SOVTimeStepType::System,
391 : OutputProcessor::SOVStoreType::Average,
392 854 : NodeID(NumNode));
393 1708 : SetupOutputVariable(state,
394 : "System Node Maximum Limit Mass Flow Rate",
395 : OutputProcessor::Unit::kg_s,
396 427 : Node(NumNode).MassFlowRateMax,
397 : OutputProcessor::SOVTimeStepType::System,
398 : OutputProcessor::SOVStoreType::Average,
399 854 : NodeID(NumNode));
400 1708 : SetupOutputVariable(state,
401 : "System Node Minimum Available Mass Flow Rate",
402 : OutputProcessor::Unit::kg_s,
403 427 : Node(NumNode).MassFlowRateMinAvail,
404 : OutputProcessor::SOVTimeStepType::System,
405 : OutputProcessor::SOVStoreType::Average,
406 854 : NodeID(NumNode));
407 1708 : SetupOutputVariable(state,
408 : "System Node Maximum Available Mass Flow Rate",
409 : OutputProcessor::Unit::kg_s,
410 427 : Node(NumNode).MassFlowRateMaxAvail,
411 : OutputProcessor::SOVTimeStepType::System,
412 : OutputProcessor::SOVStoreType::Average,
413 854 : NodeID(NumNode));
414 1708 : SetupOutputVariable(state,
415 : "System Node Setpoint Mass Flow Rate",
416 : OutputProcessor::Unit::kg_s,
417 427 : Node(NumNode).MassFlowRateSetPoint,
418 : OutputProcessor::SOVTimeStepType::System,
419 : OutputProcessor::SOVStoreType::Average,
420 854 : NodeID(NumNode));
421 1708 : SetupOutputVariable(state,
422 : "System Node Requested Mass Flow Rate",
423 : OutputProcessor::Unit::kg_s,
424 427 : Node(NumNode).MassFlowRateRequest,
425 : OutputProcessor::SOVTimeStepType::System,
426 : OutputProcessor::SOVStoreType::Average,
427 854 : NodeID(NumNode));
428 1708 : SetupOutputVariable(state,
429 : "System Node Last Timestep Temperature",
430 : OutputProcessor::Unit::C,
431 427 : Node(NumNode).TempLastTimestep,
432 : OutputProcessor::SOVTimeStepType::System,
433 : OutputProcessor::SOVStoreType::Average,
434 854 : NodeID(NumNode));
435 1708 : SetupOutputVariable(state,
436 : "System Node Last Timestep Enthalpy",
437 : OutputProcessor::Unit::J_kg,
438 427 : Node(NumNode).EnthalpyLastTimestep,
439 : OutputProcessor::SOVTimeStepType::System,
440 : OutputProcessor::SOVStoreType::Average,
441 854 : NodeID(NumNode));
442 : }
443 59425 : if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
444 1132 : SetupOutputVariable(state,
445 : "System Node CO2 Concentration",
446 : OutputProcessor::Unit::ppm,
447 283 : Node(NumNode).CO2,
448 : OutputProcessor::SOVTimeStepType::System,
449 : OutputProcessor::SOVStoreType::Average,
450 566 : NodeID(NumNode));
451 : }
452 59425 : if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
453 360 : SetupOutputVariable(state,
454 : "System Node Generic Air Contaminant Concentration",
455 : OutputProcessor::Unit::ppm,
456 90 : Node(NumNode).GenContam,
457 : OutputProcessor::SOVTimeStepType::System,
458 : OutputProcessor::SOVStoreType::Average,
459 180 : NodeID(NumNode));
460 : }
461 : }
462 : }
463 769 : state.dataNodeInputMgr->NodeVarsSetup = true;
464 :
465 769 : print(state.files.bnd, "{}\n", "! This file shows details about the branches, nodes, and other");
466 769 : print(state.files.bnd, "{}\n", "! elements of the flow connections.");
467 769 : print(state.files.bnd, "{}\n", "! This file is intended for use in \"debugging\" potential problems");
468 769 : print(state.files.bnd, "{}\n", "! that may also be detected by the program, but may be more easily");
469 769 : print(state.files.bnd, "{}\n", "! identified by \"eye\".");
470 769 : print(state.files.bnd, "{}\n", "! This file is also intended to support software which draws a");
471 769 : print(state.files.bnd, "{}\n", "! schematic diagram of the HVAC system.");
472 769 : print(state.files.bnd, "{}\n", "! ===============================================================");
473 : // Show the node names on the Branch-Node Details file
474 : static constexpr std::string_view Format_700("! #Nodes,<Number of Unique Nodes>");
475 769 : print(state.files.bnd, "{}\n", Format_700);
476 769 : print(state.files.bnd, " #Nodes,{}\n", state.dataNodeInputMgr->NumOfUniqueNodeNames);
477 769 : if (state.dataNodeInputMgr->NumOfUniqueNodeNames > 0) {
478 : static constexpr std::string_view Format_702(
479 : "! <Node>,<NodeNumber>,<Node Name>,<Node Fluid Type>,<# Times Node Referenced After Definition>");
480 704 : print(state.files.bnd, "{}\n", Format_702);
481 : }
482 769 : int Count0 = 0;
483 60194 : for (int NumNode = 1; NumNode <= state.dataNodeInputMgr->NumOfUniqueNodeNames; ++NumNode) {
484 178275 : print(state.files.bnd,
485 : " Node,{},{},{},{}\n",
486 : NumNode,
487 : NodeID(NumNode),
488 59425 : DataLoopNode::NodeFluidTypeNames[static_cast<int>(Node(NumNode).FluidType)],
489 118850 : state.dataNodeInputMgr->NodeRef(NumNode));
490 59425 : if (state.dataNodeInputMgr->NodeRef(NumNode) == 0) ++Count0;
491 : }
492 : // Show suspicious node names on the Branch-Node Details file
493 769 : if (Count0 > 0) {
494 627 : print(state.files.bnd, "{}\n", "! ===============================================================");
495 627 : print(state.files.bnd, "{}\n", "! Suspicious nodes have 0 references. It is normal for some nodes, however.");
496 627 : print(state.files.bnd, "{}\n", "! Listing nodes with 0 references (culled from previous list):");
497 : static constexpr std::string_view Format_703(
498 : "! <Suspicious Node>,<NodeNumber>,<Node Name>,<Node Fluid Type>,<# Times Node Referenced After Definition>");
499 627 : print(state.files.bnd, "{}\n", Format_703);
500 56336 : for (int NumNode = 1; NumNode <= state.dataNodeInputMgr->NumOfUniqueNodeNames; ++NumNode) {
501 55709 : if (state.dataNodeInputMgr->NodeRef(NumNode) > 0) continue;
502 16281 : print(state.files.bnd,
503 : " Suspicious Node,{},{},{},{}\n",
504 : NumNode,
505 : NodeID(NumNode),
506 5427 : DataLoopNode::NodeFluidTypeNames[static_cast<int>(Node(NumNode).FluidType)],
507 10854 : state.dataNodeInputMgr->NodeRef(NumNode));
508 : }
509 : }
510 : }
511 769 : }
512 :
513 771 : void GetNodeListsInput(EnergyPlusData &state, bool &ErrorsFound) // Set to true when requested Node List not found, unchanged otherwise
514 : {
515 :
516 : // SUBROUTINE INFORMATION:
517 : // AUTHOR Linda K. Lawrie
518 : // DATE WRITTEN September 1999
519 : // MODIFIED na
520 : // RE-ENGINEERED na
521 :
522 : // PURPOSE OF THIS SUBROUTINE:
523 : // This subroutine gets the Node Lists from the IDF and fills the
524 : // Node List Data Structure.
525 :
526 : // SUBROUTINE PARAMETER DEFINITIONS:
527 : static constexpr std::string_view RoutineName("GetNodeListsInput: ");
528 771 : static std::string const CurrentModuleObject("NodeList");
529 :
530 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
531 : int NumAlphas; // Number of alphas in IDF item
532 : int NumNumbers; // Number of numerics in IDF item
533 : int IOStatus; // IOStatus for IDF item (not checked)
534 : int NCount; // Actual number of node lists
535 : bool flagError; // true when error node list name should be output
536 1542 : Array1D_string cAlphas;
537 1542 : Array1D<Real64> rNumbers;
538 :
539 771 : bool localErrorsFound(false);
540 771 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NCount, NumAlphas, NumNumbers);
541 771 : cAlphas.allocate(NumAlphas);
542 771 : rNumbers.allocate(NumNumbers);
543 771 : state.dataNodeInputMgr->NumOfNodeLists = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
544 771 : state.dataNodeInputMgr->NodeLists.allocate(state.dataNodeInputMgr->NumOfNodeLists);
545 6678 : for (int i = 1; i <= state.dataNodeInputMgr->NumOfNodeLists; ++i) {
546 5907 : state.dataNodeInputMgr->NodeLists(i).Name.clear();
547 5907 : state.dataNodeInputMgr->NodeLists(i).NumOfNodesInList = 0;
548 : }
549 :
550 771 : NCount = 0;
551 6678 : for (int Loop = 1; Loop <= state.dataNodeInputMgr->NumOfNodeLists; ++Loop) {
552 5907 : state.dataInputProcessing->inputProcessor->getObjectItem(
553 : state, CurrentModuleObject, Loop, cAlphas, NumAlphas, rNumbers, NumNumbers, IOStatus);
554 5907 : if (UtilityRoutines::IsNameEmpty(state, cAlphas(1), CurrentModuleObject, localErrorsFound)) continue;
555 :
556 5907 : ++NCount;
557 5907 : state.dataNodeInputMgr->NodeLists(NCount).Name = cAlphas(1);
558 5907 : state.dataNodeInputMgr->NodeLists(NCount).NodeNames.allocate(NumAlphas - 1);
559 5907 : state.dataNodeInputMgr->NodeLists(NCount).NodeNames = "";
560 5907 : state.dataNodeInputMgr->NodeLists(NCount).NodeNumbers.allocate(NumAlphas - 1);
561 5907 : state.dataNodeInputMgr->NodeLists(NCount).NodeNumbers = 0;
562 5907 : state.dataNodeInputMgr->NodeLists(NCount).NumOfNodesInList = NumAlphas - 1;
563 5907 : if (NumAlphas <= 1) {
564 0 : if (NumAlphas == 1) {
565 0 : ShowSevereError(state, std::string{RoutineName} + CurrentModuleObject + "=\"" + cAlphas(1) + "\" does not have any nodes.");
566 : } else {
567 0 : ShowSevereError(state, std::string{RoutineName} + CurrentModuleObject + "=<blank> does not have any nodes or nodelist name.");
568 : }
569 0 : localErrorsFound = true;
570 0 : continue;
571 : }
572 : // Put all in, then determine unique
573 12634 : for (int Loop1 = 1; Loop1 <= NumAlphas - 1; ++Loop1) {
574 6727 : state.dataNodeInputMgr->NodeLists(NCount).NodeNames(Loop1) = cAlphas(Loop1 + 1);
575 6727 : if (cAlphas(Loop1 + 1).empty()) {
576 0 : ShowWarningError(state, std::string{RoutineName} + CurrentModuleObject + "=\"" + cAlphas(1) + "\", blank node name in list.");
577 0 : --state.dataNodeInputMgr->NodeLists(NCount).NumOfNodesInList;
578 0 : if (state.dataNodeInputMgr->NodeLists(NCount).NumOfNodesInList <= 0) {
579 0 : ShowSevereError(state, std::string{RoutineName} + CurrentModuleObject + "=\"" + cAlphas(1) + "\" does not have any nodes.");
580 0 : localErrorsFound = true;
581 0 : break;
582 : }
583 0 : continue;
584 : }
585 13454 : state.dataNodeInputMgr->NodeLists(NCount).NodeNumbers(Loop1) = AssignNodeNumber(
586 13454 : state, state.dataNodeInputMgr->NodeLists(NCount).NodeNames(Loop1), DataLoopNode::NodeFluidType::Blank, localErrorsFound);
587 6727 : if (UtilityRoutines::SameString(state.dataNodeInputMgr->NodeLists(NCount).NodeNames(Loop1),
588 6727 : state.dataNodeInputMgr->NodeLists(NCount).Name)) {
589 0 : ShowSevereError(state, std::string{RoutineName} + CurrentModuleObject + "=\"" + cAlphas(1) + "\", invalid node name in list.");
590 0 : ShowContinueError(state, format("... Node {} Name=\"{}\", duplicates NodeList Name.", Loop1, cAlphas(Loop1 + 1)));
591 0 : localErrorsFound = true;
592 : }
593 : }
594 : // Error on any duplicates
595 5907 : flagError = true;
596 12634 : for (int Loop1 = 1; Loop1 <= state.dataNodeInputMgr->NodeLists(NCount).NumOfNodesInList; ++Loop1) {
597 7871 : for (int Loop2 = Loop1 + 1; Loop2 <= state.dataNodeInputMgr->NodeLists(NCount).NumOfNodesInList; ++Loop2) {
598 1144 : if (state.dataNodeInputMgr->NodeLists(NCount).NodeNumbers(Loop1) != state.dataNodeInputMgr->NodeLists(NCount).NodeNumbers(Loop2))
599 1144 : continue;
600 0 : if (flagError) { // only list nodelist name once
601 0 : ShowSevereError(state, std::string{RoutineName} + CurrentModuleObject + "=\"" + cAlphas(1) + "\" has duplicate nodes:");
602 0 : flagError = false;
603 : }
604 0 : ShowContinueError(state,
605 0 : format("...list item={}, \"{}\", duplicate list item={}, \"{}\".",
606 : Loop1,
607 0 : state.dataLoopNodes->NodeID(state.dataNodeInputMgr->NodeLists(NCount).NodeNumbers(Loop1)),
608 : Loop2,
609 0 : state.dataLoopNodes->NodeID(state.dataNodeInputMgr->NodeLists(NCount).NodeNumbers(Loop2))));
610 0 : localErrorsFound = true;
611 : }
612 : }
613 : }
614 :
615 6678 : for (int Loop = 1; Loop <= state.dataNodeInputMgr->NumOfNodeLists; ++Loop) {
616 12634 : for (int Loop2 = 1; Loop2 <= state.dataNodeInputMgr->NodeLists(Loop).NumOfNodesInList; ++Loop2) {
617 217225 : for (int Loop1 = 1; Loop1 <= state.dataNodeInputMgr->NumOfNodeLists; ++Loop1) {
618 210498 : if (Loop == Loop1) continue; // within a nodelist have already checked to see if node name duplicates nodelist name
619 203771 : if (!UtilityRoutines::SameString(state.dataNodeInputMgr->NodeLists(Loop).NodeNames(Loop2),
620 203771 : state.dataNodeInputMgr->NodeLists(Loop1).Name))
621 203771 : continue;
622 0 : ShowSevereError(state,
623 0 : std::string{RoutineName} + CurrentModuleObject + "=\"" + state.dataNodeInputMgr->NodeLists(Loop1).Name +
624 : "\", invalid node name in list.");
625 0 : ShowContinueError(
626 : state,
627 0 : format("... Node {} Name=\"{}\", duplicates NodeList Name.", Loop2, state.dataNodeInputMgr->NodeLists(Loop).NodeNames(Loop2)));
628 0 : ShowContinueError(state, "... NodeList=\"" + state.dataNodeInputMgr->NodeLists(Loop1).Name + "\", is duplicated.");
629 0 : ShowContinueError(state, "... Items in NodeLists must not be the name of another NodeList.");
630 0 : localErrorsFound = true;
631 : }
632 : }
633 : }
634 :
635 771 : cAlphas.deallocate();
636 771 : rNumbers.deallocate();
637 :
638 771 : if (localErrorsFound) {
639 0 : ShowFatalError(state, std::string{RoutineName} + CurrentModuleObject + ": Error getting input - causes termination.");
640 0 : ErrorsFound = true;
641 : }
642 771 : }
643 :
644 275503 : int AssignNodeNumber(EnergyPlusData &state,
645 : std::string const &Name, // Name for assignment
646 : DataLoopNode::NodeFluidType const nodeFluidType, // must be valid
647 : bool &ErrorsFound)
648 : {
649 :
650 : // FUNCTION INFORMATION:
651 : // AUTHOR Linda K. Lawrie
652 : // DATE WRITTEN September 1999
653 : // MODIFIED na
654 : // RE-ENGINEERED na
655 :
656 : // PURPOSE OF THIS FUNCTION:
657 : // This function assigns a node number to this name.
658 :
659 : // METHODOLOGY EMPLOYED:
660 : // Look to see if a name has already been entered. Use the index of
661 : // the array as the node number, if there.
662 :
663 : // Return value
664 : int AssignNodeNumber;
665 :
666 319348 : if (nodeFluidType != DataLoopNode::NodeFluidType::Air && nodeFluidType != DataLoopNode::NodeFluidType::Water &&
667 131354 : nodeFluidType != DataLoopNode::NodeFluidType::Electric && nodeFluidType != DataLoopNode::NodeFluidType::Steam &&
668 43674 : nodeFluidType != DataLoopNode::NodeFluidType::Blank) {
669 0 : ShowSevereError(state, format("AssignNodeNumber: Invalid FluidType={}", nodeFluidType));
670 0 : ErrorsFound = true;
671 0 : ShowFatalError(state, "AssignNodeNumber: Preceding issue causes termination.");
672 : }
673 :
674 275503 : int NumNode = 0;
675 275503 : if (state.dataNodeInputMgr->NumOfUniqueNodeNames > 0) {
676 549594 : NumNode = UtilityRoutines::FindItemInList(
677 824391 : Name, state.dataLoopNodes->NodeID({1, state.dataNodeInputMgr->NumOfUniqueNodeNames}), state.dataNodeInputMgr->NumOfUniqueNodeNames);
678 274797 : if (NumNode > 0) {
679 215916 : AssignNodeNumber = NumNode;
680 215916 : ++state.dataNodeInputMgr->NodeRef(NumNode);
681 215916 : if (nodeFluidType != DataLoopNode::NodeFluidType::Blank) {
682 238357 : if (state.dataLoopNodes->Node(NumNode).FluidType != nodeFluidType &&
683 29978 : state.dataLoopNodes->Node(NumNode).FluidType != DataLoopNode::NodeFluidType::Blank) {
684 0 : ShowSevereError(state, "Existing Fluid type for node, incorrect for request. Node=" + state.dataLoopNodes->NodeID(NumNode));
685 0 : ShowContinueError(
686 : state,
687 0 : "Existing Fluid type=" +
688 0 : format("{}", DataLoopNode::NodeFluidTypeNames[static_cast<int>(state.dataLoopNodes->Node(NumNode).FluidType)]) +
689 0 : ", Requested Fluid Type=" + format("{}", DataLoopNode::NodeFluidTypeNames[static_cast<int>(nodeFluidType)]));
690 0 : ErrorsFound = true;
691 : }
692 : }
693 215916 : if (state.dataLoopNodes->Node(NumNode).FluidType == DataLoopNode::NodeFluidType::Blank) {
694 35778 : state.dataLoopNodes->Node(NumNode).FluidType = nodeFluidType;
695 : }
696 : } else {
697 58881 : ++state.dataNodeInputMgr->NumOfUniqueNodeNames;
698 58881 : state.dataLoopNodes->NumOfNodes = state.dataNodeInputMgr->NumOfUniqueNodeNames;
699 :
700 58881 : state.dataLoopNodes->Node.redimension(state.dataLoopNodes->NumOfNodes);
701 58881 : state.dataLoopNodes->NodeID.redimension({0, state.dataLoopNodes->NumOfNodes});
702 58881 : state.dataNodeInputMgr->NodeRef.redimension(state.dataLoopNodes->NumOfNodes);
703 58881 : state.dataLoopNodes->MarkedNode.redimension(state.dataLoopNodes->NumOfNodes);
704 58881 : state.dataLoopNodes->NodeSetpointCheck.redimension(state.dataLoopNodes->NumOfNodes);
705 : // Set new item in Node
706 58881 : state.dataLoopNodes->Node(state.dataLoopNodes->NumOfNodes).FluidType = nodeFluidType;
707 58881 : state.dataNodeInputMgr->NodeRef(state.dataLoopNodes->NumOfNodes) = 0;
708 58881 : state.dataLoopNodes->NodeID(state.dataNodeInputMgr->NumOfUniqueNodeNames) = Name;
709 :
710 58881 : AssignNodeNumber = state.dataNodeInputMgr->NumOfUniqueNodeNames;
711 : }
712 : } else {
713 706 : state.dataLoopNodes->Node.allocate(1);
714 706 : state.dataLoopNodes->Node(1).FluidType = nodeFluidType;
715 : // Allocate takes care of defining
716 706 : state.dataLoopNodes->NumOfNodes = 1;
717 706 : state.dataLoopNodes->NodeID.allocate({0, 1});
718 706 : state.dataNodeInputMgr->NodeRef.allocate(1);
719 706 : state.dataLoopNodes->MarkedNode.allocate(1);
720 706 : state.dataLoopNodes->NodeSetpointCheck.allocate(1);
721 :
722 706 : state.dataNodeInputMgr->NumOfUniqueNodeNames = 1;
723 706 : state.dataLoopNodes->NodeID(0) = "Undefined";
724 706 : state.dataLoopNodes->NodeID(state.dataNodeInputMgr->NumOfUniqueNodeNames) = Name;
725 706 : AssignNodeNumber = 1;
726 706 : state.dataNodeInputMgr->NodeRef(1) = 0;
727 : }
728 :
729 275503 : return AssignNodeNumber;
730 : }
731 :
732 224576 : int GetOnlySingleNode(EnergyPlusData &state,
733 : std::string const &NodeName,
734 : bool &errFlag,
735 : DataLoopNode::ConnectionObjectType const NodeObjectType, // Node Object Type (i.e. "Chiller:Electric")
736 : std::string const &NodeObjectName, // Node Object Name (i.e. "MyChiller")
737 : DataLoopNode::NodeFluidType const nodeFluidType, // Fluidtype for checking/setting node FluidType
738 : DataLoopNode::ConnectionType const nodeConnectionType, // Node Connection Type (see DataLoopNode)
739 : CompFluidStream const NodeFluidStream, // Which Fluid Stream
740 : bool const ObjectIsParent, // True/False
741 : std::string_view const InputFieldName // Input Field Name
742 : )
743 : {
744 :
745 : // FUNCTION INFORMATION:
746 : // AUTHOR Linda K. Lawrie; adapted from GasAbsorptionChiller;Jason Glazer
747 : // DATE WRITTEN December 2001
748 :
749 : // PURPOSE OF THIS FUNCTION:
750 : // This function gets a single node (or error message results) using the
751 : // node id from the input file.
752 :
753 : static constexpr std::string_view RoutineName("GetOnlySingleNode: ");
754 :
755 : int NumNodes;
756 : int NumParams;
757 : int NumAlphas;
758 : int NumNums;
759 :
760 224576 : std::string_view const objTypeStr = BranchNodeConnections::ConnectionObjectTypeNames[static_cast<int>(NodeObjectType)];
761 :
762 224576 : if (state.dataNodeInputMgr->GetOnlySingleNodeFirstTime) {
763 706 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "NodeList", NumParams, NumAlphas, NumNums);
764 706 : state.dataNodeInputMgr->GetOnlySingleNodeNodeNums.dimension(NumParams, 0);
765 706 : state.dataNodeInputMgr->GetOnlySingleNodeFirstTime = false;
766 : }
767 :
768 449152 : GetNodeNums(state,
769 : NodeName,
770 : NumNodes,
771 224576 : state.dataNodeInputMgr->GetOnlySingleNodeNodeNums,
772 : errFlag,
773 : nodeFluidType,
774 : NodeObjectType,
775 : NodeObjectName,
776 : nodeConnectionType,
777 : NodeFluidStream,
778 : ObjectIsParent,
779 : false,
780 : InputFieldName);
781 :
782 224576 : if (NumNodes > 1) {
783 0 : ShowSevereError(state, format("{}{}=\"{}=\", invalid data.", RoutineName, objTypeStr, NodeObjectName));
784 0 : if (!InputFieldName.empty()) {
785 0 : ShowContinueError(state, fmt::format("...Ref field={}", InputFieldName));
786 : }
787 0 : ShowContinueError(state, "Only 1st Node used from NodeList=\"" + NodeName + "\".");
788 0 : ShowContinueError(state, "...a Nodelist may not be valid in this context.");
789 0 : errFlag = true;
790 224576 : } else if (NumNodes == 0) {
791 1180 : state.dataNodeInputMgr->GetOnlySingleNodeNodeNums(1) = 0;
792 : }
793 :
794 224576 : return state.dataNodeInputMgr->GetOnlySingleNodeNodeNums(1);
795 : }
796 :
797 1038 : void InitUniqueNodeCheck(EnergyPlusData &state, std::string const &ContextName)
798 : {
799 :
800 : // SUBROUTINE INFORMATION:
801 : // AUTHOR Linda Lawrie
802 : // DATE WRITTEN November 2002
803 : // MODIFIED na
804 : // RE-ENGINEERED na
805 :
806 : // PURPOSE OF THIS SUBROUTINE:
807 : // This subroutine begins a process of checking for unique node names
808 : // in a sequence of nodes.
809 :
810 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
811 1038 : bool errFlag(false);
812 :
813 : // Begin set up of Uniqueness context
814 :
815 1038 : if (state.dataNodeInputMgr->GetNodeInputFlag) {
816 156 : GetNodeListsInput(state, errFlag);
817 156 : state.dataNodeInputMgr->GetNodeInputFlag = false;
818 : }
819 :
820 1038 : if (!state.dataNodeInputMgr->CurCheckContextName.empty()) {
821 0 : ShowFatalError(state,
822 0 : "Init Uniqueness called for \"" + ContextName + ", but checks for \"" + state.dataNodeInputMgr->CurCheckContextName +
823 : "\" was already in progress.");
824 : }
825 1038 : if (ContextName.empty()) {
826 0 : ShowFatalError(state, "Init Uniqueness called with Blank Context Name");
827 : }
828 1038 : if (allocated(state.dataNodeInputMgr->UniqueNodeNames)) {
829 0 : state.dataNodeInputMgr->UniqueNodeNames.deallocate();
830 : }
831 :
832 1038 : state.dataNodeInputMgr->NumCheckNodes = 0;
833 1038 : state.dataNodeInputMgr->MaxCheckNodes = 100;
834 1038 : state.dataNodeInputMgr->UniqueNodeNames.allocate(state.dataNodeInputMgr->MaxCheckNodes);
835 1038 : state.dataNodeInputMgr->CurCheckContextName = ContextName;
836 1038 : }
837 :
838 4328 : void CheckUniqueNodeNames(
839 : EnergyPlusData &state, std::string const &NodeTypes, bool &ErrorsFound, std::string const &CheckName, std::string const &ObjectName)
840 : {
841 :
842 : // SUBROUTINE INFORMATION:
843 : // AUTHOR Linda Lawrie
844 : // DATE WRITTEN November 2002
845 : // MODIFIED na
846 : // RE-ENGINEERED na
847 :
848 : // PURPOSE OF THIS SUBROUTINE:
849 : // This subroutine checks the appropriate input argument for uniqueness.
850 : // Call CheckUniqueNodes(NodeTypes,CheckType,ErrorsFound,CheckName,CheckNumber)
851 : // NodeTypes - used in error message (if any produced)
852 : // ErrorsFound - true if error found by routine
853 : // CheckName - NodeName entered
854 : // ObjectName - "Name" field of object (i.e., CurCheckContextName)
855 :
856 : // METHODOLOGY EMPLOYED:
857 : // checks the current list of items for this (again)
858 :
859 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
860 : int Found;
861 :
862 4328 : if (!CheckName.empty()) {
863 4328 : Found = UtilityRoutines::FindItemInList(CheckName, state.dataNodeInputMgr->UniqueNodeNames, state.dataNodeInputMgr->NumCheckNodes);
864 4328 : if (Found != 0) {
865 0 : ShowSevereError(state, state.dataNodeInputMgr->CurCheckContextName + "=\"" + ObjectName + "\", duplicate node names found.");
866 0 : ShowContinueError(state, "...for Node Type(s)=" + NodeTypes + ", duplicate node name=\"" + CheckName + "\".");
867 0 : ShowContinueError(state, "...Nodes must be unique across instances of this object.");
868 : // CALL ShowSevereError(state, 'Node Types='//TRIM(NodeTypes)//', Non Unique Name found='//TRIM(CheckName))
869 : // CALL ShowContinueError(state, 'Context='//TRIM(CurCheckContextName))
870 0 : ErrorsFound = true;
871 : } else {
872 4328 : ++state.dataNodeInputMgr->NumCheckNodes;
873 4328 : if (state.dataNodeInputMgr->NumCheckNodes > state.dataNodeInputMgr->MaxCheckNodes) {
874 7 : state.dataNodeInputMgr->UniqueNodeNames.redimension(state.dataNodeInputMgr->MaxCheckNodes += 100);
875 : }
876 4328 : state.dataNodeInputMgr->UniqueNodeNames(state.dataNodeInputMgr->NumCheckNodes) = CheckName;
877 : }
878 : }
879 4328 : }
880 :
881 9162 : void CheckUniqueNodeNumbers(
882 : EnergyPlusData &state, std::string const &NodeTypes, bool &ErrorsFound, int const CheckNumber, std::string const ObjectName)
883 : {
884 :
885 : // SUBROUTINE INFORMATION:
886 : // AUTHOR Linda Lawrie
887 : // DATE WRITTEN November 2002
888 : // MODIFIED na
889 : // RE-ENGINEERED na
890 :
891 : // PURPOSE OF THIS SUBROUTINE:
892 : // This subroutine checks the appropriate input argument for uniqueness.
893 : // Call CheckUniqueNodes(NodeTypes,CheckType,ErrorsFound,CheckName,CheckNumber)
894 : // NodeTypes - used in error message (if any produced)
895 : // ErrorsFound - true if error found by routine
896 : // CheckNumber - Node Number entered
897 : // ObjectName - "Name" field of object (i.e., CurCheckContextName)
898 :
899 : // METHODOLOGY EMPLOYED:
900 : // checks the current list of items for this (again)
901 :
902 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
903 : int Found;
904 :
905 9162 : if (CheckNumber != 0) {
906 27486 : Found = UtilityRoutines::FindItemInList(
907 27486 : state.dataLoopNodes->NodeID(CheckNumber), state.dataNodeInputMgr->UniqueNodeNames, state.dataNodeInputMgr->NumCheckNodes);
908 9162 : if (Found != 0) {
909 0 : ShowSevereError(state, state.dataNodeInputMgr->CurCheckContextName + "=\"" + ObjectName + "\", duplicate node names found.");
910 0 : ShowContinueError(state,
911 0 : "...for Node Type(s)=" + NodeTypes + ", duplicate node name=\"" + state.dataLoopNodes->NodeID(CheckNumber) + "\".");
912 0 : ShowContinueError(state, "...Nodes must be unique across instances of this object.");
913 0 : ErrorsFound = true;
914 : } else {
915 9162 : ++state.dataNodeInputMgr->NumCheckNodes;
916 9162 : if (state.dataNodeInputMgr->NumCheckNodes > state.dataNodeInputMgr->MaxCheckNodes) {
917 21 : state.dataNodeInputMgr->UniqueNodeNames.redimension(state.dataNodeInputMgr->MaxCheckNodes += 100);
918 : }
919 9162 : state.dataNodeInputMgr->UniqueNodeNames(state.dataNodeInputMgr->NumCheckNodes) = state.dataLoopNodes->NodeID(CheckNumber);
920 : }
921 : }
922 9162 : }
923 :
924 1038 : void EndUniqueNodeCheck(EnergyPlusData &state, std::string const &ContextName)
925 : {
926 :
927 : // SUBROUTINE INFORMATION:
928 : // AUTHOR Linda Lawrie
929 : // DATE WRITTEN November 2002
930 : // MODIFIED na
931 : // RE-ENGINEERED na
932 :
933 : // PURPOSE OF THIS SUBROUTINE:
934 : // This subroutine marks the end of a unique node check.
935 :
936 1038 : if (state.dataNodeInputMgr->CurCheckContextName != ContextName) {
937 0 : ShowFatalError(state,
938 0 : "End Uniqueness called for \"" + ContextName + ", but checks for \"" + state.dataNodeInputMgr->CurCheckContextName +
939 : "\" was in progress.");
940 : }
941 1038 : if (ContextName.empty()) {
942 0 : ShowFatalError(state, "End Uniqueness called with Blank Context Name");
943 : }
944 1038 : state.dataNodeInputMgr->CurCheckContextName = std::string();
945 1038 : if (allocated(state.dataNodeInputMgr->UniqueNodeNames)) {
946 1038 : state.dataNodeInputMgr->UniqueNodeNames.deallocate();
947 : }
948 1038 : }
949 :
950 690474 : void CalcMoreNodeInfo(EnergyPlusData &state)
951 : {
952 :
953 : // SUBROUTINE INFORMATION:
954 : // AUTHOR Fred Buhl
955 : // DATE WRITTEN January 2004
956 : // MODIFIED na
957 : // RE-ENGINEERED na
958 :
959 : // PURPOSE OF THIS SUBROUTINE:
960 : // Calculate additional node information for reporting
961 :
962 : // METHODOLOGY EMPLOYED:
963 : // Input is the existing node data plus environment variables. Output is
964 : // stored in MoreNodeInfo.
965 :
966 : // Using/Aliasing
967 : using FluidProperties::GetDensityGlycol;
968 : using FluidProperties::GetSatDensityRefrig;
969 : using FluidProperties::GetSatEnthalpyRefrig;
970 : using FluidProperties::GetSpecificHeatGlycol;
971 : using OutputProcessor::ReqReportVariables;
972 : using Psychrometrics::CPCW;
973 : using Psychrometrics::PsyCpAirFnW;
974 : using Psychrometrics::PsyHFnTdbW;
975 : using Psychrometrics::PsyRhFnTdbWPb;
976 : using Psychrometrics::PsyRhoAirFnPbTdbW;
977 : using Psychrometrics::PsyTdpFnWPb;
978 : using Psychrometrics::PsyTwbFnTdbWPb;
979 : using Psychrometrics::RhoH2O;
980 : using ScheduleManager::GetCurrentScheduleValue;
981 :
982 : // SUBROUTINE PARAMETER DEFINITIONS:
983 : static constexpr std::string_view RoutineName("CalcMoreNodeInfo");
984 690474 : static std::string const NodeReportingCalc("NodeReportingCalc:");
985 :
986 690474 : auto &RhoAirStdInit = state.dataNodeInputMgr->RhoAirStdInit;
987 690474 : auto &RhoWaterStdInit = state.dataNodeInputMgr->RhoWaterStdInit;
988 690474 : auto &NodeWetBulbSchedPtr = state.dataNodeInputMgr->NodeWetBulbSchedPtr;
989 690474 : auto &NodeRelHumidityRepReq = state.dataNodeInputMgr->NodeRelHumidityRepReq;
990 690474 : auto &NodeRelHumiditySchedPtr = state.dataNodeInputMgr->NodeRelHumiditySchedPtr;
991 690474 : auto &NodeDewPointRepReq = state.dataNodeInputMgr->NodeDewPointRepReq;
992 690474 : auto &NodeDewPointSchedPtr = state.dataNodeInputMgr->NodeDewPointSchedPtr;
993 690474 : auto &NodeSpecificHeatRepReq = state.dataNodeInputMgr->NodeSpecificHeatRepReq;
994 690474 : auto &NodeSpecificHeatSchedPtr = state.dataNodeInputMgr->NodeSpecificHeatSchedPtr;
995 690474 : auto &nodeReportingStrings = state.dataNodeInputMgr->nodeReportingStrings;
996 690474 : auto &nodeFluidNames = state.dataNodeInputMgr->nodeFluidNames;
997 : bool ReportWetBulb;
998 : bool ReportRelHumidity;
999 : bool ReportDewPoint;
1000 : bool ReportSpecificHeat;
1001 : Real64 SteamDensity;
1002 : Real64 EnthSteamInDry;
1003 : Real64 RhoAirCurrent; // temporary value for current air density f(baro, db , W)
1004 : Real64 rho;
1005 : Real64 Cp;
1006 : Real64 rhoStd;
1007 :
1008 690474 : if (state.dataNodeInputMgr->CalcMoreNodeInfoMyOneTimeFlag) {
1009 769 : RhoAirStdInit = state.dataEnvrn->StdRhoAir;
1010 769 : RhoWaterStdInit = RhoH2O(DataGlobalConstants::InitConvTemp);
1011 769 : state.dataNodeInputMgr->NodeWetBulbRepReq.allocate(state.dataLoopNodes->NumOfNodes);
1012 769 : NodeWetBulbSchedPtr.allocate(state.dataLoopNodes->NumOfNodes);
1013 769 : NodeRelHumidityRepReq.allocate(state.dataLoopNodes->NumOfNodes);
1014 769 : NodeRelHumiditySchedPtr.allocate(state.dataLoopNodes->NumOfNodes);
1015 769 : NodeDewPointRepReq.allocate(state.dataLoopNodes->NumOfNodes);
1016 769 : NodeDewPointSchedPtr.allocate(state.dataLoopNodes->NumOfNodes);
1017 769 : NodeSpecificHeatRepReq.allocate(state.dataLoopNodes->NumOfNodes);
1018 769 : NodeSpecificHeatSchedPtr.allocate(state.dataLoopNodes->NumOfNodes);
1019 769 : nodeReportingStrings.reserve(state.dataLoopNodes->NumOfNodes);
1020 769 : nodeFluidNames.reserve(state.dataLoopNodes->NumOfNodes);
1021 769 : state.dataNodeInputMgr->NodeWetBulbRepReq = false;
1022 769 : NodeWetBulbSchedPtr = 0;
1023 769 : NodeRelHumidityRepReq = false;
1024 769 : NodeRelHumiditySchedPtr = 0;
1025 769 : NodeDewPointRepReq = false;
1026 769 : NodeDewPointSchedPtr = 0;
1027 769 : NodeSpecificHeatRepReq = false;
1028 769 : NodeSpecificHeatSchedPtr = 0;
1029 :
1030 60194 : for (int iNode = 1; iNode <= state.dataLoopNodes->NumOfNodes; ++iNode) {
1031 59425 : nodeReportingStrings.push_back(std::string(NodeReportingCalc + state.dataLoopNodes->NodeID(iNode)));
1032 59425 : nodeFluidNames.push_back(FluidProperties::GetGlycolNameByIndex(state, state.dataLoopNodes->Node(iNode).FluidIndex));
1033 1842161 : for (int iReq = 1; iReq <= state.dataOutputProcessor->NumOfReqVariables; ++iReq) {
1034 3561415 : if (UtilityRoutines::SameString(state.dataOutputProcessor->ReqRepVars(iReq).Key, state.dataLoopNodes->NodeID(iNode)) ||
1035 1778679 : state.dataOutputProcessor->ReqRepVars(iReq).Key.empty()) {
1036 1033350 : if (UtilityRoutines::SameString(state.dataOutputProcessor->ReqRepVars(iReq).VarName, "System Node Wetbulb Temperature")) {
1037 155 : state.dataNodeInputMgr->NodeWetBulbRepReq(iNode) = true;
1038 155 : NodeWetBulbSchedPtr(iNode) = state.dataOutputProcessor->ReqRepVars(iReq).SchedPtr;
1039 1033195 : } else if (UtilityRoutines::SameString(state.dataOutputProcessor->ReqRepVars(iReq).VarName, "System Node Relative Humidity")) {
1040 22 : NodeRelHumidityRepReq(iNode) = true;
1041 22 : NodeRelHumiditySchedPtr(iNode) = state.dataOutputProcessor->ReqRepVars(iReq).SchedPtr;
1042 1033173 : } else if (UtilityRoutines::SameString(state.dataOutputProcessor->ReqRepVars(iReq).VarName, "System Node Dewpoint Temperature")) {
1043 19 : NodeDewPointRepReq(iNode) = true;
1044 19 : NodeDewPointSchedPtr(iNode) = state.dataOutputProcessor->ReqRepVars(iReq).SchedPtr;
1045 1033154 : } else if (UtilityRoutines::SameString(state.dataOutputProcessor->ReqRepVars(iReq).VarName, "System Node Specific Heat")) {
1046 0 : NodeSpecificHeatRepReq(iNode) = true;
1047 0 : NodeSpecificHeatSchedPtr(iNode) = state.dataOutputProcessor->ReqRepVars(iReq).SchedPtr;
1048 : }
1049 : }
1050 : }
1051 59425 : if (EMSManager::CheckIfNodeMoreInfoSensedByEMS(state, iNode, "System Node Wetbulb Temperature")) {
1052 0 : state.dataNodeInputMgr->NodeWetBulbRepReq(iNode) = true;
1053 0 : NodeWetBulbSchedPtr(iNode) = 0;
1054 : }
1055 59425 : if (EMSManager::CheckIfNodeMoreInfoSensedByEMS(state, iNode, "System Node Relative Humidity")) {
1056 1 : NodeRelHumidityRepReq(iNode) = true;
1057 1 : NodeRelHumiditySchedPtr(iNode) = 0;
1058 : }
1059 59425 : if (EMSManager::CheckIfNodeMoreInfoSensedByEMS(state, iNode, "System Node Dewpoint Temperature")) {
1060 0 : NodeDewPointRepReq(iNode) = true;
1061 0 : NodeDewPointSchedPtr(iNode) = 0;
1062 : }
1063 59425 : if (EMSManager::CheckIfNodeMoreInfoSensedByEMS(state, iNode, "System Node Specific Heat")) {
1064 0 : NodeSpecificHeatRepReq(iNode) = true;
1065 0 : NodeSpecificHeatSchedPtr(iNode) = 0;
1066 : }
1067 : }
1068 769 : state.dataNodeInputMgr->CalcMoreNodeInfoMyOneTimeFlag = false;
1069 : }
1070 :
1071 55927977 : for (int iNode = 1; iNode <= state.dataLoopNodes->NumOfNodes; ++iNode) {
1072 55237503 : ReportWetBulb = false;
1073 55237503 : ReportRelHumidity = false;
1074 55237503 : ReportDewPoint = false;
1075 55237503 : ReportSpecificHeat = false;
1076 55237503 : if (state.dataNodeInputMgr->NodeWetBulbRepReq(iNode) && NodeWetBulbSchedPtr(iNode) > 0) {
1077 0 : ReportWetBulb = (GetCurrentScheduleValue(state, NodeWetBulbSchedPtr(iNode)) > 0.0);
1078 55237503 : } else if (state.dataNodeInputMgr->NodeWetBulbRepReq(iNode) && NodeWetBulbSchedPtr(iNode) == 0) {
1079 80713 : ReportWetBulb = true;
1080 55156790 : } else if (state.dataLoopNodes->Node(iNode).SPMNodeWetBulbRepReq) {
1081 680 : ReportWetBulb = true;
1082 : }
1083 55237503 : if (NodeRelHumidityRepReq(iNode) && NodeRelHumiditySchedPtr(iNode) > 0) {
1084 0 : ReportRelHumidity = (GetCurrentScheduleValue(state, NodeRelHumiditySchedPtr(iNode)) > 0.0);
1085 55237503 : } else if (NodeRelHumidityRepReq(iNode) && NodeRelHumiditySchedPtr(iNode) == 0) {
1086 13002 : ReportRelHumidity = true;
1087 : }
1088 55237503 : if (NodeDewPointRepReq(iNode) && NodeDewPointSchedPtr(iNode) > 0) {
1089 0 : ReportDewPoint = (GetCurrentScheduleValue(state, NodeDewPointSchedPtr(iNode)) > 0.0);
1090 55237503 : } else if (NodeDewPointRepReq(iNode) && NodeDewPointSchedPtr(iNode) == 0) {
1091 170774 : ReportDewPoint = true;
1092 : }
1093 55237503 : if (NodeSpecificHeatRepReq(iNode) && NodeSpecificHeatSchedPtr(iNode) > 0) {
1094 0 : ReportSpecificHeat = (GetCurrentScheduleValue(state, NodeSpecificHeatSchedPtr(iNode)) > 0.0);
1095 55237503 : } else if (NodeSpecificHeatRepReq(iNode) && NodeSpecificHeatSchedPtr(iNode) == 0) {
1096 0 : ReportSpecificHeat = true;
1097 : }
1098 : // calculate the volume flow rate
1099 55237503 : if (state.dataLoopNodes->Node(iNode).FluidType == DataLoopNode::NodeFluidType::Air) {
1100 29404069 : state.dataLoopNodes->MoreNodeInfo(iNode).VolFlowRateStdRho = state.dataLoopNodes->Node(iNode).MassFlowRate / RhoAirStdInit;
1101 : // if Node%Press was reliable could be used here.
1102 88212207 : RhoAirCurrent = PsyRhoAirFnPbTdbW(
1103 88212207 : state, state.dataEnvrn->OutBaroPress, state.dataLoopNodes->Node(iNode).Temp, state.dataLoopNodes->Node(iNode).HumRat);
1104 29404069 : state.dataLoopNodes->MoreNodeInfo(iNode).Density = RhoAirCurrent;
1105 29404069 : if (RhoAirCurrent != 0.0)
1106 29404069 : state.dataLoopNodes->MoreNodeInfo(iNode).VolFlowRateCrntRho = state.dataLoopNodes->Node(iNode).MassFlowRate / RhoAirCurrent;
1107 29404069 : state.dataLoopNodes->MoreNodeInfo(iNode).ReportEnthalpy =
1108 29404069 : PsyHFnTdbW(state.dataLoopNodes->Node(iNode).Temp, state.dataLoopNodes->Node(iNode).HumRat);
1109 29404069 : if (ReportWetBulb) {
1110 : // if Node%Press was reliable could be used here.
1111 325572 : state.dataLoopNodes->MoreNodeInfo(iNode).WetBulbTemp = PsyTwbFnTdbWPb(state,
1112 81393 : state.dataLoopNodes->Node(iNode).Temp,
1113 81393 : state.dataLoopNodes->Node(iNode).HumRat,
1114 81393 : state.dataEnvrn->OutBaroPress,
1115 81393 : nodeReportingStrings[iNode - 1]);
1116 : } else {
1117 29322676 : state.dataLoopNodes->MoreNodeInfo(iNode).WetBulbTemp = 0.0;
1118 : }
1119 29404069 : if (ReportDewPoint) {
1120 170774 : state.dataLoopNodes->MoreNodeInfo(iNode).AirDewPointTemp =
1121 341548 : PsyTdpFnWPb(state, state.dataLoopNodes->Node(iNode).HumRat, state.dataEnvrn->OutBaroPress);
1122 : } else {
1123 29233295 : state.dataLoopNodes->MoreNodeInfo(iNode).AirDewPointTemp = 0.0;
1124 : }
1125 29404069 : if (ReportRelHumidity) {
1126 : // if Node%Press was reliable could be used here.
1127 : // following routines don't issue psych errors and may be more reliable.
1128 52008 : state.dataLoopNodes->MoreNodeInfo(iNode).RelHumidity = 100.0 * PsyRhFnTdbWPb(state,
1129 13002 : state.dataLoopNodes->Node(iNode).Temp,
1130 13002 : state.dataLoopNodes->Node(iNode).HumRat,
1131 13002 : state.dataEnvrn->OutBaroPress,
1132 13002 : nodeReportingStrings[iNode - 1]);
1133 : } else {
1134 29391067 : state.dataLoopNodes->MoreNodeInfo(iNode).RelHumidity = 0.0;
1135 : }
1136 29404069 : if (ReportSpecificHeat) { // only call psych routine if needed.
1137 0 : state.dataLoopNodes->MoreNodeInfo(iNode).SpecificHeat = PsyCpAirFnW(state.dataLoopNodes->Node(iNode).HumRat);
1138 : } else {
1139 29404069 : state.dataLoopNodes->MoreNodeInfo(iNode).SpecificHeat = 0.0;
1140 : }
1141 25833434 : } else if (state.dataLoopNodes->Node(iNode).FluidType == DataLoopNode::NodeFluidType::Water) {
1142 :
1143 51470646 : if (!((state.dataLoopNodes->Node(iNode).FluidIndex > 0) &&
1144 25714011 : (state.dataLoopNodes->Node(iNode).FluidIndex <= state.dataFluidProps->NumOfGlycols))) {
1145 42624 : rho = RhoWaterStdInit;
1146 42624 : rhoStd = RhoWaterStdInit;
1147 42624 : Cp = CPCW(state.dataLoopNodes->Node(iNode).Temp);
1148 : } else {
1149 102856044 : Cp = GetSpecificHeatGlycol(state,
1150 25714011 : nodeFluidNames[iNode - 1],
1151 25714011 : state.dataLoopNodes->Node(iNode).Temp,
1152 25714011 : state.dataLoopNodes->Node(iNode).FluidIndex,
1153 25714011 : nodeReportingStrings[iNode - 1]);
1154 77142033 : rhoStd = GetDensityGlycol(state,
1155 25714011 : nodeFluidNames[iNode - 1],
1156 : DataGlobalConstants::InitConvTemp,
1157 25714011 : state.dataLoopNodes->Node(iNode).FluidIndex,
1158 25714011 : nodeReportingStrings[iNode - 1]);
1159 102856044 : rho = GetDensityGlycol(state,
1160 25714011 : nodeFluidNames[iNode - 1],
1161 25714011 : state.dataLoopNodes->Node(iNode).Temp,
1162 25714011 : state.dataLoopNodes->Node(iNode).FluidIndex,
1163 25714011 : nodeReportingStrings[iNode - 1]);
1164 : }
1165 :
1166 25756635 : state.dataLoopNodes->MoreNodeInfo(iNode).VolFlowRateStdRho = state.dataLoopNodes->Node(iNode).MassFlowRate / rhoStd;
1167 25756635 : state.dataLoopNodes->MoreNodeInfo(iNode).VolFlowRateCrntRho = state.dataLoopNodes->Node(iNode).MassFlowRate / rho;
1168 25756635 : state.dataLoopNodes->MoreNodeInfo(iNode).Density = rho;
1169 25756635 : state.dataLoopNodes->MoreNodeInfo(iNode).ReportEnthalpy = Cp * state.dataLoopNodes->Node(iNode).Temp;
1170 25756635 : state.dataLoopNodes->MoreNodeInfo(iNode).SpecificHeat = Cp; // always fill since cp already always being calculated anyway
1171 25756635 : state.dataLoopNodes->MoreNodeInfo(iNode).WetBulbTemp = 0.0;
1172 25756635 : state.dataLoopNodes->MoreNodeInfo(iNode).RelHumidity = 100.0;
1173 76799 : } else if (state.dataLoopNodes->Node(iNode).FluidType == DataLoopNode::NodeFluidType::Steam) {
1174 55702 : if (state.dataLoopNodes->Node(iNode).Quality == 1.0) {
1175 158476 : SteamDensity = GetSatDensityRefrig(state,
1176 : fluidNameSteam,
1177 39619 : state.dataLoopNodes->Node(iNode).Temp,
1178 39619 : state.dataLoopNodes->Node(iNode).Quality,
1179 39619 : state.dataLoopNodes->Node(iNode).FluidIndex,
1180 39619 : RoutineName);
1181 158476 : EnthSteamInDry = GetSatEnthalpyRefrig(state,
1182 : fluidNameSteam,
1183 39619 : state.dataLoopNodes->Node(iNode).Temp,
1184 39619 : state.dataLoopNodes->Node(iNode).Quality,
1185 39619 : state.dataLoopNodes->Node(iNode).FluidIndex,
1186 39619 : RoutineName);
1187 39619 : state.dataLoopNodes->MoreNodeInfo(iNode).VolFlowRateStdRho = state.dataLoopNodes->Node(iNode).MassFlowRate / SteamDensity;
1188 39619 : state.dataLoopNodes->MoreNodeInfo(iNode).ReportEnthalpy = EnthSteamInDry;
1189 39619 : state.dataLoopNodes->MoreNodeInfo(iNode).WetBulbTemp = 0.0;
1190 39619 : state.dataLoopNodes->MoreNodeInfo(iNode).RelHumidity = 0.0;
1191 16083 : } else if (state.dataLoopNodes->Node(iNode).Quality == 0.0) { // The node has condensate water through it
1192 15123 : state.dataLoopNodes->MoreNodeInfo(iNode).VolFlowRateStdRho = state.dataLoopNodes->Node(iNode).MassFlowRate / RhoWaterStdInit;
1193 15123 : state.dataLoopNodes->MoreNodeInfo(iNode).ReportEnthalpy =
1194 15123 : CPCW(state.dataLoopNodes->Node(iNode).Temp) * state.dataLoopNodes->Node(iNode).Temp;
1195 15123 : state.dataLoopNodes->MoreNodeInfo(iNode).WetBulbTemp = 0.0;
1196 15123 : state.dataLoopNodes->MoreNodeInfo(iNode).RelHumidity = 0.0;
1197 : }
1198 21097 : } else if (state.dataLoopNodes->Node(iNode).FluidType == DataLoopNode::NodeFluidType::Electric) {
1199 6590 : state.dataLoopNodes->MoreNodeInfo(iNode).VolFlowRateStdRho = 0.0;
1200 6590 : state.dataLoopNodes->MoreNodeInfo(iNode).ReportEnthalpy = 0.0;
1201 6590 : state.dataLoopNodes->MoreNodeInfo(iNode).WetBulbTemp = 0.0;
1202 6590 : state.dataLoopNodes->MoreNodeInfo(iNode).RelHumidity = 0.0;
1203 6590 : state.dataLoopNodes->MoreNodeInfo(iNode).SpecificHeat = 0.0;
1204 : } else {
1205 14507 : state.dataLoopNodes->MoreNodeInfo(iNode).VolFlowRateStdRho = state.dataLoopNodes->Node(iNode).MassFlowRate / RhoAirStdInit;
1206 14507 : if (state.dataLoopNodes->Node(iNode).HumRat > 0.0) {
1207 0 : state.dataLoopNodes->MoreNodeInfo(iNode).ReportEnthalpy =
1208 0 : PsyHFnTdbW(state.dataLoopNodes->Node(iNode).Temp, state.dataLoopNodes->Node(iNode).HumRat);
1209 0 : if (ReportWetBulb) {
1210 0 : state.dataLoopNodes->MoreNodeInfo(iNode).WetBulbTemp = PsyTwbFnTdbWPb(
1211 0 : state, state.dataLoopNodes->Node(iNode).Temp, state.dataLoopNodes->Node(iNode).HumRat, state.dataEnvrn->StdBaroPress);
1212 : } else {
1213 0 : state.dataLoopNodes->MoreNodeInfo(iNode).WetBulbTemp = 0.0;
1214 : }
1215 0 : if (ReportSpecificHeat) {
1216 0 : state.dataLoopNodes->MoreNodeInfo(iNode).SpecificHeat = PsyCpAirFnW(state.dataLoopNodes->Node(iNode).HumRat);
1217 : } else {
1218 0 : state.dataLoopNodes->MoreNodeInfo(iNode).SpecificHeat = 0.0;
1219 : }
1220 : } else {
1221 14507 : state.dataLoopNodes->MoreNodeInfo(iNode).ReportEnthalpy =
1222 14507 : CPCW(state.dataLoopNodes->Node(iNode).Temp) * state.dataLoopNodes->Node(iNode).Temp;
1223 14507 : state.dataLoopNodes->MoreNodeInfo(iNode).WetBulbTemp = 0.0;
1224 14507 : state.dataLoopNodes->MoreNodeInfo(iNode).SpecificHeat = 0.0;
1225 : }
1226 : }
1227 : }
1228 690474 : }
1229 :
1230 63 : void MarkNode(EnergyPlusData &state,
1231 : int const NodeNumber, // Node Number to be marked
1232 : DataLoopNode::ConnectionObjectType const ObjectType,
1233 : std::string const &ObjectName,
1234 : std::string const &FieldName)
1235 : {
1236 :
1237 : // SUBROUTINE INFORMATION:
1238 : // AUTHOR Linda Lawrie
1239 : // DATE WRITTEN March 2004
1240 : // MODIFIED na
1241 : // RE-ENGINEERED na
1242 :
1243 : // PURPOSE OF THIS SUBROUTINE:
1244 : // This subroutine marks a node -- this node needs to exist in more than one object.
1245 :
1246 63 : state.dataLoopNodes->MarkedNode(NodeNumber).IsMarked = true;
1247 63 : state.dataLoopNodes->MarkedNode(NodeNumber).ObjectType = ObjectType;
1248 63 : state.dataLoopNodes->MarkedNode(NodeNumber).ObjectName = ObjectName;
1249 63 : state.dataLoopNodes->MarkedNode(NodeNumber).FieldName = FieldName;
1250 63 : }
1251 :
1252 769 : void CheckMarkedNodes(EnergyPlusData &state, bool &ErrorsFound)
1253 : {
1254 :
1255 : // SUBROUTINE INFORMATION:
1256 : // AUTHOR Linda Lawrie
1257 : // DATE WRITTEN March 2004
1258 : // MODIFIED na
1259 : // RE-ENGINEERED na
1260 :
1261 : // PURPOSE OF THIS SUBROUTINE:
1262 : // This subroutine checks "marked" nodes.
1263 :
1264 60194 : for (int NodeNum = 1; NodeNum <= state.dataLoopNodes->NumOfNodes; ++NodeNum) {
1265 59425 : if (state.dataLoopNodes->MarkedNode(NodeNum).IsMarked) {
1266 54 : if (state.dataNodeInputMgr->NodeRef(NodeNum) == 0) {
1267 : auto objType =
1268 0 : BranchNodeConnections::ConnectionObjectTypeNames[static_cast<int>(state.dataLoopNodes->MarkedNode(NodeNum).ObjectType)];
1269 0 : ShowSevereError(state, "Node=\"" + state.dataLoopNodes->NodeID(NodeNum) + "\" did not find reference by another object.");
1270 0 : ShowContinueError(state,
1271 0 : format(R"(Object="{}", Name="{}", Field=[{}])",
1272 : objType,
1273 0 : state.dataLoopNodes->MarkedNode(NodeNum).ObjectName,
1274 0 : state.dataLoopNodes->MarkedNode(NodeNum).FieldName));
1275 0 : ErrorsFound = true;
1276 : }
1277 : }
1278 : }
1279 769 : }
1280 :
1281 2313 : } // namespace EnergyPlus::NodeInputManager
|