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