Skip to content
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

Merged
merged 22 commits into from
Aug 7, 2019
Merged

Conversation

Nigusse
Copy link
Contributor

@Nigusse Nigusse commented May 29, 2019

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.

  • Title of PR should be user-synopsis style (clearly understandable in a standalone changelog context)
  • At least one of the following appropriate labels must be added to this PR to be consumed into the changelog:
    • Defect: This pull request repairs a github defect issue. The github issue should be referenced in the PR description
    • Refactoring: This pull request includes code changes that don't change the functionality of the program, just perform refactoring
    • NewFeature: This pull request includes code to add a new feature to EnergyPlus
    • Performance: This pull request includes code changes that are directed at improving the runtime performance of EnergyPlus

Review Checklist

This will not be exhaustively relevant to every PR.

  • Functional code review (it has to work!)
  • If defect, results of running current develop vs this branch should exhibit the fix
  • CI status: all green or justified
  • Performance: CI Linux results include performance check
  • Unit Test(s)
  • C++ checks:
    • Argument types
    • If any virtual classes, ensure virtual destructor included, other things
  • Documentation

@Nigusse Nigusse added Defect Includes code to repair a defect in EnergyPlus NewFeatureRequest This "issue" is a new feature request, not a defect report labels May 29, 2019
@Nigusse
Copy link
Contributor Author

Nigusse commented May 29, 2019

This initial commit is code refactor to simplify code changes that allows ZoneHVAC:EvaporativeCooler to cycle. Diffs are not expected in this commit.

@Nigusse Nigusse changed the title Allow evaporative coolers to cycle Allows ZoneHVAC:EvaporitveCooler unit to cycle May 31, 2019
@Nigusse
Copy link
Contributor Author

Nigusse commented May 31, 2019

Diffs are expected in the following three example files:

  • StripMallZoneEvapCooler.idf
  • StripMallZoneEvapCoolerAutosized.idf
  • Fault_FoulingEvapCooler_StripMallZoneEvapCooler.idf

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.
Hence large diffs are expected in thermal zone "LGstore2" and evap cooler performance serving it. The diffs observed in the other thermal zones is a secondary effect.

@Nigusse
Copy link
Contributor Author

Nigusse commented May 31, 2019

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.

EvapCoolerUnitCycling

@Nigusse
Copy link
Contributor Author

Nigusse commented Jun 5, 2019

@Myoldmopar Diffs are expected in three example files. Otherwise, this branch is ready for review.

Copy link
Member

@Myoldmopar Myoldmopar left a 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!

// This is purposefully in an anonymous namespace so nothing outside this implementation file can use it.
bool InitZoneHVACEvapCoolerOneTimeFlag(true);
bool InitEvapCoolerMyOneTimeFlag(true);
} // namespace
Copy link
Member

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);
Copy link
Member

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 Show resolved Hide resolved
MySizeFlag.dimension(NumZoneEvapUnits, true);
MyEnvrnFlag.dimension(NumZoneEvapUnits, true);
MyFanFlag.dimension(NumZoneEvapUnits, true);
MyZoneEqFlag.allocate(NumZoneEvapUnits);
MyZoneEqFlag = true;
MyOneTimeFlag = false;
InitZoneHVACEvapCoolerOneTimeFlag = false;
ZoneEquipmentListChecked = false;
Copy link
Member

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.

Copy link
Contributor Author

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);
Copy link
Member

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?

Copy link
Contributor Author

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
Copy link
Member

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;
}

Copy link
Contributor Author

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.

Copy link
Contributor

@mjwitte mjwitte Jun 5, 2019

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.

Copy link
Member

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?

Copy link
Contributor

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?

Copy link
Contributor Author

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".

Copy link
Contributor Author

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.

Copy link
Contributor Author

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.

CyclingUnit_FullFlowUnit

Copy link
Contributor

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?

Copy link
Contributor Author

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?

Copy link
Contributor

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);
Copy link
Contributor Author

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.

Copy link
Contributor Author

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);
Copy link
Contributor Author

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.

@mjwitte
Copy link
Contributor

mjwitte commented Jun 5, 2019

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);
Copy link
Contributor Author

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);
Copy link
Contributor Author

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);
Copy link
Contributor Author

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, _);
}
}
Copy link
Contributor Author

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) {
Copy link
Contributor Author

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);
}
Copy link
Contributor Author

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;
Copy link
Contributor Author

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;
}
}
Copy link
Contributor Author

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;
}
Copy link
Contributor Author

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;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new residual function ZoneEvapUnitLoadResidual().

@Nigusse
Copy link
Contributor Author

Nigusse commented Jun 5, 2019

@Myoldmopar I added inline comments about functionality and why I made the changes.

@Nigusse
Copy link
Contributor Author

Nigusse commented Jun 5, 2019

I don't see any input changes here. How would one run the fan continuously, assuming anyone would want to?

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.

