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 <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 284079 : 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 284079 : std::string_view const objTypeStr = BranchNodeConnections::ConnectionObjectTypeNames[static_cast<int>(NodeObjectType)];
117 :
118 284079 : if (state.dataNodeInputMgr->GetNodeInputFlag) {
119 633 : GetNodeListsInput(state, ErrorsFound);
120 633 : state.dataNodeInputMgr->GetNodeInputFlag = false;
121 : }
122 :
123 284079 : if (nodeFluidType != DataLoopNode::NodeFluidType::Air && nodeFluidType != DataLoopNode::NodeFluidType::Water &&
124 41276 : nodeFluidType != DataLoopNode::NodeFluidType::Electric && nodeFluidType != DataLoopNode::NodeFluidType::Steam &&
125 41058 : 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 284079 : if (!Name.empty()) {
133 274695 : int ThisOne = Util::FindItemInList(Name, state.dataNodeInputMgr->NodeLists);
134 274695 : if (ThisOne != 0) {
135 6138 : NumNodes = state.dataNodeInputMgr->NodeLists(ThisOne).NumOfNodesInList;
136 6138 : NodeNumbers({1, NumNodes}) = state.dataNodeInputMgr->NodeLists(ThisOne).NodeNumbers({1, NumNodes});
137 13119 : for (int Loop = 1; Loop <= NumNodes; ++Loop) {
138 12556 : if (nodeFluidType != DataLoopNode::NodeFluidType::Blank &&
139 5575 : state.dataLoopNodes->Node(NodeNumbers(Loop)).FluidType != DataLoopNode::NodeFluidType::Blank) {
140 578 : 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 : state,
147 0 : format("Existing Fluid type for node, incorrect for request. Node={}", state.dataLoopNodes->NodeID(NodeNumbers(Loop))));
148 0 : ShowContinueError(
149 : state,
150 0 : format("Existing Fluid type={}, Requested Fluid Type={}",
151 0 : format("{}",
152 0 : DataLoopNode::NodeFluidTypeNames[static_cast<int>(state.dataLoopNodes->Node(NodeNumbers(Loop)).FluidType)]),
153 0 : format("{}", DataLoopNode::NodeFluidTypeNames[static_cast<int>(nodeFluidType)])));
154 0 : ErrorsFound = true;
155 : }
156 : }
157 6981 : if (state.dataLoopNodes->Node(NodeNumbers(Loop)).FluidType == DataLoopNode::NodeFluidType::Blank) {
158 6230 : state.dataLoopNodes->Node(NodeNumbers(Loop)).FluidType = nodeFluidType;
159 : }
160 6981 : ++state.dataNodeInputMgr->NodeRef(NodeNumbers(Loop));
161 : }
162 : } else {
163 268557 : ThisOne = AssignNodeNumber(state, Name, nodeFluidType, ErrorsFound);
164 268557 : NumNodes = 1;
165 268557 : NodeNumbers(1) = ThisOne;
166 : }
167 : } else {
168 9384 : NumNodes = 0;
169 9384 : NodeNumbers(1) = 0;
170 : }
171 :
172 : // Most calls to this routine use a fixed fluid stream number for all nodes, this is the default
173 284079 : NodeInputManager::CompFluidStream FluidStreamNum = NodeFluidStream;
174 559617 : for (int Loop = 1; Loop <= NumNodes; ++Loop) {
175 : // If requested, assign NodeFluidStream to the first node and increment the fluid stream number
176 : // for each remaining node in the list
177 275538 : if (IncrementFluidStream) {
178 2398 : FluidStreamNum = static_cast<NodeInputManager::CompFluidStream>(static_cast<int>(NodeFluidStream) + (Loop - 1));
179 : }
180 :
181 275538 : RegisterNodeConnection(state,
182 275538 : NodeNumbers(Loop),
183 275538 : state.dataLoopNodes->NodeID(NodeNumbers(Loop)),
184 : NodeObjectType,
185 : NodeObjectName,
186 : nodeConnectionType,
187 : FluidStreamNum,
188 : ObjectIsParent,
189 : ErrorsFound,
190 : InputFieldName);
191 : }
192 284079 : }
193 :
194 795 : void SetupNodeVarsForReporting(EnergyPlusData &state)
195 : {
196 :
197 : // SUBROUTINE INFORMATION:
198 : // AUTHOR Linda K. Lawrie
199 : // DATE WRITTEN September
200 :
201 : // PURPOSE OF THIS SUBROUTINE:
202 : // This subroutine is called when the indicated number of
203 : // Nodes have been found (TOTAL NODE NUMBER) or when HVAC warmup is
204 : // complete, whichever condition is reached first.
205 :
206 795 : auto &Node = state.dataLoopNodes->Node;
207 795 : auto &NodeID = state.dataLoopNodes->NodeID;
208 :
209 795 : if (!state.dataNodeInputMgr->NodeVarsSetup) {
210 795 : if (!state.dataErrTracking->AbortProcessing) {
211 795 : state.dataLoopNodes->MoreNodeInfo.allocate(state.dataNodeInputMgr->NumOfUniqueNodeNames);
212 63030 : for (int NumNode = 1; NumNode <= state.dataNodeInputMgr->NumOfUniqueNodeNames; ++NumNode) {
213 : // Setup Report variables for the Nodes for HVAC Reporting, CurrentModuleObject='Node Name'
214 124470 : SetupOutputVariable(state,
215 : "System Node Temperature",
216 : Constant::Units::C,
217 62235 : state.dataLoopNodes->Node(NumNode).Temp,
218 : OutputProcessor::TimeStepType::System,
219 : OutputProcessor::StoreType::Average,
220 62235 : NodeID(NumNode));
221 124470 : SetupOutputVariable(state,
222 : "System Node Mass Flow Rate",
223 : Constant::Units::kg_s,
224 62235 : Node(NumNode).MassFlowRate,
225 : OutputProcessor::TimeStepType::System,
226 : OutputProcessor::StoreType::Average,
227 62235 : NodeID(NumNode));
228 124470 : SetupOutputVariable(state,
229 : "System Node Humidity Ratio",
230 : Constant::Units::kgWater_kgDryAir,
231 62235 : Node(NumNode).HumRat,
232 : OutputProcessor::TimeStepType::System,
233 : OutputProcessor::StoreType::Average,
234 62235 : NodeID(NumNode));
235 124470 : SetupOutputVariable(state,
236 : "System Node Setpoint Temperature",
237 : Constant::Units::C,
238 62235 : Node(NumNode).TempSetPoint,
239 : OutputProcessor::TimeStepType::System,
240 : OutputProcessor::StoreType::Average,
241 62235 : NodeID(NumNode));
242 124470 : SetupOutputVariable(state,
243 : "System Node Setpoint High Temperature",
244 : Constant::Units::C,
245 62235 : Node(NumNode).TempSetPointHi,
246 : OutputProcessor::TimeStepType::System,
247 : OutputProcessor::StoreType::Average,
248 62235 : NodeID(NumNode));
249 124470 : SetupOutputVariable(state,
250 : "System Node Setpoint Low Temperature",
251 : Constant::Units::C,
252 62235 : Node(NumNode).TempSetPointLo,
253 : OutputProcessor::TimeStepType::System,
254 : OutputProcessor::StoreType::Average,
255 62235 : NodeID(NumNode));
256 124470 : SetupOutputVariable(state,
257 : "System Node Setpoint Humidity Ratio",
258 : Constant::Units::kgWater_kgDryAir,
259 62235 : Node(NumNode).HumRatSetPoint,
260 : OutputProcessor::TimeStepType::System,
261 : OutputProcessor::StoreType::Average,
262 62235 : NodeID(NumNode));
263 124470 : SetupOutputVariable(state,
264 : "System Node Setpoint Minimum Humidity Ratio",
265 : Constant::Units::kgWater_kgDryAir,
266 62235 : Node(NumNode).HumRatMin,
267 : OutputProcessor::TimeStepType::System,
268 : OutputProcessor::StoreType::Average,
269 62235 : NodeID(NumNode));
270 124470 : SetupOutputVariable(state,
271 : "System Node Setpoint Maximum Humidity Ratio",
272 : Constant::Units::kgWater_kgDryAir,
273 62235 : Node(NumNode).HumRatMax,
274 : OutputProcessor::TimeStepType::System,
275 : OutputProcessor::StoreType::Average,
276 62235 : NodeID(NumNode));
277 124470 : SetupOutputVariable(state,
278 : "System Node Relative Humidity",
279 : Constant::Units::Perc,
280 62235 : state.dataLoopNodes->MoreNodeInfo(NumNode).RelHumidity,
281 : OutputProcessor::TimeStepType::System,
282 : OutputProcessor::StoreType::Average,
283 62235 : NodeID(NumNode));
284 124470 : SetupOutputVariable(state,
285 : "System Node Pressure",
286 : Constant::Units::Pa,
287 62235 : Node(NumNode).Press,
288 : OutputProcessor::TimeStepType::System,
289 : OutputProcessor::StoreType::Average,
290 62235 : NodeID(NumNode));
291 124470 : SetupOutputVariable(state,
292 : "System Node Standard Density Volume Flow Rate",
293 : Constant::Units::m3_s,
294 62235 : state.dataLoopNodes->MoreNodeInfo(NumNode).VolFlowRateStdRho,
295 : OutputProcessor::TimeStepType::System,
296 : OutputProcessor::StoreType::Average,
297 62235 : NodeID(NumNode));
298 89286 : if (Node(NumNode).FluidType == DataLoopNode::NodeFluidType::Air ||
299 27051 : Node(NumNode).FluidType == DataLoopNode::NodeFluidType::Water) { // setup volume flow rate report for actual/current density
300 124084 : SetupOutputVariable(state,
301 : "System Node Current Density Volume Flow Rate",
302 : Constant::Units::m3_s,
303 62042 : state.dataLoopNodes->MoreNodeInfo(NumNode).VolFlowRateCrntRho,
304 : OutputProcessor::TimeStepType::System,
305 : OutputProcessor::StoreType::Average,
306 62042 : NodeID(NumNode));
307 124084 : SetupOutputVariable(state,
308 : "System Node Current Density",
309 : Constant::Units::kg_m3,
310 62042 : state.dataLoopNodes->MoreNodeInfo(NumNode).Density,
311 : OutputProcessor::TimeStepType::System,
312 : OutputProcessor::StoreType::Average,
313 62042 : NodeID(NumNode));
314 124084 : SetupOutputVariable(state,
315 : "System Node Specific Heat",
316 : Constant::Units::J_kgK,
317 62042 : state.dataLoopNodes->MoreNodeInfo(NumNode).SpecificHeat,
318 : OutputProcessor::TimeStepType::System,
319 : OutputProcessor::StoreType::Average,
320 62042 : NodeID(NumNode));
321 : }
322 :
323 124470 : SetupOutputVariable(state,
324 : "System Node Enthalpy",
325 : Constant::Units::J_kg,
326 62235 : state.dataLoopNodes->MoreNodeInfo(NumNode).ReportEnthalpy,
327 : OutputProcessor::TimeStepType::System,
328 : OutputProcessor::StoreType::Average,
329 62235 : NodeID(NumNode));
330 124470 : SetupOutputVariable(state,
331 : "System Node Wetbulb Temperature",
332 : Constant::Units::C,
333 62235 : state.dataLoopNodes->MoreNodeInfo(NumNode).WetBulbTemp,
334 : OutputProcessor::TimeStepType::System,
335 : OutputProcessor::StoreType::Average,
336 62235 : NodeID(NumNode));
337 124470 : SetupOutputVariable(state,
338 : "System Node Dewpoint Temperature",
339 : Constant::Units::C,
340 62235 : state.dataLoopNodes->MoreNodeInfo(NumNode).AirDewPointTemp,
341 : OutputProcessor::TimeStepType::System,
342 : OutputProcessor::StoreType::Average,
343 62235 : NodeID(NumNode));
344 124470 : SetupOutputVariable(state,
345 : "System Node Wind Speed",
346 : Constant::Units::m_s,
347 62235 : Node(NumNode).OutAirWindSpeed,
348 : OutputProcessor::TimeStepType::System,
349 : OutputProcessor::StoreType::Average,
350 62235 : NodeID(NumNode));
351 124470 : SetupOutputVariable(state,
352 : "System Node Wind Direction",
353 : Constant::Units::deg,
354 62235 : Node(NumNode).OutAirWindDir,
355 : OutputProcessor::TimeStepType::System,
356 : OutputProcessor::StoreType::Average,
357 62235 : NodeID(NumNode));
358 124470 : SetupOutputVariable(state,
359 : "System Node Quality",
360 : Constant::Units::None,
361 62235 : Node(NumNode).Quality,
362 : OutputProcessor::TimeStepType::System,
363 : OutputProcessor::StoreType::Average,
364 62235 : NodeID(NumNode));
365 124470 : SetupOutputVariable(state,
366 : "System Node Height",
367 : Constant::Units::m,
368 62235 : Node(NumNode).Height,
369 : OutputProcessor::TimeStepType::System,
370 : OutputProcessor::StoreType::Average,
371 62235 : NodeID(NumNode));
372 62235 : if (state.dataGlobal->DisplayAdvancedReportVariables) {
373 928 : SetupOutputVariable(state,
374 : "System Node Minimum Temperature",
375 : Constant::Units::C,
376 464 : Node(NumNode).TempMin,
377 : OutputProcessor::TimeStepType::System,
378 : OutputProcessor::StoreType::Average,
379 464 : NodeID(NumNode));
380 928 : SetupOutputVariable(state,
381 : "System Node Maximum Temperature",
382 : Constant::Units::C,
383 464 : Node(NumNode).TempMax,
384 : OutputProcessor::TimeStepType::System,
385 : OutputProcessor::StoreType::Average,
386 464 : NodeID(NumNode));
387 928 : SetupOutputVariable(state,
388 : "System Node Minimum Limit Mass Flow Rate",
389 : Constant::Units::kg_s,
390 464 : Node(NumNode).MassFlowRateMin,
391 : OutputProcessor::TimeStepType::System,
392 : OutputProcessor::StoreType::Average,
393 464 : NodeID(NumNode));
394 928 : SetupOutputVariable(state,
395 : "System Node Maximum Limit Mass Flow Rate",
396 : Constant::Units::kg_s,
397 464 : Node(NumNode).MassFlowRateMax,
398 : OutputProcessor::TimeStepType::System,
399 : OutputProcessor::StoreType::Average,
400 464 : NodeID(NumNode));
401 928 : SetupOutputVariable(state,
402 : "System Node Minimum Available Mass Flow Rate",
403 : Constant::Units::kg_s,
404 464 : Node(NumNode).MassFlowRateMinAvail,
405 : OutputProcessor::TimeStepType::System,
406 : OutputProcessor::StoreType::Average,
407 464 : NodeID(NumNode));
408 928 : SetupOutputVariable(state,
409 : "System Node Maximum Available Mass Flow Rate",
410 : Constant::Units::kg_s,
411 464 : Node(NumNode).MassFlowRateMaxAvail,
412 : OutputProcessor::TimeStepType::System,
413 : OutputProcessor::StoreType::Average,
414 464 : NodeID(NumNode));
415 928 : SetupOutputVariable(state,
416 : "System Node Setpoint Mass Flow Rate",
417 : Constant::Units::kg_s,
418 464 : Node(NumNode).MassFlowRateSetPoint,
419 : OutputProcessor::TimeStepType::System,
420 : OutputProcessor::StoreType::Average,
421 464 : NodeID(NumNode));
422 928 : SetupOutputVariable(state,
423 : "System Node Requested Mass Flow Rate",
424 : Constant::Units::kg_s,
425 464 : Node(NumNode).MassFlowRateRequest,
426 : OutputProcessor::TimeStepType::System,
427 : OutputProcessor::StoreType::Average,
428 464 : NodeID(NumNode));
429 928 : SetupOutputVariable(state,
430 : "System Node Last Timestep Temperature",
431 : Constant::Units::C,
432 464 : Node(NumNode).TempLastTimestep,
433 : OutputProcessor::TimeStepType::System,
434 : OutputProcessor::StoreType::Average,
435 464 : NodeID(NumNode));
436 928 : SetupOutputVariable(state,
437 : "System Node Last Timestep Enthalpy",
438 : Constant::Units::J_kg,
439 464 : Node(NumNode).EnthalpyLastTimestep,
440 : OutputProcessor::TimeStepType::System,
441 : OutputProcessor::StoreType::Average,
442 464 : NodeID(NumNode));
443 : }
444 62235 : if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
445 610 : SetupOutputVariable(state,
446 : "System Node CO2 Concentration",
447 : Constant::Units::ppm,
448 305 : Node(NumNode).CO2,
449 : OutputProcessor::TimeStepType::System,
450 : OutputProcessor::StoreType::Average,
451 305 : NodeID(NumNode));
452 : }
453 62235 : if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
454 180 : SetupOutputVariable(state,
455 : "System Node Generic Air Contaminant Concentration",
456 : Constant::Units::ppm,
457 90 : Node(NumNode).GenContam,
458 : OutputProcessor::TimeStepType::System,
459 : OutputProcessor::StoreType::Average,
460 90 : NodeID(NumNode));
461 : }
462 : }
463 : }
464 795 : state.dataNodeInputMgr->NodeVarsSetup = true;
465 :
466 795 : print(state.files.bnd, "{}\n", "! This file shows details about the branches, nodes, and other");
467 795 : print(state.files.bnd, "{}\n", "! elements of the flow connections.");
468 795 : print(state.files.bnd, "{}\n", "! This file is intended for use in \"debugging\" potential problems");
469 795 : print(state.files.bnd, "{}\n", "! that may also be detected by the program, but may be more easily");
470 795 : print(state.files.bnd, "{}\n", "! identified by \"eye\".");
471 795 : print(state.files.bnd, "{}\n", "! This file is also intended to support software which draws a");
472 795 : print(state.files.bnd, "{}\n", "! schematic diagram of the HVAC system.");
473 795 : print(state.files.bnd, "{}\n", "! ===============================================================");
474 : // Show the node names on the Branch-Node Details file
475 : static constexpr std::string_view Format_700("! #Nodes,<Number of Unique Nodes>");
476 795 : print(state.files.bnd, "{}\n", Format_700);
477 795 : print(state.files.bnd, " #Nodes,{}\n", state.dataNodeInputMgr->NumOfUniqueNodeNames);
478 795 : if (state.dataNodeInputMgr->NumOfUniqueNodeNames > 0) {
479 : static constexpr std::string_view Format_702(
480 : "! <Node>,<NodeNumber>,<Node Name>,<Node Fluid Type>,<# Times Node Referenced After Definition>");
481 727 : print(state.files.bnd, "{}\n", Format_702);
482 : }
483 795 : int Count0 = 0;
484 63030 : for (int NumNode = 1; NumNode <= state.dataNodeInputMgr->NumOfUniqueNodeNames; ++NumNode) {
485 124470 : print(state.files.bnd,
486 : " Node,{},{},{},{}\n",
487 : NumNode,
488 : NodeID(NumNode),
489 62235 : DataLoopNode::NodeFluidTypeNames[static_cast<int>(Node(NumNode).FluidType)],
490 62235 : state.dataNodeInputMgr->NodeRef(NumNode));
491 62235 : if (state.dataNodeInputMgr->NodeRef(NumNode) == 0) ++Count0;
492 : }
493 : // Show suspicious node names on the Branch-Node Details file
494 795 : if (Count0 > 0) {
495 646 : print(state.files.bnd, "{}\n", "! ===============================================================");
496 646 : print(state.files.bnd, "{}\n", "! Suspicious nodes have 0 references. It is normal for some nodes, however.");
497 646 : print(state.files.bnd, "{}\n", "! Listing nodes with 0 references (culled from previous list):");
498 : static constexpr std::string_view Format_703(
499 : "! <Suspicious Node>,<NodeNumber>,<Node Name>,<Node Fluid Type>,<# Times Node Referenced After Definition>");
500 646 : print(state.files.bnd, "{}\n", Format_703);
501 59087 : for (int NumNode = 1; NumNode <= state.dataNodeInputMgr->NumOfUniqueNodeNames; ++NumNode) {
502 58441 : if (state.dataNodeInputMgr->NodeRef(NumNode) > 0) continue;
503 11420 : print(state.files.bnd,
504 : " Suspicious Node,{},{},{},{}\n",
505 : NumNode,
506 : NodeID(NumNode),
507 5710 : DataLoopNode::NodeFluidTypeNames[static_cast<int>(Node(NumNode).FluidType)],
508 5710 : state.dataNodeInputMgr->NodeRef(NumNode));
509 : }
510 : }
511 : }
512 795 : }
513 :
514 796 : void GetNodeListsInput(EnergyPlusData &state, bool &ErrorsFound) // Set to true when requested Node List not found, unchanged otherwise
515 : {
516 :
517 : // SUBROUTINE INFORMATION:
518 : // AUTHOR Linda K. Lawrie
519 : // DATE WRITTEN September 1999
520 : // MODIFIED na
521 : // RE-ENGINEERED na
522 :
523 : // PURPOSE OF THIS SUBROUTINE:
524 : // This subroutine gets the Node Lists from the IDF and fills the
525 : // Node List Data Structure.
526 :
527 : // SUBROUTINE PARAMETER DEFINITIONS:
528 : static constexpr std::string_view RoutineName("GetNodeListsInput: ");
529 796 : static std::string const CurrentModuleObject("NodeList");
530 :
531 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
532 : int NumAlphas; // Number of alphas in IDF item
533 : int NumNumbers; // Number of numerics in IDF item
534 : int IOStatus; // IOStatus for IDF item (not checked)
535 : int NCount; // Actual number of node lists
536 : bool flagError; // true when error node list name should be output
537 796 : Array1D_string cAlphas;
538 796 : Array1D<Real64> rNumbers;
539 :
540 796 : bool localErrorsFound(false);
541 796 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NCount, NumAlphas, NumNumbers);
542 796 : cAlphas.allocate(NumAlphas);
543 796 : rNumbers.allocate(NumNumbers);
544 796 : state.dataNodeInputMgr->NumOfNodeLists = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
545 796 : state.dataNodeInputMgr->NodeLists.allocate(state.dataNodeInputMgr->NumOfNodeLists);
546 6989 : for (int i = 1; i <= state.dataNodeInputMgr->NumOfNodeLists; ++i) {
547 6193 : state.dataNodeInputMgr->NodeLists(i).Name.clear();
548 6193 : state.dataNodeInputMgr->NodeLists(i).NumOfNodesInList = 0;
549 : }
550 :
551 796 : NCount = 0;
552 6989 : for (int Loop = 1; Loop <= state.dataNodeInputMgr->NumOfNodeLists; ++Loop) {
553 6193 : state.dataInputProcessing->inputProcessor->getObjectItem(
554 : state, CurrentModuleObject, Loop, cAlphas, NumAlphas, rNumbers, NumNumbers, IOStatus);
555 6193 : if (Util::IsNameEmpty(state, cAlphas(1), CurrentModuleObject, localErrorsFound)) continue;
556 :
557 6193 : ++NCount;
558 6193 : state.dataNodeInputMgr->NodeLists(NCount).Name = cAlphas(1);
559 6193 : state.dataNodeInputMgr->NodeLists(NCount).NodeNames.allocate(NumAlphas - 1);
560 6193 : state.dataNodeInputMgr->NodeLists(NCount).NodeNames = "";
561 6193 : state.dataNodeInputMgr->NodeLists(NCount).NodeNumbers.allocate(NumAlphas - 1);
562 6193 : state.dataNodeInputMgr->NodeLists(NCount).NodeNumbers = 0;
563 6193 : state.dataNodeInputMgr->NodeLists(NCount).NumOfNodesInList = NumAlphas - 1;
564 6193 : if (NumAlphas <= 1) {
565 0 : if (NumAlphas == 1) {
566 0 : ShowSevereError(state, format("{}{}=\"{}\" does not have any nodes.", RoutineName, CurrentModuleObject, cAlphas(1)));
567 : } else {
568 0 : ShowSevereError(state, format("{}{}=<blank> does not have any nodes or nodelist name.", RoutineName, CurrentModuleObject));
569 : }
570 0 : localErrorsFound = true;
571 0 : continue;
572 : }
573 : // Put all in, then determine unique
574 13247 : for (int Loop1 = 1; Loop1 <= NumAlphas - 1; ++Loop1) {
575 7054 : state.dataNodeInputMgr->NodeLists(NCount).NodeNames(Loop1) = cAlphas(Loop1 + 1);
576 7054 : if (cAlphas(Loop1 + 1).empty()) {
577 0 : ShowWarningError(state, format("{}{}=\"{}\", blank node name in list.", RoutineName, CurrentModuleObject, cAlphas(1)));
578 0 : --state.dataNodeInputMgr->NodeLists(NCount).NumOfNodesInList;
579 0 : if (state.dataNodeInputMgr->NodeLists(NCount).NumOfNodesInList <= 0) {
580 0 : ShowSevereError(state, format("{}{}=\"{}\" does not have any nodes.", RoutineName, CurrentModuleObject, cAlphas(1)));
581 0 : localErrorsFound = true;
582 0 : break;
583 : }
584 0 : continue;
585 : }
586 7054 : state.dataNodeInputMgr->NodeLists(NCount).NodeNumbers(Loop1) = AssignNodeNumber(
587 7054 : state, state.dataNodeInputMgr->NodeLists(NCount).NodeNames(Loop1), DataLoopNode::NodeFluidType::Blank, localErrorsFound);
588 7054 : if (Util::SameString(state.dataNodeInputMgr->NodeLists(NCount).NodeNames(Loop1), state.dataNodeInputMgr->NodeLists(NCount).Name)) {
589 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid node name in list.", RoutineName, CurrentModuleObject, cAlphas(1)));
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 6193 : flagError = true;
596 13247 : for (int Loop1 = 1; Loop1 <= state.dataNodeInputMgr->NodeLists(NCount).NumOfNodesInList; ++Loop1) {
597 8261 : for (int Loop2 = Loop1 + 1; Loop2 <= state.dataNodeInputMgr->NodeLists(NCount).NumOfNodesInList; ++Loop2) {
598 1207 : if (state.dataNodeInputMgr->NodeLists(NCount).NodeNumbers(Loop1) != state.dataNodeInputMgr->NodeLists(NCount).NodeNumbers(Loop2))
599 1207 : continue;
600 0 : if (flagError) { // only list nodelist name once
601 0 : ShowSevereError(state, format("{}{}=\"{}\" has duplicate nodes:", RoutineName, CurrentModuleObject, cAlphas(1)));
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 6989 : for (int Loop = 1; Loop <= state.dataNodeInputMgr->NumOfNodeLists; ++Loop) {
616 13247 : for (int Loop2 = 1; Loop2 <= state.dataNodeInputMgr->NodeLists(Loop).NumOfNodesInList; ++Loop2) {
617 236594 : for (int Loop1 = 1; Loop1 <= state.dataNodeInputMgr->NumOfNodeLists; ++Loop1) {
618 229540 : if (Loop == Loop1) continue; // within a nodelist have already checked to see if node name duplicates nodelist name
619 222486 : if (!Util::SameString(state.dataNodeInputMgr->NodeLists(Loop).NodeNames(Loop2), state.dataNodeInputMgr->NodeLists(Loop1).Name))
620 222486 : continue;
621 0 : ShowSevereError(
622 : state,
623 0 : format(
624 0 : "{}{}=\"{}\", invalid node name in list.", RoutineName, CurrentModuleObject, state.dataNodeInputMgr->NodeLists(Loop1).Name));
625 0 : ShowContinueError(
626 : state,
627 0 : format("... Node {} Name=\"{}\", duplicates NodeList Name.", Loop2, state.dataNodeInputMgr->NodeLists(Loop).NodeNames(Loop2)));
628 0 : ShowContinueError(state, format("... NodeList=\"{}\", is duplicated.", state.dataNodeInputMgr->NodeLists(Loop1).Name));
629 0 : ShowContinueError(state, "... Items in NodeLists must not be the name of another NodeList.");
630 0 : localErrorsFound = true;
631 : }
632 : }
633 : }
634 :
635 796 : cAlphas.deallocate();
636 796 : rNumbers.deallocate();
637 :
638 796 : if (localErrorsFound) {
639 0 : ShowFatalError(state, format("{}{}: Error getting input - causes termination.", RoutineName, CurrentModuleObject));
640 0 : ErrorsFound = true;
641 : }
642 796 : }
643 :
644 275611 : 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 275611 : if (nodeFluidType != DataLoopNode::NodeFluidType::Air && nodeFluidType != DataLoopNode::NodeFluidType::Water &&
667 47321 : nodeFluidType != DataLoopNode::NodeFluidType::Electric && nodeFluidType != DataLoopNode::NodeFluidType::Steam &&
668 47104 : 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 275611 : int NumNode = 0;
675 275611 : if (state.dataNodeInputMgr->NumOfUniqueNodeNames > 0) {
676 274883 : NumNode = Util::FindItemInList(
677 549766 : Name, state.dataLoopNodes->NodeID({1, state.dataNodeInputMgr->NumOfUniqueNodeNames}), state.dataNodeInputMgr->NumOfUniqueNodeNames);
678 274883 : if (NumNode > 0) {
679 213290 : AssignNodeNumber = NumNode;
680 213290 : ++state.dataNodeInputMgr->NodeRef(NumNode);
681 213290 : if (nodeFluidType != DataLoopNode::NodeFluidType::Blank) {
682 235560 : if (state.dataLoopNodes->Node(NumNode).FluidType != nodeFluidType &&
683 31618 : state.dataLoopNodes->Node(NumNode).FluidType != DataLoopNode::NodeFluidType::Blank) {
684 0 : ShowSevereError(state,
685 0 : format("Existing Fluid type for node, incorrect for request. Node={}", state.dataLoopNodes->NodeID(NumNode)));
686 0 : ShowContinueError(
687 : state,
688 0 : format("Existing Fluid type={}, Requested Fluid Type={}",
689 0 : format("{}", DataLoopNode::NodeFluidTypeNames[static_cast<int>(state.dataLoopNodes->Node(NumNode).FluidType)]),
690 0 : format("{}", DataLoopNode::NodeFluidTypeNames[static_cast<int>(nodeFluidType)])));
691 0 : ErrorsFound = true;
692 : }
693 : }
694 213290 : if (state.dataLoopNodes->Node(NumNode).FluidType == DataLoopNode::NodeFluidType::Blank) {
695 38445 : state.dataLoopNodes->Node(NumNode).FluidType = nodeFluidType;
696 : }
697 : } else {
698 61593 : ++state.dataNodeInputMgr->NumOfUniqueNodeNames;
699 61593 : state.dataLoopNodes->NumOfNodes = state.dataNodeInputMgr->NumOfUniqueNodeNames;
700 :
701 61593 : state.dataLoopNodes->Node.redimension(state.dataLoopNodes->NumOfNodes);
702 61593 : state.dataLoopNodes->NodeID.redimension({0, state.dataLoopNodes->NumOfNodes});
703 61593 : state.dataNodeInputMgr->NodeRef.redimension(state.dataLoopNodes->NumOfNodes);
704 61593 : state.dataLoopNodes->MarkedNode.redimension(state.dataLoopNodes->NumOfNodes);
705 61593 : state.dataLoopNodes->NodeSetpointCheck.redimension(state.dataLoopNodes->NumOfNodes);
706 : // Set new item in Node
707 61593 : state.dataLoopNodes->Node(state.dataLoopNodes->NumOfNodes).FluidType = nodeFluidType;
708 61593 : state.dataNodeInputMgr->NodeRef(state.dataLoopNodes->NumOfNodes) = 0;
709 61593 : state.dataLoopNodes->NodeID(state.dataNodeInputMgr->NumOfUniqueNodeNames) = Name;
710 :
711 61593 : AssignNodeNumber = state.dataNodeInputMgr->NumOfUniqueNodeNames;
712 : }
713 : } else {
714 728 : state.dataLoopNodes->Node.allocate(1);
715 728 : state.dataLoopNodes->Node(1).FluidType = nodeFluidType;
716 : // Allocate takes care of defining
717 728 : state.dataLoopNodes->NumOfNodes = 1;
718 728 : state.dataLoopNodes->NodeID.allocate({0, 1});
719 728 : state.dataNodeInputMgr->NodeRef.allocate(1);
720 728 : state.dataLoopNodes->MarkedNode.allocate(1);
721 728 : state.dataLoopNodes->NodeSetpointCheck.allocate(1);
722 :
723 728 : state.dataNodeInputMgr->NumOfUniqueNodeNames = 1;
724 728 : state.dataLoopNodes->NodeID(0) = "Undefined";
725 728 : state.dataLoopNodes->NodeID(state.dataNodeInputMgr->NumOfUniqueNodeNames) = Name;
726 728 : AssignNodeNumber = 1;
727 728 : state.dataNodeInputMgr->NodeRef(1) = 0;
728 : }
729 :
730 275611 : return AssignNodeNumber;
731 : }
732 :
733 222512 : int GetOnlySingleNode(EnergyPlusData &state,
734 : std::string const &NodeName,
735 : bool &errFlag,
736 : DataLoopNode::ConnectionObjectType const NodeObjectType, // Node Object Type (i.e. "Chiller:Electric")
737 : std::string const &NodeObjectName, // Node Object Name (i.e. "MyChiller")
738 : DataLoopNode::NodeFluidType const nodeFluidType, // Fluidtype for checking/setting node FluidType
739 : DataLoopNode::ConnectionType const nodeConnectionType, // Node Connection Type (see DataLoopNode)
740 : CompFluidStream const NodeFluidStream, // Which Fluid Stream
741 : bool const ObjectIsParent, // True/False
742 : std::string_view const InputFieldName // Input Field Name
743 : )
744 : {
745 :
746 : // FUNCTION INFORMATION:
747 : // AUTHOR Linda K. Lawrie; adapted from GasAbsorptionChiller;Jason Glazer
748 : // DATE WRITTEN December 2001
749 :
750 : // PURPOSE OF THIS FUNCTION:
751 : // This function gets a single node (or error message results) using the
752 : // node id from the input file.
753 :
754 : static constexpr std::string_view RoutineName("GetOnlySingleNode: ");
755 :
756 : int NumNodes;
757 : int NumParams;
758 : int NumAlphas;
759 : int NumNums;
760 :
761 222512 : std::string_view const objTypeStr = BranchNodeConnections::ConnectionObjectTypeNames[static_cast<int>(NodeObjectType)];
762 :
763 222512 : if (state.dataNodeInputMgr->GetOnlySingleNodeFirstTime) {
764 728 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "NodeList", NumParams, NumAlphas, NumNums);
765 728 : state.dataNodeInputMgr->GetOnlySingleNodeNodeNums.dimension(NumParams, 0);
766 728 : state.dataNodeInputMgr->GetOnlySingleNodeFirstTime = false;
767 : }
768 :
769 445024 : GetNodeNums(state,
770 : NodeName,
771 : NumNodes,
772 222512 : state.dataNodeInputMgr->GetOnlySingleNodeNodeNums,
773 : errFlag,
774 : nodeFluidType,
775 : NodeObjectType,
776 : NodeObjectName,
777 : nodeConnectionType,
778 : NodeFluidStream,
779 : ObjectIsParent,
780 : false,
781 : InputFieldName);
782 :
783 222512 : if (NumNodes > 1) {
784 0 : ShowSevereError(state, format("{}{}=\"{}=\", invalid data.", RoutineName, objTypeStr, NodeObjectName));
785 0 : if (!InputFieldName.empty()) {
786 0 : ShowContinueError(state, fmt::format("...Ref field={}", InputFieldName));
787 : }
788 0 : ShowContinueError(state, format("Only 1st Node used from NodeList=\"{}\".", NodeName));
789 0 : ShowContinueError(state, "...a Nodelist may not be valid in this context.");
790 0 : errFlag = true;
791 222512 : } else if (NumNodes == 0) {
792 1203 : state.dataNodeInputMgr->GetOnlySingleNodeNodeNums(1) = 0;
793 : }
794 :
795 222512 : return state.dataNodeInputMgr->GetOnlySingleNodeNodeNums(1);
796 : }
797 :
798 1072 : void InitUniqueNodeCheck(EnergyPlusData &state, std::string const &ContextName)
799 : {
800 :
801 : // SUBROUTINE INFORMATION:
802 : // AUTHOR Linda Lawrie
803 : // DATE WRITTEN November 2002
804 : // MODIFIED na
805 : // RE-ENGINEERED na
806 :
807 : // PURPOSE OF THIS SUBROUTINE:
808 : // This subroutine begins a process of checking for unique node names
809 : // in a sequence of nodes.
810 :
811 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
812 1072 : bool errFlag(false);
813 :
814 : // Begin set up of Uniqueness context
815 :
816 1072 : if (state.dataNodeInputMgr->GetNodeInputFlag) {
817 163 : GetNodeListsInput(state, errFlag);
818 163 : state.dataNodeInputMgr->GetNodeInputFlag = false;
819 : }
820 :
821 1072 : if (!state.dataNodeInputMgr->CurCheckContextName.empty()) {
822 0 : ShowFatalError(state,
823 0 : format("Init Uniqueness called for \"{}, but checks for \"{}\" was already in progress.",
824 : ContextName,
825 0 : state.dataNodeInputMgr->CurCheckContextName));
826 : }
827 1072 : if (ContextName.empty()) {
828 0 : ShowFatalError(state, "Init Uniqueness called with Blank Context Name");
829 : }
830 1072 : if (allocated(state.dataNodeInputMgr->UniqueNodeNames)) {
831 0 : state.dataNodeInputMgr->UniqueNodeNames.deallocate();
832 : }
833 :
834 1072 : state.dataNodeInputMgr->NumCheckNodes = 0;
835 1072 : state.dataNodeInputMgr->MaxCheckNodes = 100;
836 1072 : state.dataNodeInputMgr->UniqueNodeNames.allocate(state.dataNodeInputMgr->MaxCheckNodes);
837 1072 : state.dataNodeInputMgr->CurCheckContextName = ContextName;
838 1072 : }
839 :
840 4551 : void CheckUniqueNodeNames(
841 : EnergyPlusData &state, std::string const &NodeTypes, bool &ErrorsFound, std::string const &CheckName, std::string const &ObjectName)
842 : {
843 :
844 : // SUBROUTINE INFORMATION:
845 : // AUTHOR Linda Lawrie
846 : // DATE WRITTEN November 2002
847 : // MODIFIED na
848 : // RE-ENGINEERED na
849 :
850 : // PURPOSE OF THIS SUBROUTINE:
851 : // This subroutine checks the appropriate input argument for uniqueness.
852 : // Call CheckUniqueNodes(NodeTypes,CheckType,ErrorsFound,CheckName,CheckNumber)
853 : // NodeTypes - used in error message (if any produced)
854 : // ErrorsFound - true if error found by routine
855 : // CheckName - NodeName entered
856 : // ObjectName - "Name" field of object (i.e., CurCheckContextName)
857 :
858 : // METHODOLOGY EMPLOYED:
859 : // checks the current list of items for this (again)
860 :
861 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
862 : int Found;
863 :
864 4551 : if (!CheckName.empty()) {
865 4551 : Found = Util::FindItemInList(CheckName, state.dataNodeInputMgr->UniqueNodeNames, state.dataNodeInputMgr->NumCheckNodes);
866 4551 : if (Found != 0) {
867 0 : ShowSevereError(state, format("{}=\"{}\", duplicate node names found.", state.dataNodeInputMgr->CurCheckContextName, ObjectName));
868 0 : ShowContinueError(state, format("...for Node Type(s)={}, duplicate node name=\"{}\".", NodeTypes, CheckName));
869 0 : ShowContinueError(state, "...Nodes must be unique across instances of this object.");
870 : // CALL ShowSevereError(state, 'Node Types='//TRIM(NodeTypes)//', Non Unique Name found='//TRIM(CheckName))
871 : // CALL ShowContinueError(state, 'Context='//TRIM(CurCheckContextName))
872 0 : ErrorsFound = true;
873 : } else {
874 4551 : ++state.dataNodeInputMgr->NumCheckNodes;
875 4551 : if (state.dataNodeInputMgr->NumCheckNodes > state.dataNodeInputMgr->MaxCheckNodes) {
876 7 : state.dataNodeInputMgr->UniqueNodeNames.redimension(state.dataNodeInputMgr->MaxCheckNodes += 100);
877 : }
878 4551 : state.dataNodeInputMgr->UniqueNodeNames(state.dataNodeInputMgr->NumCheckNodes) = CheckName;
879 : }
880 : }
881 4551 : }
882 :
883 9676 : void CheckUniqueNodeNumbers(
884 : EnergyPlusData &state, std::string const &NodeTypes, bool &ErrorsFound, int const CheckNumber, std::string const &ObjectName)
885 : {
886 :
887 : // SUBROUTINE INFORMATION:
888 : // AUTHOR Linda Lawrie
889 : // DATE WRITTEN November 2002
890 : // MODIFIED na
891 : // RE-ENGINEERED na
892 :
893 : // PURPOSE OF THIS SUBROUTINE:
894 : // This subroutine checks the appropriate input argument for uniqueness.
895 : // Call CheckUniqueNodes(NodeTypes,CheckType,ErrorsFound,CheckName,CheckNumber)
896 : // NodeTypes - used in error message (if any produced)
897 : // ErrorsFound - true if error found by routine
898 : // CheckNumber - Node Number entered
899 : // ObjectName - "Name" field of object (i.e., CurCheckContextName)
900 :
901 : // METHODOLOGY EMPLOYED:
902 : // checks the current list of items for this (again)
903 :
904 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
905 : int Found;
906 :
907 9676 : if (CheckNumber != 0) {
908 9676 : Found = Util::FindItemInList(
909 9676 : state.dataLoopNodes->NodeID(CheckNumber), state.dataNodeInputMgr->UniqueNodeNames, state.dataNodeInputMgr->NumCheckNodes);
910 9676 : if (Found != 0) {
911 0 : ShowSevereError(state, format("{}=\"{}\", duplicate node names found.", state.dataNodeInputMgr->CurCheckContextName, ObjectName));
912 0 : ShowContinueError(state,
913 0 : format("...for Node Type(s)={}, duplicate node name=\"{}\".", NodeTypes, state.dataLoopNodes->NodeID(CheckNumber)));
914 0 : ShowContinueError(state, "...Nodes must be unique across instances of this object.");
915 0 : ErrorsFound = true;
916 : } else {
917 9676 : ++state.dataNodeInputMgr->NumCheckNodes;
918 9676 : if (state.dataNodeInputMgr->NumCheckNodes > state.dataNodeInputMgr->MaxCheckNodes) {
919 23 : state.dataNodeInputMgr->UniqueNodeNames.redimension(state.dataNodeInputMgr->MaxCheckNodes += 100);
920 : }
921 9676 : state.dataNodeInputMgr->UniqueNodeNames(state.dataNodeInputMgr->NumCheckNodes) = state.dataLoopNodes->NodeID(CheckNumber);
922 : }
923 : }
924 9676 : }
925 :
926 1072 : void EndUniqueNodeCheck(EnergyPlusData &state, std::string const &ContextName)
927 : {
928 :
929 : // SUBROUTINE INFORMATION:
930 : // AUTHOR Linda Lawrie
931 : // DATE WRITTEN November 2002
932 : // MODIFIED na
933 : // RE-ENGINEERED na
934 :
935 : // PURPOSE OF THIS SUBROUTINE:
936 : // This subroutine marks the end of a unique node check.
937 :
938 1072 : if (state.dataNodeInputMgr->CurCheckContextName != ContextName) {
939 0 : ShowFatalError(state,
940 0 : format("End Uniqueness called for \"{}, but checks for \"{}\" was in progress.",
941 : ContextName,
942 0 : state.dataNodeInputMgr->CurCheckContextName));
943 : }
944 1072 : if (ContextName.empty()) {
945 0 : ShowFatalError(state, "End Uniqueness called with Blank Context Name");
946 : }
947 1072 : state.dataNodeInputMgr->CurCheckContextName = std::string();
948 1072 : if (allocated(state.dataNodeInputMgr->UniqueNodeNames)) {
949 1072 : state.dataNodeInputMgr->UniqueNodeNames.deallocate();
950 : }
951 1072 : }
952 :
953 1097533 : void CalcMoreNodeInfo(EnergyPlusData &state)
954 : {
955 :
956 : // SUBROUTINE INFORMATION:
957 : // AUTHOR Fred Buhl
958 : // DATE WRITTEN January 2004
959 : // MODIFIED na
960 : // RE-ENGINEERED na
961 :
962 : // PURPOSE OF THIS SUBROUTINE:
963 : // Calculate additional node information for reporting
964 :
965 : // METHODOLOGY EMPLOYED:
966 : // Input is the existing node data plus environment variables. Output is
967 : // stored in MoreNodeInfo.
968 :
969 : // Using/Aliasing
970 : using FluidProperties::GetDensityGlycol;
971 : using FluidProperties::GetSatDensityRefrig;
972 : using FluidProperties::GetSatEnthalpyRefrig;
973 : using FluidProperties::GetSpecificHeatGlycol;
974 : using Psychrometrics::CPCW;
975 : using Psychrometrics::PsyCpAirFnW;
976 : using Psychrometrics::PsyHFnTdbW;
977 : using Psychrometrics::PsyRhFnTdbWPb;
978 : using Psychrometrics::PsyRhoAirFnPbTdbW;
979 : using Psychrometrics::PsyTdpFnWPb;
980 : using Psychrometrics::PsyTwbFnTdbWPb;
981 : using Psychrometrics::RhoH2O;
982 : using ScheduleManager::GetCurrentScheduleValue;
983 :
984 : // SUBROUTINE PARAMETER DEFINITIONS:
985 : static constexpr std::string_view RoutineName("CalcMoreNodeInfo");
986 1097533 : static std::string const NodeReportingCalc("NodeReportingCalc:");
987 :
988 1097533 : auto &RhoAirStdInit = state.dataNodeInputMgr->RhoAirStdInit;
989 1097533 : auto &RhoWaterStdInit = state.dataNodeInputMgr->RhoWaterStdInit;
990 1097533 : auto &NodeWetBulbSchedPtr = state.dataNodeInputMgr->NodeWetBulbSchedPtr;
991 1097533 : auto &NodeRelHumidityRepReq = state.dataNodeInputMgr->NodeRelHumidityRepReq;
992 1097533 : auto &NodeRelHumiditySchedPtr = state.dataNodeInputMgr->NodeRelHumiditySchedPtr;
993 1097533 : auto &NodeDewPointRepReq = state.dataNodeInputMgr->NodeDewPointRepReq;
994 1097533 : auto &NodeDewPointSchedPtr = state.dataNodeInputMgr->NodeDewPointSchedPtr;
995 1097533 : auto &NodeSpecificHeatRepReq = state.dataNodeInputMgr->NodeSpecificHeatRepReq;
996 1097533 : auto &NodeSpecificHeatSchedPtr = state.dataNodeInputMgr->NodeSpecificHeatSchedPtr;
997 1097533 : auto &nodeReportingStrings = state.dataNodeInputMgr->nodeReportingStrings;
998 1097533 : auto &nodeFluidNames = state.dataNodeInputMgr->nodeFluidNames;
999 : bool ReportWetBulb;
1000 : bool ReportRelHumidity;
1001 : bool ReportDewPoint;
1002 : bool ReportSpecificHeat;
1003 : Real64 SteamDensity;
1004 : Real64 EnthSteamInDry;
1005 : Real64 RhoAirCurrent; // temporary value for current air density f(baro, db , W)
1006 : Real64 rho;
1007 : Real64 Cp;
1008 : Real64 rhoStd;
1009 :
1010 1097533 : if (state.dataNodeInputMgr->CalcMoreNodeInfoMyOneTimeFlag) {
1011 794 : RhoAirStdInit = state.dataEnvrn->StdRhoAir;
1012 794 : RhoWaterStdInit = RhoH2O(Constant::InitConvTemp);
1013 794 : state.dataNodeInputMgr->NodeWetBulbRepReq.allocate(state.dataLoopNodes->NumOfNodes);
1014 794 : NodeWetBulbSchedPtr.allocate(state.dataLoopNodes->NumOfNodes);
1015 794 : NodeRelHumidityRepReq.allocate(state.dataLoopNodes->NumOfNodes);
1016 794 : NodeRelHumiditySchedPtr.allocate(state.dataLoopNodes->NumOfNodes);
1017 794 : NodeDewPointRepReq.allocate(state.dataLoopNodes->NumOfNodes);
1018 794 : NodeDewPointSchedPtr.allocate(state.dataLoopNodes->NumOfNodes);
1019 794 : NodeSpecificHeatRepReq.allocate(state.dataLoopNodes->NumOfNodes);
1020 794 : NodeSpecificHeatSchedPtr.allocate(state.dataLoopNodes->NumOfNodes);
1021 794 : nodeReportingStrings.reserve(state.dataLoopNodes->NumOfNodes);
1022 794 : nodeFluidNames.reserve(state.dataLoopNodes->NumOfNodes);
1023 794 : state.dataNodeInputMgr->NodeWetBulbRepReq = false;
1024 794 : NodeWetBulbSchedPtr = 0;
1025 794 : NodeRelHumidityRepReq = false;
1026 794 : NodeRelHumiditySchedPtr = 0;
1027 794 : NodeDewPointRepReq = false;
1028 794 : NodeDewPointSchedPtr = 0;
1029 794 : NodeSpecificHeatRepReq = false;
1030 794 : NodeSpecificHeatSchedPtr = 0;
1031 :
1032 62943 : for (int iNode = 1; iNode <= state.dataLoopNodes->NumOfNodes; ++iNode) {
1033 62149 : nodeReportingStrings.push_back(std::string(NodeReportingCalc + state.dataLoopNodes->NodeID(iNode)));
1034 62149 : nodeFluidNames.push_back(FluidProperties::GetGlycolNameByIndex(state, state.dataLoopNodes->Node(iNode).FluidIndex));
1035 :
1036 2036901 : for (auto const *reqVar : state.dataOutputProcessor->reqVars) {
1037 1974752 : if (Util::SameString(reqVar->key, state.dataLoopNodes->NodeID(iNode)) || reqVar->key.empty()) {
1038 1132803 : if (Util::SameString(reqVar->name, "System Node Wetbulb Temperature")) {
1039 157 : state.dataNodeInputMgr->NodeWetBulbRepReq(iNode) = true;
1040 157 : NodeWetBulbSchedPtr(iNode) = reqVar->SchedPtr;
1041 1132646 : } else if (Util::SameString(reqVar->name, "System Node Relative Humidity")) {
1042 22 : NodeRelHumidityRepReq(iNode) = true;
1043 22 : NodeRelHumiditySchedPtr(iNode) = reqVar->SchedPtr;
1044 1132624 : } else if (Util::SameString(reqVar->name, "System Node Dewpoint Temperature")) {
1045 22 : NodeDewPointRepReq(iNode) = true;
1046 22 : NodeDewPointSchedPtr(iNode) = reqVar->SchedPtr;
1047 1132602 : } else if (Util::SameString(reqVar->name, "System Node Specific Heat")) {
1048 0 : NodeSpecificHeatRepReq(iNode) = true;
1049 0 : NodeSpecificHeatSchedPtr(iNode) = reqVar->SchedPtr;
1050 : }
1051 : }
1052 62149 : }
1053 62149 : if (EMSManager::CheckIfNodeMoreInfoSensedByEMS(state, iNode, "System Node Wetbulb Temperature")) {
1054 0 : state.dataNodeInputMgr->NodeWetBulbRepReq(iNode) = true;
1055 0 : NodeWetBulbSchedPtr(iNode) = 0;
1056 : }
1057 62149 : if (EMSManager::CheckIfNodeMoreInfoSensedByEMS(state, iNode, "System Node Relative Humidity")) {
1058 1 : NodeRelHumidityRepReq(iNode) = true;
1059 1 : NodeRelHumiditySchedPtr(iNode) = 0;
1060 : }
1061 62149 : if (EMSManager::CheckIfNodeMoreInfoSensedByEMS(state, iNode, "System Node Dewpoint Temperature")) {
1062 0 : NodeDewPointRepReq(iNode) = true;
1063 0 : NodeDewPointSchedPtr(iNode) = 0;
1064 : }
1065 62149 : if (EMSManager::CheckIfNodeMoreInfoSensedByEMS(state, iNode, "System Node Specific Heat")) {
1066 0 : NodeSpecificHeatRepReq(iNode) = true;
1067 0 : NodeSpecificHeatSchedPtr(iNode) = 0;
1068 : }
1069 : }
1070 794 : state.dataNodeInputMgr->CalcMoreNodeInfoMyOneTimeFlag = false;
1071 : }
1072 :
1073 66713253 : for (int iNode = 1; iNode <= state.dataLoopNodes->NumOfNodes; ++iNode) {
1074 65615720 : ReportWetBulb = false;
1075 65615720 : ReportRelHumidity = false;
1076 65615720 : ReportDewPoint = false;
1077 65615720 : ReportSpecificHeat = false;
1078 65615720 : if (state.dataNodeInputMgr->NodeWetBulbRepReq(iNode) && NodeWetBulbSchedPtr(iNode) > 0) {
1079 0 : ReportWetBulb = (GetCurrentScheduleValue(state, NodeWetBulbSchedPtr(iNode)) > 0.0);
1080 65615720 : } else if (state.dataNodeInputMgr->NodeWetBulbRepReq(iNode) && NodeWetBulbSchedPtr(iNode) == 0) {
1081 82194 : ReportWetBulb = true;
1082 65533526 : } else if (state.dataLoopNodes->Node(iNode).SPMNodeWetBulbRepReq) {
1083 674 : ReportWetBulb = true;
1084 : }
1085 65615720 : if (NodeRelHumidityRepReq(iNode) && NodeRelHumiditySchedPtr(iNode) > 0) {
1086 0 : ReportRelHumidity = (GetCurrentScheduleValue(state, NodeRelHumiditySchedPtr(iNode)) > 0.0);
1087 65615720 : } else if (NodeRelHumidityRepReq(iNode) && NodeRelHumiditySchedPtr(iNode) == 0) {
1088 12978 : ReportRelHumidity = true;
1089 : }
1090 65615720 : if (NodeDewPointRepReq(iNode) && NodeDewPointSchedPtr(iNode) > 0) {
1091 0 : ReportDewPoint = (GetCurrentScheduleValue(state, NodeDewPointSchedPtr(iNode)) > 0.0);
1092 65615720 : } else if (NodeDewPointRepReq(iNode) && NodeDewPointSchedPtr(iNode) == 0) {
1093 172250 : ReportDewPoint = true;
1094 : }
1095 65615720 : if (NodeSpecificHeatRepReq(iNode) && NodeSpecificHeatSchedPtr(iNode) > 0) {
1096 0 : ReportSpecificHeat = (GetCurrentScheduleValue(state, NodeSpecificHeatSchedPtr(iNode)) > 0.0);
1097 65615720 : } else if (NodeSpecificHeatRepReq(iNode) && NodeSpecificHeatSchedPtr(iNode) == 0) {
1098 0 : ReportSpecificHeat = true;
1099 : }
1100 : // calculate the volume flow rate
1101 65615720 : if (state.dataLoopNodes->Node(iNode).FluidType == DataLoopNode::NodeFluidType::Air) {
1102 39109161 : state.dataLoopNodes->MoreNodeInfo(iNode).VolFlowRateStdRho = state.dataLoopNodes->Node(iNode).MassFlowRate / RhoAirStdInit;
1103 : // if Node%Press was reliable could be used here.
1104 78218322 : RhoAirCurrent = PsyRhoAirFnPbTdbW(
1105 39109161 : state, state.dataEnvrn->OutBaroPress, state.dataLoopNodes->Node(iNode).Temp, state.dataLoopNodes->Node(iNode).HumRat);
1106 39109161 : state.dataLoopNodes->MoreNodeInfo(iNode).Density = RhoAirCurrent;
1107 39109161 : if (RhoAirCurrent != 0.0)
1108 39109161 : state.dataLoopNodes->MoreNodeInfo(iNode).VolFlowRateCrntRho = state.dataLoopNodes->Node(iNode).MassFlowRate / RhoAirCurrent;
1109 39109161 : state.dataLoopNodes->MoreNodeInfo(iNode).ReportEnthalpy =
1110 39109161 : PsyHFnTdbW(state.dataLoopNodes->Node(iNode).Temp, state.dataLoopNodes->Node(iNode).HumRat);
1111 39109161 : if (ReportWetBulb) {
1112 : // if Node%Press was reliable could be used here.
1113 165736 : state.dataLoopNodes->MoreNodeInfo(iNode).WetBulbTemp = PsyTwbFnTdbWPb(state,
1114 82868 : state.dataLoopNodes->Node(iNode).Temp,
1115 82868 : state.dataLoopNodes->Node(iNode).HumRat,
1116 82868 : state.dataEnvrn->OutBaroPress,
1117 82868 : nodeReportingStrings[iNode - 1]);
1118 : } else {
1119 39026293 : state.dataLoopNodes->MoreNodeInfo(iNode).WetBulbTemp = 0.0;
1120 : }
1121 39109161 : if (ReportDewPoint) {
1122 172250 : state.dataLoopNodes->MoreNodeInfo(iNode).AirDewPointTemp =
1123 344500 : PsyTdpFnWPb(state, state.dataLoopNodes->Node(iNode).HumRat, state.dataEnvrn->OutBaroPress);
1124 : } else {
1125 38936911 : state.dataLoopNodes->MoreNodeInfo(iNode).AirDewPointTemp = 0.0;
1126 : }
1127 39109161 : if (ReportRelHumidity) {
1128 : // if Node%Press was reliable could be used here.
1129 : // following routines don't issue psych errors and may be more reliable.
1130 25956 : state.dataLoopNodes->MoreNodeInfo(iNode).RelHumidity = 100.0 * PsyRhFnTdbWPb(state,
1131 12978 : state.dataLoopNodes->Node(iNode).Temp,
1132 12978 : state.dataLoopNodes->Node(iNode).HumRat,
1133 12978 : state.dataEnvrn->OutBaroPress,
1134 12978 : nodeReportingStrings[iNode - 1]);
1135 : } else {
1136 39096183 : state.dataLoopNodes->MoreNodeInfo(iNode).RelHumidity = 0.0;
1137 : }
1138 39109161 : if (ReportSpecificHeat) { // only call psych routine if needed.
1139 0 : state.dataLoopNodes->MoreNodeInfo(iNode).SpecificHeat = PsyCpAirFnW(state.dataLoopNodes->Node(iNode).HumRat);
1140 : } else {
1141 39109161 : state.dataLoopNodes->MoreNodeInfo(iNode).SpecificHeat = 0.0;
1142 : }
1143 26506559 : } else if (state.dataLoopNodes->Node(iNode).FluidType == DataLoopNode::NodeFluidType::Water) {
1144 :
1145 52782174 : if (!((state.dataLoopNodes->Node(iNode).FluidIndex > 0) &&
1146 26369836 : (state.dataLoopNodes->Node(iNode).FluidIndex <= state.dataFluidProps->glycols.isize()))) {
1147 42502 : rho = RhoWaterStdInit;
1148 42502 : rhoStd = RhoWaterStdInit;
1149 42502 : Cp = CPCW(state.dataLoopNodes->Node(iNode).Temp);
1150 : } else {
1151 52739672 : Cp = GetSpecificHeatGlycol(state,
1152 26369836 : nodeFluidNames[iNode - 1],
1153 26369836 : state.dataLoopNodes->Node(iNode).Temp,
1154 26369836 : state.dataLoopNodes->Node(iNode).FluidIndex,
1155 26369836 : nodeReportingStrings[iNode - 1]);
1156 52739672 : rhoStd = GetDensityGlycol(state,
1157 26369836 : nodeFluidNames[iNode - 1],
1158 : Constant::InitConvTemp,
1159 26369836 : state.dataLoopNodes->Node(iNode).FluidIndex,
1160 26369836 : nodeReportingStrings[iNode - 1]);
1161 52739672 : rho = GetDensityGlycol(state,
1162 26369836 : nodeFluidNames[iNode - 1],
1163 26369836 : state.dataLoopNodes->Node(iNode).Temp,
1164 26369836 : state.dataLoopNodes->Node(iNode).FluidIndex,
1165 26369836 : nodeReportingStrings[iNode - 1]);
1166 : }
1167 :
1168 26412338 : state.dataLoopNodes->MoreNodeInfo(iNode).VolFlowRateStdRho = state.dataLoopNodes->Node(iNode).MassFlowRate / rhoStd;
1169 26412338 : state.dataLoopNodes->MoreNodeInfo(iNode).VolFlowRateCrntRho = state.dataLoopNodes->Node(iNode).MassFlowRate / rho;
1170 26412338 : state.dataLoopNodes->MoreNodeInfo(iNode).Density = rho;
1171 26412338 : state.dataLoopNodes->MoreNodeInfo(iNode).ReportEnthalpy = Cp * state.dataLoopNodes->Node(iNode).Temp;
1172 26412338 : state.dataLoopNodes->MoreNodeInfo(iNode).SpecificHeat = Cp; // always fill since cp already always being calculated anyway
1173 26412338 : state.dataLoopNodes->MoreNodeInfo(iNode).WetBulbTemp = 0.0;
1174 26412338 : state.dataLoopNodes->MoreNodeInfo(iNode).RelHumidity = 100.0;
1175 94221 : } else if (state.dataLoopNodes->Node(iNode).FluidType == DataLoopNode::NodeFluidType::Steam) {
1176 72608 : if (state.dataLoopNodes->Node(iNode).Quality == 1.0) {
1177 49613 : SteamDensity = GetSatDensityRefrig(state,
1178 : fluidNameSteam,
1179 49613 : state.dataLoopNodes->Node(iNode).Temp,
1180 49613 : state.dataLoopNodes->Node(iNode).Quality,
1181 49613 : state.dataLoopNodes->Node(iNode).FluidIndex,
1182 : RoutineName);
1183 49613 : EnthSteamInDry = GetSatEnthalpyRefrig(state,
1184 : fluidNameSteam,
1185 49613 : state.dataLoopNodes->Node(iNode).Temp,
1186 49613 : state.dataLoopNodes->Node(iNode).Quality,
1187 49613 : state.dataLoopNodes->Node(iNode).FluidIndex,
1188 : RoutineName);
1189 49613 : state.dataLoopNodes->MoreNodeInfo(iNode).VolFlowRateStdRho = state.dataLoopNodes->Node(iNode).MassFlowRate / SteamDensity;
1190 49613 : state.dataLoopNodes->MoreNodeInfo(iNode).ReportEnthalpy = EnthSteamInDry;
1191 49613 : state.dataLoopNodes->MoreNodeInfo(iNode).WetBulbTemp = 0.0;
1192 49613 : state.dataLoopNodes->MoreNodeInfo(iNode).RelHumidity = 0.0;
1193 22995 : } else if (state.dataLoopNodes->Node(iNode).Quality == 0.0) { // The node has condensate water through it
1194 22035 : state.dataLoopNodes->MoreNodeInfo(iNode).VolFlowRateStdRho = state.dataLoopNodes->Node(iNode).MassFlowRate / RhoWaterStdInit;
1195 22035 : state.dataLoopNodes->MoreNodeInfo(iNode).ReportEnthalpy =
1196 22035 : CPCW(state.dataLoopNodes->Node(iNode).Temp) * state.dataLoopNodes->Node(iNode).Temp;
1197 22035 : state.dataLoopNodes->MoreNodeInfo(iNode).WetBulbTemp = 0.0;
1198 22035 : state.dataLoopNodes->MoreNodeInfo(iNode).RelHumidity = 0.0;
1199 : }
1200 21613 : } else if (state.dataLoopNodes->Node(iNode).FluidType == DataLoopNode::NodeFluidType::Electric) {
1201 6544 : state.dataLoopNodes->MoreNodeInfo(iNode).VolFlowRateStdRho = 0.0;
1202 6544 : state.dataLoopNodes->MoreNodeInfo(iNode).ReportEnthalpy = 0.0;
1203 6544 : state.dataLoopNodes->MoreNodeInfo(iNode).WetBulbTemp = 0.0;
1204 6544 : state.dataLoopNodes->MoreNodeInfo(iNode).RelHumidity = 0.0;
1205 6544 : state.dataLoopNodes->MoreNodeInfo(iNode).SpecificHeat = 0.0;
1206 : } else {
1207 15069 : state.dataLoopNodes->MoreNodeInfo(iNode).VolFlowRateStdRho = state.dataLoopNodes->Node(iNode).MassFlowRate / RhoAirStdInit;
1208 15069 : if (state.dataLoopNodes->Node(iNode).HumRat > 0.0) {
1209 0 : state.dataLoopNodes->MoreNodeInfo(iNode).ReportEnthalpy =
1210 0 : PsyHFnTdbW(state.dataLoopNodes->Node(iNode).Temp, state.dataLoopNodes->Node(iNode).HumRat);
1211 0 : if (ReportWetBulb) {
1212 0 : state.dataLoopNodes->MoreNodeInfo(iNode).WetBulbTemp = PsyTwbFnTdbWPb(
1213 0 : state, state.dataLoopNodes->Node(iNode).Temp, state.dataLoopNodes->Node(iNode).HumRat, state.dataEnvrn->StdBaroPress);
1214 : } else {
1215 0 : state.dataLoopNodes->MoreNodeInfo(iNode).WetBulbTemp = 0.0;
1216 : }
1217 0 : if (ReportSpecificHeat) {
1218 0 : state.dataLoopNodes->MoreNodeInfo(iNode).SpecificHeat = PsyCpAirFnW(state.dataLoopNodes->Node(iNode).HumRat);
1219 : } else {
1220 0 : state.dataLoopNodes->MoreNodeInfo(iNode).SpecificHeat = 0.0;
1221 : }
1222 : } else {
1223 15069 : state.dataLoopNodes->MoreNodeInfo(iNode).ReportEnthalpy =
1224 15069 : CPCW(state.dataLoopNodes->Node(iNode).Temp) * state.dataLoopNodes->Node(iNode).Temp;
1225 15069 : state.dataLoopNodes->MoreNodeInfo(iNode).WetBulbTemp = 0.0;
1226 15069 : state.dataLoopNodes->MoreNodeInfo(iNode).SpecificHeat = 0.0;
1227 : }
1228 : }
1229 : }
1230 1097533 : }
1231 :
1232 66 : void MarkNode(EnergyPlusData &state,
1233 : int const NodeNumber, // Node Number to be marked
1234 : DataLoopNode::ConnectionObjectType const ObjectType,
1235 : std::string const &ObjectName,
1236 : std::string const &FieldName)
1237 : {
1238 :
1239 : // SUBROUTINE INFORMATION:
1240 : // AUTHOR Linda Lawrie
1241 : // DATE WRITTEN March 2004
1242 : // MODIFIED na
1243 : // RE-ENGINEERED na
1244 :
1245 : // PURPOSE OF THIS SUBROUTINE:
1246 : // This subroutine marks a node -- this node needs to exist in more than one object.
1247 :
1248 66 : state.dataLoopNodes->MarkedNode(NodeNumber).IsMarked = true;
1249 66 : state.dataLoopNodes->MarkedNode(NodeNumber).ObjectType = ObjectType;
1250 66 : state.dataLoopNodes->MarkedNode(NodeNumber).ObjectName = ObjectName;
1251 66 : state.dataLoopNodes->MarkedNode(NodeNumber).FieldName = FieldName;
1252 66 : }
1253 :
1254 795 : void CheckMarkedNodes(EnergyPlusData &state, bool &ErrorsFound)
1255 : {
1256 :
1257 : // SUBROUTINE INFORMATION:
1258 : // AUTHOR Linda Lawrie
1259 : // DATE WRITTEN March 2004
1260 : // MODIFIED na
1261 : // RE-ENGINEERED na
1262 :
1263 : // PURPOSE OF THIS SUBROUTINE:
1264 : // This subroutine checks "marked" nodes.
1265 :
1266 63030 : for (int NodeNum = 1; NodeNum <= state.dataLoopNodes->NumOfNodes; ++NodeNum) {
1267 62235 : if (state.dataLoopNodes->MarkedNode(NodeNum).IsMarked) {
1268 57 : if (state.dataNodeInputMgr->NodeRef(NodeNum) == 0) {
1269 : std::string_view objType =
1270 0 : BranchNodeConnections::ConnectionObjectTypeNames[static_cast<int>(state.dataLoopNodes->MarkedNode(NodeNum).ObjectType)];
1271 0 : ShowSevereError(state, format("Node=\"{}\" did not find reference by another object.", state.dataLoopNodes->NodeID(NodeNum)));
1272 0 : ShowContinueError(state,
1273 0 : format(R"(Object="{}", Name="{}", Field=[{}])",
1274 : objType,
1275 0 : state.dataLoopNodes->MarkedNode(NodeNum).ObjectName,
1276 0 : state.dataLoopNodes->MarkedNode(NodeNum).FieldName));
1277 0 : ErrorsFound = true;
1278 : }
1279 : }
1280 : }
1281 795 : }
1282 :
1283 : } // namespace EnergyPlus::NodeInputManager
|