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