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 390 forks source link

HPWH coil removing heat from tank #4558

Closed ejhw closed 9 years ago

ejhw commented 10 years ago

Affects plant-loop connected heat pump water heaters (HPWH) but not HPWHs with scheduled draws (Use Flow Rate Fraction Schedule). Shows up in 8.2, but not 8.1. We confirmed that this was a byproduct of the fix to #4455. Might be related to updating of tank source side inlet/outlet temperatures.

The HeatPumpWaterHeater.idf example file has five HPWHs, in different configurations:

  1. Zone 5 - HPWH using mixer/splitter nodes to blend outdoor air with zone air
  2. Zone 4 - HPWH without mixer/splitter nodes using only zone air
  3. Outdoors - HPWH located outdoors and not connected to a plant loop
  4. Scheduled - HPWH using scheduled ambient conditions
  5. Plant - HPWH located outdoors and connected to a plant loop which serves zone 1-5 reheat coils and the main heating coil in the air loop.

Only (5) shows a difference in energy usage between E+ v8.1 and v8.2. I believe this is because it is the only HPWH connected to a loop via Use Side Inlet/Outlet Nodes, as opposed to a “Use Flow Rate Fraction Schedule.” Because we use a DHW loop in BEopt (as would most models doing detailed DHW simulations), this bug affects our HPWH results: • ~50% increase in heat pump coil heating energy • ~50% increase in heat pump coil electricity use • Minor change in heat pump COP (as expected due to lower tank temperatures) • ~50% lower system COP OpenStudio measures written by PSD use DHW plant loops, so this would affect OpenStudio projects as well.

To confirm that this bug affects plant-loop-connected HPWHs, I made a copy of the Zone4HeatPumpWaterHeater from the example file (“Zone4bHeatPumpWaterHeater”) and connected it to a DHW loop with the exact same draw profile as the Zone4HeatPumpWaterHeater (see attached HeatPumpWaterHeater_V810.idf and HeatPumpWaterHeater_V820.idf). Confirming the hot water draws are identical: wh use side mass flow rate

Results for the scheduled Zone4HPWH are identical between 8.1 and 8.2: zone 4 tank temps zone 4 coil water heating

But in v8.2, the plant-loop-connected Zone4bHPWH shows sagging tank temperatures and much more water heating energy: zone 4b tank temps zone4b coil water heating

Here is a table summarizing totals for the four days in the example file. As you can see, the results for the scheduled Zone4HPWH are consistent from 8.1 to 8.2, but the plant-loop-connected Zone4bHPWH actually has negative net Source Side Heat Transfer for the four days. 8 1 8 2 zone4 zone4b table

The negative source side heat transfer rate in the 8.2 Zone4bHPWH run can be seen below. Manually calculating the source side heat transfer rate using mCpΔT agrees with the reported value, more or less. It looks like the problem is that with a plant-loop-connected HPWH, the coil removes a lot of heat from the tank at the beginning of each cycle, before recovering with either the element and heat pump, or heat pump alone. hpwh negative source hx zone 4b source side temps and coil and element heating

mjwitte commented 10 years ago

@ejhw Thanks for posting the new issue. I've added the defect files here https://github.com/NREL/EnergyPlusDevSupport/tree/master/DefectFiles/4558

ejhw commented 10 years ago

@nmerket and I are working on a proposed solution. (cc @rraustad)

mjwitte commented 10 years ago

@ejhw @nmerket Excellent. You can make a new branch and push the changes there for review.

ejhw commented 10 years ago

@nmerket's commit proposes breaking out of the for loop iteration if the set point is overshot, instead of commenting out the entire loop. This fixes the issue seen in #4455 (ran in Miami), and prevents the heat removal issue described above in the #4558 idfs. We still need to confirm that this solves the issue in our typical BEopt idf runs.

Interestingly, running the #4455 idfs in Atlanta, where the compressor is disabled at times due to ambient temperatures below 5ºC, shows a disagreement between coil heating rate and source site heating rate (coil heating rate is 10x higher), so there still seems to be an issue there. However, 4455-in-actual_HPWH.idf, is a pretty extreme case. The characteristics of the HPWH (840 kW heat pump, 0.1 m3 (26 gal) tank volume, 37 kg/s condenser flow rate) cause the entire volume of water in the tank to be pumped through the condenser every 3 seconds or 200 times every timestep. I think this contributes to the problem with the temperature blowing up in the for loop, leading to the very low PLR and high COP.

