Skip to content

Fix #11181 - Wrong Sunlit fractions for Detached Shading Surfaces when Sun is Down#11237

Merged
mitchute merged 3 commits intodevelopfrom
11181_Sunlit_Fractions_shading
Oct 1, 2025
Merged

Fix #11181 - Wrong Sunlit fractions for Detached Shading Surfaces when Sun is Down#11237
mitchute merged 3 commits intodevelopfrom
11181_Sunlit_Fractions_shading

Conversation

@jmarrec
Copy link
Contributor

@jmarrec jmarrec commented Sep 29, 2025

Pull request overview

Some solar shading arrays are not cleared.

Description of the purpose of this PR

The issue with #11181 was that the arrays were NOT being cleared for the detached shading surfaces, so the previous values were retained when the Sun was down, because FigureSolarBeamAtTimestep returns early in that case

Original regression appeared in v9.6.0, and is due to #8820
Specifically the commit, the change in SolarShading.cc c10a756#diff-18fbb8a5b1334b62513de2441bdb4bb4ef1fbe5fbec24d5dd0effcd019dfc33dR4795

Before, the ObjexxFCL assignment was used to reset everything this commit changed the initialization to explicit loop variables, BUT it does it only for heat transfer surfaces linked to a zone/space, and no longer does it for detached shading surfaces.

Pull Request Author

  • Title of PR should be user-synopsis style (clearly understandable in a standalone changelog context)
  • Label the PR with at least one of: Defect, Refactoring, NewFeature, Performance, and/or DoNoPublish
  • Pull requests that impact EnergyPlus code must also include unit tests to cover enhancement or defect repair
  • Author should provide a "walkthrough" of relevant code changes using a GitHub code review comment process
  • If any diffs are expected, author must demonstrate they are justified using plots and descriptions
  • If changes fix a defect, the fix should be demonstrated in plots and descriptions
  • If any defect files are updated to a more recent version, upload new versions here or on DevSupport
  • If IDD requires transition, transition source, rules, ExpandObjects, and IDFs must be updated, and add IDDChange label
  • If structural output changes, add to output rules file and add OutputChange label
  • If adding/removing any LaTeX docs or figures, update that document's CMakeLists file dependencies

Reviewer

  • Perform a Code Review on GitHub
  • If branch is behind develop, merge develop and build locally to check for side effects of the merge
  • If defect, verify by running develop branch and reproducing defect, then running PR and reproducing fix
  • If feature, test running new feature, try creative ways to break it
  • CI status: all green or justified
  • Check that performance is not impacted (CI Linux results include performance check)
  • Run Unit Test(s) locally
  • Check any new function arguments for performance impacts
  • Verify IDF naming conventions and styles, memos and notes and defaults
  • If new idf included, locally check the err file and other outputs

@jmarrec jmarrec self-assigned this Sep 29, 2025
@jmarrec jmarrec added Defect Includes code to repair a defect in EnergyPlus NotIDDChange Code does not impact IDD (can be merged after IO freeze) labels Sep 29, 2025
s_surf->SurfaceWindow was not allocated in this test.

Previously SolarShading.cc was doing

```c++
for (auto &e : s_surf->SurfaceWindow) {
            std::fill(e.OutProjSLFracMult.begin(), e.OutProjSLFracMult.end(), 1.0);
            std::fill(e.InOutProjSLFracMult.begin(), e.InOutProjSLFracMult.end(), 1.0);
        }
```

And I changed this to an index based loop, so it fails
@jmarrec
Copy link
Contributor Author

jmarrec commented Sep 29, 2025

Running the Shoebox_v25.1.idf from DevSupport.

before fix, see #11181 (comment)

After fix:

image

@github-actions
Copy link

⚠️ Regressions detected on ubuntu-24.04 for commit 072b941

Regression Summary
  • ESO Big Diffs: 2

@github-actions
Copy link

⚠️ Regressions detected on macos-14 for commit 072b941

Regression Summary
  • ESO Big Diffs: 2

@jmarrec
Copy link
Contributor Author

jmarrec commented Sep 29, 2025

Side by side comparison for Shoebox v25.1.idf

image

@github-actions
Copy link

⚠️ Regressions detected on ubuntu-24.04 for commit 5b690e9

Regression Summary
  • ESO Big Diffs: 2

Comment on lines -4921 to -4925
for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
auto &thisSpace = state.dataHeatBal->space(spaceNum);
int firstSurf = thisSpace.OpaqOrIntMassSurfaceFirst;
int lastSurf = thisSpace.OpaqOrIntMassSurfaceLast;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was only doing it for attached building surfaces

Comment on lines +4922 to +4958
// Array1D and 1D-ish
for (int surfNum = 1; surfNum <= state.dataSurface->TotSurfaces; ++surfNum) {
s_surf->SurfOpaqAO(surfNum) = 0.0;
state.dataSolarShading->SurfSunCosTheta(surfNum) = 0.0;

for (int hour = 1; hour <= 24; ++hour) {
s_surf->SurfaceWindow(surfNum).OutProjSLFracMult[hour] = 1.0;
s_surf->SurfaceWindow(surfNum).InOutProjSLFracMult[hour] = 1.0;
}
}
} else {
for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
auto &thisSpace = state.dataHeatBal->space(spaceNum);
int const firstSurf = thisSpace.HTSurfaceFirst;
int const lastSurf = thisSpace.HTSurfaceLast;
for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
state.dataSolarShading->SurfSunCosTheta(surfNum) = 0.0;
s_surf->SurfOpaqAO(surfNum) = 0.0;
state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, surfNum) = 0.0;
state.dataHeatBal->SurfSunlitFracWithoutReveal(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, surfNum) = 0.0;
state.dataHeatBal->SurfSunlitFracHR(state.dataGlobal->HourOfDay, surfNum) = 0.0;
state.dataHeatBal->SurfCosIncAngHR(state.dataGlobal->HourOfDay, surfNum) = 0.0;
state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, surfNum) = 0.0;

// Array2D
for (int hour = 1; hour <= 24; ++hour) {
for (int surfNum = 1; surfNum <= state.dataSurface->TotSurfaces; ++surfNum) {
state.dataHeatBal->SurfSunlitFracHR(hour, surfNum) = 0.0;
state.dataHeatBal->SurfCosIncAngHR(hour, surfNum) = 0.0;
}
}

// Array3D
for (int hour = 1; hour <= 24; ++hour) {
for (int timestep = 1; timestep <= state.dataGlobal->TimeStepsInHour; ++timestep) {
for (int surfNum = 1; surfNum <= state.dataSurface->TotSurfaces; ++surfNum) {
state.dataHeatBal->SurfSunlitFrac(hour, timestep, surfNum) = 0.0;
state.dataHeatBal->SurfCosIncAng(hour, timestep, surfNum) = 0.0;
state.dataHeatBal->SurfSunlitFracWithoutReveal(hour, timestep, surfNum) = 0.0;
}
}
}

