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

Fix VRF FluidTCtrl negative outdoor unit fan power #10649

Open
wants to merge 20 commits into
base: develop
Choose a base branch
from
Open
Changes from 2 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
7f2acaf
use abs(QCoil) in air flow calculation
Aug 8, 2024
ae3fec6
Merge remote-tracking branch 'origin/develop' into fixVRFnegativeFanP…
Aug 13, 2024
cabd9e6
revert abs(Q_coil), reduce h_IU_cond_in label230, fix Q_evap_req neg
Aug 22, 2024
765218b
Merge remote-tracking branch 'origin/develop' into fixVRFnegativeFanP…
Aug 23, 2024
35d4b69
add converge check that h_comp_out_new changed
Aug 23, 2024
0f1d4fd
Merge remote-tracking branch 'origin/develop' into fixVRFnegativeFanP…
Oct 4, 2024
935df9e
Revert "add converge check that h_comp_out_new changed"
Oct 7, 2024
38ad9f1
Patch for Q_cond_req < min speed power, CompSpdActual int to real
Oct 7, 2024
d54f356
clang-format
Oct 7, 2024
39567c8
fix unit test
Oct 7, 2024
aae3346
simplify the code by condition on sign of Q_evap_req
Oct 14, 2024
bd53fd7
Merge remote-tracking branch 'origin/develop' into fixVRFnegativeFanP…
Oct 14, 2024
4e979ea
use PLR in compressor speed calculation
Oct 21, 2024
1b58521
modify PLR application on the speed level > 1 case
Oct 21, 2024
cce66e0
Merge remote-tracking branch 'origin/develop' into fixVRFnegativeFanP…
Oct 21, 2024
a135044
fix unit test after changing compSpdActual calculation
Oct 21, 2024
835253a
remove unused Q_evap_req, remove C_cap_operation adjustment
Oct 22, 2024
436f277
fix unit test after removing C_cap_operation adjustment
Oct 22, 2024
a777bf5
fix uninitialized RatedHeatCapacity in VRF HR model
Oct 23, 2024
380d580
use newly derived r to compute compressor speed and Q_evap_req
Oct 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/EnergyPlus/HVACVariableRefrigerantFlow.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13288,7 +13288,7 @@ Real64 VRFCondenserEquipment::VRFOU_FlowRate(EnergyPlusData &state,
deltaT = this->C3Tc * pow_2(SHSC) + this->C2Tc * SHSC + this->C1Tc;
T_coil_surf = TeTc - deltaT;
T_coil_out = T_coil_in + (T_coil_surf - T_coil_in) * (1 - BF);
m_air = Q_coil / (T_coil_out - T_coil_in) / 1005.0;
m_air = abs(Q_coil) / (T_coil_out - T_coil_in) / 1005.0;
Copy link
Contributor

Choose a reason for hiding this comment

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

If I'm understanding Q_coil correctly, it should never be <0. While this fixes the issue (which occurs only a few timesteps in the year) it masks a problem higher up. The Q that is passed in to this function shouldn't be <0, ever.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

So Q_coil is negative when it's in cooling mode. It is positive when it's heating

Copy link
Contributor

Choose a reason for hiding this comment

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

So Q_coil is negative when it's in cooling mode. It is positive when it's heating

I'm not sure that's the case. Q_coil here is the heat rejection when the unit is in cooling mode. So it's heating the outdoor air, so (Tcoilout-Tcoilin) should be positive, so you would expect Q_coil to be positive.

In the next block where it's in heating mode (so it's cooling the outdoor air) delta is (h_coil_in - h_coil_out so, again deltaH is positive and so Q_coil should be positive.

I ran in the debugger and saw both positive and negative values of Q_coil in the OperationMode == HXOpMode::CondMode block. Tried to watch the values in the OperationMode == HXOpMode::EvapMode block, but it never goes there. Even with Atlanta weather. That doesn't seem correct. Is it possible that the value passed in for OperationMode is not correct here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Now I'm not certain whether Q_coil should be always positive or not.
Although, from the definition of this function, it seems they do need to be absolute value of Q_coil.

Real64 VRFCondenserEquipment::VRFOU_FlowRate(EnergyPlusData &state,
                                             HXOpMode const OperationMode, // Mode 0 for running as condenser, 1 for evaporator
                                             Real64 const TeTc,            // VRF Tc at cooling mode, or Te at heating mode [C]
                                             Real64 const SHSC,            // SC for OU condenser or SH for OU evaporator [C]
                                             Real64 const Q_coil,          // absolute value of OU coil heat release or heat extract [W] <----- here they require absolute value
                                             Real64 const T_coil_in,       // Temperature of air at OU coil inlet [C]
                                             Real64 const W_coil_in        // Humidity ratio of air at OU coil inlet [kg/kg]
) const
{

Maybe I should just add a Q_coil = abs(Q_coil) at the beginning of the call to this function? @mjwitte

Copy link
Contributor

@mjwitte mjwitte Aug 19, 2024

Choose a reason for hiding this comment

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

Maybe I should just add a Q_coil = abs(Q_coil) at the beginning of the call to this function?

No, I think that will mask other problems. To me, the "absolute value" comment implies that the value passed in will always be positive. We need to understand if HXOpMode is being passed in correctly and better understand the variables that are being passed in for Q_coil.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I see. I will look into it. Currently there are definitely both positive and negatives for the same mode

Copy link
Collaborator Author

@yujiex yujiex Aug 20, 2024

Choose a reason for hiding this comment

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

I've done some investigations and had a few findings. Although I'm not sure if this is enough to figure out a fix. @mjwitte

about the operation mode

According to the documentation, there are 6 heat recovery modes

  • Mode 1: Cooling load only. No heating load. Both OU heat exchangers operate as condensers.
  • Mode 2: Simultaneous heating and cooling. The sum of the zone cooling loads and compressor heat is much larger than the sum of the zone heating loads. Both OU heat exchangers operate as condensers.
  • Mode 3: Simultaneous heating and cooling. The sum of the zone cooling loads and compressor heat is slightly larger than the sum of the zone heating loads. One OU heat exchanger operates as a condenser while the other as an evaporator.
  • Mode 4: Simultaneous heating and cooling. The sum of the zone cooling loads and compressor heat is slightly smaller than the sum of the zone heating loads. One OU heat exchanger operates as a condenser while the other as an evaporator.
  • Mode 5: Simultaneous heating and cooling. The sum of the zone cooling loads and compressor heat is much smaller than the sum of the zone heating loads. Both OU heat exchangers operate as evaporators.
  • Mode 6: Heating load only. No cooling load. Both OU heat exchangers operate as evaporators.

Here is how the heat recovery mode is determined


// Determine FlagToLower
// this->DiffOUTeTo is "Difference between Outdoor Unit Evaporating Temperature and Outdoor Air Temperature in Heat Recovery Mode" from user input
if (state.dataEnvrn->OutDryBulbTemp - this->DiffOUTeTo < Tsuction) {
    temp_Tsuction = state.dataEnvrn->OutDryBulbTemp - this->DiffOUTeTo;
    FlagToLower = true;
} else {
    temp_Tsuction = Tsuction;
    FlagToLower = false;
}

// Calculate compressor speed satisfying IU loads: rps1_evap & rps2_cond
this->VRFOU_CompSpd(state, Q_c_TU_PL, HXOpMode::EvapMode, temp_Tsuction, Tdischarge, h_IU_evap_in, h_IU_PLc_out, rps1_evap);
this->VRFOU_CompSpd(state, Q_h_TU_PL, HXOpMode::CondMode, temp_Tsuction, Tdischarge, h_IU_evap_in, h_IU_PLc_out, rps2_cond);

// Determine FlagMode5
if (rps1_evap <= rps2_cond) {
    FlagMode5 = true;
} else {
    FlagMode5 = false;
}

// Determine HR Mode
if (FlagMode5) {
    HRMode = 5;
    if (FlagToLower)
        HRMode_sub = 1;
    else
        HRMode_sub = 2;
} else {

    if (FlagToLower)
        HRMode = 3; // Mode 3&4 share the same logics below
    else
        HRMode = 2;
}

One issue I saw is that rps2_cond is negative sometimes. Here's some debugging print. I used the
VariableRefrigerantFlow_FluidTCtrl_HR_5Zone.idf and USA_FL_Miami.Intl.AP.722020_TMY3.epw combination. For the 01/02 07, 4th time step, rps2_cond is negative.

01/02 07-4 HRMode=2, flag5=false, rps1_evap=14.796895201613392,rps2_cond=-103.04599155624868: Q_c_TU_PL=279.7809733457191, Q_h_TU_PL=300.59323456715885, temp_Tsuction=14.000000000000002,Tdischarge=36

This is caused by the following in VRFCondenserEquipment::VRFOU_CompSpd, where Q_req is smaller than the CompEvaporatingPWRSpd(CounterCompSpdTemp) when CounterCompSpdTemp = 1.

Q_cond_req = Q_req;
...
Q_evap_req = Q_cond_req - CompEvaporatingPWRSpd(CounterCompSpdTemp);

I was considering, maybe Q_evap_req = Q_cond_req - CompEvaporatingPWRSpd(CounterCompSpdTemp); should be Q_evap_req = max(0.0, Q_cond_req - CompEvaporatingPWRSpd(CounterCompSpdTemp));

Even with this, there still remains a question of how this "much larger" or "much smaller" in mode 2 and 5 is reflected in the code. I feel the current code seems to be just testing for "larger" or "smaller".

about the Q_coil sign

the input argument Q_h_OU in m_air_cond = this->VRFOU_FlowRate( state, HXOpMode::CondMode, Tdischarge, this->SC, Q_h_OU, state.dataEnvrn->OutDryBulbTemp, state.dataEnvrn->OutHumRat); corresponds to the Q_coil referred to in the last comment.

Here is how it's computed. As Q_c_tot + Ncomp is smaller than Q_h_TU_PL, the Q_h_OU is negative.

// compressor: Ncomp & Q_c_tot
this->VRFOU_CompCap(state, CompSpdActual, Tsuction, Tdischarge, h_IU_evap_in, h_comp_in, Q_c_tot, Ncomp);

Real64 Q_h_tot;                 // Total condenser capacity [W]
Real64 Q_h_TU_PL;                // Heating load to be met at heating mode, including the piping loss (W)
Real64 &Q_h_OU,        // OU condenser load [W]
Q_h_tot = Q_c_tot + Ncomp; 
Q_h_OU = Q_h_tot - Q_h_TU_PL;

Following is the debug print

01/02 07-4 Q_h_OU=-14.889397577117904=285.70383699004094 - 300.59323456715885

For this specific instance, the Q_h_TU_PL is mostly on the piping loss term.
Q_h_TU_PL = TU_HeatingLoad + Pipe_Q_h;

01/02 07-4 Q_h_TU_PL=300.59323456715885=0.8205014721511905 + 299.77273309500765

Maybe being in HR mode 2 should have ensured Q_c_tot + Ncomp much larger than Q_h_TU_PL? (as Q_c_tot and Ncomp is the compressor performance at the compressor speed rps1_evap that meets the cooling load Q_c_TU_PL). But currently it's not.

about the high piping loss

There's also some strange behavior about the very large piping loss.

Piping loss is calculated here, in the iterations (label230 region), other input arguments stay the same, the h_IU_cond_in updates, leading to updates in piping loss (Pipe_Q_h).

 this->VRFOU_PipeLossH(
            state, m_ref_IU_cond, max(min(Pcond, RefPHigh), RefPLow), h_IU_cond_in, OutdoorDryBulb, Pipe_Q_h, Pipe_DeltP_h, h_comp_out);

The convergence for the label230 checks whether h_comp_out and h_comp_out_new is close and whether h_IU_cond_in is maxed out. So before it's converged h_IU_cond_in keeps increasing till it reaches the upper bound h_IU_cond_in_up.

((std::abs(h_comp_out - h_comp_out_new) > Tolerance * h_comp_out) && (h_IU_cond_in < h_IU_cond_in_up))

I've added some debug print after this line.

        //* Update h_comp_out in iteration (Label230)
        h_comp_out_new = Ncomp / (m_ref_IU_evap + m_ref_OU_evap) + h_comp_in;

The following is the output for the iteration. h_comp_out_new stays the same while h_comp_out gets updated in function VRFOU_PipeLossH(). However, the h_comp_out is not going in the right direction. It's much larger than h_comp_out_new at the beginning and keeps increasing each round till h_IU_cond_in is maxed out. Large h_IU_cond_in will lead to high piping loss. This potentially contributes to the fact that Q_h_tot - Q_h_TU_PL is negative (Q_h_TU_PL gets too large as the piping loss term is large)

-------------before iteration !!! ----------------------------------
01/02 07-4 h_comp_out_new=451462.4133081403=20.990626990893254 / (0.0013282280846405876 + 0) + 435658.9325403223, h_comp_out=25374199.615089763
01/02 07-4 h_comp_out_new=451462.4133081403=20.990626990893254 / (0.0013282280846405876 + 0) + 435658.9325403223, h_comp_out=29927864.42684107
01/02 07-4 h_comp_out_new=451462.4133081403=20.990626990893254 / (0.0013282280846405876 + 0) + 435658.9325403223, h_comp_out=34929581.8246451
01/02 07-4 h_comp_out_new=451462.4133081403=20.990626990893254 / (0.0013282280846405876 + 0) + 435658.9325403223, h_comp_out=40339405.37992493
01/02 07-4 h_comp_out_new=451462.4133081403=20.990626990893254 / (0.0013282280846405878 + 0) + 435658.9325403223, h_comp_out=46137187.431805536
01/02 07-4 h_comp_out_new=451462.4133081403=20.990626990893254 / (0.0013282280846405878 + 0) + 435658.9325403223, h_comp_out=52302549.03700723
01/02 07-4 h_comp_out_new=451462.4133081403=20.990626990893254 / (0.0013282280846405878 + 0) + 435658.9325403223, h_comp_out=58808375.97752049
01/02 07-4 h_comp_out_new=451462.4133081403=20.990626990893254 / (0.0013282280846405878 + 0) + 435658.9325403223, h_comp_out=65654625.1845655
01/02 07-4 h_comp_out_new=451462.4133081403=20.990626990893254 / (0.0013282280846405878 + 0) + 435658.9325403223, h_comp_out=72837775.9464217
01/02 07-4 h_comp_out_new=451462.4133081403=20.990626990893254 / (0.0013282280846405876 + 0) + 435658.9325403223, h_comp_out=80330393.31041604
01/02 07-4 h_comp_out_new=451462.4133081403=20.990626990893254 / (0.0013282280846405878 + 0) + 435658.9325403223, h_comp_out=88762784.65486081
-------------after iteration !!! ----------------------------------

Copy link
Contributor

@rraustad rraustad Aug 23, 2024

Choose a reason for hiding this comment

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

So during these iterations h_comp_out_new did not change but h_comp_out did change? That makes no sense. It feels like this iteration loop isn't updating something that SHOULD change in the h_comp_out_new equation otherwise the loop should terminate.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yeah, for the specific time step when the fan power became negative, this is what happens. Maybe that could be another criteria (checking whether h_comp_out_new changes) to add to the convergence check


} else if (OperationMode == HXOpMode::EvapMode) {
// IU Heating: OperationMode 1
Expand Down
Loading