Nevertheless, we agree with @rraustad 's questioning of the for loop (see #4455). I think it has a purpose (iterating on coil capacity and tank temp), but I don't think it is doing that correctly. We made an attempt at revising it, but didn't have much luck. I'll add more details on this later.

ejhw commented 10 years ago

Plots showing that @nmerket 's commit fixes the #4455 high COP problem (running 4455-in-actual_hpwh.idf in Miami): 4455-in-actual_hpwh idf miami cops 4455-in-actual_hpwh idf miami

ejhw commented 10 years ago

Plots showing that @nmerket 's commit fixes the #4558 source side heat transfer problem (running HeatPumpWaterHeater_V810.idf and HeatPumpWaterHeater_V820.idf): EnergyPlus 8.1 8 1 EnergyPlus 8.2 with @nmerket's commit: 8 2 with fix

rraustad commented 10 years ago

What happens when the use side demand is greater than that of the HPWH?

rraustad commented 10 years ago

The fundamental problem I have with this issue is that the HPWH condenser entering water temperature "during" this time step is not equal to the tank source side outlet water temperature at the end of "this" time step. It is instead equal to the average of the tank source side outlet temperature over the "entire" time step. If the model recalculates HPWH performance on iteration 2 using the tank source outlet temp at the end of iteration 1, then the HPWH condenser outlet temp (tank source inlet temp) is wrong. I tried to figure out a way to moderate the temperature used by the HPWH model, but did not finish that effort. For example, HPWH condenser inlet water temp = (Tsourceoutletpreviousiteration + Tsourceoutlet)/2, but this did not quite give me what I was looking for.

I am also wondering if the tank source side heating rate is calculated with respect to the tank temperature or the source side inlet temperature (as is done with the DX coil model).

ejhw commented 10 years ago

Should be the same thing that happened in 8.1: the tank temperature gets pulled down by the draw.

We are proposing this an an interim fix (for 8.2.3 hopefully) that resolves both #4455 and #4558, until someone can take the time to dig deeper into the source code and revise the for-loop so that it converges properly on the timestep average condenser inlet temperature. This fix at least gets us back to a state without egregious errors.

EnergyArchmage commented 10 years ago

If I am following Rich, I think the issue may be that the function FindStratifiedTankSensedTemp may need to be revised to use the average node temperature over the timestep, rather than the “final”.

So this

                            SensedTemp = WaterThermalTank( WaterThermalTankNum ).Node( StratNodeToUse ).Temp;

Would change to

                            SensedTemp = WaterThermalTank( WaterThermalTankNum ).Node( StratNodeToUse ).TempAvg;

