ZoneBaseboard:OutdoorTemperatureControlled autosizing is missing#11579
ZoneBaseboard:OutdoorTemperatureControlled autosizing is missing#11579joseph-robertson wants to merge 31 commits into
Conversation
|
|
|
Does it seem like |
| if (state.dataEnvrn->CurEnvirNum != ScannedEnvirNum) { | ||
| ScannedEnvirNum = state.dataEnvrn->CurEnvirNum; | ||
| DesDayOutDryBulbTemp(ScannedEnvirNum) = state.dataEnvrn->OutDryBulbTemp; | ||
| if (state.dataEnvrn->CurEnvirNum <= state.dataEnvrn->TotDesDays) { // FIXME: this was == in the original code |
There was a problem hiding this comment.
What original code? I don't see any code that was deleted. I think == was used to determine when all design days have simulated (i.e., components don't usually size until zone sizing is complete). But each design day has multiple time steps so just looking at the CurEnvirNum isn't enough to know that sizing has completed. Most sizing routines are not called until !state.dataGlobal->SysSizingCalc. This does seem weird in that state.dataEnvrn->OutDryBulbTemp is set by the weather manager each time step, so this code is capturing the last time step's OAT in each specific design day. Not what I would expect. Also, at line 6926 below it's looking for max OAT not the min (i.e., if (MinDesOutTemp > DesDayOutDryBulbTemp(Loop))). Too much to discuss in a comment.
There was a problem hiding this comment.
Sorry, I was just referring to the original code in #4236.
I tried introducing !state.dataGlobal->ZoneSizingCalc in d994859. It brings the InitInternalHeatGains call down from "Initializing Internal Heat Gains" to "Initializing Simulation", which I think aligns with the other baseboard type.
From what I can tell the code is permitting input of a design zone heating setpoint (high temperature), but then looking to design day (days?) for a low temperature? But as you point out, looking at state.dataEnvrn->OutDryBulbTemp which would be the design day's last timestep's OAT; is there a precendence for this kind of weather info gathering, or why couldn't low temperature just be defaulted/input like high temperature?
I'll dig around and see how infiltration and ventilation MCPI and MCPV are used in other places.
There was a problem hiding this comment.
What would typically happen in a sizing routine is the component would look to FinalZoneSizing data for information needed for sizing (which means you don't need to gather data as done here with DesDayOutDryBulbTemp(ScannedEnvirNum)). In this case it would be FinalZoneSizing(zn).OutTempAtHeatPeak but using that data would need to be tested to make sure the size of the baseboard was sufficient to meet the peak baseboard load. For example, what is the total infiltration and ventilation load at the peak heating timestep? Is there a time where infiltration and ventilation would be larger and therefore the baseboard would not have sufficient capacity to meet the load? There is also an array of this same data using the min of CalcFinalZoneSizing(zn).HeatOutTempSeq(ts) which would give the minimum OAT for the peak heating design day. There are always questions of this nature regarding which sizing data is appropriate for component sizing (e.g., the peak heating load may not correspond to the peak infiltration or ventilation load).
There was a problem hiding this comment.
@rraustad I made several updates based on your suggestions. Using state.dataSize->FinalZoneSizing(NZ).OutTempAtHeatPeak seems to give me the appropriate design size low temperature.
On the topic of infiltration/ventilation MCPI and MCPV, because they are timestep variables and we'd want the peak, could I just add new peak variables in ZoneEquipmentManager analogous to OutTempAtHeatPeak? But instead of using HeatOutTempSeq(ts), it would use MCPI/MCPV. (I don't totally understand how the original implementation of this code dealt/found peaks of MCPV/MCPV.)
There was a problem hiding this comment.
What you have done so far looks good by tracking HeatMCPI(V) and HeatMCPI(V)Seq.
The BaseBoards do have a size function, but this object is managed in InternalHeatGains, for whatever reason. Sizing is typically called from the init function with proper protection to ensure it is called after sizing completes. So this does seem OK since it's called from void InitBaseboard() So this new code does call a sizing function, it's called from init in the code that manages the object, and the sizing call should be protected to only call the new size function after sizing is complete. Using |
| Real64 NominalUwithConvCoeffs = 0.0; | ||
| if (surf.Construction > 0 && surf.Construction <= state.dataHeatBal->TotConstructs) { | ||
| bool isWithConvCoefValid = false; | ||
| NominalUwithConvCoeffs = DataHeatBalance::ComputeNominalUwithConvCoeffs(state, SurfNum, isWithConvCoefValid); | ||
| } |
There was a problem hiding this comment.
I've replaced UNomFilm in the old code with NominalUwithConvCoeffs.
| ZnInfilSensLoad = state.dataSize->FinalZoneSizing(NZ).MCPIAtHeatPeak * DeltaTMax; | ||
| ZnVentSensLoad = state.dataSize->FinalZoneSizing(NZ).MCPVAtHeatPeak * DeltaTMax; |
There was a problem hiding this comment.
I'm using the new peak variables for MCPI and MCPV here.
| LowTemperatureDes = state.dataSize->FinalZoneSizing(NZ).OutTempAtHeatPeak; | ||
| if (IsAutosize) { | ||
| thisBBHeat.LowTemperature = LowTemperatureDes; | ||
| BaseSizer::reportSizerOutput( |
There was a problem hiding this comment.
I'm a little unclear whether I should be using BaseSizer::reportSizerOutput directly or some other class/method.
There was a problem hiding this comment.
Either call a dedicated function in the sizer instead of sizing here (see All_Simple_Sizing, and associated calling sites) or call reportSizerOutput. Either method is fine.
| autosize, !- Capacity at Low Temperature {W} | ||
| autosize, !- Low Temperature {C} | ||
| autosize, !- Capacity at High Temperature {W} | ||
| autosize, !- High Temperature {C} |
There was a problem hiding this comment.
From the docs for Field: High Temperature, "If autosized, this is equal to the design zone heating setpoint temperature described below, so that the capacity at high temperature is zero."
So seeing a zero "Design Size Capacity at High Temperature [W]" value for "SPACE5-1 BBHEAT 1" seems consistent/expected.
There was a problem hiding this comment.
This just seems a little odd. You don't but a baseboard (or any other component) in a building and then say "what is the capacity at a high entering air temperature" do you? Because it's obvious. Leave this for now as to not add scope creep.
| if (!state.dataGlobal->ZoneSizingCalc && state.dataHeatBal->ZoneBBHeat(Loop).MySizeFlag) { | ||
| SizeOaControlledBaseboard(state, Loop); | ||
| state.dataHeatBal->ZoneBBHeat(Loop).MySizeFlag = false; | ||
| } | ||
|
|
There was a problem hiding this comment.
Much much cleaner and simpler than the original code. Thanks for pointing me in the right direction, @rraustad.
|
|
|
|
||
| if (thisBBHeat.LowTemperature == DataSizing::AutoSize) { | ||
| IsAutosize = true; | ||
| } |
There was a problem hiding this comment.
Oops, I forgot to tell you an important point about sizing functions. The user could hard size the inputs and NOT perform a sizing run. In this case FinalZoneSizing will not be allocated and line 7034 will crash. Inside the above check add:
CheckZoneSizing(state, CompType, thisBBHeat.Name);
The simulation will fatal out if a sizing run is not performed.
Then add right after line 7032:
bool SizingDesRunThisZone = false;
CheckThisZoneForSizing(state, state.dataSize->CurZoneEqNum, SizingDesRunThisZone);
And you can use this flag to protect for FinalZoneSizing being allocated. Check other zone equipment sizing routines to get a feel for this. Also run a test file with and without zone sizing to check for crashes.
There was a problem hiding this comment.
Or you could add another struct variable as bool anyInputAutosized that is set in getInput and just call CheckZoneSizing once at the top of the sizing function.
| "Design Size Low Temperature [C]", | ||
| LowTemperatureDes, | ||
| "User-Specified Low Temperature [C]", | ||
| LowTemperatureUser); |
There was a problem hiding this comment.
This call is specific for when the user hard sizes an input AND a sizing run is performed. If a sizing run is not performed you won't have LowTemperatureDes available to report. Also you might not want to report to the eio when hardsized because the user already knows the size of the baseboard. You can report user specified inputs if you like and I don't have any issue with that, in fact I think all autosizable inputs should be reported to the eio regardless of whether or not they are autosized. You just have to add logic to report the right information when appropriate. i.e., you use this call when hard sized AND a sizing run is performed. You use line 7037 when hard sized and a sizing run is not performed and also change Design Size to User-Specified.
There was a problem hiding this comment.
Thanks. I've captured this and your other comment in e5aeb46.
But how does state.dataSize->CurZoneEqNum get incremented? It looks like it remains at a value of zero at the point of calling the baseboard sizing routine, which then doesn't turn SizingDesRunThisZone to true.
Edit: Oh. It's OA controlled, so maybe this is intentional. But any idea what the path forward should be then? Maybe this?
There was a problem hiding this comment.
@joseph-robertson you can probably use this method to set the current zone variable used in sizing methods:
state.dataSize->CurZoneEqNum = Util::FindItemInList(ZoneName, state.dataHeatBal->Zone);
You may have to save CurZoneEqNum and reset after your new sizing function so as not to break anything but I'm not sure that would be necessary, it depends on calling order and whether some other zone component would also be calling sizing. If CurZoneEqNum was not actually set (it's set/reset only in 1 place in ZoneEquipmentManager) before calling your sizing function you probably don't have to worry about resetting this variable.
|
|
|
|
|
|
|
|
|
|
|
|
| BaseSizer::reportSizerOutput(state, | ||
| CompType, | ||
| CompName, | ||
| "Design Size " + SizingString, | ||
| LowTemperatureDes, | ||
| "User-Specified " + SizingString, | ||
| thisBBHeat.LowTemperature); | ||
| if (state.dataGlobal->DisplayExtraWarnings) { | ||
| if (std::abs(LowTemperatureDes - thisBBHeat.LowTemperature) > state.dataSize->AutoVsHardSizingDeltaTempThreshold) { |
There was a problem hiding this comment.
Stick with calling reportSizerOutput for temperature fields (vs. using HeatingCapacitySizer) -- the AutoVsHardSizingDeltaTempThreshold variable implies a delta check, and also I'm not sure HeatingCapacitySizer would even support negative temperature values.
| } | ||
|
|
||
| ZoneEqSizing.HeatingCapacity = true; | ||
| ZoneEqSizing.DesHeatingLoad = CapatLowTemperatureDes; |
There was a problem hiding this comment.
I believe we are essentially overriding DesHeatingLoad with our own sizing value here.
|
|
|
|
Pull request overview
5ZoneEndUses.idf:
Description of the purpose of this PR
Pull Request Author
Reviewer