NREL / EnergyPlus

EnergyPlus™ is a whole building energy simulation program that engineers, architects, and researchers use to model both energy consumption and water use in buildings.
https://energyplus.net
Other
1.14k stars 392 forks source link

Controller:OutdoorAir "Heat Recovery Bypass Control Type" causing erratic oa rates #4568

Closed kbenne closed 9 years ago

kbenne commented 10 years ago

An example file and graphs will be uploaded to demonstrate this issue. A value of "BypassWhenOAFlowGreaterThanMinimum" in Controller:OutdoorAir "Heat Recovery Bypass Control Type" will produce very unusual results. Generally, OA rates are found running way above spec, forcing fan to run at full capacity. In some cases very large discrepancies between supply outlet node flow rate and demand inlet node flow rate. Using a value of "BypassWhenWithinEconomizerLimits" corrects the issue. This can be demonstrated in models that don't even have heat recovery devices on the oa system.

kbenne commented 10 years ago

I'm not going to upload a defect file unless someone requests it. The issue can be demonstrated by just replacing the OA controller object in the 5ZoneAirCooled.idf example file with the following:

  Controller:OutdoorAir,
    OA Controller 1,         !- Name
    Relief Air Outlet Node 1,!- Relief Air Outlet Node Name
    VAV Sys 1 Inlet Node,    !- Return Air Node Name
    Mixed Air Node 1,        !- Mixed Air Node Name
    Outside Air Inlet Node 1,!- Actuator Node Name
    1.04982,                !- Minimum Outdoor Air Flow Rate {m3/s}
    1.04982,                !- Maximum Outdoor Air Flow Rate {m3/s}
    NoEconomizer,            !- Economizer Control Type
    ModulateFlow,            !- Economizer Control Action Type
    19.,                     !- Economizer Maximum Limit Dry-Bulb Temperature {C}
    ,                        !- Economizer Maximum Limit Enthalpy {J/kg}
    ,                        !- Economizer Maximum Limit Dewpoint Temperature {C}
    ,                        !- Electronic Enthalpy Limit Curve Name
    4.6,                     !- Economizer Minimum Limit Dry-Bulb Temperature {C}
    NoLockout,               !- Lockout Type
    ProportionalMinimum,            !- Minimum Limit Type
    ,            !- Minimum Outdoor Air Schedule Name
    ,                                       !- Minimum Fraction of Outdoor Air Schedule Name
    ,                      !- Maximum Fraction of Outdoor Air Schedule Name
    , !- Mechanical Ventilation Controller Name
    ,                                       !- Time of Day Economizer Control Schedule Name
    No,                                     !- High Humidity Control
    ,                                       !- Humidistat Control Zone Name
    ,                                       !- High Humidity Outdoor Air Flow Ratio
    Yes,                                    !- Control High Indoor Humidity Based on Outdoor Humidity Ratio
    BypassWhenOAFlowGreaterThanMinimum;       !- Heat Recovery Bypass Control Type

The key change is the addition of the last field with value "BypassWhenOAFlowGreaterThanMinimum"

Here are the incorrect oa rates we see:

screen shot 2014-10-30 at 2 35 26 pm

Here is what we expect when the example file runs normally: screen shot 2014-10-30 at 2 37 35 pm

The issue seems to be emphasized in during heating hours.

mjwitte commented 9 years ago

Helpdesk ticket 10673 User: I've attached 2 IDF files. They're identical with the exception of 'Heat Recovery Bypass Control' input in the controller:OutdoorAir. Neither of these have a heat exchanger or economizer. From what I understand from the I/O reference, this input then shouldn't have any impact on the energy use of a building. However, the heating energy use is ~75% lower when the bypass control is specified as 'BypassWhenOAFlowGreaterThanMinimum'.

These files have been added as defect files. Upping the priority on this.

rraustad commented 9 years ago

At around line 4190 in MixedAir.cc there is a test. I suspect this test occurs whether or not a HX exists.

// set the air loop economizer and high humidity control flags. if ( EconomizerOperationFlag ) { if ( OAController( OAControllerNum ).HeatRecoveryBypassControlType == BypassWhenOAFlowGreaterThanMinimum ) {

// Optional heat recovery bypass control flag uses additional logic to allow ERV optimization if ( AirLoopControlInfo( AirLoopNum ).CheckHeatRecoveryBypassStatus && AirLoopControlInfo( AirLoopNum ).OASysComponentsSimulated ) {

I can think of 2 ways to fix this. 1) check for HX and if not present flip the HeatRecoveryBypassControl type back to default, or 2) include a HXPresent flag in this IF test.