From: Richard Raustad [mailto:notifications@github.com] Sent: Monday, October 27, 2014 11:25 AM To: NREL/EnergyPlus Subject: Re: [EnergyPlus] HPWH coil removing heat from tank (#4558)

The fundamental problem I have with this issue is that the HPWH condenser entering water temperature "during" this time step is not equal to the tank source side outlet water temperature at the end of "this" time step. It is instead equal to the average of the tank source side outlet temperature over the "entire" time step. If the model recalculates HPWH performance on iteration 2 using the tank source outlet temp at the end of iteration 1, then the HPWH condenser outlet temp (tank source inlet temp) is wrong. I tried to figure out a way to moderate the temperature used by the HPWH model, but did not finish that effort. For example, HPWH condenser inlet water temp = (Tsourceoutletpreviousiteration + Tsourceoutlet)/2, but this did not quite give me what I was looking for.

I am also wondering if the tank source side heating rate is calculated with respect to the tank temperature or the source side inlet temperature (as is done with the DX coil model).

— Reply to this email directly or view it on GitHub https://github.com/NREL/EnergyPlus/issues/4558#issuecomment-60632427 . https://github.com/notifications/beacon/AIWWUaATw3UhSnDD5b2qG21bFTIYBFjVks5nHndOgaJpZM4CyuoO.gif

ejhw commented 10 years ago

Thanks for chiming in Brent. @nmerket and I just tried your suggestion (but with a mixed tank instead of stratified): Node( HPWaterInletNode ).Temp = WaterThermalTank( WaterThermalTankNum ).TankTempAvg; Not sure why, but x.TankTempAvg came out almost the same as x.TankTemp. Even if it did come out halfway between the start-of-timestep tank temp and the end-of-timestep tank temp, the tank temp would still "run away", albeit more slowly, since the node temperatures are not reset to start-of-timestep values each iteration of the for loop. We made an attempt to implement this reset, but it ended up causing other issues.

nmerket commented 10 years ago

@rraustad,

In response to your comment, I think you're right. I propose you, me, and @ejhw have a phone call to figure out the right way to fix this.

rraustad commented 10 years ago

Good idea, except that I am still at a loss for how to fix this. I think we need some more basic information. For example, if a hot water coil is connected to the mixed tank model, do the heat transfer rates agree? If so, if the tank electric heating element capacity is lowered so that the use or source heating rate is higher than the tank electric heating element capacity, does this problem then show up (i.e., is there a problem only when the tank temps change, or even when the tank set point is maintained)? I've never looked at that. So is it just the HPWH model, or the energy balance for the tank model that is the problem? All I am saying is that the HPWH model connects to the tank the same way any other equipment would. If there is a problem with the HPWH model, might there also be a problem with any other equipment model connected to the water tank? If so, then what would the solution be?

Let's go back to finding the energy balance in the results and then test the energy balance with other equipment models. I think any model should show this same problem since all the HPWH model does is set a mass flow and temperature on the tank inlet node (DXCoils line 6396: OutletWaterTemp = InletWaterTemp + TotalTankHeatingCapacity / ( CpWater * CondInletMassFlowRate )).

ejhw commented 10 years ago

@rraustad, to answer your question, I think there is only a problem with the HPWH model. I just did annual HPWH runs in 8.1.0, 8.2.0, and this branch, and the annual tank energy balance checks out (equals zero) in all three versions. I calculated the annual energy balance using:

Water Heater Use Side Heat Transfer Rate +
Water Heater Source Side Heat Transfer Rate +
Water Heater Heat Loss Rate

I think there are two issues:

  1. In 8.1.0 and 8.2.0, the HPWH coil heating rate disagrees with the tank Source Side HX rate (12% low and 13% high, respectively, in my annual runs). They are only 1% off in this branch. I'd guess the disagreement is because the HPWH coil mass flow rate and node temperatures are not kept consistent with the tank source side mass flow rate and node temperatures.
  2. The coil capacity and COP curves are using the wrong coil inlet temperature, because of the runaway for loop.

Can you help us tackle number 2 and then hopefully number 1 will be resolved as a byproduct?

rraustad commented 10 years ago

The only solution I can think of is using (T tanksourceoutletnode, lasttimestep + T tanksourceoutletnode, thisiteration ) / 2

rraustad commented 10 years ago

Oh wait, what if we used the equation above for the DX coil performance curve, and always used last time step tank temperature to calculate the HPWH condenser water outlet temp (Tank source inlet node temp)?

ejhw commented 10 years ago

So, let me see if I understand:

  1. Use your equation above for the call to CalcHPWHDXCoil( HPWaterHeater( HPNum ).DXCoilNum, HPPartLoadRatio );
  2. Calculate the CondenserDeltaT and add that to the last time step tank temperature to determine the HPWH condenser water outlet temp (Tank source inlet node temp).

That sounds good to me. What would be the best way to iterate on the coil inlet temperature? I think iteration is necessary since the coil capacity is a function of the coil inlet temperature, which is a function of the coil capacity. Could we use the call to the RegulaFalsi subroutine? Or would this have to be done in a for loop iteration as was present in 8.1?

EnergyArchmage commented 10 years ago

I can't quite recall, but I believe the for loop was introduced to fix a challenging CR for 8.0, but I can't track down the old CR numbers anymore. There was a big disconnect in the heat transfer rates between what the heat pump dx coil said and the tank said was happening at the source side. I thought it was jon or eric who reported that. I couldn't find a good fix at the time, but the for loop got fairly close. Should maybe reopen that old CR.

The variation in tank temperature over the timestep is exponential, not linear as implied by Rich's equation, and resolved at 1 sec. The tank model should already be doing what is needed to come up with the average. I think the condenser inlet should be an average for the current timestep. If I remember correctly, the old problem was that it was the last timestep value.

The system nodes connecting heat pump to the tank are a different beast than any other system nodes in Plant; they do not fit in the plant scheme at all and node updates need to be done locally.

just chiming in with more background...

rraustad commented 10 years ago

Not exactly, 1) the call to CalcHPWHDXcoil inherently uses the coil water node inlet temp in the calculation of both heating capacity and outlet water temp. So a new method must be used. If these 2 temps were passed as an argument, they could then be used in the necessary calculations. The coil model would update the DX coil condenser outlet node temp so there would be no need for 2).

Alternately, maybe if you just updated CondenserDeltaT to equal the equation above, both capacity and outlet water temp would use this value and things might work out OK?

