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

Multiple shading controls referenced by a single subsurface #4066

Merged
merged 52 commits into from
Sep 18, 2020

Conversation

joseph-robertson
Copy link
Collaborator

@joseph-robertson joseph-robertson commented Sep 4, 2020

Pull request overview

SubSurface

  • boost::optional<ShadingControl> shadingControl() const (OS_DEPRECATED; only returns if there is 1 shading control)
  • std::vector<ShadingControl> shadingControls() const (NEW)
  • unsigned int numberofShadingControls() const (NEW)
  • bool setShadingControl(const ShadingControl& shadingControl) (OS_DEPRECATED; will remove any existing shading controls and then add the one shading control)
  • void resetShadingControl() (OS_DEPRECATED; will remove any existing shading controls)
  • bool addShadingControl(const ShadingControl& shadingControl) (NEW)
  • bool addShadingControls(const std::vector<ShadingControl> &shadingControls) (NEW)
  • void removeShadingControl(const ShadingControl& shadingControl) (NEW)
  • void removeAllShadingControls() (NEW)

ShadingControl

  • unsigned int numberofSubSurfaces() const (NEW)
  • bool addSubSurface(const SubSurface& subSurface) (NEW)
  • bool addSubSurfaces(const std::vector<SubSurface> &subSurfaces) (NEW)
  • void removeSubSurface(const SubSurface& subSurface) (NEW)
  • void removeAllSubSurfaces() (NEW)
  • bool glareControlIsActivate() const (NEW)
  • std::string typeofSlatAngleControlforBlinds() const (NEW)
  • bool isTypeofSlatAngleControlforBlindsDefault() const (NEW)
  • boost::optional<Schedule> slatAngleSchedule() const (NEW)
  • std::string multipleSurfaceControlType() const (NEW)
  • bool setGlareControlIsActive(bool glareControlIsActive) (NEW)
  • void resetGlareControlIsActive() (NEW)
  • bool setTypeofSlatAngleControlforBlinds(const std::string& typeofSlatAngleControlforBlinds) (NEW)
  • void resetTypeofSlatAngleControlforBlinds() (NEW)
  • bool setSlatAngleSchedule(const Schedule& slatAngleSchedule) (NEW)
  • void resetSlatAngleSchedule() (NEW)
  • bool setMultipleSurfaceControlType(const std::string& multipleSurfaceControlType) (NEW)

Please read OpenStudio Pull Requests to better understand the OpenStudio Pull Request protocol.

Pull Request Author

Add to this list or remove from it as applicable. This is a simple templated set of guidelines.

  • Model API Changes / Additions
  • Any new or modified fields have been implemented in the EnergyPlus ForwardTranslator (and ReverseTranslator as appropriate)
  • Model API methods are tested (in src/model/test)
  • EnergyPlus ForwardTranslator Tests (in src/energyplus/Test)
  • If a new object or method, added a test in NREL/OpenStudio-resources: Add Link
  • If needed, added VersionTranslation rules for the objects (src/osversion/VersionTranslator.cpp)
  • Checked behavior in OpenStudioApplication, adjusted policies as needed (src/openstudio_lib/library/OpenStudioPolicy.xml)
  • Verified that C# bindings built fine on Windows, partial classes used as needed, etc.
  • All new and existing tests passes
  • If methods have been deprecated, update rest of code to use the new methods

Labels:

  • If change to an IDD file, add the label IDDChange
  • If breaking existing API, add the label APIChange
  • If deemed ready, add label Pull Request - Ready for CI so that CI builds your PR

Review Checklist

This will not be exhaustively relevant to every PR.

  • Perform a Code Review on GitHub
  • Code Style, strip trailing whitespace, etc.
  • All related changes have been implemented: model changes, model tests, FT changes, FT tests, VersionTranslation, OS App
  • Labeling is ok
  • 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

@jmarrec
Copy link
Collaborator

jmarrec commented Sep 4, 2020

@joseph-robertson I'll take a deeper look on monday. Mostly I think I need to look up how the E+ objects interact exactly... but I have a couple of naive comments that perhaps you can clear out today:

  1. seems like you are providing add/remove API from both SubSurface and ShadingControl, which looks unusual. Having getters as convenience on both objects isn't unusual, but setters on both is. Typically the the one to many relationship would be that the one who has the referencing field would have the setter. As in shadingControl.setSurbSurface. And you would have SubSurface::shadingControls() getter or something.
  2. You'll need a serious VersioNTranslation for this change probably.
  3. I would reckon you may have to break API in this... I haven't looked in detail but it's a possibility that breaking API could provide a cleaner API.

@joseph-robertson
Copy link
Collaborator Author

joseph-robertson commented Sep 4, 2020