mjwitte commented 9 years ago

@rraustad If there is no HX present, then it shouldn't matter what the bypass status is set to. Why does this test change anything? It should simply set a flag that gets ignored because there is no HX to look at it.

rraustad commented 9 years ago

I agree with you it should be ignored, but it appears it's not ignored (so I would look here first).

At line 4213: if ( MixedAirTempAtMinOAFlow <= Node( OAController( OAControllerNum ).MixNode ).TempSetPoint ) {

AirLoopControlInfo( AirLoopNum ).EconomizerFlowLocked = true;

then at line 4236: if ( AirLoopControlInfo( AirLoopNum ).EconomizerFlowLocked ) { OAController( OAControllerNum ).OAMassFlow = AirLoopFlow( AirLoopNum ).MinOutAir; }

I still think my suggestion above would fix this, but it's still a guess until it's tested.

rraustad commented 9 years ago

There is already a way to check for a OAHX, still TBD whether that flag can be used for this fix.

        SimOAComponent( CompType, CompName, OutsideAirSys( OASysNum ).ComponentType_Num( CompNum ), FirstHVACIteration, OutsideAirSys( OASysNum ).ComponentIndex( CompNum ), AirLoopNum, Sim, OASysNum, OAHeatCoil, OACoolCoil, OAHX );
        if ( OAHX ) ReSim = true;
mjwitte commented 9 years ago

@rraustad I still contend this should not be necessary. Something else somewhere is misusing the bypass flag.

mjwitte commented 9 years ago

Defect files have been added. There is more going on than just the Heat Recovery Bypass Control Type Field. For 5ZoneAirCooled, I could not reproduce the problem without using the exact Controller:OutdoorAir object shown above (from @kbenne ).

For the user files (check the flow at "Node 47") I did make a variant which removes Controller:MechanicalVentilation for the first system, and the problem still shows. I suspect some of the other economizer limit fields may be impacting this (which would be why I couldn't reproduce it with plain vanilla 5ZoneAirCooled).

For the user files, BypassWhenOAFlowGreaterThanMinimum gives the correct OA flow at Node 47 (0.54899 is the autosized min OA flow rate) while BypassWhenWithinEconomizerLimits give the wrong OA flow rate (0.3271). Note that both files always report zero for Economizer Status and Heat Recovery Bypass Status.

MatthewSteen commented 9 years ago

+1

mjwitte commented 9 years ago

@kbenne @Myoldmopar @rraustad @wfbuhl Running 5ZoneAirCooled-BypassWhenOAFlowGreaterThanMinimum-PerKB defect which has no heat exchanger, no economizer, NoLockout, and ProportionalMinimum. Note that both Max and Min Outdoor Air Flow Rates are both set to 1.04982 (this is a contributing factor).

Right out of the gate, it's landing in this block of code:

            if ( AirLoopControlInfo( AirLoopNum ).HeatingActiveFlag && OAController( OAControllerNum ).HeatRecoveryBypassControlType == BypassWhenOAFlowGreaterThanMinimum ) {
                AirLoopControlInfo( AirLoopNum ).HeatRecoveryBypass = false;
                OAController( OAControllerNum ).HeatRecoveryBypassStatus = 0;
                OAController( OAControllerNum ).HRHeatingCoilActive = 1;
                // reset the OA flow to minimum
                OAController( OAControllerNum ).OAMassFlow = AirLoopFlow( AirLoopNum ).MinOutAir;
                AirLoopFlow( AirLoopNum ).OAFrac = OAController( OAControllerNum ).OAMassFlow / OAController( OAControllerNum ).MixMassFlow;
                AirLoopFlow( AirLoopNum ).OAMinFrac = AirLoopFlow( AirLoopNum ).OAFrac;
  1. This looks like the heating economizer lockout - should be checking for LockOutWithHeating rather than BypassWhenOAFlowGreaterThanMinimum.
  2. At this point, AirLoopFlow(1) looks like this. Note the supply and return flows are 0.37, but MinOutAir is 1.23. So OAMassFlow gets set to 1.23 - which somehow later is trying for force the supply flow back up to 1.23 resulting in max iteration problems.
    image
  3. *MinOutAir should never be > the current supply flow, should it? I guess that depends on how MinOutAir will be used, especially in this case where the Min OA flow rate is fixed at the design supply flow rate in a VAV system (which isn't really valid) but the same condition could occur if, say, a DCV controller asked for more OA than the current supply flow - in that case who should rule?
  4. There are times where users would like the OA requirement to override the supply air flow rate, but it's not supposed to be happening at this point. I/O Ref description for the OA controller is not clear about this, and the Engineering Ref just tosses this in at the end in a list of constraints. image Will need to track down where the OA controller is messing with the mixed air flow rate.

Stay tuned . . .

mjwitte commented 9 years ago

This BypassWhenOAFlowGreaterThanMinimum section of code was introduced initially for CR9030 / #3803 with this commit

And then modified for CR9054 / #3826 with this commit

rraustad commented 9 years ago

The point here was to use the minimum OA flow rate if the heating coil was active (found on first pass through then used during the second iteration) when using BypassWhenOAFlowGreaterThanMinimum. This had nothing to do with LockOutWithHeating back when this was added. Not to say is shouldn't have checked, but the user specifically requested that the HX not bypass when the heating coil was active (to minimize heating), and if so, then reset the flow rate back to the minimum (so the HX could stay on ... HeatRecoveryBypass = false). This was long ago so maybe some of the facts are blurred. I worked days on this and finally the user was happy with the result. When he gave his approval, I stopped messing with the logic.

IDD: \note BypassWhenOAFlowGreaterThanMinimum specifies enhanced economizer \note controls to allow heat recovery when economizer is active \note (within limits) but the outdoor air flow rate is at the minimum.

Maybe that line should also check for SA flow rate to see which is lower? And why was the supply air flow rate lower than the minimum OA flow rate? I guess the VAV boxes don't know of the OA minimum? And OAFrac was > 1 here (what does that mean)?

I wouldn't think it would hurt to use|(the point was just to go to a minimum):||

OAController( OAControllerNum ).OAMassFlow = min( SAFlow, AirLoopFlow( AirLoopNum ).MinOutAir ); |

I would check where the OA flow is capped by the minimum to see where this code is relative to that code.

This falls into the issue of locking down the OA controller when some decision is made. I've been thinking about this lately. These max iterations have made me question whether this is being done correctly (here and elsewhere).

On 9/9/2015 10:06 AM, Michael J. Witte wrote:

@kbenne https://github.com/kbenne @Myoldmopar https://github.com/Myoldmopar @rraustad https://github.com/rraustad @wfbuhl https://github.com/wfbuhl Running 5ZoneAirCooled-BypassWhenOAFlowGreaterThanMinimum-PerKB defect which has no heat exchanger, no economizer, NoLockout, and ProportionalMinimum. /Note that both Max and Min Outdoor Air Flow Rates are both set to 1.04982 (this is a contributing factor)/.

Right out of the gate, it's landing in this block of code https://github.com/NREL/EnergyPlus/blob/develop/src/EnergyPlus/MixedAir.cc#L4354-L4362:

|if ( AirLoopControlInfo( AirLoopNum ).HeatingActiveFlag && OAController( OAControllerNum ).HeatRecoveryBypassControlType == BypassWhenOAFlowGreaterThanMinimum ) { AirLoopControlInfo( AirLoopNum ).HeatRecoveryBypass = false; OAController( OAControllerNum ).HeatRecoveryBypassStatus = 0; OAController( OAControllerNum ).HRHeatingCoilActive = 1; // reset the OA flow to minimum OAController( OAControllerNum ).OAMassFlow = AirLoopFlow( AirLoopNum ).MinOutAir; AirLoopFlow( AirLoopNum ).OAFrac = OAController( OAControllerNum ).OAMassFlow / OAController( OAControllerNum ).MixMassFlow; AirLoopFlow( AirLoopNum ).OAMinFrac = AirLoopFlow( AirLoopNum ).OAFrac; |

  1. This looks like the heating economizer lockout - should be checking for LockOutWithHeating rather than BypassWhenOAFlowGreaterThanMinimum.
  2. At this point, AirLoopFlow(1) looks like this. /Note the supply and return flows are 0.37, but MinOutAir is 1.23./ So OAMassFlow gets set to 1.23 - which somehow later is trying for force the supply flow back up to 1.23 resulting in max iteration problems. image https://cloud.githubusercontent.com/assets/4991075/9762823/7db1624c-56cb-11e5-9387-bceebe4c9541.png
  3. *MinOutAir should never be > the current supply flow, should it? I guess that depends on how MinOutAir will be used, especially in this case where the Min OA flow rate is fixed at the design supply flow rate in a VAV system (which isn't really valid) but the same condition could occur if, say, a DCV controller asked for more OA than the current supply flow - in that case who should rule?
  4. There are times where users would like the OA requirement to override the supply air flow rate, but it's not supposed to be happening at this point. I/O Ref description for the OA controller is not clear about this, and the Engineering Ref just tosses this in at the end in a list of constraints. image https://cloud.githubusercontent.com/assets/4991075/9763632/41ad4cb6-56d0-11e5-97ed-906b6183fe7d.png Will need to track down where the OA controller is messing with the mixed air flow rate.

Stay tuned . . .

— Reply to this email directly or view it on GitHub https://github.com/NREL/EnergyPlus/issues/4568#issuecomment-138919533.

Richard Raustad Florida Solar Energy Center 1679 Clearlake Road Cocoa, FL 32922 Ph: (321)638-1454 http://www.fsec.ucf.edu/en/

Program Director Electric Vehicle Transportation Center http://evtc.fsec.ucf.edu/

mjwitte commented 9 years ago

@rraustad But this isn't testing if OAflow is > minimum anymore. And BypassWhenOAFlowGreaterThanMinimum should only touch the HX bypass flag, and it should only take action when OAflow is > minimum. So resetting OA flow to minimum based on this flag seems wrong.

My simple mind says the economizer should make it's decision about OA flow rate regardless of the HX bypass option (which I think it is already doing).

Then Heat Recovery Bypass Control Type option should set the bypass flag true if within economizer limits (BypassWhenWithinEconomizerLimits) or OA flow > min (BypassWhenOAFlowGreaterThanMinimum). Nothing more. It shouldn't touch any flow rates.

So, I need to look back at the original problem that prompted this code and see where the disconnect is.

rraustad commented 9 years ago

On 9/9/2015 11:04 AM, Michael J. Witte wrote:

@rraustad https://github.com/rraustad But this isn't testing if OAflow is > minimum anymore.

Correct, it just senses the heating coil activity and resets flow to minimum. The OA flow should not be above the minimum if the heating coil is active, that is no longer an economizer and would just waste energy.

And BypassWhenOAFlowGreaterThanMinimum should only touch the HX bypass flag, and it should only take action when OAflow /is/ > minimum. So resetting OA flow to minimum based on this flag seems wrong.

Hard to disagree with that unless the flag name is misleading (what if it were OptimizeEconomizerAndHXOperation). There is also other logic there that looks at a calculated mixed air temperature, and if conditions are right, will allow the HX to turn on if it calculates that the heating coil would turn on. See line 4306 if ( OAController( OAControllerNum ).HeatRecoveryBypassControlType == BypassWhenOAFlowGreaterThanMinimum ) { // Optional heat recovery bypass control flag uses additional logic to allow ERV optimization

There is also another OAMassFlow = MinOutAir line of code in there.

My simple mind says the economizer should make it's decision about OA flow rate regardless of the HX bypass option (which I think it is already doing).

I'm not saying there is no possibility of a logic mistake. It's just that in this case the SA flow is lower than the minimum, which wasn't expected. And that this was working very well for the original defect file (both the user and I agreed, I can't recall if you reviewed).

Then Heat Recovery Bypass Control Type option should set the bypass flag true if within economizer limits (BypassWhenWithinEconomizerLimits)

agreed

or OA flow > min (BypassWhenOAFlowGreaterThanMinimum). Nothing more. It shouldn't touch any flow rates.

So if the heating coil is on and the flow > min, leave the flow alone (I think this was the original complaint)? Maybe, but in that case shouldn't the HX turn on to minimize heating energy (or users should be able to optimize this themselves without logic intervention).

So, I need to look back at the original problem that prompted this code and see where the disconnect is.

— Reply to this email directly or view it on GitHub https://github.com/NREL/EnergyPlus/issues/4568#issuecomment-138939666.

Also note the forced iteration flags at line 4363 that were added to get this to work.

Richard Raustad Florida Solar Energy Center 1679 Clearlake Road Cocoa, FL 32922 Ph: (321)638-1454 http://www.fsec.ucf.edu/en/

Program Director Electric Vehicle Transportation Center http://evtc.fsec.ucf.edu/

mjwitte commented 9 years ago

Need to think through all the possibilities here. I don't disagree that the heating coil operation vs hx operation check is useful, but it should be separate - either linked LockoutWithHeating, or as you suggest, another HX bypass choice. Will chew on this a bit and propose a change.

Myoldmopar commented 9 years ago

@mjwitte Your commit message (c11e0d9) shows 'addresses', but your PR description in #5219 says 'partially addresses'. I'm closing this since I think your commit message is more likely to be accurate.

Closed via #5219