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

Fix #4802 - E+ 23.1.0: Wrap SolarCollectorPerformance:PhotovoltaicThermal:BIPVT #4813

Merged
merged 25 commits into from
Mar 16, 2023

Conversation

jmarrec
Copy link
Collaborator

@jmarrec jmarrec commented Mar 7, 2023

Pull request overview

Pull Request Author

  • 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:
  • If needed, added VersionTranslation rules for the objects (src/osversion/VersionTranslator.cpp)
  • 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 jmarrec added Enhancement Request component - Model component - IDF Translation Pull Request - Ready for CI This pull request if finalized and is ready for continuous integration verification prior to merge. labels Mar 7, 2023
@jmarrec jmarrec self-assigned this Mar 7, 2023
jmarrec added a commit to NREL/OpenStudio-resources that referenced this pull request Mar 7, 2023
jmarrec added a commit to NREL/OpenStudio-resources that referenced this pull request Mar 7, 2023
@joseph-robertson joseph-robertson mentioned this pull request Mar 7, 2023
5 tasks
@@ -5118,6 +5118,36 @@ MaterialProperty:VariableThermalConductivity,
\note for Temperature-Thermal Conductivity function corresponding to temperature 1
\units W/m-K

MaterialProperty:VariableAbsorptance,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Sneaking this in (unrelated to this PR), right?

Copy link
Collaborator Author

@jmarrec jmarrec Mar 8, 2023

Choose a reason for hiding this comment

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

Yes. I realized between this PR and the ones you added so far, it was going to be the only missing one. See commit message of 90005f1

