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