I think I'd start with this inside the for loop (to see if this helps converge on heating rates): WaterThermalTank( WaterThermalTankNum ).SourceInletTemp = HPWaterInletNodeTempSaved + CondenserDeltaT; Where HPWaterInletNodeTempSaved is the tank temp from last time step.

I'm still unsure of the tank calculation for Source Side Heat Transfer Rate, is it source inlet temp wrt the source outlet temp or the tank set point temp? If it's tank set point temp, the coil and tank heating rates will never be equal.

I'd avoid RegulaFalsi for this issue at this point. Once it's figured out, then a RegulaFalsi function may be devised to find a quicker solution.

mjwitte commented 10 years ago

@EnergyArchmage Looking at EnergyPlusArchive at the f90 source file and pressing "blame" it appears that this loop and lots of other code were added in Mar 2012.

https://github.com/NREL/EnergyPlusArchive/commit/08b06e071c51d29c72c0a89d8da568bde6a58ea1

Still trying to connect a CR number to this change.

mjwitte commented 10 years ago

It wasn't a CR, it was a new feature. From the v7.0 featurechanges.csv fle

3/15/2012 BG NewFeature allow Heat pump water heater to use stratified tank

rraustad commented 10 years ago

"I think the condenser inlet should be an average for the current timestep. If I remember correctly, the old problem was that it was the last timestep value."

this would then imply for ( loopIter = 1; loopIter <= 2; ++loopIter )

The HPWH condenser inlet temp should still be the average tank temp, not the ending tank temp. What's the average of an exponential curve when you don't know tau?

EnergyArchmage commented 10 years ago

The CR came up at the same time and went in with the new feature.

From: Michael J. Witte [mailto:notifications@github.com] Sent: Wednesday, October 29, 2014 1:51 PM To: NREL/EnergyPlus Cc: Brent Griffith Subject: Re: [EnergyPlus] HPWH coil removing heat from tank (#4558)

It wasn't a CR, it was a new feature. From the v7.0 featurechanges.csv fle

3/15/2012 BG NewFeature allow Heat pump water heater to use stratified tank

— Reply to this email directly or view it on GitHub https://github.com/NREL/EnergyPlus/issues/4558#issuecomment-60992314 . https://github.com/notifications/beacon/AIWWUbJ5xvtVpHQ7NsWG1825XpKL3-0Vks5nITyGgaJpZM4CyuoO.gif

ejhw commented 10 years ago

Looking at EnergyPlusArchive at the f90 source file and pressing "blame" it appears that this loop and lots of other code were added in Mar 2012.

@mjwitte, the DO loopIter = 1, 4 was actually present before that commit; there was just some whitespace removed from those lines.

mjwitte commented 10 years ago

Oh - you're right - moving too fast. Unfortunately, it appears that the history in the github archive thinks this commit changed every line, so there's no blame tracing backward from there.

12.01.27 Change copyright date to 2012

If we really want to know (or care) when the loop was introduced, we'll need to look back until "loopiter" isn't there anymore.

On 10/30/2014 1:51 PM, Eric Wilson wrote:

Looking at EnergyPlusArchive at the f90 source file and pressing
"blame" it appears that this loop and lots of other code were
added in Mar 2012.

@mjwitte https://github.com/mjwitte, the |DO loopIter = 1, 4| was actually present before that commit; there was just some whitespace removed from those lines https://github.com/NREL/EnergyPlusArchive/commit/08b06e071c51d29c72c0a89d8da568bde6a58ea1#diff-dbbb5286ce2c6d6e001e8201b2cfc183L7832.

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

ejhw commented 10 years ago

Trying to summarize some of our thoughts:

ejhw commented 10 years ago

Regarding @rraustad 's question:

I'm still unsure of the tank calculation for Source Side Heat Transfer Rate, is it source inlet temp wrt the source outlet temp or the tank set point temp?

I've always assumed the Source Side Heat Transfer Rate was the _m_dot cp deltaT across the Source Side Inlet and Outlet nodes, but I think @rraustad is correct that it is deltaT with respect to the tank temperature(s). See relevant code for mixed tank and stratified tank. Does anyone know why this would be the case? It seems counterintuitive.

rraustad commented 10 years ago

Because the impact on the tank is the source/use inlet temps and mass flow rates wrt the tank temperature, which is changing over the time step. The corresponding outlet node conditions are also inherently tied to the tank temp. The problem is that the external models (e.g., HPWH) only simulate using the tank outlet node temps at one point in time. I still can't believe that this issue isn't apparent in other models. If not, identifying that reason may help here.

EnergyArchmage commented 10 years ago

to

WaterThermalTank( WaterThermalTankNum ).SourceInletTemp = HPWaterInletNodeTempSaved + CondenserDeltaT;

within the for loop, so that the HPWaterInletNodeTemp is reset to the beginning of timestep value.

I doubt this is going to work. This is the usual approach with quasi-steady models, but the tank is a dynamic model and needs different thinking. Both the inlet and the outlet need to be solved for the current timestep, and that requires iterating/solving as it cannot be calculated directly. I suspect the for loop needs to be set up to detect convergence (in source side heat transfer rates) and exit based on criteria, or get reworked to use regula falsi or something. Maybe the original, fast-changing defect file needed more than 4 iterations.

nmerket commented 10 years ago

After stepping through in a debugger trying to figure out how to get things to line up for Atlanta on 4455-in-actual_HPWH.idf, I'm finding that the CalcWaterThermTankMixed calculation of the tank's source side heat transfer rate has issues.

see line 5052 of WaterThermalTanks.cc:

Qsource = SourceMassFlowRate * Cp * ( SourceInletTemp - SetPointTemp );

Qsource is noted as being the steady-state heat rate. In this problematic case where the tank temperature has dropped so far that the source inlet temperature from the heat pump is less than the set point temperature, it actually shows that the heat pump is removing heat from the tank, which is incorrect. The effect becomes worse because the flow rate of the water through the heat pump is really high (just shy of 600 gpm or in other words all of the water in the tank cycles through the heat pump 22.5 times every minute). So, even though the heat pump is actually adding heat at a very high rate of 840,000 W at that high flow rate, the tank thinks that because the Qsource above is hugely negative due to the big mass flow rate it's actually losing a lot of heat. This seems to only be a large effect in this crazy system with grossly out of proportion heat pump and tank size. However, it will throw off the calculations any time the heat pump is recovering the tank temperature and it will take longer than one time step.

rraustad commented 10 years ago

I saw that line of code but it is unclear if that is simply a preliminary calculation or is actually used in the solution. Since Qneeded is not used in the call to CalcTimeNeeded nor CalcTankTemp

Note this comment: // Qneeded does not account for the extra energy needed to recover to the setpoint Qneeded = -Quse - Qsource - Qloss - Qoncycheat;

// Calculate time needed to recover to the setpoint at maximum heater capacity TimeNeeded = CalcTimeNeeded( TankTemp, SetPointTemp, AmbientTemp, UseInletTemp, SourceInletTemp, TankMass, Cp, UseMassFlowRate, SourceMassFlowRate, LossCoeff, Qheat );

NewTankTemp = CalcTankTemp( TankTemp, AmbientTemp, UseInletTemp, SourceInletTemp, TankMass, Cp, UseMassFlowRate, SourceMassFlowRate, LossCoeff, Qheat, TimeNeeded );

I guess I'm not ready to jump to any conclusions here especially since this appeared to partially work when using the previous for loop and the comments specifically call out the fact that Qneeded does not account for the extra energy needed to recover to the setpoint.

EnergyArchmage commented 10 years ago

Ahh the huge flow rate is a familiar problem, the model just can’t handle it. There is this trap for that situation when used with the stratified tank, probably needs to be extended to the mixed tank.

                       // check for sizing issues that model can not suppport

                       // if stratified tank model, ensure that nominal change over rate is greater than one minute, avoid numerical problems.

                       if ( ( WaterThermalTank( WaterThermalTankNum ).TypeNum == StratifiedWaterHeater ) || ( WaterThermalTank( WaterThermalTankNum ).TypeNum == StratifiedChilledWaterStorage ) ) {

                              MaxSideVolFlow = max( WaterThermalTank( WaterThermalTankNum ).UseDesignVolFlowRate, WaterThermalTank( WaterThermalTankNum ).SourceDesignVolFlowRate );

                              if ( MaxSideVolFlow > 0.0 ) { // protect div by zero

                                     TankChangeRateScale = WaterThermalTank( WaterThermalTankNum ).Volume / MaxSideVolFlow;

                                     if ( TankChangeRateScale < 60.0 ) { // nominal change over in less than one minute

                                            ShowSevereError( "InitWaterThermalTank: Detected problem for stratified tank model.  Model cannot be applied." );

                                            ShowContinueError( "Occurs for stratified tank name = " + WaterThermalTank( WaterThermalTankNum ).Name );

                                            ShowContinueError( "Tank volume = " + RoundSigDigits( WaterThermalTank( WaterThermalTankNum ).Volume, 4 ) + " [m3]" );

                                            ShowContinueError( "Tank use side volume flow rate = " + RoundSigDigits( WaterThermalTank( WaterThermalTankNum ).UseDesignVolFlowRate, 4 ) + " [m3/s]" );

                                            ShowContinueError( "Tank source side volume flow rate = " + RoundSigDigits( WaterThermalTank( WaterThermalTankNum ).SourceDesignVolFlowRate, 4 ) + " [m3/s]" );

                                            ShowContinueError( "Nominal tank change over rate = " + RoundSigDigits( TankChangeRateScale, 2 ) + " [s]" );

                                            ShowContinueError( "Change over rate is too fast, increase tank volume, decrease connection flow rates" " or use mixed tank model" );

                                            ShowFatalError( "InitWaterThermalTank: Simulation halted because of sizing problem in stratified tank model." );

                                     }

                              }

                       }

The effect becomes worse because the flow rate of the water through the heat pump is really high (just shy of 600 gpm or in other words all of the water in the tank cycles through the heat pump 22.5 times every minute). So, even though the heat pump is actually adding heat at a very high rate of 840,000 W at that high flow rate, the tank thinks that because the Qsource above is hugely negative due to the big mass flow rate it's actually losing a lot of heat. This seems to only be a large effect in this crazy system with grossly out of proportion heat pump and tank size.

Reply to this email directly or view it on GitHub https://github.com/NREL/EnergyPlus/issues/4558#issuecomment-61729746 . https://github.com/notifications/beacon/AIWWUT5u9gdm3Vq8GwOpbetTd7k17Q5sks5nKU-DgaJpZM4CyuoO.gif

nmerket commented 10 years ago

@rraustad,

You're right in that Qneeded is a preliminary calculation there. However, that same problem pops up in CalcTimeNeeded because it is using the SourceInletTemp and SourceMassFlowRate to do the same m_dot Cp deltaT calculation. I keep seeing that function return a TimeNeeded of effectively forever because in it thinks the heat pump is removing large amounts of energy from the tank. The same problem exists in CalcTankTemp.

@EnergyArchmage,

I think it makes sense to throw an error like that for mixed tanks as well as stratified. I'm not convinced that it's catching it for stratified tank models, though. One of the examples for #4455 uses a stratified tank and doesn't seem to run into that error. I need to check but I think it's the same tank and heat pump configuration.

I'm going to continue walking through this but with a model that has a more reasonable tank size to source flow rate ratio--probably the one that we posted to dev support for this ticket. It's still showing inconsistencies between the coil heat transfer rate and the tank source side heat transfer rate.

nmerket commented 9 years ago

I think I know what's going on now. There are two sort of related things going on here:

The 4x for loop

This for loop (and it's corresponding identical twin) were put in to make sure CalcHPWHDXCoil is called with the average tank temperature for its inlet for that time step by iterating a few times to converge. Previously it would just climb a few degrees every iteration. Now it converges on the average temperature for the time step. I'm pretty sure this is working correctly now, but it didn't solve the problem for why we opened this ticket. It seems like most of the time this wasn't a really big issue and caused maybe second order effects on the results. This was good to fix, but mostly a red herring.

High use side flow rates causing instability in the tank calculations

This is the problem I believe we were seeing in both #4455 and this issue. Unfortunately the for loop issue above seemed to trigger it sometimes. What happens is that when the use side mass flow rate is high relative to the tank volume and time step it causes a sudden drop in tank temperature. (In most of our examples it was on the order of changing out all the water in the tank or more during a time step, but it seems to happen sometimes with lower flow rates as well.) When the heat pump function sees this it kicks on. The problem arises because the tank calculations assume a constant source side inlet temperature for the entire time step. The loop above makes sure that the heat pump is using the "average" temperature given the draw as the tank source outlet and returns a temperature a few degrees higher for the tank source side inlet. If the draw was so big and so fast that within one time step the source side inlet temperature is less than the set point temperature it sets off an instability in the tank calculation where it assumes that the heat pump is actually removing heat from the tank. From there it will never recover as long as the draw is still happening. The effect get magnified each time step. When the draw finally ends, it takes several more time steps for the tank to see the heat being added by the heat pump and recover to normal operation.

In our test file, we saw this on only the system (4B) that used a PlantLoop for the draws and not just the plain scheduled draws. This is because the PlantLoop runs a few iterations in the HVAC loop (I assume) at maximum draw before each time step. That ended up being about 60 gal/min on a 100 gal tank and triggered the instability. When I change the idf so that the maximum flow rate is more reasonable it runs into this problem less, but still hits it.

It would seem that the error in the aforementioned for loop caused us not to hit this as often because it would artificially inflate the source side inlet temperature, but now that it's more accurately determining the average source side inlet and outlet temperatures over the time step and calculating the delta T across the heat pump based on that, we're hitting this more.

Now what?

I am fairly certain that it is working right as of now except that it is very sensitive to this use side mass flow rate issue. It's not an easy issue to address, though. Some ideas I have are:

I haven't done anything with stratified tanks yet, so I have no idea what fun awaits us there on these issues.

rraustad commented 9 years ago

I really like this one: •Have an input on the tank calc functions that tells it to perform its calculations by using the heat pump condenser delta T instead of just using the static value over the time step.

Not sure what this will do to the HPWH and tank source side heating rate differences seen previously.

nmerket commented 9 years ago

Does anybody know why when the water heater is connected to a plant loop, it calls the the tank calculation functions with the maximum possible use flow rate for the attached WaterUse:Equipment disregarding maximum schedule values for a few iterations at the beginning of each time step?

rraustad commented 9 years ago

It's looking to see what the maximum available capacity is before calculating operating capacity?

EnergyArchmage commented 9 years ago

It may be more of a coincidence that some key design flow rates have the same value as the WaterUse:Equipment's max.

nmerket commented 9 years ago

I think I've got this one worked out. I generated some results comparing my changes to 8.1. You can see the plots at https://github.com/NREL/EnergyPlusDevSupport/blob/master/DefectFiles/4000s/4558/plot_verifyall.html Unfortunately it doesn't render the page in GitHub. If you have the repository cloned on your machine you can just do a git pull and the double click on it and it should open in your web browser.

I'm going to do a few more tests with some HPWHs we are using in BEopt to see if there's anything weird going on there and then I'll issue the pull request.

rraustad commented 9 years ago

This looks better. The question now is why doesn't the use side match up with the source side? If the use side is the load, and the source side is the capacity, why don't they match? The tank temps don't start and end at the same value, but that shouldn't cause that large of a difference between use and source energy (actually power in these plots). What are the parasitic losses? Is the same thing happening on the use side that was happening on the source side that started this whole mess?

nmerket commented 9 years ago

First, I think some of those numbers are alarming because they are big. They are in units of W * timestep or W * (15 min). Therefore, to convert to something that's easier to comprehend we need to multiply by 0.00025 to get it into kWh.

Secondly, those numbers are not accounting for tank skin losses. Below I calculate an energy balance for the whole simulation by summing the source side heat transfer rate, use side heat transfer rate, and the water heater heat loss rate.

The problem is different depending on which tank model we use:

Mixed Tank

The total energy balance of the tank in kWh is:

mixed81
Energy Balance 4    -1.604851
Energy Balance 4B   -1.604866

mixed82
Energy Balance 4    -1.605955
Energy Balance 4B   -1.605955

Therefore the tank is losing about 1.6 kWh over the whole simulation, or the amount of energy that would cause a 3.6 degC temperature change in that tank. As it turns out, that simulation is broken out over four different days, with a warmup between each. At the end of each day the tank temperature is about 0.9 degC lower than the start:

index

When you add that up you get (drumroll please) 3.6 degC. Energy is conserved. This model is working and reporting as expected.

Stratified Tank

Calculating the energy balance for the stratified tank isn't quite so tidy. Once again these are in kWh.

stratified81
Energy Balance 4     15.626901
Energy Balance 4B    15.725015

stratified82
Energy Balance 4     27.856060
Energy Balance 4B    27.833997

I do want to point out that this is not a new problem since it was very much present in 8.1. However, the changes I made do seem to amplify it. I think that is because all the source side energy wasn't being fully accounted for previously due to the issue that I fixed.

The problem here seems to be in the way that the use side energy rate is being calculated for reporting. The issue comes from this line in CalcWaterThermalTankStratified:

// Heat transfer due to fluid flow entering an inlet node
Quse = UseMassFlowRate * Cp * ( UseInletTemp - NodeTemp );

This calculation happens at the use inlet node, which in my tank is at the bottom and gets cold as time marches on during a draw. Meanwhile the use outlet node is at the top of the tank where temperatures are much closer to set point. From the perspective of the tank what we'd expect in the reporting is to calculate Quse like:

Quse = UseMassFlowRate * Cp * (UseInletTemp - UseOutletTemp);

but that's not what's happening. You can see the reported magnitude of Quse decrease as the draw continues and the use inlet node temperature plummets. Then in increases again as the heat pump kicks on and starts dumping heat into that node.

index1

I think the way Quse is being calculated is correct for that node because the energy balance on that node is relative to the temperature of that node. However, when that value is summed up and averaged over the whole time step to represent the use side heat transfer rate of the whole tank, it will always underestimate it.

A way to fix this would be to sum and average the tank Quse separately based on the temperature difference between the use inlet and outlet nodes. However, I'd feel better about charging ahead with it if @EnergyArchmage took a look and made sure it makes sense.

EnergyArchmage commented 9 years ago

I haven't spent much time on this, but at a first read I am uneasy about it. I think I recall a CR that FSEC handled to fix these sort of rates for the stratified tank to the method used now.

Balance checks on these dynamic models are not straightforward. When calculating the energy balance in the stratified tank, make sure you (or the outputs) are accounting for beginning and ending temperature states in all the different nodes. Going to need to include McpDT/dt terms for node temperature change for each volume of water.

nmerket commented 9 years ago

Okay so I went ahead and did it anyway just to see what would happen. It improved the situation. Here's what the heat transfer rates look like now for the stratified tank.

index3

The energy balance is closer now only 17 kWh off now instead of 27, almost the difference we saw in 8.1.

stratified81
Energy Balance 4     15.626901
Energy Balance 4B    15.725015

stratified82
Energy Balance 4     17.596198
Energy Balance 4B    17.561052

The main thing this does is change the value that is reported. I didn't change any of the calculations, which is I think what your concern is @EnergyArchmage.

EnergyArchmage commented 9 years ago

Maybe it is just a subtle shift in how the output variables for 'side heat transfer need to be interpreted, especially when switching from mixed tank context to stratified tank. The inward flowing flux into the control volume is what is significant for the tank's heat balance. This was the subject of an old CR.

nmerket commented 9 years ago

I’m happy to put it back the way it was as long as we’re all satisfied that it’s calculating it correctly.

On Dec 16, 2014, at 3:16 PM, Brent Griffith notifications@github.com<mailto:notifications@github.com> wrote:

Maybe it is just a subtle shift in how the output variables for 'side heat transfer need to be interpreted, especially when switching from mixed tank context to stratified tank. The inward flowing flux into the control volume is what is significant for the tank's heat balance. This was the subject of an old CR.

— Reply to this email directly or view it on GitHubhttps://github.com/NREL/EnergyPlus/issues/4558#issuecomment-67242892.

ejhw commented 9 years ago

@EnergyArchmage, isn't the hot water leaving the control volume also significant?

@nmerket, any ideas why it still isn't zero after your change?

nmerket commented 9 years ago

@ejhw, I am out of ideas as to why it still isn't zero at this point.

I propose this energy balance problem be considered in another issue for the following reasons:

rraustad commented 9 years ago

I thought we already determined that the change in tank temperature accounted for the differences (figure above with yellow circles). What is the energy balance for an annual simulation?

nmerket commented 9 years ago

I believe it is accounted for in the mixed tank model. The stratified tank is another story. In that case the report says we're missing 17.6 kWh or about a 40 degC temperature difference in the tank, which is not negligible. When you account for the temperature difference in the day jumps and between the beginning and end of the simulation it's 1.2 degC, so there's something going on.

index

Maybe I'm missing something important that makes this whole energy balance calculation irrelevant. I sure hope so.

EnergyArchmage commented 9 years ago

maybe you can share the full spreadsheet or whatever you are using to check the balance.

I think the definition of the report variable was subtly changed as part of an old CR. I don't mind changing it back... but just have that sinking feeling there might be some CR-whipsawing going on here. It would be good to at least review the discussion under the old CR if possible. I think it started as source side reporting issue and then the change was done on both the source and use sides.

@ejhw Sorry I am so terse, I just meant from the point of view of the tank, it is the inlets that determine state. Of course outlet's matter downstream, but what skews my thinking about this is that the outward flowing terms tend to fall out and not drive the solution of these sort of control volume models.

As a user, I would only pay attention to the system node mass flow rates and temperatures. Both definitons seem flawed to me and the concept of one overall "Use side heat transfer" is a bit murky for stratified tank . Maybe there should be three flavors of the report: Use Side Inlet HT (current), Use Side Outlet HT, and Use Side Net HT (this commit).