jmarrec added 3 commits March 8, 2023 09:00
…atPlatePhotovoltaicThermal isn't RT'ed, neither is SurfacePropertyOtherSideConditionsModel)
Comment on lines +77 to +78
* [#4813](https://github.com/NREL/OpenStudio/pull/4813) - Wrap `SolarCollectorPerformance:PhotovoltaicThermal:BIPVT`
* `SolarCollectorFlatPlatePhotovoltaicThermal` has API-breaking changes in the `solarCollectorPerformance` getter due to the addition of this new object: it used to return a `SolarCollectorPerformancePhotovoltaicThermalSimple` (the only performance object at the time), now it's a `ModelObject`.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Document API break in SolarCollectorFlatPlatePhotovoltaicThermal

Copy link
Collaborator

Choose a reason for hiding this comment

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

👍

Comment on lines +5132 to +5138
A3 , \field Control Signal
\type choice
\key SurfaceTemperature
\key SurfaceReceivedSolarRadiation
\key SpaceHeatingCoolingMode
\key Scheduled
\default SurfaceTemperature
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

MaterialProperty:VariableAbsorptance: I removed the \required-field in E+ idd since it already has a \default

@@ -70,7 +73,7 @@ namespace model {
/** @name Getters */
//@{

SolarCollectorPerformancePhotovoltaicThermalSimple solarCollectorPerformance() const;
ModelObject solarCollectorPerformance() const;
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

API break in SolarCollectorFlatPlatePhotovoltaicThermal. It is unavoidable, now that we have two potential Performance objects.

I am considering adding a base (shallow) class SolarCollectorPerformancePhotovoltaicThermal

Copy link
Collaborator

Choose a reason for hiding this comment

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

👍

Comment on lines +90 to +92
/// Deletes the current performance and clones the performance passed in
bool setSolarCollectorPerformance(const SolarCollectorPerformancePhotovoltaicThermalBIPVT& performance);
bool setSolarCollectorPerformance(const SolarCollectorPerformancePhotovoltaicThermalSimple& performance);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I don't really like changing the parameter type to the overly generic "ModelObject" one here. It would work fine if you passed any ModelObject and just return false but that's silent-ish. Whether constraining the Type would create a type error message with the prototype(s) accepted.

That is the reason I am considering a base class SolarCollectorPerformancePhotovoltaicThermalhere. But maybe it's too much complexity.
So so far I've used two specific overloads for the setter. The only annoyance is that you need to cast if you retrieve the performance from one object to set to another.

-pvt2.setPerformance(pvt.performance())
+pvt2.setperformance(pvt.performance().to_SolarCollectorPerformancePhotovoltaicThermalSimple)

Copy link
Collaborator

Choose a reason for hiding this comment

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

Seems consistent with how we've been breaking API in the recent past...

@@ -195,7 +195,7 @@ namespace model {
boost::optional<SurfacePropertyOtherSideCoefficients> surfacePropertyOtherSideCoefficients() const;

/** Sets the SurfacePropertyOtherSideCoefficients. */
bool setSurfacePropertyOtherSideCoefficients(SurfacePropertyOtherSideCoefficients& otherSideCoefficients);
bool setSurfacePropertyOtherSideCoefficients(const SurfacePropertyOtherSideCoefficients& otherSideCoefficients);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This isn't exactly related to this PR but I noticed the const-correctness issue while creating a GTest (It was forcing me to create a temporary before I could use these)

setSurfacePropertyOtherSideCoefficients / setSurfacePropertyOtherSideConditionsModel in both Surface and SubSurface need to have a const.

Comment on lines +57 to +76
{
Model m;
SolarCollectorFlatPlatePhotovoltaicThermal testObject(m);
auto performance = testObject.solarCollectorPerformance();
EXPECT_TRUE(performance.optionalCast<SolarCollectorPerformancePhotovoltaicThermalSimple>());
}
{
Model m;
SolarCollectorPerformancePhotovoltaicThermalSimple performance(m);
SolarCollectorFlatPlatePhotovoltaicThermal testObject(performance);
EXPECT_TRUE(performance.optionalCast<SolarCollectorPerformancePhotovoltaicThermalSimple>());
EXPECT_EQ(testObject.solarCollectorPerformance(), performance);
}
{
Model m;
SolarCollectorPerformancePhotovoltaicThermalBIPVT performance(m);
SolarCollectorFlatPlatePhotovoltaicThermal testObject(performance);
EXPECT_TRUE(performance.optionalCast<SolarCollectorPerformancePhotovoltaicThermalBIPVT>());
EXPECT_EQ(testObject.solarCollectorPerformance(), performance);
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

test the new explicit ctors for the Solar Collector PVT

Copy link
Collaborator

Choose a reason for hiding this comment

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

👍

* that means correct node names in the ChillerElectricASHRAE205 but also
* on the Branches
*/
TEST_F(EnergyPlusFixture, ForwardTranslator_SolarCollectorPerformancePhotovoltaicThermalBIPVT) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Full FT test


namespace energyplus {

boost::optional<ModelObject> ReverseTranslator::translateSurfacePropertyOtherSideConditionsModel(const WorkspaceObject& workspaceObject) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

New RT for SurfacePropertyOtherSideConditionsModel, I needed this so the BIPVT one would not be too useless.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ah, I see.

Comment on lines +58 to +78
// Boundary Conditions Model Name: Required Object
if (boost::optional<WorkspaceObject> wo_ =
workspaceObject.getTarget(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::BoundaryConditionsModelName)) {
if (boost::optional<ModelObject> mo_ = translateAndMapWorkspaceObject(wo_.get())) {
// TODO: check return types
if (boost::optional<SurfacePropertyOtherSideConditionsModel> boundaryConditionsModel_ =
mo_->optionalCast<SurfacePropertyOtherSideConditionsModel>()) {
// The Ctor creates a BoundaryConditionsModel for us, so we can remove it now that we found the right one
auto defaultOSCM = modelObject.boundaryConditionsModel();
modelObject.setBoundaryConditionsModel(boundaryConditionsModel_.get());
defaultOSCM.remove();
} else {
LOG(Warn, workspaceObject.briefDescription() << " has a wrong type for 'Boundary Conditions Model Name'");
}
} else {
LOG(Error, "For " << workspaceObject.briefDescription()
<< ", cannot reverse translate required object 'Boundary Conditions Model Name'. Using defaulted one.");
}
LOG(Warn,
"For " << workspaceObject.briefDescription() << ", cannot find required object 'Boundary Conditions Model Name'. Using defaulted one.");
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

BIPVT: just warn if the OSCM can't be found (and keep using the defaulted one).

Comment on lines +883 to +886
case openstudio::IddObjectType::SolarCollectorPerformance_PhotovoltaicThermal_BIPVT: {
modelObject = translateSolarCollectorPerformancePhotovoltaicThermalBIPVT(workspaceObject);
break;
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'm adding the RT for the future mostly, since the SolarCollectorPVT isn't RT'ed (since PlantLoop isn't).

But this can still be useful if you want to grab the Perf data from an IDF to assign to a model-time created SolarCollectorPVT.

@jmarrec jmarrec added this to the OpenStudio SDK 3.6.0 milestone Mar 8, 2023
@jmarrec jmarrec requested a review from joseph-robertson March 8, 2023 09:15
Copy link
Collaborator Author

@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.

Final walkthrough comments. This is ready for review. Not sure who wants to review: @joseph-robertson @tijcolem

} // namespace detail

/** SolarCollectorPerformancePhotovoltaicThermalBIPVT is a ModelObject that wraps the OpenStudio IDD object 'OS:SolarCollectorPerformance:PhotovoltaicThermal:BIPVT'. */
class MODEL_API SolarCollectorPerformancePhotovoltaicThermalBIPVT : public ModelObject
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Note: I made this a ModelObject because the SolarCollectorPerformancePhotovoltaicThermalSimple already was. I kinda find it weird that these aren't ResourceObjects, and that the SolarCollectorPVT just clones whatever Perf object you pass, but that's the way it is, I didn't want to break API.

bool SolarCollectorFlatPlatePhotovoltaicThermal_Impl::setSolarCollectorPerformance(
const SolarCollectorPerformancePhotovoltaicThermalSimple& performance) {
bool result(false);
SolarCollectorPerformancePhotovoltaicThermalSimple current = this->solarCollectorPerformance();
if (current.handle() == performance.handle()) {
return true; // no-op
}
ModelObject clone = performance.clone(this->model());
result = setSolarCollectorPerformanceNoClone(clone.cast<SolarCollectorPerformancePhotovoltaicThermalSimple>());
if (result) {
current.remove();
} else {
result = setSolarCollectorPerformanceNoClone(current);
OS_ASSERT(result);
return false;
}
return result;
}

Copy link
Collaborator

@joseph-robertson joseph-robertson left a comment

Choose a reason for hiding this comment

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

Looks good to me. Just a few clarifying questions.

Comment on lines +77 to +78
* [#4813](https://github.com/NREL/OpenStudio/pull/4813) - Wrap `SolarCollectorPerformance:PhotovoltaicThermal:BIPVT`
* `SolarCollectorFlatPlatePhotovoltaicThermal` has API-breaking changes in the `solarCollectorPerformance` getter due to the addition of this new object: it used to return a `SolarCollectorPerformancePhotovoltaicThermalSimple` (the only performance object at the time), now it's a `ModelObject`.
Copy link
Collaborator

Choose a reason for hiding this comment

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

👍

Comment on lines +32349 to +32436
OS:SolarCollectorPerformance:PhotovoltaicThermal:BIPVT,
\memo Thermal performance parameters for Building-Integrated Photovoltaic-Thermal (BIPVT) solar collector.
\min-fields 17
A1, \field Handle
\type handle
\required-field
A2 , \field Name
\required-field
\type alpha
\reference FlatPlatePVTParameters
A3, \field Boundary Conditions Model Name
\required-field
\type object-list
\object-list OSCMNames
\note Enter the name of a SurfaceProperty:OtherSideConditionsModel object
A4 , \field Availability Schedule Name
\note Availability schedule name for this collector. Schedule value > 0 means it is available.
\note If this field is blank, the collector is always available.
\type object-list
\object-list ScheduleNames
\required-field
N1 , \field Effective Plenum Gap Thickness Behind PV Modules
\required-field
\type real
\units m
\minimum> 0.0
N2 , \field PV Cell Normal Transmittance-Absorptance Product
\type real
\required-field
\minimum> 0.0
\maximum< 1.00
N3 , \field Backing Material Normal Transmittance-Absorptance Product
\type real
\required-field
\minimum> 0.0
\maximum< 1.00
N4 , \field Cladding Normal Transmittance-Absorptance Product
\type real
\required-field
\minimum> 0.0
\maximum< 1.00
N5 , \field Fraction of Collector Gross Area Covered by PV Module
\type real
\required-field
\minimum> 0.0
\maximum< 1.00
N6 , \field Fraction of PV Cell Area to PV Module Area
\type real
\required-field
\minimum> 0.0
\maximum< 1.00
N7 , \field PV Module Top Thermal Resistance
\type real
\units m2-K/W
\required-field
\minimum> 0.0
N8 , \field PV Module Bottom Thermal Resistance
\type real
\units m2-K/W
\required-field
\minimum> 0.0
N9 ,\field PV Module Front Longwave Emissivity
\type real
\required-field
\minimum> 0.0
\maximum< 1.00
N10 ,\field PV Module Back Longwave Emissivity
\type real
\required-field
\minimum> 0.0
\maximum< 1.00
N11 ,\field Glass Thickness
\type real
\required-field
\units m
\minimum> 0.0
\maximum< 0.01
N12 ,\field Glass Refraction Index
\type real
\required-field
\minimum> 1.0
\maximum< 10.00
N13 ;\field Glass Extinction Coefficient
\type real
\required-field
\units 1/m
\minimum> 0.0
\maximum< 100.00
Copy link
Collaborator

Choose a reason for hiding this comment

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

👍

@@ -394,12 +395,12 @@ set(${target_name}_src
ForwardTranslator/ForwardTranslateSurfacePropertyConvectionCoefficients.cpp
ForwardTranslator/ForwardTranslateSurfacePropertyConvectionCoefficientsMultipleSurface.cpp
ForwardTranslator/ForwardTranslateSurfacePropertyExposedFoundationPerimeter.cpp
ForwardTranslator/ForwardTranslateSurfacePropertyGroundSurfaces.cpp
ForwardTranslator/ForwardTranslateSurfacePropertyIncidentSolarMultiplier.cpp
Copy link
Collaborator

Choose a reason for hiding this comment

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

Alphabetizing.

ReverseTranslator/ReverseTranslateSurfacePropertyGroundSurfaces.cpp
ReverseTranslator/ReverseTranslateSurfacePropertyIncidentSolarMultiplier.cpp
ReverseTranslator/ReverseTranslateSurfacePropertyLocalEnvironment.cpp
ReverseTranslator/ReverseTranslateSurfacePropertyOtherSideConditionsModel.cpp
Copy link
Collaborator

Choose a reason for hiding this comment

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

Alphabetizing, and new RT for existing object.


namespace energyplus {

boost::optional<ModelObject> ReverseTranslator::translateSurfacePropertyOtherSideConditionsModel(const WorkspaceObject& workspaceObject) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Ah, I see.

@@ -70,7 +73,7 @@ namespace model {
/** @name Getters */
//@{

SolarCollectorPerformancePhotovoltaicThermalSimple solarCollectorPerformance() const;
ModelObject solarCollectorPerformance() const;
Copy link
Collaborator

Choose a reason for hiding this comment

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

👍

Comment on lines +90 to +92
/// Deletes the current performance and clones the performance passed in
bool setSolarCollectorPerformance(const SolarCollectorPerformancePhotovoltaicThermalBIPVT& performance);
bool setSolarCollectorPerformance(const SolarCollectorPerformancePhotovoltaicThermalSimple& performance);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Seems consistent with how we've been breaking API in the recent past...


/// Deletes the current parameters and constructs a new default set of parameters
/// Deletes the current performance and constructs a new default set of performance
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe I missed it, but where does it actually construct a new default set of performance?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I see it now.

Comment on lines +57 to +76
{
Model m;
SolarCollectorFlatPlatePhotovoltaicThermal testObject(m);
auto performance = testObject.solarCollectorPerformance();
EXPECT_TRUE(performance.optionalCast<SolarCollectorPerformancePhotovoltaicThermalSimple>());
}
{
Model m;
SolarCollectorPerformancePhotovoltaicThermalSimple performance(m);
SolarCollectorFlatPlatePhotovoltaicThermal testObject(performance);
EXPECT_TRUE(performance.optionalCast<SolarCollectorPerformancePhotovoltaicThermalSimple>());
EXPECT_EQ(testObject.solarCollectorPerformance(), performance);
}
{
Model m;
SolarCollectorPerformancePhotovoltaicThermalBIPVT performance(m);
SolarCollectorFlatPlatePhotovoltaicThermal testObject(performance);
EXPECT_TRUE(performance.optionalCast<SolarCollectorPerformancePhotovoltaicThermalBIPVT>());
EXPECT_EQ(testObject.solarCollectorPerformance(), performance);
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

👍

// Bad Value
EXPECT_FALSE(solarCollectorPerformancePhotovoltaicThermalBIPVT.setGlassExtinctionCoefficient(-10.0));
EXPECT_EQ(94.444, solarCollectorPerformancePhotovoltaicThermalBIPVT.glassExtinctionCoefficient());
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

We check for clone, remove, etc. in parent Thermal test?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yes.

@jmarrec jmarrec merged commit 518f3f9 into develop Mar 16, 2023
@jmarrec jmarrec deleted the 4802_SolarCollectorPerf_BIPVT branch March 16, 2023 10:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component - IDF Translation component - Model Enhancement Request 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.

E+ 23.1.0: Wrap SolarCollectorPerformance:PhotovoltaicThermal:BIPVT
3 participants