@Myoldmopar
Copy link
Member

@Myoldmopar I added inline comments about functionality and why I made the changes.

Thanks! That's a great walkthrough of the code changes!

@mjwitte mjwitte changed the title Allows ZoneHVAC:EvaporitveCooler unit to cycle Allows ZoneHVAC:EvaporativeCooler unit to cycle Jun 11, 2019
@mjwitte mjwitte removed the NewFeatureRequest This "issue" is a new feature request, not a defect report label Jul 5, 2019

DataZoneEquipment::ZoneEquipConfig(1).ExhaustNode(1) = thisZoneEvapCooler.UnitReliefNodeNum;

DataLoopNode::Node.redimension(NumOfNodes);
Copy link
Contributor

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.

Copy link
Contributor Author

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;

Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor Author

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.

using DataHVACGlobals::FanType_SimpleConstVolume;
using DataHVACGlobals::FanType_SimpleOnOff;
// using DataHVACGlobals::FanType_SimpleConstVolume;
// using DataHVACGlobals::FanType_SimpleOnOff;
Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Node(EvapCond(ZoneEvapUnit(UnitNum).EvapCooler_2_Index).OutletNode).MassFlowRateMaxAvail = 0.0;
}
// METHODOLOGY EMPLOYED:
// na

Copy link
Contributor

@mjwitte mjwitte Jul 5, 2019

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}
// Using/Aliasing
using DataHVACGlobals::ZoneCompTurnFansOff;
using DataHVACGlobals::ZoneCompTurnFansOn;
Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated as suggested.

Copy link
Contributor

@mjwitte mjwitte left a 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?

@Nigusse
Copy link
Contributor Author

Nigusse commented Jul 8, 2019

Addressed failed unit test by adding module variables to clear function and moving a static local variable to module level namespace.

@Nigusse
Copy link
Contributor Author

Nigusse commented Jul 8, 2019

@mjwitte Made minor modification in the Engineering Document for "ZoneTemperatureDeadbandOnOffCycling" and "ZoneCoolingLoadOnOffCycling" control type to reflect the cycling operation added.

@Myoldmopar
Copy link
Member

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?

@mjwitte
Copy link
Contributor

mjwitte commented Jul 16, 2019

@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.

@mjwitte mjwitte added this to the EnergyPlus 9.2.0 milestone Aug 5, 2019
Copy link
Contributor

@mjwitte mjwitte left a 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.

Real64 FlowFraction = 1.0;
Real64 MassFlowRateMax = Node(EvapCond(EvapCoolNum).InletNode).MassFlowRateMax;
if (MassFlowRateMax > 0) {
FlowFraction = EvapCond(EvapCoolNum).InletMassFlowRate / MassFlowRateMax;
Copy link
Contributor

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?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. I would expect MassFlowRateMax = branch max flow so this max looks accurate.
  2. Does EvapCooler have a VS pump? Probably no since the misters need high pressure to mist water.
  3. if EvapCooler cycles then this seems reasonable for pump power, if EvapCooler runs entire time step then previous pump power calc was accurate.
  4. Don't care if it's VAV. How long does the pump run this time step is more important.

Copy link
Contributor

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?

Copy link
Contributor

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
}

Copy link
Contributor

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.

Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

@yzhou601 yzhou601 Aug 7, 2019

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.

Copy link
Contributor

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.

Copy link
Contributor

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.

@@ -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)
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor Author

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);
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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;
Copy link
Contributor

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?

Copy link
Contributor Author

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.

@mjwitte
Copy link
Contributor

mjwitte commented Aug 7, 2019

@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?

@Nigusse
Copy link
Contributor Author

Nigusse commented Aug 7, 2019

@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.

@mjwitte
Copy link
Contributor

mjwitte commented Aug 7, 2019

Nice! Now we're down to diffs in just the 3 files with ZoneHVAC:EvaporativeCoolerUnit. Will let CI finish up and then merge.

@mjwitte mjwitte merged commit 9b9ece4 into develop Aug 7, 2019
@mjwitte mjwitte deleted the 166330897_Issue6707 branch August 7, 2019 18:42
} else if (SELECT_CASE_var == iEvapCoolerInDirectWETCOIL) {
CalcWetIndirectEvapCooler(EvapCoolNum);
CalcWetIndirectEvapCooler(EvapCoolNum, ZoneEvapCoolerPLR);
} else if (SELECT_CASE_var == iEvapCoolerInDirectRDDSpecial) {
Copy link
Contributor

@yzhou601 yzhou601 Aug 9, 2019

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

Copy link
Contributor Author

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.

Copy link
Contributor

@yzhou601 yzhou601 Aug 9, 2019

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).

Copy link
Contributor

@yzhou601 yzhou601 Aug 9, 2019

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. 😛

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Defect Includes code to repair a defect in EnergyPlus
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants