Skip to content

Commit e83cd80

Browse files
author
Matt Mitchell
committed
Merge branch 'develop' into fix_unitary_system_afn_runtime_fracs_alt
2 parents 0ee296b + 93c7e0c commit e83cd80

13 files changed

Lines changed: 1896 additions & 464 deletions

File tree

.github/workflows/test_pull_requests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,5 +281,5 @@ jobs:
281281
- name: Fail on Regressions from Forked Repository
282282
if: always() && matrix.run_regressions && steps.regressions.outcome == 'failure' && github.event.pull_request.head.repo.full_name != 'NatLabRockies/EnergyPlus'
283283
run: |
284-
echo "::error::Regressions detected in pull request from forked repository, check job summary for details and to download regression results"
284+
echo "::error::Regressions detected in pull request from forked repository. Download regression results: ${{ steps.upload_regressions.outputs.artifact-url }}"
285285
exit 1

design/FY2026/NFP_SkyLW_Actuator.md

Lines changed: 240 additions & 0 deletions
Large diffs are not rendered by default.

doc/input-output-reference/src/overview/group-surface-construction-elements.tex

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4071,6 +4071,10 @@ \subsubsection{Outputs}\label{outputs-36-1}
40714071

40724072
This output is the heat energy added after material layer N from the EMS heat flux actuator (Component type: ``CondFD Surface Material Layer''; Control type: ``Heat Flux''). Energy is aggregated on the electricity meter and is only valid for the CondFD solution algorithm.
40734073

4074+
\paragraph{CondFD EMS Sky Longwave Radiation Override Heat Flux}
4075+
4076+
This output is the user-specified net sky longwave radiation heat flux applied to the exterior surface via the EMS actuator (Component type: ``CondFD Surface''; Control type: ``Sky Longwave Radiation Override''). Reports 0.0 when not actuated. Only valid for exterior CondFD surfaces.
4077+
40744078
\subsection{Construction:AirBoundary}\label{constructionairboundary}
40754079

40764080
Construction:AirBoundary indicates an open boundary between two zones. It may be used for base surfaces and fenestration surfaces.

doc/readthedocs/sphinx/ems-application-guide/ems-application-guide.rst

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2523,6 +2523,20 @@ described below.
25232523
used to add energy (i.e. positive numbers only), and the energy used
25242524
is added to the electric heating sub-meter.
25252525

2526+
A separate actuator, called “CondFD Surface,” is available for exterior
2527+
surfaces that use the Conduction Finite Difference solution algorithm.
2528+
Unlike the material-layer actuators above, this actuator operates on the
2529+
surface as a whole and is identified by the surface name alone (not
2530+
SurfName:MatName).
2531+
2532+
- “Sky Longwave Radiation Override”. Has units of [W/m2]. Replaces
2533+
the default sky longwave radiation term (h_sky * (T_sky - T_surf))
2534+
in the exterior face heat balance with a user-specified net heat
2535+
flux. Positive values indicate net radiation into the surface;
2536+
negative values indicate net radiation leaving the surface (cooling).
2537+
Only applies to exterior CondFD surfaces. The actuated component
2538+
unique name is the surface name (e.g. “ZN001:ROOF001”).
2539+
25262540
Conduction Finite Difference Outputs
25272541
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
25282542

@@ -2554,6 +2568,15 @@ CondFD EMS Heat Source Energy After Layer N
25542568

25552569
This output reports the heat energy added after material layer N
25562570

2571+
- Zone,Average,CondFD EMS Sky Longwave Radiation Override Heat Flux [W/m2]
2572+
2573+
CondFD EMS Sky Longwave Radiation Override Heat Flux
2574+
''''''''''''''''''''''''''''''''''''''''''''''''''''
2575+
2576+
This output reports the user-specified net sky longwave radiation heat
2577+
flux applied to the exterior surface via the EMS actuator. Reports 0.0
2578+
when not actuated.
2579+
25572580
Air Movement
25582581
------------
25592582

src/EnergyPlus/HeatBalFiniteDiffManager.cc

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,6 +1038,24 @@ namespace HeatBalFiniteDiffManager {
10381038
OutputProcessor::Group::Building,
10391039
OutputProcessor::EndUseCat::Heating);
10401040
}
1041+
1042+
// Setup EMS Actuator for Sky LW Radiation Override (per-surface)
1043+
if (state.dataSurface->Surface(SurfNum).ExtBoundCond == DataSurfaces::ExternalEnvironment) {
1044+
EnergyPlus::SetupEMSActuator(state,
1045+
"CondFD Surface",
1046+
state.dataSurface->Surface(SurfNum).Name,
1047+
"Sky Longwave Radiation Override",
1048+
"[W/m2]",
1049+
SurfaceFD(SurfNum).enetActuator.isActuated,
1050+
SurfaceFD(SurfNum).enetActuator.actuatedValue);
1051+
SetupOutputVariable(state,
1052+
"CondFD EMS Sky Longwave Radiation Override Heat Flux",
1053+
Constant::Units::W_m2,
1054+
SurfaceFD(SurfNum).enetActuatorReport,
1055+
OutputProcessor::TimeStepType::Zone,
1056+
OutputProcessor::StoreType::Average,
1057+
state.dataSurface->Surface(SurfNum).Name);
1058+
}
10411059
}
10421060

10431061
int TotNodes = ConstructFD(state.dataSurface->Surface(SurfNum).Construction).TotNodes; // Full size nodes, start with outside face.
@@ -1594,6 +1612,8 @@ namespace HeatBalFiniteDiffManager {
15941612

15951613
auto &s_hbfd = state.dataHeatBalFiniteDiffMgr;
15961614
auto const &surface(state.dataSurface->Surface(Surf));
1615+
auto &surfaceFD = s_hbfd->SurfaceFD(Surf);
1616+
surfaceFD.enetActuatorReport = surfaceFD.enetActuator.isActuated ? surfaceFD.enetActuator.actuatedValue : 0.0;
15971617
int const surface_ExtBoundCond(surface.ExtBoundCond);
15981618

15991619
Real64 Tsky;
@@ -1625,7 +1645,6 @@ namespace HeatBalFiniteDiffManager {
16251645
if (surface_ExtBoundCond == Surf) { // adiabatic surface, PT added since it is not the same as interzone wall
16261646
// as Outside Boundary Condition Object can be left blank.
16271647

1628-
auto &surfaceFD = s_hbfd->SurfaceFD(Surf);
16291648
InteriorBCEqns(state,
16301649
Delt,
16311650
NodeIn,
@@ -1699,7 +1718,6 @@ namespace HeatBalFiniteDiffManager {
16991718

17001719
// Boundary Conditions from Simulation for Exterior
17011720
Real64 const hconvo(state.dataMstBal->HConvExtFD(Surf));
1702-
17031721
Real64 const hrad(state.dataMstBal->HAirFD(Surf));
17041722
Real64 const hsky(state.dataMstBal->HSkyFD(Surf));
17051723
Real64 const hgnd(state.dataMstBal->HGrndFD(Surf));
@@ -1708,6 +1726,11 @@ namespace HeatBalFiniteDiffManager {
17081726
Real64 const Tgnd(Tgndsurface);
17091727
Real64 const Tsurr(TsurrSurface);
17101728

1729+
// Sky longwave radiation actuator and reusable variables
1730+
auto const &enetAct = s_hbfd->SurfaceFD(Surf).enetActuator;
1731+
Real64 const eHsky = (enetAct.isActuated) ? 0.0 : hsky;
1732+
Real64 const eHskyTsky = (enetAct.isActuated) ? enetAct.actuatedValue : hsky * Tsky;
1733+
17111734
if (surface.HeatTransferAlgorithm == DataSurfaces::HeatTransferModel::CondFD) {
17121735

17131736
int const ConstrNum(surface.Construction);
@@ -1724,8 +1747,8 @@ namespace HeatBalFiniteDiffManager {
17241747
if (mat->ROnly || mat->group == Material::Group::AirGap) { // R Layer or Air Layer **********
17251748
// Use algebraic equation for TDT based on R
17261749
Real64 const Rlayer(mat->Resistance);
1727-
TDT_i = (TDT_p + (QRadSWOutFD + hgnd * Tgnd + (hconvo + hrad) * Toa + hsky * Tsky + hsurr * Tsurr) * Rlayer) /
1728-
(1.0 + (hconvo + hgnd + hrad + hsky + hsurr) * Rlayer);
1750+
TDT_i = (TDT_p + (QRadSWOutFD + hgnd * Tgnd + (hconvo + hrad) * Toa + eHskyTsky + hsurr * Tsurr) * Rlayer) /
1751+
(1.0 + (hconvo + hgnd + hrad + eHsky + hsurr) * Rlayer);
17291752

17301753
} else { // Regular or phase change material layer
17311754

@@ -1793,27 +1816,27 @@ namespace HeatBalFiniteDiffManager {
17931816
if (s_hbfd->CondFDSchemeType == CondFDScheme::CrankNicholsonSecondOrder) { // Second Order equation
17941817
Real64 const Cp_DelX_RhoS_2Delt(Cp * DelX * RhoS / (2.0 * Delt));
17951818
Real64 const kt_2DelX(kt / (2.0 * DelX));
1796-
Real64 const hsum(0.5 * (hconvo + hgnd + hrad + hsky + hsurr));
1819+
Real64 const hsum(0.5 * (hconvo + hgnd + hrad + eHsky + hsurr));
17971820
TDT_i = (QRadSWOutFD + Cp_DelX_RhoS_2Delt * TD_i + kt_2DelX * (TDT_p - TD_i + TD(i + 1)) + hgnd * Tgnd +
1798-
(hconvo + hrad) * Toa + hsky * Tsky + hsurr * Tsurr - hsum * TD_i) /
1821+
(hconvo + hrad) * Toa + eHskyTsky + hsurr * Tsurr - hsum * TD_i) /
17991822
(hsum + kt_2DelX + Cp_DelX_RhoS_2Delt);
18001823
} else if (s_hbfd->CondFDSchemeType == CondFDScheme::FullyImplicitFirstOrder) { // First Order
18011824
Real64 const Two_Delt_DelX(2.0 * Delt_DelX);
18021825
Real64 const Cp_DelX2_RhoS(Cp * pow_2(DelX) * RhoS);
18031826
Real64 const Two_Delt_kt(2.0 * Delt * kt);
1804-
TDT_i = (Two_Delt_DelX * (QRadSWOutFD + hgnd * Tgnd + (hconvo + hrad) * Toa + hsky * Tsky + hsurr * Tsurr) +
1827+
TDT_i = (Two_Delt_DelX * (QRadSWOutFD + hgnd * Tgnd + (hconvo + hrad) * Toa + eHskyTsky + hsurr * Tsurr) +
18051828
Cp_DelX2_RhoS * TD_i + Two_Delt_kt * TDT_p) /
1806-
(Two_Delt_DelX * (hconvo + hgnd + hrad + hsky + hsurr) + Two_Delt_kt + Cp_DelX2_RhoS);
1829+
(Two_Delt_DelX * (hconvo + hgnd + hrad + eHsky + hsurr) + Two_Delt_kt + Cp_DelX2_RhoS);
18071830
}
18081831

18091832
} else { // HMovInsul > 0.0: Transparent insulation on outside
18101833
// Transparent insulation additions
18111834

18121835
// Movable Insulation Layer Outside surface temp
18131836

1814-
Real64 const TInsulOut(
1815-
(QRadSWOutMvInsulFD + hgnd * Tgnd + HMovInsul * TDT_i + (hconvo + hrad) * Toa + hsky * Tsky + hsurr * Tsurr) /
1816-
(hconvo + hgnd + HMovInsul + hrad + hsky + hsurr)); // Temperature of outside face of Outside Insulation
1837+
Real64 const TInsulOut =
1838+
(QRadSWOutMvInsulFD + hgnd * Tgnd + HMovInsul * TDT_i + (hconvo + hrad) * Toa + eHskyTsky + hsurr * Tsurr) /
1839+
(hconvo + hgnd + HMovInsul + hrad + eHsky + hsurr);
18171840
Real64 const Two_Delt_DelX(2.0 * Delt_DelX);
18181841
Real64 const Cp_DelX2_RhoS(Cp * pow_2(DelX) * RhoS);
18191842
Real64 const Two_Delt_kt(2.0 * Delt * kt);
@@ -1844,15 +1867,15 @@ namespace HeatBalFiniteDiffManager {
18441867
// One formulation that works for Fully Implicit and CrankNicholson and massless wall
18451868

18461869
Real64 const Toa_TDT_i(Toa - TDT_i);
1847-
Real64 const QNetSurfFromOutside(
1848-
QRadSWOutFD + (hgnd * (-TDT_i + Tgnd) + (hconvo + hrad) * Toa_TDT_i + hsky * (-TDT_i + Tsky) + hsurr * (-TDT_i + Tsurr)));
1870+
Real64 const QNetSurfFromOutside =
1871+
QRadSWOutFD + (hgnd * (-TDT_i + Tgnd) + (hconvo + hrad) * Toa_TDT_i - eHsky * TDT_i + eHskyTsky + hsurr * (-TDT_i + Tsurr));
18491872

18501873
// Same sign convention as CTFs
18511874
state.dataHeatBalSurf->SurfOpaqOutFaceCondFlux(Surf) = -QNetSurfFromOutside;
18521875

18531876
// Report all outside BC heat fluxes
18541877
state.dataHeatBalSurf->SurfQdotRadOutRepPerArea(Surf) =
1855-
-(hgnd * (TDT_i - Tgnd) + hrad * (-Toa_TDT_i) + hsky * (TDT_i - Tsky) + hsurr * (TDT_i - Tsurr));
1878+
-(hgnd * (TDT_i - Tgnd) + hrad * (-Toa_TDT_i) + eHsky * TDT_i - eHskyTsky + hsurr * (TDT_i - Tsurr));
18561879
state.dataHeatBalSurf->SurfQdotRadOutRep(Surf) = surface.Area * state.dataHeatBalSurf->SurfQdotRadOutRepPerArea(Surf);
18571880
state.dataHeatBalSurf->SurfQRadOutReport(Surf) = state.dataHeatBalSurf->SurfQdotRadOutRep(Surf) * state.dataGlobal->TimeStepZoneSec;
18581881

src/EnergyPlus/HeatBalFiniteDiffManager.hh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,8 @@ namespace HeatBalFiniteDiffManager {
166166
// Includes the EMS heat source
167167
Array1D<Real64> heatSourceEMSFluxLayerReport;
168168
Array1D<Real64> heatSourceEMSFluxEnergyLayerReport;
169+
MaterialActuatorData enetActuator; // Sky LW radiation EMS override [W/m2]
170+
Real64 enetActuatorReport = 0.0; // Reported sky LW radiation EMS override [W/m2], zero when inactive
169171

170172
// Default Constructor
171173
SurfaceDataFD() : SourceNodeNum(0), QSource(0.0), GSloopCounter(0), MaxNodeDelTemp(0.0), EnthalpyM(0.0), EnthalpyF(0.0), PhaseChangeState(0)

src/EnergyPlus/UnitarySystem.cc

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4718,8 +4718,8 @@ namespace UnitarySystems {
47184718
// **** How to get this info ****
47194719
// UnitarySystem( UnitarySysNum ).DesignHeatingCapacity =
47204720
// GetWtoAHPCoilCapacity(CoolingCoilType, this->m_CoolingCoilName, errFlag );
4721-
HeatingCoilInletNode = thisHeatCoil.Air(1).InletNodeNum;
4722-
HeatingCoilOutletNode = thisHeatCoil.Air(1).OutletNodeNum;
4721+
HeatingCoilInletNode = thisHeatCoil.AirConnections[primaryConnIdx].InletNodeNum;
4722+
HeatingCoilOutletNode = thisHeatCoil.AirConnections[primaryConnIdx].OutletNodeNum;
47234723
}
47244724
}
47254725

@@ -5396,8 +5396,8 @@ namespace UnitarySystems {
53965396
// **** How to get this info ****
53975397
// UnitarySystem( UnitarySysNum ).DesignCoolingCapacity =
53985398
// GetWtoAHPCoilCapacity(CoolingCoilType, this->m_CoolingCoilName, errFlag );
5399-
CoolingCoilInletNode = thisCoolCoil.Air(1).InletNodeNum;
5400-
CoolingCoilOutletNode = thisCoolCoil.Air(1).OutletNodeNum;
5399+
CoolingCoilInletNode = thisCoolCoil.AirConnections[primaryConnIdx].InletNodeNum;
5400+
CoolingCoilOutletNode = thisCoolCoil.AirConnections[primaryConnIdx].OutletNodeNum;
54015401
}
54025402
}
54035403

@@ -5432,9 +5432,8 @@ namespace UnitarySystems {
54325432
}
54335433
}
54345434

5435-
} else { // IF(.NOT. lAlphaBlanks(16))THEN
5435+
} else {
54365436
ShowSevereError(state, EnergyPlus::format("{} = {}", cCurrentModuleObject, thisObjectName));
5437-
// ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(iCoolingCoilTypeAlphaNum), Alphas(iCoolingCoilTypeAlphaNum)));
54385437
errorsFound = true;
54395438
}
54405439

@@ -5714,9 +5713,9 @@ namespace UnitarySystems {
57145713
errFlag = false;
57155714
} else {
57165715
auto const &thisSuppCoil = state.dataUserDefinedComponents->UserCoil(this->m_SuppHeatCoilIndex);
5717-
SupHeatCoilInletNode = thisSuppCoil.Air(1).InletNodeNum;
5716+
SupHeatCoilInletNode = thisSuppCoil.AirConnections[primaryConnIdx].InletNodeNum;
57185717
this->m_SuppCoilAirInletNode = SupHeatCoilInletNode;
5719-
SupHeatCoilOutletNode = thisSuppCoil.Air(1).OutletNodeNum;
5718+
SupHeatCoilOutletNode = thisSuppCoil.AirConnections[primaryConnIdx].OutletNodeNum;
57205719
this->SuppCoilOutletNodeNum = SupHeatCoilOutletNode;
57215720
}
57225721
}

0 commit comments

Comments
 (0)