Skip to content

Commit

Permalink
Merge pull request #8556 from jcyuan2020/I8554_I8555_chillerheater_pl…
Browse files Browse the repository at this point in the history
…ant_loop_fixes

Absorption chillerheater plant loop fixes
  • Loading branch information
Myoldmopar authored Mar 20, 2021
2 parents 1f819a2 + 01507f3 commit 74f2aeb
Show file tree
Hide file tree
Showing 5 changed files with 305 additions and 58 deletions.
108 changes: 77 additions & 31 deletions src/EnergyPlus/ChillerExhaustAbsorption.cc
Original file line number Diff line number Diff line change
Expand Up @@ -131,23 +131,47 @@ namespace EnergyPlus::ChillerExhaustAbsorption {

void ExhaustAbsorberSpecs::simulate(EnergyPlusData &state, const PlantLocation &calledFromLocation, bool FirstHVACIteration, Real64 &CurLoad, bool RunFlag)
{
DataPlant::BrLoopType brIdentity(DataPlant::BrLoopType::NoMatch);

int branchTotalComp = state.dataPlnt->PlantLoop(calledFromLocation.loopNum)
.LoopSide(calledFromLocation.loopSideNum)
.Branch(calledFromLocation.branchNum)
.TotalComponents;

for (int iComp = 1; iComp <= branchTotalComp; iComp++) {
// kind of a hacky way to find the location of this, but it's what plantloopequip was doing
int compInletNodeNum = state.dataPlnt->PlantLoop(calledFromLocation.loopNum)
.LoopSide(calledFromLocation.loopSideNum)
.Branch(calledFromLocation.branchNum)
.Comp(iComp)
.NodeNumIn;

// Match inlet node name of calling branch to determine if this call is for heating or cooling
if (compInletNodeNum == this->ChillReturnNodeNum) { // Operate as chiller
brIdentity = DataPlant::BrLoopType::Chiller; // chiller
break;
} else if (compInletNodeNum == this->HeatReturnNodeNum) { // Operate as heater
brIdentity = DataPlant::BrLoopType::Heater; // heater
break;
} else if (compInletNodeNum == this->CondReturnNodeNum) { // called from condenser loop
brIdentity = DataPlant::BrLoopType::Condenser; // condenser
break;
} else {
brIdentity = DataPlant::BrLoopType::NoMatch;
}
}

// kind of a hacky way to find the location of this, but it's what plantloopequip was doing
int BranchInletNodeNum =
state.dataPlnt->PlantLoop(calledFromLocation.loopNum).LoopSide(calledFromLocation.loopSideNum).Branch(calledFromLocation.branchNum).NodeNumIn;

// Match inlet node name of calling branch to determine if this call is for heating or cooling
if (BranchInletNodeNum == this->ChillReturnNodeNum) { // Operate as chiller
if (brIdentity == DataPlant::BrLoopType::Chiller) {
this->InCoolingMode = RunFlag != 0;
this->initialize(state);
this->calcChiller(state, CurLoad);
this->updateCoolRecords(state, CurLoad, RunFlag);
} else if (BranchInletNodeNum == this->HeatReturnNodeNum) { // Operate as heater
} else if (brIdentity == DataPlant::BrLoopType::Heater) {
this->InHeatingMode = RunFlag != 0;
this->initialize(state);
this->calcHeater(state, CurLoad, RunFlag);
this->updateHeatRecords(state, CurLoad, RunFlag);
} else if (BranchInletNodeNum == this->CondReturnNodeNum) { // called from condenser loop
} else if (brIdentity == DataPlant::BrLoopType::Condenser) {
if (this->CDLoopNum > 0) {
PlantUtilities::UpdateChillerComponentCondenserSide(state,
this->CDLoopNum,
Expand All @@ -161,8 +185,8 @@ namespace EnergyPlus::ChillerExhaustAbsorption {
this->CondWaterFlowRate,
FirstHVACIteration);
}

} else { // Error, nodes do not match
} else {
// Error, nodes do not match
ShowSevereError(state, "Invalid call to Exhaust Absorber Chiller " + this->Name);
ShowContinueError(state, "Node connections in branch are not consistent with object nodes.");
ShowFatalError(state, "Preceding conditions cause termination.");
Expand All @@ -171,26 +195,48 @@ namespace EnergyPlus::ChillerExhaustAbsorption {

void ExhaustAbsorberSpecs::getDesignCapacities(EnergyPlusData &state, const PlantLocation &calledFromLocation, Real64 &MaxLoad, Real64 &MinLoad, Real64 &OptLoad)
{

// kind of a hacky way to find the location of this, but it's what plantloopequip was doing
int BranchInletNodeNum =
state.dataPlnt->PlantLoop(calledFromLocation.loopNum).LoopSide(calledFromLocation.loopSideNum).Branch(calledFromLocation.branchNum).NodeNumIn;

// Match inlet node name of calling branch to determine if this call is for heating or cooling
if (BranchInletNodeNum == this->ChillReturnNodeNum) { // Operate as chiller
MinLoad = this->NomCoolingCap * this->MinPartLoadRat;
MaxLoad = this->NomCoolingCap * this->MaxPartLoadRat;
OptLoad = this->NomCoolingCap * this->OptPartLoadRat;
} else if (BranchInletNodeNum == this->HeatReturnNodeNum) { // Operate as heater
Real64 Sim_HeatCap = this->NomCoolingCap * this->NomHeatCoolRatio; // W - nominal heating capacity
MinLoad = Sim_HeatCap * this->MinPartLoadRat;
MaxLoad = Sim_HeatCap * this->MaxPartLoadRat;
OptLoad = Sim_HeatCap * this->OptPartLoadRat;
} else if (BranchInletNodeNum == this->CondReturnNodeNum) { // called from condenser loop
MinLoad = 0.0;
MaxLoad = 0.0;
OptLoad = 0.0;
} else { // Error, nodes do not match
bool matchfound(false);

int branchTotalComp = state.dataPlnt->PlantLoop(calledFromLocation.loopNum)
.LoopSide(calledFromLocation.loopSideNum)
.Branch(calledFromLocation.branchNum)
.TotalComponents;

for (int iComp = 1; iComp <= branchTotalComp; iComp++) {
// kind of a hacky way to find the location of this, but it's what plantloopequip was doing
int compInletNodeNum = state.dataPlnt->PlantLoop(calledFromLocation.loopNum)
.LoopSide(calledFromLocation.loopSideNum)
.Branch(calledFromLocation.branchNum)
.Comp(iComp)
.NodeNumIn;

// Match inlet node name of calling branch to determine if this call is for heating or cooling
if (compInletNodeNum == this->ChillReturnNodeNum) { // Operate as chiller
MinLoad = this->NomCoolingCap * this->MinPartLoadRat;
MaxLoad = this->NomCoolingCap * this->MaxPartLoadRat;
OptLoad = this->NomCoolingCap * this->OptPartLoadRat;
matchfound = true;
break;
} else if (compInletNodeNum == this->HeatReturnNodeNum) { // Operate as heater
Real64 Sim_HeatCap = this->NomCoolingCap * this->NomHeatCoolRatio; // W - nominal heating capacity
MinLoad = Sim_HeatCap * this->MinPartLoadRat;
MaxLoad = Sim_HeatCap * this->MaxPartLoadRat;
OptLoad = Sim_HeatCap * this->OptPartLoadRat;
matchfound = true;
break;
} else if (compInletNodeNum == this->CondReturnNodeNum) { // called from condenser loop
MinLoad = 0.0;
MaxLoad = 0.0;
OptLoad = 0.0;
matchfound = true;
break;
} else {
matchfound = false;
}
}

if(!matchfound) {
// Error, nodes do not match
ShowSevereError(state, "SimExhaustAbsorber: Invalid call to Exhaust Absorbtion Chiller-Heater " + this->Name);
ShowContinueError(state, "Node connections in branch are not consistent with object nodes.");
ShowFatalError(state, "Preceding conditions cause termination.");
Expand Down Expand Up @@ -1629,7 +1675,7 @@ namespace EnergyPlus::ChillerExhaustAbsorption {
} else {
ShowSevereError(state, "CalcExhaustAbsorberChillerModel: Condenser flow = 0, for Exhaust Absorber Chiller=" + this->Name);
ShowContinueErrorTimeStamp(state, "");
ShowFatalError(state, "Program Terminates due to previous error condition.");
// ShowFatalError(state, "Program Terminates due to previous error condition.");
}
} else {
lCondSupplyTemp = lCondReturnTemp; // if air cooled condenser just set supply and return to same temperature
Expand Down
101 changes: 74 additions & 27 deletions src/EnergyPlus/ChillerGasAbsorption.cc
Original file line number Diff line number Diff line change
Expand Up @@ -130,27 +130,50 @@ namespace EnergyPlus::ChillerGasAbsorption {

void GasAbsorberSpecs::simulate(EnergyPlusData &state, const PlantLocation &calledFromLocation, bool FirstHVACIteration, Real64 &CurLoad, bool RunFlag)
{
DataPlant::BrLoopType brIdentity(DataPlant::BrLoopType::NoMatch);

int branchTotalComp = state.dataPlnt->PlantLoop(calledFromLocation.loopNum)
.LoopSide(calledFromLocation.loopSideNum)
.Branch(calledFromLocation.branchNum)
.TotalComponents;

for (int iComp = 1; iComp <= branchTotalComp; iComp++) {
// kind of a hacky way to find the location of this, but it's what plantloopequip was doing
int compInletNodeNum = state.dataPlnt->PlantLoop(calledFromLocation.loopNum)
.LoopSide(calledFromLocation.loopSideNum)
.Branch(calledFromLocation.branchNum)
.Comp(iComp)
.NodeNumIn;
// Match inlet node name of calling branch to determine if this call is for heating or cooling
if (compInletNodeNum == this->ChillReturnNodeNum) { // Operate as chiller
brIdentity = DataPlant::BrLoopType::Chiller;
break;
} else if (compInletNodeNum == this->HeatReturnNodeNum) { // Operate as heater
brIdentity = DataPlant::BrLoopType::Heater;
break;
} else if (compInletNodeNum == this->CondReturnNodeNum) { // called from condenser loop
brIdentity = DataPlant::BrLoopType::Condenser;
break;
} else {
brIdentity = DataPlant::BrLoopType::NoMatch;
}
}

// kind of a hacky way to find the location of this, but it's what plantloopequip was doing
int BranchInletNodeNum =
state.dataPlnt->PlantLoop(calledFromLocation.loopNum).LoopSide(calledFromLocation.loopSideNum).Branch(calledFromLocation.branchNum).NodeNumIn;

// Match inlet node name of calling branch to determine if this call is for heating or cooling
if (BranchInletNodeNum == this->ChillReturnNodeNum) { // Operate as chiller
if (brIdentity == DataPlant::BrLoopType::Chiller) {
// Calculate Node Values
// Calculate Equipment and Update Variables
this->InCoolingMode = RunFlag != 0;
this->initialize(state);
this->calculateChiller(state, CurLoad);
this->updateCoolRecords(state, CurLoad, RunFlag);
} else if (BranchInletNodeNum == this->HeatReturnNodeNum) { // Operate as heater
} else if (brIdentity == DataPlant::BrLoopType::Heater) {
// Calculate Node Values
// Calculate Equipment and Update Variables
this->InHeatingMode = RunFlag != 0;
this->initialize(state);
this->calculateHeater(state, CurLoad, RunFlag);
this->updateHeatRecords(state, CurLoad, RunFlag);
} else if (BranchInletNodeNum == this->CondReturnNodeNum) { // called from condenser loop
} else if (brIdentity == DataPlant::BrLoopType::Condenser) {
if (this->CDLoopNum > 0) {
PlantUtilities::UpdateChillerComponentCondenserSide(state,
this->CDLoopNum,
Expand All @@ -164,7 +187,8 @@ namespace EnergyPlus::ChillerGasAbsorption {
this->CondWaterFlowRate,
FirstHVACIteration);
}
} else { // Error, nodes do not match
} else {
// Error, nodes do not match
ShowSevereError(state, "Invalid call to Gas Absorber Chiller " + this->Name);
ShowContinueError(state, "Node connections in branch are not consistent with object nodes.");
ShowFatalError(state, "Preceding conditions cause termination.");
Expand All @@ -173,24 +197,47 @@ namespace EnergyPlus::ChillerGasAbsorption {

void GasAbsorberSpecs::getDesignCapacities(EnergyPlusData &state, const PlantLocation &calledFromLocation, Real64 &MaxLoad, Real64 &MinLoad, Real64 &OptLoad)
{
// kind of a hacky way to find the location of this, but it's what plantloopequip was doing
int BranchInletNodeNum =
state.dataPlnt->PlantLoop(calledFromLocation.loopNum).LoopSide(calledFromLocation.loopSideNum).Branch(calledFromLocation.branchNum).NodeNumIn;
bool matchfound(false);

int branchTotalComp = state.dataPlnt->PlantLoop(calledFromLocation.loopNum)
.LoopSide(calledFromLocation.loopSideNum)
.Branch(calledFromLocation.branchNum)
.TotalComponents;

for (int iComp = 1; iComp <= branchTotalComp; iComp++) {
// kind of a hacky way to find the location of this, but it's what plantloopequip was doing
int compInletNodeNum = state.dataPlnt->PlantLoop(calledFromLocation.loopNum)
.LoopSide(calledFromLocation.loopSideNum)
.Branch(calledFromLocation.branchNum)
.Comp(iComp)
.NodeNumIn;

if (compInletNodeNum == this->ChillReturnNodeNum) { // Operate as chiller
MinLoad = this->NomCoolingCap * this->MinPartLoadRat;
MaxLoad = this->NomCoolingCap * this->MaxPartLoadRat;
OptLoad = this->NomCoolingCap * this->OptPartLoadRat;
matchfound = true;
break;
} else if (compInletNodeNum == this->HeatReturnNodeNum) { // Operate as heater
Real64 Sim_HeatCap = this->NomCoolingCap * this->NomHeatCoolRatio;
MinLoad = Sim_HeatCap * this->MinPartLoadRat;
MaxLoad = Sim_HeatCap * this->MaxPartLoadRat;
OptLoad = Sim_HeatCap * this->OptPartLoadRat;
matchfound = true;
break;
} else if (compInletNodeNum == this->CondReturnNodeNum) { // called from condenser loop
MinLoad = 0.0;
MaxLoad = 0.0;
OptLoad = 0.0;
matchfound = true;
break;
} else {
matchfound = false;
}
}

if (BranchInletNodeNum == this->ChillReturnNodeNum) { // Operate as chiller
MinLoad = this->NomCoolingCap * this->MinPartLoadRat;
MaxLoad = this->NomCoolingCap * this->MaxPartLoadRat;
OptLoad = this->NomCoolingCap * this->OptPartLoadRat;
} else if (BranchInletNodeNum == this->HeatReturnNodeNum) { // Operate as heater
Real64 Sim_HeatCap = this->NomCoolingCap * this->NomHeatCoolRatio;
MinLoad = Sim_HeatCap * this->MinPartLoadRat;
MaxLoad = Sim_HeatCap * this->MaxPartLoadRat;
OptLoad = Sim_HeatCap * this->OptPartLoadRat;
} else if (BranchInletNodeNum == this->CondReturnNodeNum) { // called from condenser loop
MinLoad = 0.0;
MaxLoad = 0.0;
OptLoad = 0.0;
} else { // Error, nodes do not match
if (!matchfound) {
// Error, nodes do not match
ShowSevereError(state, "SimGasAbsorber: Invalid call to Gas Absorbtion Chiller-Heater " + this->Name);
ShowContinueError(state, "Node connections in branch are not consistent with object nodes.");
ShowFatalError(state, "Preceding conditions cause termination.");
Expand Down Expand Up @@ -1565,7 +1612,7 @@ namespace EnergyPlus::ChillerGasAbsorption {
} else {
ShowSevereError(state, "CalcGasAbsorberChillerModel: Condenser flow = 0, for Gas Absorber Chiller=" + this->Name);
ShowContinueErrorTimeStamp(state, "");
ShowFatalError(state, "Program Terminates due to previous error condition.");
// ShowFatalError(state, "Program Terminates due to previous error condition.");
}
} else {
lCondSupplyTemp = lCondReturnTemp; // if air cooled condenser just set supply and return to same temperature
Expand Down
9 changes: 9 additions & 0 deletions src/EnergyPlus/Plant/Enums.hh
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,15 @@ namespace EnergyPlus::DataPlant {
DualOp, // Constant for Cooling or Heating Operation
};

// branch loop type for absorption chillerheater models
enum class BrLoopType
{
Chiller,
Heater,
Condenser,
NoMatch
};

} // namespace EnergyPlus

#endif
Loading

0 comments on commit 74f2aeb

Please sign in to comment.