// Array4D
for (int hour = 1; hour <= 24; ++hour) {
for (int timestep = 1; timestep <= state.dataGlobal->TimeStepsInHour; ++timestep) {
for (int backSurfNum = 1; backSurfNum <= state.dataBSDFWindow->MaxBkSurf; ++backSurfNum) {
for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
state.dataHeatBal->SurfWinBackSurfaces(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, backSurfNum, surfNum) = 0;
state.dataHeatBal->SurfWinOverlapAreas(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, backSurfNum, surfNum) = 0.0;
for (int surfNum = 1; surfNum <= state.dataSurface->TotSurfaces; ++surfNum) {
state.dataHeatBal->SurfWinBackSurfaces(hour, timestep, backSurfNum, surfNum) = 0.0;
state.dataHeatBal->SurfWinOverlapAreas(hour, timestep, backSurfNum, surfNum) = 0.0;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do it for all arrays, keeping the explicit init instead of relying (like pre v9.6.0) on ObjexxFCL assign functors

Comment on lines +4965 to +4987
for (int surfNum = 1; surfNum <= state.dataSurface->TotSurfaces; ++surfNum) {
state.dataSolarShading->SurfSunCosTheta(surfNum) = 0.0;
s_surf->SurfOpaqAO(surfNum) = 0.0;

s_surf->SurfaceWindow(surfNum).OutProjSLFracMult[state.dataGlobal->HourOfDay] = 1.0;
s_surf->SurfaceWindow(surfNum).InOutProjSLFracMult[state.dataGlobal->HourOfDay] = 1.0;

// Array2D
state.dataHeatBal->SurfSunlitFracHR(state.dataGlobal->HourOfDay, surfNum) = 0.0;
state.dataHeatBal->SurfCosIncAngHR(state.dataGlobal->HourOfDay, surfNum) = 0.0;

// Array3D
state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, surfNum) = 0.0;
state.dataHeatBal->SurfSunlitFracWithoutReveal(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, surfNum) = 0.0;
state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, surfNum) = 0.0;
}

// Array4D
for (int backSurfNum = 1; backSurfNum <= state.dataBSDFWindow->MaxBkSurf; ++backSurfNum) {
for (int surfNum = 1; surfNum <= state.dataSurface->TotSurfaces; ++surfNum) {
state.dataHeatBal->SurfWinBackSurfaces(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, backSurfNum, surfNum) = 0;
state.dataHeatBal->SurfWinOverlapAreas(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, backSurfNum, surfNum) = 0.0;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same idea when DetailedSolarTimestepIntegration is on

Comment on lines +176 to +185
TEST_F(EnergyPlusFixture, SolarShadingTest_CalcPerSolarBeamTestResetsFrac)
{
// Test for #11181 - Test inits for integrated and non-integrated shading calcs, including for DETACHED shading surfaces
// We are going to mimic the case where we have two surfaces:
// 1) A surface part a zone
// 2) A detached or building shading surface, not part of any zone
//
// We also assume we are in a case where we're starting a new environment, and the SurfSunlitFrac is already filled with numbers
// The issue with #11181 was that the arrays were NOT being cleared for the detached shading surfaces, so the previous values were retained when
// the Sun was down, because FigureSolarBeamAtTimestep returns early in that case
Copy link
Contributor Author

Choose a reason for hiding this comment

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

New explicit test.

Comment on lines +268 to +309
// Prefill with some values
state->dataHeatBal->SurfSunlitFrac = 0.5;
state->dataHeatBal->SurfSunlitFracHR = 0.5;
// Test non-integrated option first, CalcPerSolarBeam should set OutProjSLFracMult and InOutProjSLFracMult to 1.0 for all hours
for (int SurfNum = 1; SurfNum <= state->dataSurface->TotSurfaces; ++SurfNum) {
for (int Hour = 1; Hour <= Constant::iHoursInDay; ++Hour) {
state->dataSurface->SurfaceWindow(SurfNum).OutProjSLFracMult[Hour] = 999.0;
state->dataSurface->SurfaceWindow(SurfNum).InOutProjSLFracMult[Hour] = 888.0;
}
}

SolarShading::DetermineShadowingCombinations(*state);

state->dataSysVars->DetailedSolarTimestepIntegration = false;
CalcPerSolarBeam(*state, AvgEqOfTime, AvgSinSolarDeclin, AvgCosSolarDeclin);

int constexpr sunRiseHour = 8;
int constexpr sunRiseTimeStep = 1;
int constexpr sunSetHour = 17;
int constexpr sunSetTimeStep = 1;

auto isSunUp = [=](int hour, int timestep) {
if ((hour < sunRiseHour || (hour == sunRiseHour && timestep < sunRiseTimeStep))) {
return false;
}
if (hour > sunSetHour || (hour == sunSetHour && timestep > sunSetTimeStep)) {
return false;
}

return true;
};

// Ensure we have sun is Up working properly
for (int hour = 1; hour <= Constant::iHoursInDay; ++hour) {
for (int timestep = 1; timestep <= state->dataGlobal->TimeStepsInHour; ++timestep) {
if (isSunUp(hour, timestep)) {
EXPECT_GT(state->dataBSDFWindow->SUNCOSTS(timestep, hour).z, 0.0);
} else {
EXPECT_LT(state->dataBSDFWindow->SUNCOSTS(timestep, hour).z, 0.0);
}
}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We prefill the arrays with some values (0.5 all around).

Then we call CalcPerSolarBeam.

I create a lambda that checks if the sun is up, and ensure it works like I expect it to. It does.

Comment on lines +311 to +333
// Check that the fraction Sunlit is properly set to 1.0 when the sun is Up and ZERO otherwis: it does NOT remember previously set values
for (int surfNum = 1; surfNum <= state->dataSurface->TotSurfaces; ++surfNum) {
SCOPED_TRACE(fmt::format("Surface {}='{}'", surfNum, state->dataSurface->Surface(surfNum).Name));
for (int hour = 1; hour <= Constant::iHoursInDay; ++hour) {
SCOPED_TRACE(fmt::format("Hour={}", hour));
if (isSunUp(hour, state->dataGlobal->TimeStepsInHour)) {
EXPECT_DOUBLE_EQ(1.0, state->dataHeatBal->SurfSunlitFracHR(hour, surfNum)) << "Failed when Sun is Up";
} else {
EXPECT_DOUBLE_EQ(0.0, state->dataHeatBal->SurfSunlitFracHR(hour, surfNum)) << "Failed when Sun is Down";
}
for (int timestep = 1; timestep <= state->dataGlobal->TimeStepsInHour; ++timestep) {
SCOPED_TRACE(fmt::format("Timestep={}", timestep));
if (isSunUp(hour, timestep)) {
EXPECT_DOUBLE_EQ(1.0, state->dataHeatBal->SurfSunlitFrac(hour, timestep, surfNum)) << "Failed when Sun is Up";
} else {
EXPECT_DOUBLE_EQ(0.0, state->dataHeatBal->SurfSunlitFrac(hour, timestep, surfNum)) << "Failed when Sun is Down";
}
}

EXPECT_EQ(1.0, state->dataSurface->SurfaceWindow(surfNum).OutProjSLFracMult[hour]);
EXPECT_EQ(1.0, state->dataSurface->SurfaceWindow(surfNum).InOutProjSLFracMult[hour]);
}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

It will fail a bunch on develop, when the SunIsDown, and only for the DETACHED shading surface.

[ RUN      ] EnergyPlusFixture.SolarShadingTest_CalcPerSolarBeamTestResetsFrac
/home/julien/Software/Others/EnergyPlus2/tst/EnergyPlus/unit/SolarShading.unit.cc:319: Failure
Expected equality of these values:
  0.0
    Which is: 0
  state->dataHeatBal->SurfSunlitFracHR(hour, surfNum)
    Which is: 0.5
Failed when Sun is Down
Google Test trace:
/home/julien/Software/Others/EnergyPlus2/tst/EnergyPlus/unit/SolarShading.unit.cc:315: Hour=1
/home/julien/Software/Others/EnergyPlus2/tst/EnergyPlus/unit/SolarShading.unit.cc:313: Surface 2='SHADING'
/home/julien/Software/Others/EnergyPlus2/tst/EnergyPlus/unit/SolarShading.unit.cc:326: Failure
Expected equality of these values:
  0.0
    Which is: 0
  state->dataHeatBal->SurfSunlitFrac(hour, timestep, surfNum)
    Which is: 0.5
Failed when Sun is Down
Google Test trace:
/home/julien/Software/Others/EnergyPlus2/tst/EnergyPlus/unit/SolarShading.unit.cc:322: Timestep=1
/home/julien/Software/Others/EnergyPlus2/tst/EnergyPlus/unit/SolarShading.unit.cc:315: Hour=1
/home/julien/Software/Others/EnergyPlus2/tst/EnergyPlus/unit/SolarShading.unit.cc:313: Surface 2='SHADING'
/home/julien/Software/Others/EnergyPlus2/tst/EnergyPlus/unit/SolarShading.unit.cc:326: Failure
Expected equality of these values:
  0.0
    Which is: 0
  state->dataHeatBal->SurfSunlitFrac(hour, timestep, surfNum)
    Which is: 0.5
Failed when Sun is Down
Google Test trace:
/home/julien/Software/Others/EnergyPlus2/tst/EnergyPlus/unit/SolarShading.unit.cc:322: Timestep=2
/home/julien/Software/Others/EnergyPlus2/tst/EnergyPlus/unit/SolarShading.unit.cc:315: Hour=1
/home/julien/Software/Others/EnergyPlus2/tst/EnergyPlus/unit/SolarShading.unit.cc:313: Surface 2='SHADING'
/home/julien/Software/Others/EnergyPlus2/tst/EnergyPlus/unit/SolarShading.unit.cc:326: Failure
Expected equality of these values:
  0.0
    Which is: 0
  state->dataHeatBal->SurfSunlitFrac(hour, timestep, surfNum)
    Which is: 0.5
Failed when Sun is Down
Google Test trace:
/home/julien/Software/Others/EnergyPlus2/tst/EnergyPlus/unit/SolarShading.unit.cc:322: Timestep=3
/home/julien/Software/Others/EnergyPlus2/tst/EnergyPlus/unit/SolarShading.unit.cc:315: Hour=1
/home/julien/Software/Others/EnergyPlus2/tst/EnergyPlus/unit/SolarShading.unit.cc:313: Surface 2='SHADING'
/home/julien/Software/Others/EnergyPlus2/tst/EnergyPlus/unit/SolarShading.unit.cc:326: Failure
Expected equality of these values:
  0.0
    Which is: 0
  state->dataHeatBal->SurfSunlitFrac(hour, timestep, surfNum)
    Which is: 0.5
Failed when Sun is Down
Google Test trace:
/home/julien/Software/Others/EnergyPlus2/tst/EnergyPlus/unit/SolarShading.unit.cc:322: Timestep=4
/home/julien/Software/Others/EnergyPlus2/tst/EnergyPlus/unit/SolarShading.unit.cc:315: Hour=1
/home/julien/Software/Others/EnergyPlus2/tst/EnergyPlus/unit/SolarShading.unit.cc:313: Surface 2='SHADING'
/home/julien/Software/Others/EnergyPlus2/tst/EnergyPlus/unit/SolarShading.unit.cc:319: Failure

[...]

Comment on lines +335 to +373
// Test integrated option, CalcPerSolarBeam should set OutProjSLFracMult and InOutProjSLFracMult to 1.0 only for the specified hour
// Re-initialize to new values
for (int surfNum = 1; surfNum <= state->dataSurface->TotSurfaces; ++surfNum) {
for (int hour = 1; hour <= Constant::iHoursInDay; ++hour) {
state->dataSurface->SurfaceWindow(surfNum).OutProjSLFracMult[hour] = 555.0;
state->dataSurface->SurfaceWindow(surfNum).InOutProjSLFracMult[hour] = 444.0;
}
}
state->dataHeatBal->SurfSunlitFrac = 0.5;
state->dataHeatBal->SurfSunlitFracHR = 0.5;

state->dataSysVars->DetailedSolarTimestepIntegration = true;
state->dataGlobal->HourOfDay = 23;
state->dataGlobal->TimeStep = 3;
CalcPerSolarBeam(*state, AvgEqOfTime, AvgSinSolarDeclin, AvgCosSolarDeclin);

for (int surfNum = 1; surfNum <= state->dataSurface->TotSurfaces; ++surfNum) {
SCOPED_TRACE(fmt::format("Surface {}='{}'", surfNum, state->dataSurface->Surface(surfNum).Name));
for (int hour = 1; hour <= Constant::iHoursInDay; ++hour) {
SCOPED_TRACE(fmt::format("Hour={}", hour));
if (hour == state->dataGlobal->HourOfDay) {
EXPECT_EQ(1.0, state->dataSurface->SurfaceWindow(surfNum).OutProjSLFracMult[hour]);
EXPECT_EQ(1.0, state->dataSurface->SurfaceWindow(surfNum).InOutProjSLFracMult[hour]);
EXPECT_DOUBLE_EQ(0.0, state->dataHeatBal->SurfSunlitFracHR(hour, surfNum));
} else {
EXPECT_EQ(555.0, state->dataSurface->SurfaceWindow(surfNum).OutProjSLFracMult[hour]);
EXPECT_EQ(444.0, state->dataSurface->SurfaceWindow(surfNum).InOutProjSLFracMult[hour]);
EXPECT_DOUBLE_EQ(0.5, state->dataHeatBal->SurfSunlitFracHR(hour, surfNum));
}
for (int timestep = 1; timestep <= state->dataGlobal->TimeStepsInHour; ++timestep) {
SCOPED_TRACE(fmt::format("Timestep={}", timestep));
if (hour == state->dataGlobal->HourOfDay && timestep == state->dataGlobal->TimeStep) {
EXPECT_DOUBLE_EQ(0.0, state->dataHeatBal->SurfSunlitFrac(hour, timestep, surfNum));
} else {
EXPECT_DOUBLE_EQ(0.5, state->dataHeatBal->SurfSunlitFrac(hour, timestep, surfNum));
}
}
}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Another pass with DetailedTimeStepIntegration. It fails as well for the shading surface on develop

/home/julien/Software/Others/EnergyPlus2/tst/EnergyPlus/unit/SolarShading.unit.cc:358: Failure
Expected equality of these values:
  0.0
    Which is: 0
  state->dataHeatBal->SurfSunlitFracHR(hour, surfNum)
    Which is: 0.5
Google Test trace:
/home/julien/Software/Others/EnergyPlus2/tst/EnergyPlus/unit/SolarShading.unit.cc:354: Hour=23
/home/julien/Software/Others/EnergyPlus2/tst/EnergyPlus/unit/SolarShading.unit.cc:352: Surface 2='SHADING'
/home/julien/Software/Others/EnergyPlus2/tst/EnergyPlus/unit/SolarShading.unit.cc:367: Failure
Expected equality of these values:
  0.0
    Which is: 0
  state->dataHeatBal->SurfSunlitFrac(hour, timestep, surfNum)
    Which is: 0.5
Google Test trace:
/home/julien/Software/Others/EnergyPlus2/tst/EnergyPlus/unit/SolarShading.unit.cc:365: Timestep=3
/home/julien/Software/Others/EnergyPlus2/tst/EnergyPlus/unit/SolarShading.unit.cc:354: Hour=23
/home/julien/Software/Others/EnergyPlus2/tst/EnergyPlus/unit/SolarShading.unit.cc:352: Surface 2='SHADING'
[  FAILED  ] EnergyPlusFixture.SolarShadingTest_CalcPerSolarBeamTestResetsFrac (1065 ms)

@github-actions
Copy link

⚠️ Regressions detected on macos-14 for commit 5b690e9

Regression Summary
  • ESO Big Diffs: 2

@jmarrec
Copy link
Contributor Author

jmarrec commented Sep 29, 2025

ExerciseOutput1 / ExerciseOutput1A have expected changes

image

Mir-Overhang is now properly working like the roof as we expect.

Left is develop, right is this branch. I am plotting a "regular" surface then the changed ones

image

@jmarrec jmarrec requested a review from mitchute September 29, 2025 15:24
Copy link
Collaborator

@mitchute mitchute left a comment

Choose a reason for hiding this comment

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

This all looks reasonable.

@mitchute mitchute merged commit 900b047 into develop Oct 1, 2025
11 checks passed
@mitchute mitchute deleted the 11181_Sunlit_Fractions_shading branch October 1, 2025 16:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Defect Includes code to repair a defect in EnergyPlus NotIDDChange Code does not impact IDD (can be merged after IO freeze)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Sunlit fractions for PV surfaces

4 participants