Skip to content

Commit

Permalink
Fix #4060 - Handling cloning dual duct AirLoopHVACs
Browse files Browse the repository at this point in the history
  • Loading branch information
jmarrec committed Mar 23, 2021
1 parent 84df077 commit e904d2b
Showing 1 changed file with 85 additions and 24 deletions.
109 changes: 85 additions & 24 deletions src/model/AirLoopHVAC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -721,40 +721,101 @@ namespace model {

airLoopClone.getImpl<detail::AirLoopHVAC_Impl>()->createTopology();

auto supplyComps = supplyComponents();
auto outletNodeClone = airLoopClone.supplyOutletNode();
std::vector<Node> supplyNodes;
struct HVACPath
{
HVACPath(const HVACComponent& t_originalStart, const HVACComponent& t_originalEnd, const HVACComponent& t_clonedStartOrEndOfPath,
const Node& t_clonedAddNode, bool t_reverse)
: originalStart(t_originalStart),
originalEnd(t_originalEnd),
clonedStartOrEndOfPath(t_clonedStartOrEndOfPath),
clonedAddNode(t_clonedAddNode),
reverse(t_reverse){};

HVACComponent originalStart;
HVACComponent originalEnd;
HVACComponent clonedStartOrEndOfPath; // If reverse is false, it's the start, if reverse is true, it's the end
Node clonedAddNode;
bool reverse;
};

for (const auto& comp : supplyComps) {
if (comp.iddObjectType() == Node::iddObjectType()) {
supplyNodes.push_back(comp.cast<Node>());
} else {
auto compClone = comp.clone(model).cast<HVACComponent>();
compClone.addToNode(outletNodeClone);
// If the original component was also on a PlantLoop
if (boost::optional<HVACComponent> hvacComp = comp.optionalCast<HVACComponent>()) {
if (boost::optional<PlantLoop> pl = hvacComp->plantLoop()) {
// Connect the clone to the plantLoop too
pl->addDemandBranchForComponent(compClone);
std::vector<HVACPath> pathsToHandle;

if (isDualDuct()) {
// Add the Splitter to make it a dual duct
auto supplyInletNodeClone = airLoopClone.supplyInletNode();
ConnectorSplitter supplySplitterClone(model);
supplySplitterClone.addToNode(supplyInletNodeClone);
airLoopClone.getImpl<detail::AirLoopHVAC_Impl>()->setSupplySplitter(supplySplitterClone);

auto supplyOutletNodeClones = airLoopClone.supplyOutletNodes();

auto supplySplitter = this->supplySplitter().get();
auto supplyInletNode = this->supplyInletNode();
auto supplyOutletNodes = this->supplyOutletNodes();

pathsToHandle.emplace_back(supplyInletNode, supplySplitter, supplySplitterClone, supplyInletNodeClone, true);
pathsToHandle.emplace_back(supplySplitter, supplyOutletNodes[0], supplySplitterClone, supplyOutletNodeClones[0], false);
pathsToHandle.emplace_back(supplySplitter, supplyOutletNodes[1], supplySplitterClone, supplyOutletNodeClones[1], false);

} else {

pathsToHandle.emplace_back(this->supplyInletNode(), this->supplyOutletNode(), airLoopClone.supplyInletNode(), airLoopClone.supplyOutletNode(),
false);
}

for (const auto& path : pathsToHandle) {

auto supplyComps = supplyComponents(path.originalStart, path.originalEnd);
if (path.reverse) {
std::reverse(supplyComps.begin(), supplyComps.end());
}
auto clonedAddNode = path.clonedAddNode;
std::vector<Node> supplyNodes;

for (const auto& comp : supplyComps) {
if (comp.iddObjectType() == Node::iddObjectType()) {
supplyNodes.push_back(comp.cast<Node>());
// Don't want to clone the splitter...
} else if (comp.iddObjectType() != ConnectorSplitter::iddObjectType()) {
std::cerr << "Cloning " << comp.briefDescription() << " and adding to node " << clonedAddNode.nameString() << '\n';
auto compClone = comp.clone(model).cast<HVACComponent>();
compClone.addToNode(clonedAddNode);
// If the original component was also on a PlantLoop
if (boost::optional<HVACComponent> hvacComp = comp.optionalCast<HVACComponent>()) {
if (boost::optional<PlantLoop> pl = hvacComp->plantLoop()) {
// Connect the clone to the plantLoop too
pl->addDemandBranchForComponent(compClone);
}
}
}
}
}

auto supplyNodeClones = subsetCastVector<Node>(airLoopClone.supplyComponents());
std::vector<ModelObject> supplyCompClones;

OS_ASSERT(supplyNodes.size() == supplyNodeClones.size());
for (size_t i = 0; i < supplyNodes.size(); ++i) {
const auto node = supplyNodes[i];
auto cloneNode = supplyNodeClones[i];
if (path.reverse) {
supplyCompClones = airLoopClone.supplyComponents(path.clonedAddNode, path.clonedStartOrEndOfPath);
std::reverse(supplyCompClones.begin(), supplyCompClones.end());
} else {
supplyCompClones = airLoopClone.supplyComponents(path.clonedStartOrEndOfPath, path.clonedAddNode);
}

auto supplyNodeClones = subsetCastVector<Node>(supplyCompClones);

OS_ASSERT(supplyNodes.size() == supplyNodeClones.size());
for (size_t i = 0; i < supplyNodes.size(); ++i) {
const auto node = supplyNodes[i];
auto cloneNode = supplyNodeClones[i];

auto spms = node.setpointManagers();
for (const auto& spm : spms) {
auto spmclone = spm.clone(model).cast<SetpointManager>();
spmclone.addToNode(cloneNode);
auto spms = node.setpointManagers();
for (const auto& spm : spms) {
auto spmclone = spm.clone(model).cast<SetpointManager>();
spmclone.addToNode(cloneNode);
}
}
}

// Demand Side: same regardless of whether it's a Dual Duct or not

auto terms = terminals();
std::vector<IddObjectType> termtypes;

Expand Down

0 comments on commit e904d2b

Please sign in to comment.