I think we're setting up a many-to-many relationship. You can have:

  • a sub surface with multiple shading controls
  • a shading control that is shared across multiple sub surfaces

The second bullet was already supported. I'm thinking we wouldn't have to break API to support the first bullet. subSurface.setShadingControl(shadingControl) would just call shadingControl.addSubSurface(subSurface). Version translation would just be: take the shading control object referenced on the sub surface object, and do shadingControl.addSubSurface(subSurface).

Copy link
Collaborator

@jmarrec jmarrec left a comment

Choose a reason for hiding this comment

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

@joseph-robertson I missed the many-to-many relationship aspect, this makes sense now, thanks for the clarification!

A couple more comments for discussion. The relationship between these two objects in E+ is quite awkward, and I'm still unsure how we would deal with the "Shading Control Sequence Number" in particular.

src/model/ShadingControl.hpp Outdated Show resolved Hide resolved
src/model/ShadingControl.hpp Show resolved Hide resolved
src/model/ShadingControl.hpp Outdated Show resolved Hide resolved
src/model/SubSurface_Impl.hpp Outdated Show resolved Hide resolved
@@ -152,6 +152,12 @@ namespace detail {

boost::optional<ShadingControl> shadingControl() const;

std::vector<ShadingControl> shadingControls();

ShadingControl getShadingControl(unsigned shadingControlIndex);
Copy link
Collaborator

Choose a reason for hiding this comment

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

That may be a bit weird. The order here is kinda undefined isn't it? Unlike ShadingControl which has an ordered list via its extensible groups, here it will depend on the order of the objects in the model (the shadingControls() is fine though, as this doesn't make any promises in terms of order)

