@@ -287,7 +287,7 @@ namespace AirflowNetwork {
287287
288288 if (AirflowNetworkFanActivated && distribution_simulated) {
289289 if (ValidateDistributionSystemFlag) {
290- validate_distribution ();
290+ finalize_distribution ();
291291 validate_fan_flowrate();
292292 ValidateDistributionSystemFlag = false;
293293 if (simulation_control.autosize_ducts) {
@@ -3923,7 +3923,7 @@ namespace AirflowNetwork {
39233923 DisSysNodeData(i).node_name = Alphas(2); // Name of associated EnergyPlus node
39243924 DisSysNodeData(i).EPlusType = Alphas(3); // Name of associated EnergyPlus type
39253925 DisSysNodeData(i).Height = Numbers(1); // Nodal height
3926- DisSysNodeData(i).EPlusNodeNum = 0; // EPlus node number
3926+ DisSysNodeData(i).node_number = 0; // EPlus node number
39273927 // verify EnergyPlus object type
39283928 if (Util::SameString(Alphas(3), "AirLoopHVAC:ZoneMixer") || Util::SameString(Alphas(3), "AirLoopHVAC:ZoneSplitter") ||
39293929 Util::SameString(Alphas(3), "AirLoopHVAC:OutdoorAirSystem") || Util::SameString(Alphas(3), "OAMixerOutdoorAirStreamNode") ||
@@ -4261,7 +4261,7 @@ namespace AirflowNetwork {
42614261 AirflowNetworkNodeData(i).NodeTypeNum = 0;
42624262 AirflowNetworkNodeData(i).EPlusZoneNum = 0;
42634263 AirflowNetworkNodeData(i).NodeHeight = DisSysNodeData(i - NumOfNodesMultiZone).Height;
4264- AirflowNetworkNodeData(i).EPlusNodeNum = DisSysNodeData(i - NumOfNodesMultiZone).EPlusNodeNum ;
4264+ AirflowNetworkNodeData(i).EPlusNodeNum = DisSysNodeData(i - NumOfNodesMultiZone).node_number ;
42654265 // Get mixer information
42664266 if (Util::SameString(DisSysNodeData(i - NumOfNodesMultiZone).EPlusType, "AirLoopHVAC:ZoneMixer")) {
42674267 AirflowNetworkNodeData(i).EPlusTypeNum = NodeType::MIX;
@@ -9992,17 +9992,19 @@ namespace AirflowNetwork {
99929992 OpenFactorMult = 1.0;
99939993 } else if (DelEnthal >= UpperValInOutEnthalDiff) {
99949994 OpenFactorMult = LimValVentOpenFacMult;
9995- } else {
9996- OpenFactorMult =
9997- LimValVentOpenFacMult + ((UpperValInOutEnthalDiff - DelEnthal) / (UpperValInOutEnthalDiff - LowerValInOutEnthalDiff)) *
9998- (1 - LimValVentOpenFacMult);
9995+ }
9996+ else {
9997+ OpenFactorMult =
9998+ LimValVentOpenFacMult + ((UpperValInOutEnthalDiff - DelEnthal) / (UpperValInOutEnthalDiff - LowerValInOutEnthalDiff)) *
9999+ (1 - LimValVentOpenFacMult);
999910000 }
1000010001 OpenFactor *= OpenFactorMult;
1000110002 m_state.dataSurface->SurfWinVentingOpenFactorMultRep(SurfNum) = OpenFactorMult;
1000210003 }
10003- } else {
10004- OpenFactor = 0.0;
10005- m_state.dataSurface->SurfWinVentingOpenFactorMultRep(SurfNum) = -1.0;
10004+ }
10005+ else {
10006+ OpenFactor = 0.0;
10007+ m_state.dataSurface->SurfWinVentingOpenFactorMultRep(SurfNum) = -1.0;
1000610008 }
1000710009 }
1000810010
@@ -10022,13 +10024,16 @@ namespace AirflowNetwork {
1002210024 m_state.dataThermalComforts->ThermalComfortData(PeopleInd).TComfASH55) {
1002310025 OpenFactor = MultizoneSurfaceData(i).Factor;
1002410026 m_state.dataSurface->SurfWinVentingOpenFactorMultRep(SurfNum) = 1.0;
10025- } else {
10027+ }
10028+ else {
1002610029 OpenFactor = 0.0;
1002710030 }
10028- } else {
10031+ }
10032+ else {
1002910033 OpenFactor = 0.0;
1003010034 }
10031- } else {
10035+ }
10036+ else {
1003210037 OpenFactor = 0.0;
1003310038 }
1003410039 }
@@ -10041,13 +10046,16 @@ namespace AirflowNetwork {
1004110046 m_state.dataThermalComforts->ThermalComfortData(PeopleInd).TComfCEN15251) {
1004210047 OpenFactor = MultizoneSurfaceData(i).Factor;
1004310048 m_state.dataSurface->SurfWinVentingOpenFactorMultRep(SurfNum) = 1.0;
10044- } else {
10049+ }
10050+ else {
1004510051 OpenFactor = 0.0;
1004610052 }
10047- } else {
10053+ }
10054+ else {
1004810055 OpenFactor = 0.0;
1004910056 }
10050- } else {
10057+ }
10058+ else {
1005110059 OpenFactor = 0.0;
1005210060 }
1005310061 }
@@ -10078,7 +10086,26 @@ namespace AirflowNetwork {
1007810086 }
1007910087 }
1008010088
10081- void Solver::validate_distribution()
10089+ bool Solver::validate_network()
10090+ {
10091+ bool result = true;
10092+ // Technically, the nodes could be verified at input time with a bunch of string comparisons on the names,
10093+ // but this will likely be faster and should get the same result
10094+ std::vector<int> nodes_already_in_use;
10095+ for (auto& node : DisSysNodeData) {
10096+ if (node.node_number)
10097+ if (std::find(nodes_already_in_use.begin(), nodes_already_in_use.end(), node.node_number) == nodes_already_in_use.end()) {
10098+ // Node number already in use
10099+ ShowWarningError(m_state, format("validate_network: Node \"{}\" (node number {}) is used more than once as an AirflowNetwork distribution node, verify that this matches the modeling intent", node.node_name, node.node_number));
10100+ result = false;
10101+ } else {
10102+ nodes_already_in_use.push_back(node.node_number);
10103+ }
10104+ }
10105+ return result;
10106+ }
10107+
10108+ void Solver::finalize_distribution()
1008210109 {
1008310110
1008410111 // SUBROUTINE INFORMATION:
@@ -10088,9 +10115,14 @@ namespace AirflowNetwork {
1008810115 // RE-ENGINEERED na
1008910116
1009010117 // PURPOSE OF THIS SUBROUTINE:
10091- // This subroutine validates the inputs of distribution system, since node data from a primary airloop
10092- // are not available in the first call during reading input data of airflownetwork objects.
10093- // Note: this routine shouldn't be called more than once
10118+ // This subroutine finalizes the inputs of distribution system, since node data from a primary airloop
10119+ // are not available in the first call during reading input data of AirflowNetwork objects.
10120+ // Note: this routine shouldn't be called more than once, which is enforced with the distribution_is_final
10121+ // flag. Some of the validation may be moved to the validate_network function.
10122+
10123+ if (distribution_is_final) {
10124+ return;
10125+ }
1009410126
1009510127 // Using/Aliasing
1009610128 using BranchNodeConnections::GetNodeConnectionType;
@@ -10148,7 +10180,7 @@ namespace AirflowNetwork {
1014810180 "The entered name is " + DisSysNodeData(i).node_name + " in an AirflowNetwork:Distribution:Node object.");
1014910181 ErrorsFound = true;
1015010182 }
10151- DisSysNodeData(i).EPlusNodeNum = j;
10183+ DisSysNodeData(i).node_number = j;
1015210184 AirflowNetworkNodeData(NumOfNodesMultiZone + i).EPlusNodeNum = j;
1015310185 AirflowNetworkNodeData(NumOfNodesMultiZone + i).AirLoopNum = DisSysNodeData(i).AirLoopNum;
1015410186 NodeFound(j) = true;
@@ -10168,7 +10200,7 @@ namespace AirflowNetwork {
1016810200 ErrorsFound = true;
1016910201 }
1017010202 }
10171- if (DisSysNodeData(i).EPlusNodeNum == 0) {
10203+ if (DisSysNodeData(i).node_number == 0) {
1017210204 ShowSevereError(m_state,
1017310205 format(RoutineName) +
1017410206 "Primary Air Loop Node is not found in AIRFLOWNETWORK:DISTRIBUTION:NODE = " + DisSysNodeData(i).Name);
@@ -11007,6 +11039,9 @@ namespace AirflowNetwork {
1100711039 }
1100811040 if (NumOfFans > 1) break;
1100911041 }
11042+
11043+ distribution_is_final = true;
11044+
1101011045 if (NumOfFans > 1) {
1101111046 ShowSevereError(m_state,
1101211047 format(RoutineName) + "An AirLoop branch, " + m_state.dataAirSystemsData->PrimaryAirSystems(1).Branch(BranchNum).Name +
0 commit comments