-
Notifications
You must be signed in to change notification settings - Fork 421
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allows ZoneHVAC:EvaporativeCooler unit to cycle #7319
Conversation
This initial commit is code refactor to simplify code changes that allows ZoneHVAC:EvaporativeCooler to cycle. Diffs are not expected in this commit. |
Diffs are expected in the following three example files:
There are 10 ZoneHVAC Evap Cooler units in each test file. Each evap cooler unit serves a single zone. Evap cooler serving "LGstore2" zone has OnOff fan type hence it is cycling now but not prior to this fix. |
The two plots below show ZoneHVAC EvapCooler unit cycling operation before and after this fix. After the fix (orange color line) shows the zone air is temperature is not over-cooled and the evaporator cooling rate is also scaled by PLR to match zone cooling load. Where the air temperature is over-cooled (before the fix), the unit PLR is less than 1.0. Where the cooling rate and zone air temperature values after the fix match the values prior to the fix, the PLR is always equal to 1 as expected. |
@Myoldmopar Diffs are expected in three example files. Otherwise, this branch is ready for review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Nigusse everything I've seen seems OK, but I'd like for you to comment up the changes a little bit so I can confirm that I understand the impact. Thanks!
src/EnergyPlus/EvaporativeCoolers.cc
Outdated
// This is purposefully in an anonymous namespace so nothing outside this implementation file can use it. | ||
bool InitZoneHVACEvapCoolerOneTimeFlag(true); | ||
bool InitEvapCoolerMyOneTimeFlag(true); | ||
} // namespace |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 👍
@@ -958,12 +968,11 @@ namespace EvaporativeCoolers { | |||
int OutNode; | |||
int EvapUnitNum; | |||
static bool MySetPointCheckFlag(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you need to get rid of these statics at the same time?
src/EnergyPlus/EvaporativeCoolers.cc
Outdated
MySizeFlag.dimension(NumZoneEvapUnits, true); | ||
MyEnvrnFlag.dimension(NumZoneEvapUnits, true); | ||
MyFanFlag.dimension(NumZoneEvapUnits, true); | ||
MyZoneEqFlag.allocate(NumZoneEvapUnits); | ||
MyZoneEqFlag = true; | ||
MyOneTimeFlag = false; | ||
InitZoneHVACEvapCoolerOneTimeFlag = false; | ||
ZoneEquipmentListChecked = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know you didn't add any arrays here, but this is another place where the Evap structure could just have booleans:
struct Evap {
bool mySize = true;
bool myEnvrn = true;
bool myFan = true;
bool myZoneEq = true;
}
Then we don't have a bunch of extra static arrays to manage. Nothing for you to necessarily do here just saying it is a welcomed change whenever you are working on code like this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Myoldmopar updated Evap structure.
// calculate part load ratio for cycling fan/unit first | ||
ControlZoneEvapUnitOutput(UnitNum, ZoneCoolingLoad); | ||
PartLoadRatio = ZoneEvapUnit(UnitNum).UnitPartLoadRatio; | ||
CalcZoneEvapUnitOutput(UnitNum, PartLoadRatio, SensibleOutputProvided, LatentOutputProvided); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was getting nervous about where all this code went but I see you moved it to separate functions. This is good, just makes it a little difficult to spot the changes you specifically made to the functionality. Can you make some comments in the code here on the lines you may have changed to get this working?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function CalcZoneEvapUnitOutput() is now runs with PLR determined for current cooling load. When the unit is allowed to cycle, it delivers just the requested zone cooling load, instead of the available capacity.
@@ -188,6 +188,7 @@ set( test_src | |||
XingGroundTemperatureModel.unit.cc | |||
ZoneContaminantPredictorCorrector.unit.cc | |||
ZoneEquipmentManager.unit.cc | |||
ZoneHVACEvaporativeCooler.unit |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's become rare for entirely new unit test files!
} else { | ||
ZoneEvapUnit(UnitLoop).OpMode = DataHVACGlobals::ContFanCycCoil; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is new code added in Get Input to catch and set the fan operating mode. Later the "OpMode" is used whether to allow or not allow the unit to cycle.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh I see, onoff is triggered by fan type. This won't fly after we deprecate all of the old fans and move to Fan:SystemModel as the only fan. This unit probably needs a Supply Fan Operating Mode Schedule Name, similar to PTAC, PTHP, FanCoil, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mjwitte are you requesting he add this on this PR? If not, are you satisfied with the current state?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should add the field now. It does require some thought for the variable fan case. Does it currently check the settings inside Fan:SystemModel to determine if it's VAV?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. I will append new field at the end. But we do not want to stretch this issue into "new feature".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. I will revise the code accordingly and push to remote. And I will review the regression results.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mjwitte I created a single zone model to investigate electric power consumption. see below the fan and evap unit electric power for "EvaporativeCooler:Direct:CelDekPad". The Unit's electric power for this evap cooler is the electric power of the Water Pump only. The supply fan power reported is consistent with the operation mode of the fan type (cycling for Fan:OnOff and Full Flow for Fan:ConstantVolume) when the evap unit is ON depending the controller action. The control type tested is ZoneCoolingLoadOnOffCycling. I see a problem with the electric power (water Pump Electric Power), it shouldn't have been constant for cycling fan/Unit (the first graph) when the PLR is less than 1.0. This should be fixed, but I am afraid this may be the case for the other evap cooler types as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But I'm trying to get away from the fan type affecting operation. Why aren't these two cases the same?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we allow Fan:ConstantVolume fan to cycle? The original code allowed FULL flow regardless of the fan type when the unit ON and causing zone over-cool. Now, this fix allowed the unit/fan to cycle but only with these three fan types (Fan:OnOff, Fan:SystemModel, Fan:ComponentModel). I can change the fix to allow the unit to cycle regardless of the fan type, if you agree?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's what I thought we agreed on. That's assuming Fan:ConstantVolume will work that way. The IDD notes for it imply otherwise:
Fan:ConstantVolume,
\memo Constant volume fan that is intended to operate continuously based on a time schedule.
\memo This fan will not cycle on and off based on cooling/heating load or other control
\memo signals.
If that's true, then we should throw an error if it's used with a cycling control option and add a transition rule to replace it with Fan:OnOff when use with the evap cooler.
@Myoldmopar It's time we dump all of these old fans. They should all be marked obsolete for this release. And possibly transitioned away in this release and the next.
} | ||
|
||
if (ZoneEvapUnit(UnitNum).EvapCooler_1_AvailStatus) { | ||
SimEvapCooler(ZoneEvapUnit(UnitNum).EvapCooler_1_Name, ZoneEvapUnit(UnitNum).EvapCooler_1_Index); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code section is is duplicate for the three ControlSchemeType available. I moved and created a new function called CalcZoneEvapUnitOutput(). This was the first step I did and made sure it did not break any thing. After confirming CI machine no diffs, then I broke the code for cycling and continuous run operating mode depending on the fan type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this function what changed is the supply flow rate is multiplied by PLR to determine the actual delivered out put. For Continuous fan operating mode, the PLR is always set to 1.0.
if (ZoneEvapUnit(UnitNum).OpMode == DataHVACGlobals::ContFanCycCoil) { | ||
PartLoadRatio = 1.0; | ||
ZoneEvapUnit(UnitNum).UnitPartLoadRatio = PartLoadRatio; | ||
CalcZoneEvapUnitOutput(UnitNum, PartLoadRatio, SensibleOutputProvided, LatentOutputProvided); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This section is for continuous fan operating mode (continuous Zone Evap Cooler). I set the PLR to 1.0 such that is maintains the original operating mode. The "ELSE" section is the one that allows the evap unit to cycle if the condition is favourable. Under this new section I determine a PLR such that evap unit meet the zone cooling load. For this I added a new function ControlZoneEvapUnitOutput() that calculates PLR.
I don't see any input changes here. How would one run the fan continuously, assuming anyone would want to? |
} else { | ||
ZoneCoolingLoad = ZoneSysEnergyDemand(ZoneNum).RemainingOutputReqToCoolSP; | ||
// calculate part load ratio for cycling fan/unit first | ||
ControlZoneEvapUnitOutput(UnitNum, ZoneCoolingLoad); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
new function added for calculating PLR using root solver.
} | ||
|
||
if (ZoneEvapUnit(UnitNum).EvapCooler_1_AvailStatus) { | ||
SimEvapCooler(ZoneEvapUnit(UnitNum).EvapCooler_1_Name, ZoneEvapUnit(UnitNum).EvapCooler_1_Index); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this function what changed is the supply flow rate is multiplied by PLR to determine the actual delivered out put. For Continuous fan operating mode, the PLR is always set to 1.0.
// calculate part load ratio for cycling fan/unit first | ||
ControlZoneEvapUnitOutput(UnitNum, ZoneCoolingLoad); | ||
PartLoadRatio = ZoneEvapUnit(UnitNum).UnitPartLoadRatio; | ||
CalcZoneEvapUnitOutput(UnitNum, PartLoadRatio, SensibleOutputProvided, LatentOutputProvided); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function CalcZoneEvapUnitOutput() is now runs with PLR determined for current cooling load. When the unit is allowed to cycle, it delivers just the requested zone cooling load, instead of the available capacity.
} else { | ||
HVACFan::fanObjs[ZoneEvapUnit(UnitNum).FanIndex]->simulate(_, ZoneCompTurnFansOn, ZoneCompTurnFansOff, _); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This ELSE section was meant to set the flow to zero when the evap unit is off. Now I can do the same with PLR set to zero and running the same function CalcZoneEvapUnitOutput(). This function also set these mass flow rates to zero if the PLR is zero. I consolidated the On and Off operating modes of the evap unit using the same function CalcZoneEvapUnitOutput() and works for the three ControlSchemeType.
} | ||
PartLoadRatio = 0.0; | ||
ZoneEvapUnit(UnitNum).UnitPartLoadRatio = PartLoadRatio; | ||
CalcZoneEvapUnitOutput(UnitNum, PartLoadRatio, SensibleOutputProvided, LatentOutputProvided); | ||
} | ||
|
||
} else if (SELECT_CASE_var == ZoneCoolingLoadOnOffCycling) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same comment applies to the ControlSchemeType ZoneCoolingLoadOnOffCycling.
(Node(ZoneEvapUnit(UnitNum).UnitOutletNodeNum).HumRat - Node(ZoneEvapUnit(UnitNum).ZoneNodeNum).HumRat); | ||
Node(OutletNodeNum).MassFlowRate * (PsyHFnTdbW(Node(OutletNodeNum).Temp, MinHumRat) - PsyHFnTdbW(Node(ZoneNodeNum).Temp, MinHumRat)); | ||
LatentOutputProvided = Node(OutletNodeNum).MassFlowRate * (Node(OutletNodeNum).HumRat - Node(ZoneNodeNum).HumRat); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function CalcZoneEvapUnitOutput() is factored from an existing code to handle the On and Off operating modes and scale the supply flow rate as a function of PLR. Also set the flow rates to zero when the unit is off (PLR=0). Factoring out this code removed duplicate code sections.
|
||
// calculate unit sensible cooling output | ||
if (PartLoadRatio > 0) { | ||
Node(OAInletNodeNum).MassFlowRate = ZoneEvapUnit(UnitNum).DesignAirMassFlowRate * PartLoadRatio; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PLR is used to modulate the supply air flow. Prior to this fix, the avp units always run at full flow, and some times over-cooled the space. This is one of the main request of the user, avoiding over cool.
Node(EvapCond(EvapCooler_2_Index).OutletNode).MassFlowRate = 0.0; | ||
Node(EvapCond(EvapCooler_2_Index).OutletNode).MassFlowRateMaxAvail = 0.0; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Set all flow rates to zero if the unit is off (PLR = 0).
PartLoadRatio = 1.0; | ||
} | ||
ZoneEvapUnit(UnitNum).UnitPartLoadRatio = PartLoadRatio; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The above function ControlZoneEvapUnitOutput() solves for the PLR.
|
||
Residual = QSensOutputProvided - LoadToBeMet; | ||
|
||
return Residual; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
new residual function ZoneEvapUnitLoadResidual().
@Myoldmopar I added inline comments about functionality and why I made the changes. |
Now that depends on the Fan Type only. Only OnOff and SystemModel fan types are allowed to cycle. All other fan types will run continuously. We do not have input field for fan operating mode in ZoneHVACEvap unit for now. So the unit will run only in one of the two operating modes through out the simulation. |
Thanks! That's a great walkthrough of the code changes! |
|
||
DataZoneEquipment::ZoneEquipConfig(1).ExhaustNode(1) = thisZoneEvapCooler.UnitReliefNodeNum; | ||
|
||
DataLoopNode::Node.redimension(NumOfNodes); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, redimension after GetInputZoneEvaporativeCoolerUnit
? Not following why that should happen here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Required to include the zone related nodes defined in the EnergyPlusFixture::SetUp() here;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name of the evap cooler is different from the base fixture and the zone inlet node name looks unique, so number of nodes will probably be different from what was expected based on the base fixture setup. But I agree that the need for reallocation of nodes is suspect. Didn't GetInputZoneEvaporativeCoolerUnit
allocate new nodes as they were read in (e.g., DataZoneEquipment::ZoneEquipConfig(1).ZoneNode should be a valid node)? What was NumOfNodes compared to the allocated Node array size?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Get input does not allocate all nodes required for zone connection. That is why I re-dimension the "Node" array.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The number of nodes allocated during get input depends on the unit test but it was some where between 4 - 7, I think. I reserved node number 9 and 10 for return and zone air node.
src/EnergyPlus/EvaporativeCoolers.cc
Outdated
using DataHVACGlobals::FanType_SimpleConstVolume; | ||
using DataHVACGlobals::FanType_SimpleOnOff; | ||
// using DataHVACGlobals::FanType_SimpleConstVolume; | ||
// using DataHVACGlobals::FanType_SimpleOnOff; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If these are other changes needed, these should be deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
src/EnergyPlus/EvaporativeCoolers.cc
Outdated
Node(EvapCond(ZoneEvapUnit(UnitNum).EvapCooler_2_Index).OutletNode).MassFlowRateMaxAvail = 0.0; | ||
} | ||
// METHODOLOGY EMPLOYED: | ||
// na | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't add unused boiler plate comments anymore to new functions, here and below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
src/EnergyPlus/EvaporativeCoolers.cc
Outdated
} | ||
// Using/Aliasing | ||
using DataHVACGlobals::ZoneCompTurnFansOff; | ||
using DataHVACGlobals::ZoneCompTurnFansOn; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor, but prefer to avoid using
in new functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated as suggested.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Getting started on final review. I've merged in the latest develop branch and will push that here.
When running all unit tests serially, ZoneHVACEvapCoolerUnitTest.DirectResearchSpecial_CyclingUnit_Sim fails with an array bounds error. I don't see any deallocates in EvapCoolers::clear_state
for EvapCond, ZoneEvapUnit, or ZoneEvapCoolerUnitFields
.
Some review comments below. I haven't tested idf files yet, so more next week.
Does this need any changes to the Engineering Reference?
Addressed failed unit test by adding module variables to clear function and moving a static local variable to module level namespace. |
@mjwitte Made minor modification in the Engineering Document for "ZoneTemperatureDeadbandOnOffCycling" and "ZoneCoolingLoadOnOffCycling" control type to reflect the cycling operation added. |
Wow. This has been a lengthy and informative read. Thanks to @Nigusse @mjwitte and @rraustad for all the effort in making code changes and reviewing. Can I get a feel for where I could step in at this point to provide review support to get this merged in? Running test files and checking diffs? Something else? |
@Myoldmopar Next steps here, run unit tests to make sure clear_state solves the noted problem, run test files, try some disallowed options to see if they are trapped correctly, make sure fan operation and tstat control are as expected. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested this with all fan types. New temperature control is excellent. Since it's been a few weeks, merging in develop and letting CI make another pass. Otherwise, this is great.
src/EnergyPlus/EvaporativeCoolers.cc
Outdated
Real64 FlowFraction = 1.0; | ||
Real64 MassFlowRateMax = Node(EvapCond(EvapCoolNum).InletNode).MassFlowRateMax; | ||
if (MassFlowRateMax > 0) { | ||
FlowFraction = EvapCond(EvapCoolNum).InletMassFlowRate / MassFlowRateMax; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Nigusse @Myoldmopar @rraustad So, I was puzzled by the meter diffs in 1ZoneEvapCooler and 1ZoneParameterAspect, because these have airloop evap coolers, no zoneHVAC.
It turns out that 1ZoneParameterAspect is hard-sized with the airloop, fan, and OA controller all at 3.0 but the terminal unit is at 2.5. So, the evap cooler power is always 2.5/3.0 on this branch compared to develop. (1ZoneEvapCooler is similar with 2.0 vs 1.5). I don't see anything in the comments to indicate that the different flow rates are intentional. So, one option here is to simply fix those to use the terminal unit flow rate throughout and then the diffs would go away.
Since there is no design flow rate input for EvaporativeCooler:*:CelDekPad, using the node max flow rate is a clever solution to calculate a "plr" for the evap cooler, but will this always produce the desired evap cooler power consumption? What if the evap cooler is in a VAV system, does that still make sense?
Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- I would expect MassFlowRateMax = branch max flow so this max looks accurate.
- Does EvapCooler have a VS pump? Probably no since the misters need high pressure to mist water.
- if EvapCooler cycles then this seems reasonable for pump power, if EvapCooler runs entire time step then previous pump power calc was accurate.
- Don't care if it's VAV. How long does the pump run this time step is more important.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, perhaps instead of using flow rate as a proxy for PLR, the PLR should default to 1.0 and ZoneHVAC:EvapCooler needs to pass a PLR to the evap cooler component?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The outlet conditions are correct now so I was thinking more like:
If (constant fan){
same power equation as before
} else {
new PLR equation
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The base evap cooler component doesn't know anything about fan type - only the ZoneHVAC:EvapCooler knows that. If the eval cooler component is loose on a branch, then it doesn't know what the fan will do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If evap cooler is loose on the air loop branch you can use this bool and probably also if AirLoopNum > 0:
AirLoopControlInfo(AirLoopNum).AnyContFan, or could pass PLR = 1 as @mjwitte suggested.
If evap cooler is in the ZoneHVAC:EvapCooler then you need to pass info to the evap cooler to tell it if it is cycling or constant.
Passing PLR as an argument is probably easiest unless you can think of something else.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mjwitte @rraustad I am thinking to pass the ZoneHVAC:EvapCooler unit PLR as an optional argument to SimEvapCooler() function and cascade it to CalcDirectEvapCooler() and CalcDryIndirectEvapCooler() functions. If the PLR argument is not present, then I will reset it to 1.0. The later will be used for air loop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rraustad @mjwitte @Nigusse Hi, sorry for jumping into the conversation which I might haven't understood thoroughly. So, is there a way to model cycling fan and cycling evap cooler pump in loose air loop? So far I didn't find any approach to directly put cycling fan into air loop and make it cycling properly. And as far as I've learned in this conversation, there's no way to communicate PLR between fan and evap cooler (this PR is going to pass 1.0 for air loop), correct? Because my recent work involves modeling evap cooler in a loose air loop, it would be good to know.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no way presently to model cycling fans on built-up branches. EvaporativeCooler:*:ResearchSpecial is able to control itself to a setpoint.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's true for purely component built-up branches, but when evap cooler is used with parent objects, the fan operating mode schedule is known as AirLoopControlInfo(AirLoopNum).CycFanSchedPtr (as long as this variable is set correctly everywhere) and could, in the future, be used to cycle the evap cooler.
src/EnergyPlus/EvaporativeCoolers.cc
Outdated
@@ -193,7 +193,7 @@ namespace EvaporativeCoolers { | |||
|
|||
// Functions | |||
|
|||
void SimEvapCooler(std::string const &CompName, int &CompIndex) | |||
void SimEvapCooler(std::string const &CompName, int &CompIndex, Optional<Real64 const> PartLoadRatio) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Nigusse We're trying to avoid using optional arguments (for performance). A default value for the argument is better (if the argument is left off then it's set to the default value). See discussion here. Then you don't need if (present . . .)
. You can just use and pass PartLoadRatio
directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mjwitte Okay, will modify the code accordingly. Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
@@ -4966,11 +4908,11 @@ namespace EvaporativeCoolers { | |||
} | |||
|
|||
if (ZoneEvapUnit(UnitNum).EvapCooler_1_AvailStatus) { | |||
SimEvapCooler(ZoneEvapUnit(UnitNum).EvapCooler_1_Name, ZoneEvapUnit(UnitNum).EvapCooler_1_Index); | |||
SimEvapCooler(ZoneEvapUnit(UnitNum).EvapCooler_1_Name, ZoneEvapUnit(UnitNum).EvapCooler_1_Index, FanSpeedRatio); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As @mjwitte found with a lower max TU flow rate than the branch max flow, this isn't really the PLR of the evap cooler. I assume the diff's found yesterday would still be there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PLR is passed to zone evaporative coolers only. When an evap cooler in airloop the PLR defaults to 1.0. The fanspeedratio is used when the zone HVAC evaporative cooler control type is ZoneCoolingLoadVariableSpeedFan.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok then, as long as this is the actual PLR based on time.
EvapCond(EvapCoolNum).EvapCoolerPower += | ||
EvapCond(EvapCoolNum).IndirectFanDeltaPress * EvapCond(EvapCoolNum).IndirectVolFlowRate / EvapCond(EvapCoolNum).IndirectFanEff; | ||
EvapCond(EvapCoolNum).EvapCoolerPower += FlowFraction * EvapCond(EvapCoolNum).IndirectFanDeltaPress * | ||
EvapCond(EvapCoolNum).IndirectVolFlowRate / EvapCond(EvapCoolNum).IndirectFanEff; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The indirect fan power is still based on FlowFraction. Is that appropriate or should this also be based on PLR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think, it should be based on PLR. It is an oversight. I will make the changes.
@Nigusse Comparing the latest vs yesterday's code, there is a change in StripMallZoneEvapCooler (and likely similar in StripMallZoneEvapCoolerAutosized but I haven't looked). SMSTORE7 DIRECT EVAPORATIVE COOLER:Evaporative Cooler Electric Energy [J] is now varying every hour, whereas yesterday it was always at full power. Since SMSTORE7 INDIRECT EVAPORATIVE COOLER:Evaporative Cooler Electric Energy J varies both yesterday and today, I'm concluding that today's result is correct for SMSTORE7 Direct. Would you agree? |
@mjwitte I run the StripMallZoneEvapCooler test file with latest code of this branch, and I see the Evaporative Cooler Electric Energy and Evaporative Cooler Electric Power "proportional" to PLR. I agree varying values should be the trend expected. |
Nice! Now we're down to diffs in just the 3 files with ZoneHVAC:EvaporativeCoolerUnit. Will let CI finish up and then merge. |
} else if (SELECT_CASE_var == iEvapCoolerInDirectWETCOIL) { | ||
CalcWetIndirectEvapCooler(EvapCoolNum); | ||
CalcWetIndirectEvapCooler(EvapCoolNum, ZoneEvapCoolerPLR); | ||
} else if (SELECT_CASE_var == iEvapCoolerInDirectRDDSpecial) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Nigusse Hi, Bereket, is there any specific reason not to allow researchspecial types cycling with fan as well? In these lines, it confused me that it reported power consumption by FlowRatio
if there's modifier curve (regardless of PartLoad
which is calculated to meet outlet setpoint), but by PartLoad
if there's not(regardless of flow ratio). Actually I am not sure what should it be though, the current approach looks confusing to me. @rraustad @mjwitte
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The research special evaporative coolers models are different from the other models. They have pump power modifier curve that accounts for pump power calculation as a function of flow fraction. The PartLoad is used only if user did not provide pump power correction curve.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Nigusse Yes that's correct. So if there's no modifier curve, the pump power would only be calculated based on PartLoad
ignoring mass flow ratio in air loop, so whatever amount of supply air the thermal zones need, it just cycling to meet outlet temperature controlled by setpoint manager (more like supply air temperature). Where it is different with other types is that others always assume a full load outlet temperature. At least in this case ( the else
condition), it seems to be close to this PR's purpose to fix it.
In my personal opinion (might be wrong), it seems only consider one of them in each situation looks not enough to include both outlet temperature control (PLR) and mass flow rate control (PLR).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I knew that type is different so you didn't touch that in this PR. I mean maybe we could rethink about if we need to change something there as well. 😛
Pull request overview
Addresses issue #6707. This fix allows ZoneHVAC:EvaporitveCooler unit to cycle when the cooling load is less than the available capacity and the fan type specified is either Fan:OnOff or Fan:SystemModel. Previously, it assumed continuous fan flow for all fan types. Allowing the unit to cycle avoids over cooling of the zone.
Diffs are expected/justified based on this change for these fan types. The unit may cycle when the "Cooler Unit Control Method" specified is either "ZoneTemperatureDeadbandOnOffCycling" or "ZoneCoolingLoadOnOffCycling". Cycling is supported for all five Evaporative Cooler Object Type currently allowed.
Work Checklist
Add to this list or remove from it as applicable. This is a simple templated set of guidelines.
Review Checklist
This will not be exhaustively relevant to every PR.