src/model/SubSurface_Impl.hpp Outdated Show resolved Hide resolved
@@ -186,6 +192,14 @@ namespace detail {

void resetShadingControl();

bool setShadingControls(const std::vector<ShadingControl> &shadingControls);

bool insertShadingControl(unsigned shadingControlIndex, const ShadingControl &shadingControl);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same comment about order as above. I am not sure it's appropriate or even wanted?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Is the idea to tie into the field "Shading Control Sequence Number" on the ShadingControl object? That field is a bit weird...

boost::optional<int> sequenceNumber = modelObject.additionalProperties().getFeatureAsInteger("Shading Control Sequence Number");
if (sequenceNumber) {
idfObject.setInt(WindowShadingControlFields::ShadingControlSequenceNumber, *sequenceNumber);
} else {
LOG(Error, modelObject.briefDescription() << " has unknown Shading Control Sequence Number");
}

src/model/ShadingControl.cpp Outdated Show resolved Hide resolved
src/model/ShadingControl.cpp Show resolved Hide resolved
src/model/ShadingControl.cpp Outdated Show resolved Hide resolved
src/model/ShadingControl.cpp Outdated Show resolved Hide resolved
src/model/SubSurface.cpp Show resolved Hide resolved
@@ -487,7 +487,36 @@ namespace detail {

boost::optional<ShadingControl> SubSurface_Impl::shadingControl() const
{
return getObject<SubSurface>().getModelObjectTarget<ShadingControl>(OS_SubSurfaceFields::ShadingControlName);
if (numberofShadingControls() > 1) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I would warn that there are more than 1, then return the first found.

Copy link
Collaborator

Choose a reason for hiding this comment

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

You cna also do that on the public side only, and remove the ShadingControl() method from Impl altogether.

src/model/SubSurface.hpp Outdated Show resolved Hide resolved
src/model/SubSurface.hpp Show resolved Hide resolved
EXPECT_EQ(2, shadingControl.numberofSubSurfaces());
shadingControl.removeAllSubSurfaces();
EXPECT_EQ(0, shadingControl.numberofSubSurfaces());
Copy link
Collaborator

Choose a reason for hiding this comment

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

Expand the test. Assign subSurface1 and subSurface2, then subSurface2.remove() => what happens to the numberOfSurbSurfaces.

Add a clone test too: are the extensible groups cleared? (do we want them to be?)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@jmarrec I added tests for these two scenarios. They both fail. For the first, shadingControl.numberofSubSurfaces remains at what it was before. For the second, cloning the shadingControl object throws an error.

src/osversion/VersionTranslator.cpp Show resolved Hide resolved
@joseph-robertson joseph-robertson added the Pull Request - Ready for CI This pull request if finalized and is ready for continuous integration verification prior to merge. label Sep 10, 2020
@joseph-robertson joseph-robertson marked this pull request as ready for review September 10, 2020 16:55
@jmarrec jmarrec force-pushed the multiple-shading-controls branch from 8902811 to 3118db0 Compare September 11, 2020 10:54
@jmarrec jmarrec force-pushed the multiple-shading-controls branch from 3118db0 to 6619cbf Compare September 11, 2020 10:59
@jmarrec
Copy link
Collaborator

jmarrec commented Sep 15, 2020

For #4074, fix is here: d6041d8
Can someone please make sure I interpreted the E+ docs correctly and didn't mess up something there?

Edit: Follow up in 361e509

@kbenne @asparke2 @joseph-robertson

@jmarrec jmarrec force-pushed the multiple-shading-controls branch from 3448990 to 7bea01b Compare September 16, 2020 09:22
src/model/ShadingControl.hpp Show resolved Hide resolved
src/model/ShadingControl.hpp Show resolved Hide resolved
src/model/ShadingControl.hpp Show resolved Hide resolved
@jmarrec
Copy link
Collaborator

jmarrec commented Sep 17, 2020

@joseph-robertson did we restrict the SubSurfaces to be part of the same ThermalZOne? I think we perhaps should?

@shorowit
Copy link
Contributor

shorowit commented Sep 17, 2020

@joseph-robertson did we restrict the SubSurfaces to be part of the same ThermalZOne? I think we perhaps should?

I don't agree with this. See #3380 for example.

EDIT: So note that there is a warning for this case.

@joseph-robertson
Copy link
Collaborator Author

@joseph-robertson did we restrict the SubSurfaces to be part of the same ThermalZOne? I think we perhaps should?

@jmarrec Why do you think we should?

@jmarrec
Copy link
Collaborator

jmarrec commented Sep 17, 2020

I think I misread the doc for the field https://bigladdersoftware.com/epx/docs/9-3/input-output-reference/group-thermal-zone-description-geometry.html#shading-control-sequence-number (I read that they should be in the same zone) as I had just read the comment in the ForwardTranslator just before it. Now I see it's not a problem to span across zones

If multiple WindowShadingControl objects are used in the same zone, then the order that they deploy the window shades can be set with this field. The first WindowShadingControl should be 1 and subsequent WindowShadingControl should 2, 3, etc. This is usually used when the Multiple Surface Control Type field is set to Group to control groups of windows in a certain order.

Well then it goes back to the action item I added: Does the logic in the ForwardTrnaslator.cpp need to be updated?

// ensure shading controls only reference windows in a single zone and determine control sequence number
// DLM: ideally E+ would not need to know the zone, shading controls could work across zones
std::vector<ShadingControl> shadingControls = model.getConcreteModelObjects<ShadingControl>();

@kbenne
Copy link
Contributor

kbenne commented Sep 18, 2020

I have merged this into #4073 and will go ahead and merge the combined work which will close #4066 and #4073. Lets just please pay close attention to the regression tests, and @joseph-robertson consider adding a regression test to demonstrate the multiple shading surfaces.

@kbenne kbenne merged commit d32be89 into develop Sep 18, 2020
@kbenne kbenne deleted the multiple-shading-controls branch September 18, 2020 15:46
@jmarrec jmarrec mentioned this pull request Mar 16, 2021
20 tasks
@joseph-robertson
Copy link
Collaborator Author

I think I misread the doc for the field https://bigladdersoftware.com/epx/docs/9-3/input-output-reference/group-thermal-zone-description-geometry.html#shading-control-sequence-number (I read that they should be in the same zone) as I had just read the comment in the ForwardTranslator just before it. Now I see it's not a problem to span across zones

If multiple WindowShadingControl objects are used in the same zone, then the order that they deploy the window shades can be set with this field. The first WindowShadingControl should be 1 and subsequent WindowShadingControl should 2, 3, etc. This is usually used when the Multiple Surface Control Type field is set to Group to control groups of windows in a certain order.

Well then it goes back to the action item I added: Does the logic in the ForwardTrnaslator.cpp need to be updated?

// ensure shading controls only reference windows in a single zone and determine control sequence number
// DLM: ideally E+ would not need to know the zone, shading controls could work across zones
std::vector<ShadingControl> shadingControls = model.getConcreteModelObjects<ShadingControl>();

@jmarrec @shorowit

Here is a new test (shadingcontrol_multizone.rb) related to this: NREL/OpenStudio-resources#147.

From what I can tell, the idf contains shading controls with sub surfaces from different zones. However, the "Window Control" table in eplustbl.htm shows only a single shading control object for each sub surface. In fact, when I look at eplustbl.htm for shadingcontrol_singlezone.rb I see a similar thing. So I'm not sure if this is working. Shouldn't we see multiple shading control objects for the same sub surface?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component - Model IDDChange Pull Request - Ready for CI This pull request if finalized and is ready for continuous integration verification prior to merge.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants