Skip to content

Commit

Permalink
Implementation of diffuse now contains correct radiances. Output beam…
Browse files Browse the repository at this point in the history
… view factors are not matching.
  • Loading branch information
vidanovic committed Nov 5, 2024
1 parent 0bf318b commit fa5f628
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 350 deletions.
114 changes: 63 additions & 51 deletions src/SingleLayerOptics/src/VenetianSegments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,35 +81,8 @@ namespace SingleLayerOptics

if(!m_SlatIrradiances.count(t_IncomingDirection))
{
auto BVF = beamVector(Side::Front,
m_SlatSegmentsMesh.numberOfSegments,
m_Cell->beamViewFactors(Side::Front, t_IncomingDirection),
m_Cell->T_dir_dir(Side::Front, t_IncomingDirection));

// Beam vector is calculated for uniform diffuse case and needs to be scaled for the
// directional diffuse case The way beamVector is calculated in WINDOW could be a bug,
// since they both need to be scaled by the same factor This is a workaround for the bug
// so that the engine is consistent with WINDOW output
std::vector<double> irradiances_beam(BVF.size(), 0);
for(size_t i = 0u; i < BVF.size(); ++i)
{
irradiances_beam[i] =
BVF[i].percentViewed * BVF[i].dotProduct
/ std::cos(FenestrationCommon::radians(t_IncomingDirection.profileAngle()));
}

const auto frontIndexes{m_SlatSegmentsMesh.surfaceIndexes.frontSideMeshIndex};
const auto backIndexes{m_SlatSegmentsMesh.surfaceIndexes.backSideMeshIndex};

// Calculate incoming irradiances for the directional diffuse case
for(size_t i = 1u; i < m_SlatSegmentsMesh.numberOfSegments;
++i) // Skipping interior and exterior segments
{
auto frontIndex = frontIndexes[i - 1u];
auto backIndex = backIndexes[i];
BVF[frontIndex].viewFactor = irradiances_beam[frontIndex];
BVF[backIndex].viewFactor = irradiances_beam[backIndex];
}
auto BVF =
beamVectorForUniform(m_SlatSegmentsMesh, *m_Cell, t_IncomingDirection, Side::Front);

const auto irradiance{slatIrradiances(slatsRadiancesMatrix, BVF, m_SlatSegmentsMesh)};

Expand All @@ -126,36 +99,39 @@ namespace SingleLayerOptics

const auto & radiance = m_SlatRadiances.at(t_IncomingDirection);

auto testVF = m_Cell->beamViewFactors(Side::Front, t_OutgoingDirection);

std::vector<BeamSegmentView> BVFout =
beamVector(Side::Back,
m_SlatSegmentsMesh.numberOfSegments,
m_Cell->beamViewFactors(Side::Back, t_OutgoingDirection),
m_Cell->T_dir_dir(Side::Back, t_OutgoingDirection));
m_Cell->beamViewFactors(Side::Front, t_OutgoingDirection),
m_Cell->T_dir_dir(Side::Front, t_OutgoingDirection));

double aResult = 0;

// Counting starts from one because this should exclude beam to beam energy.
for(size_t i = 1; i < radiance.size(); ++i)
{
aResult += radiance[i]
* BVFout[i].percentViewed
* std::abs(BVFout[i].dotProduct) * m_Cell->segmentLength(i);
aResult += radiance[i] * BVFout[i].percentViewed * std::abs(BVFout[i].dotProduct)
* m_Cell->segmentLength(i);
}

return aResult
/ (insideSegLength
* std::cos(FenestrationCommon::radians(t_OutgoingDirection.profileAngle())));
return std::abs(
aResult
/ (insideSegLength
* std::cos(FenestrationCommon::radians(t_OutgoingDirection.profileAngle()))));
}

double CVenetianCellEnergy::R_dir_dir(const CBeamDirection & t_IncomingDirection,
const CBeamDirection & t_OutgoingDirection)
{
const auto insideSegLength = m_Cell->segmentLength(m_SlatSegmentsMesh.numberOfSegments);
assert(insideSegLength != 0);

if(!m_SlatIrradiances.count(t_IncomingDirection))
{
const auto BVF = beamVector(Side::Front,
m_SlatSegmentsMesh.numberOfSegments,
m_Cell->beamViewFactors(Side::Front, t_IncomingDirection),
m_Cell->T_dir_dir(Side::Front, t_IncomingDirection));
auto BVF =
beamVectorForUniform(m_SlatSegmentsMesh, *m_Cell, t_IncomingDirection, Side::Front);

const auto irradiance{slatIrradiances(slatsRadiancesMatrix, BVF, m_SlatSegmentsMesh)};

Expand All @@ -170,28 +146,27 @@ namespace SingleLayerOptics
m_SlatRadiances[t_IncomingDirection] = radiance;
}

const auto & radiance = m_SlatRadiances[t_IncomingDirection];
const auto & radiance = m_SlatRadiances.at(t_IncomingDirection);

std::vector<BeamSegmentView> BVF =
std::vector<BeamSegmentView> BVFout =
beamVector(Side::Front,
m_SlatSegmentsMesh.numberOfSegments,
m_Cell->beamViewFactors(Side::Front, t_OutgoingDirection),
m_Cell->T_dir_dir(Side::Front, t_OutgoingDirection));

double aResult = 0;

// Counting starts from one because this should exclude beam to beam energy.
for(size_t i = 1; i < radiance.size(); ++i)
{
aResult +=
radiance[i] * BVF[i].percentViewed * BVF[i].viewFactor / m_Cell->segmentLength(i);
aResult += radiance[i] * BVFout[i].percentViewed * std::abs(BVFout[i].dotProduct)
* m_Cell->segmentLength(i);
}

// Area weighting. Needs to be multiplied with number of segments
double insideSegLength = m_Cell->segmentLength(m_SlatSegmentsMesh.numberOfSegments);

assert(insideSegLength != 0);

return insideSegLength * aResult;
return std::abs(
aResult
/ (insideSegLength
* std::cos(FenestrationCommon::radians(t_OutgoingDirection.profileAngle()))));
}

double CVenetianCellEnergy::T_dif_dif()
Expand Down Expand Up @@ -344,6 +319,43 @@ namespace SingleLayerOptics
return B;
}

std::vector<BeamSegmentView> beamVectorForUniform(const SlatSegmentsMesh & slatSegmentsMesh,
CVenetianCellDescription & cell,
const CBeamDirection & direction,
FenestrationCommon::Side t_Side)
{
auto BVF = beamVector(t_Side,
slatSegmentsMesh.numberOfSegments,
cell.beamViewFactors(t_Side, direction),
cell.T_dir_dir(t_Side, direction));

// Beam vector is calculated for uniform diffuse case and needs to be scaled for the
// directional diffuse case The way beamVector is calculated in WINDOW could be a bug,
// since they both need to be scaled by the same factor This is a workaround for the bug
// so that the engine is consistent with WINDOW output
std::vector<double> irradiances_beam(BVF.size(), 0);
for(size_t i = 0u; i < BVF.size(); ++i)
{
irradiances_beam[i] = std::abs(BVF[i].percentViewed * BVF[i].dotProduct
/ std::cos(FenestrationCommon::radians(direction.profileAngle())));
}

const auto frontIndexes{slatSegmentsMesh.surfaceIndexes.frontSideMeshIndex};
const auto backIndexes{slatSegmentsMesh.surfaceIndexes.backSideMeshIndex};

// Calculate incoming irradiances for the directional diffuse case
for(size_t i = 1u; i < slatSegmentsMesh.numberOfSegments;
++i) // Skipping interior and exterior segments
{
auto frontIndex = frontIndexes[i - 1u];
auto backIndex = backIndexes[i];
BVF[frontIndex].viewFactor = irradiances_beam[frontIndex];
BVF[backIndex].viewFactor = irradiances_beam[backIndex];
}

return BVF;
}

std::vector<double> slatRadiances(const std::vector<SegmentIrradiance> & slatIrradiances,
const SlatSegmentsMesh & slats,
const LayerProperties & properties)
Expand Down
9 changes: 8 additions & 1 deletion src/SingleLayerOptics/src/VenetianSegments.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,20 @@ namespace SingleLayerOptics
const std::vector<Viewer::BeamViewFactor> & t_BeamViewFactors,
double T_dir_dir);

//! Create beam view factors for given incoming direction and side.
std::vector<BeamSegmentView> beamVectorForUniform(const SlatSegmentsMesh & slatSegmentsMesh,
CVenetianCellDescription & cell,
const CBeamDirection & direction,
FenestrationCommon::Side t_Side);

// Irradiances for given incoming direction
std::vector<SegmentIrradiance>
slatIrradiances(const FenestrationCommon::SquareMatrix & radianceMatrix,
const std::vector<BeamSegmentView> & beamViewFactors,
const SlatSegmentsMesh & mesh);

std::vector<SegmentIrradiance> slatIrradiances(const std::vector<BeamSegmentView> & beamViewFactors);
std::vector<SegmentIrradiance>
slatIrradiances(const std::vector<BeamSegmentView> & beamViewFactors);

// Radiances for given incoming direction
std::vector<double> slatRadiances(const std::vector<SegmentIrradiance> & slatIrradiances,
Expand Down
Loading

0 comments on commit fa5f628

Please sign in to comment.