Repository: NREL/OpenStudio (language: python)

Issue:
E+ 23.1.0: Wrap SolarCollectorPerformance:PhotovoltaicThermal:BIPVT
Enhancement Request
--------------
<!--- Provide a general summary of the feature you would like to see implemented -->

## Detailed Description
<!--- Provide a detailed description of the change or addition you are proposing. Include screenshot/schemas as appropriate -->

## Possible Implementation
<!--- Not mandatory, but if you can, suggest an idea for implementing the feature -->

E+ 23.1.0: Wrap SolarCollectorPerformance:PhotovoltaicThermal:BIPVT
Enhancement Request
--------------
<!--- Provide a general summary of the feature you would like to see implemented -->

## Detailed Description
<!--- Provide a detailed description of the change or addition you are proposing. Include screenshot/schemas as appropriate -->

## Possible Implementation
<!--- Not mandatory, but if you can, suggest an idea for implementing the feature -->



Discussion / hints:

Fix patch:
diff --git a/developer/doc/ReleaseNotes/OpenStudio_Release_Notes_3_6_0_TBD.md b/developer/doc/ReleaseNotes/OpenStudio_Release_Notes_3_6_0_TBD.md
index bc3567da615..28aff5f9e0d 100644
--- a/developer/doc/ReleaseNotes/OpenStudio_Release_Notes_3_6_0_TBD.md
+++ b/developer/doc/ReleaseNotes/OpenStudio_Release_Notes_3_6_0_TBD.md
@@ -74,6 +74,9 @@ You can also refer to the [OpenStudio SDK Python Binding Version Compatibility M
 
 * [#4740](https://github.com/NREL/OpenStudio/pull/4740) - Fix issues around `ScheduleFixedInterval`, with A minor API breaking change: `intervalLength`/`setIntervalLength` now return/accept an `int` rather than a `double` to conform to the IDD type `\integer`
 
+* [#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`.
+
 ## Minor changes and bug fixes
 
 
diff --git a/resources/energyplus/ProposedEnergy+.idd b/resources/energyplus/ProposedEnergy+.idd
index b3fc2b54416..1838d1d7348 100644
--- a/resources/energyplus/ProposedEnergy+.idd
+++ b/resources/energyplus/ProposedEnergy+.idd
@@ -5118,6 +5118,36 @@ MaterialProperty:VariableThermalConductivity,
        \note for Temperature-Thermal Conductivity function corresponding to temperature 1
        \units W/m-K
 
+MaterialProperty:VariableAbsorptance,
+  A1 , \field Name
+       \required-field
+       \type alpha
+       \note The name of the dynamic coating material with variable thermal or solar absorptance.
+  A2 , \field Reference Material Name
+       \required-field
+       \type object-list
+       \object-list MaterialName
+       \note Regular Material Name to which the additional properties will be added.
+       \note this the material name for the basic material properties.
+  A3 , \field Control Signal
+       \type choice
+       \key SurfaceTemperature
+       \key SurfaceReceivedSolarRadiation
+       \key SpaceHeatingCoolingMode
+       \key Scheduled
+       \default SurfaceTemperature
+       \note the variable that drives the change in thermal/solar absorptance
+  A4 , \field Thermal Absorptance Function Name
+       \note A Curve:* or Table:Lookup object encoding the relationship between
+       \note the control signal value and the surface thermal absorptance.
+  A5 , \field Thermal Absorptance Schedule Name
+       \note only used when Control Signal = "Scheduled"
+  A6 , \field Solar Absorptance Function Name
+       \note A Curve:* or Table:Lookup object encoding the relationship between
+       \note the control signal value and the surface solar absorptance.
+  A7 ; \field Solar Absorptance Schedule Name
+       \note only used when Control Signal = "Scheduled"
+
 MaterialProperty:HeatAndMoistureTransfer:Settings,
     \memo HeatBalanceAlgorithm = CombinedHeatAndMoistureFiniteElement solution algorithm only.
     \memo Additional material properties for surfaces.
@@ -41825,6 +41855,88 @@ SolarCollectorPerformance:PhotovoltaicThermal:Simple,
        \minimum> 0.00
        \maximum< 1.00
 
+SolarCollectorPerformance:PhotovoltaicThermal:BIPVT,
+        \memo Thermal performance parameters for Building-Integrated Photovoltaic-Thermal (BIPVT) solar collector.
+  A1 ,  \field Name
+        \reference FlatPlatePVTParameters
+  A2,   \field Boundary Conditions Model Name
+        \required-field
+        \type object-list
+        \object-list OSCMNames
+        \note Enter the name of a SurfaceProperty:OtherSideConditionsModel object
+  A3 ,  \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
+  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
+        \default 0.957
+        \minimum> 0.0
+        \maximum< 1.00
+  N3 ,  \field Backing Material Normal Transmittance-Absorptance Product
+        \type real
+        \default 0.87
+        \minimum> 0.0
+        \maximum< 1.00
+  N4 ,  \field Cladding Normal Transmittance-Absorptance Product
+        \type real
+        \default 0.85
+        \minimum> 0.0
+        \maximum< 1.00
+  N5 ,  \field Fraction of Collector Gross Area Covered by PV Module
+        \type real
+        \default 0.85
+        \minimum> 0.0
+        \maximum< 1.00
+  N6 ,  \field Fraction of PV Cell Area to PV Module Area
+        \type real
+        \default 0.9
+        \minimum> 0.0
+        \maximum< 1.00
+  N7 ,  \field PV Module Top Thermal Resistance
+        \type real
+        \units m2-K/W
+        \default 0.0044
+        \minimum> 0.0
+  N8 ,  \field PV Module Bottom Thermal Resistance
+        \type real
+        \units m2-K/W
+        \default 0.0039
+        \minimum> 0.0
+  N9  , \field PV Module Front Longwave Emissivity
+        \type real
+        \default 0.85
+        \minimum> 0.0
+        \maximum< 1.00
+  N10 , \field PV Module Back Longwave Emissivity
+        \type real
+        \default 0.9
+        \minimum> 0.0
+        \maximum< 1.00
+  N11 , \field Glass Thickness
+        \type real
+        \default 0.002
+        \units m
+        \minimum> 0.0
+        \maximum< 0.01
+  N12 , \field Glass Refraction Index
+        \type real
+        \default 1.526
+        \minimum> 1.0
+        \maximum< 10.00
+  N13 ; \field Glass Extinction Coefficient
+        \type real
+        \default 4.0
+        \units 1/m
+        \minimum> 0.0
+        \maximum< 100.00
+
 SolarCollector:IntegralCollectorStorage,
        \memo Glazed solar collector with integral storage unit. Thermal and optical properties are
        \memo taken from the referenced SolarCollectorPerformance:IntegralCollectorStorage object.
diff --git a/resources/model/OpenStudio.idd b/resources/model/OpenStudio.idd
index d91c19dfadc..ac183a07021 100644
--- a/resources/model/OpenStudio.idd
+++ b/resources/model/OpenStudio.idd
@@ -32346,6 +32346,95 @@ OS:SolarCollectorPerformance:PhotovoltaicThermal:Simple,
        \minimum> 0.00
        \maximum< 1.00
 
+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
+
 OS:SolarCollector:FlatPlate:PhotovoltaicThermal,
        \memo Models hybrid photovoltaic-thermal (PVT) solar collectors that convert incident solar
        \memo energy into both electricity and useful thermal energy by heating air or water.
diff --git a/src/energyplus/CMakeLists.txt b/src/energyplus/CMakeLists.txt
index 986c2f95cad..312e8d814d2 100644
--- a/src/energyplus/CMakeLists.txt
+++ b/src/energyplus/CMakeLists.txt
@@ -380,6 +380,7 @@ set(${target_name}_src
   ForwardTranslator/ForwardTranslateSolarCollectorIntegralCollectorStorage.cpp
   ForwardTranslator/ForwardTranslateSolarCollectorPerformanceFlatPlate.cpp
   ForwardTranslator/ForwardTranslateSolarCollectorPerformanceIntegralCollectorStorage.cpp
+  ForwardTranslator/ForwardTranslateSolarCollectorPerformancePhotovoltaicThermalBIPVT.cpp
   ForwardTranslator/ForwardTranslateSolarCollectorPerformancePhotovoltaicThermalSimple.cpp
   ForwardTranslator/ForwardTranslateSpaceType.cpp
   ForwardTranslator/ForwardTranslateSpaceInfiltrationDesignFlowRate.cpp
@@ -394,12 +395,12 @@ set(${target_name}_src
   ForwardTranslator/ForwardTranslateSurfacePropertyConvectionCoefficients.cpp
   ForwardTranslator/ForwardTranslateSurfacePropertyConvectionCoefficientsMultipleSurface.cpp
   ForwardTranslator/ForwardTranslateSurfacePropertyExposedFoundationPerimeter.cpp
+  ForwardTranslator/ForwardTranslateSurfacePropertyGroundSurfaces.cpp
+  ForwardTranslator/ForwardTranslateSurfacePropertyIncidentSolarMultiplier.cpp
   ForwardTranslator/ForwardTranslateSurfacePropertyLocalEnvironment.cpp
   ForwardTranslator/ForwardTranslateSurfacePropertyOtherSideCoefficients.cpp
   ForwardTranslator/ForwardTranslateSurfacePropertyOtherSideConditionsModel.cpp
   ForwardTranslator/ForwardTranslateSurfacePropertySurroundingSurfaces.cpp
-  ForwardTranslator/ForwardTranslateSurfacePropertyGroundSurfaces.cpp
-  ForwardTranslator/ForwardTranslateSurfacePropertyIncidentSolarMultiplier.cpp
   ForwardTranslator/ForwardTranslateSwimmingPoolIndoor.cpp
   ForwardTranslator/ForwardTranslateTableMultiVariableLookup.cpp
   ForwardTranslator/ForwardTranslateTableLookup.cpp
@@ -596,15 +597,17 @@ set(${target_name}_src
   ReverseTranslator/ReverseTranslateSizingSystem.cpp
   ReverseTranslator/ReverseTranslateSizingZone.cpp
   ReverseTranslator/ReverseTranslateSizingPeriodDesignDay.cpp
+  ReverseTranslator/ReverseTranslateSolarCollectorPerformancePhotovoltaicThermalBIPVT.cpp
   ReverseTranslator/ReverseTranslateSteamEquipment.cpp
   ReverseTranslator/ReverseTranslateSurfaceControlMovableInsulation.cpp
   ReverseTranslator/ReverseTranslateSurfaceConvectionAlgorithmInside.cpp
   ReverseTranslator/ReverseTranslateSurfaceConvectionAlgorithmOutside.cpp
   ReverseTranslator/ReverseTranslateSurfacePropertyExposedFoundationPerimeter.cpp
-  ReverseTranslator/ReverseTranslateSurfacePropertyLocalEnvironment.cpp
-  ReverseTranslator/ReverseTranslateSurfacePropertySurroundingSurfaces.cpp
   ReverseTranslator/ReverseTranslateSurfacePropertyGroundSurfaces.cpp
   ReverseTranslator/ReverseTranslateSurfacePropertyIncidentSolarMultiplier.cpp
+  ReverseTranslator/ReverseTranslateSurfacePropertyLocalEnvironment.cpp
+  ReverseTranslator/ReverseTranslateSurfacePropertyOtherSideConditionsModel.cpp
+  ReverseTranslator/ReverseTranslateSurfacePropertySurroundingSurfaces.cpp
   ReverseTranslator/ReverseTranslateSwimmingPoolIndoor.cpp
   ReverseTranslator/ReverseTranslateTableLookup.cpp
   ReverseTranslator/ReverseTranslateTableIndependentVariable.cpp
@@ -778,6 +781,7 @@ set(${target_name}_test_src
   Test/SiteGroundTemperatureUndisturbedXing_GTest.cpp
   Test/SizingSystem_GTest.cpp
   Test/SizingZone_GTest.cpp
+  Test/SolarCollectorPerformancePhotovoltaicThermalBIPVT_GTest.cpp
   Test/Space_GTest.cpp
   Test/SpaceInfiltrationDesignFlowRate_GTest.cpp
   Test/SpaceInfiltrationEffectiveLeakageArea_GTest.cpp
@@ -787,10 +791,11 @@ set(${target_name}_test_src
   Test/Surface_GTest.cpp
   Test/SurfaceControlMovableInsulation_GTest.cpp
   Test/SurfacePropertyConvectionCoefficients_GTest.cpp
-  Test/SurfacePropertyLocalEnvironment_GTest.cpp
-  Test/SurfacePropertySurroundingSurfaces_GTest.cpp
   Test/SurfacePropertyGroundSurfaces_GTest.cpp
   Test/SurfacePropertyIncidentSolarMultiplier_GTest.cpp
+  Test/SurfacePropertyLocalEnvironment_GTest.cpp
+  Test/SurfacePropertyOtherSideConditionsModel_GTest.cpp
+  Test/SurfacePropertySurroundingSurfaces_GTest.cpp
   Test/SwimmingPoolIndoor_GTest.cpp
   Test/TableMultiVariableLookup_GTest.cpp
   Test/TableLookup_GTest.cpp
diff --git a/src/energyplus/ForwardTranslator.cpp b/src/energyplus/ForwardTranslator.cpp
index 7ea159033da..f73b5529316 100644
--- a/src/energyplus/ForwardTranslator.cpp
+++ b/src/energyplus/ForwardTranslator.cpp
@@ -2831,6 +2831,11 @@ namespace energyplus {
         retVal = translateSolarCollectorPerformanceIntegralCollectorStorage(mo);
         break;
       }
+      case openstudio::IddObjectType::OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVT: {
+        auto mo = modelObject.cast<SolarCollectorPerformancePhotovoltaicThermalBIPVT>();
+        retVal = translateSolarCollectorPerformancePhotovoltaicThermalBIPVT(mo);
+        break;
+      }
       case openstudio::IddObjectType::OS_SolarCollectorPerformance_PhotovoltaicThermal_Simple: {
         auto mo = modelObject.cast<SolarCollectorPerformancePhotovoltaicThermalSimple>();
         retVal = translateSolarCollectorPerformancePhotovoltaicThermalSimple(mo);
diff --git a/src/energyplus/ForwardTranslator.hpp b/src/energyplus/ForwardTranslator.hpp
index 4f6c0087c7e..d0a782a2c36 100644
--- a/src/energyplus/ForwardTranslator.hpp
+++ b/src/energyplus/ForwardTranslator.hpp
@@ -441,6 +441,7 @@ namespace model {
   class SolarCollectorIntegralCollectorStorage;
   class SolarCollectorPerformanceFlatPlate;
   class SolarCollectorPerformanceIntegralCollectorStorage;
+  class SolarCollectorPerformancePhotovoltaicThermalBIPVT;
   class SolarCollectorPerformancePhotovoltaicThermalSimple;
   class Space;
   class SpaceInfiltrationDesignFlowRate;
@@ -1428,6 +1429,9 @@ namespace energyplus {
     boost::optional<IdfObject>
       translateSolarCollectorPerformanceIntegralCollectorStorage(model::SolarCollectorPerformanceIntegralCollectorStorage& modelObject);
 
+    boost::optional<IdfObject>
+      translateSolarCollectorPerformancePhotovoltaicThermalBIPVT(model::SolarCollectorPerformancePhotovoltaicThermalBIPVT& modelObject);
+
     boost::optional<IdfObject>
       translateSolarCollectorPerformancePhotovoltaicThermalSimple(model::SolarCollectorPerformancePhotovoltaicThermalSimple& modelObject);
 
diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateSolarCollectorFlatPlatePhotovoltaicThermal.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateSolarCollectorFlatPlatePhotovoltaicThermal.cpp
index 30c52b6a1a2..55e41c85114 100644
--- a/src/energyplus/ForwardTranslator/ForwardTranslateSolarCollectorFlatPlatePhotovoltaicThermal.cpp
+++ b/src/energyplus/ForwardTranslator/ForwardTranslateSolarCollectorFlatPlatePhotovoltaicThermal.cpp
@@ -37,6 +37,7 @@
 #include "../../model/SolarCollectorFlatPlatePhotovoltaicThermal.hpp"
 #include "../../model/SolarCollectorFlatPlatePhotovoltaicThermal_Impl.hpp"
 #include "../../model/SolarCollectorPerformancePhotovoltaicThermalSimple.hpp"
+#include "../../model/SolarCollectorPerformancePhotovoltaicThermalBIPVT.hpp"
 #include "../../utilities/core/Logger.hpp"
 #include "../../utilities/core/Assert.hpp"
 #include <utilities/idd/SolarCollector_FlatPlate_PhotovoltaicThermal_FieldEnums.hxx>
diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateSolarCollectorPerformancePhotovoltaicThermalBIPVT.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateSolarCollectorPerformancePhotovoltaicThermalBIPVT.cpp
new file mode 100644
index 00000000000..8b729c6a571
--- /dev/null
+++ b/src/energyplus/ForwardTranslator/ForwardTranslateSolarCollectorPerformancePhotovoltaicThermalBIPVT.cpp
@@ -0,0 +1,122 @@
+/***********************************************************************************************************************
+*  OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved.
+*
+*  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+*  following conditions are met:
+*
+*  (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+*  disclaimer.
+*
+*  (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+*  disclaimer in the documentation and/or other materials provided with the distribution.
+*
+*  (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products
+*  derived from this software without specific prior written permission from the respective party.
+*
+*  (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works
+*  may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior
+*  written permission from Alliance for Sustainable Energy, LLC.
+*
+*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+*  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED
+*  STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+*  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+*  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+*  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+*  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************************************************************/
+
+#include "../ForwardTranslator.hpp"
+
+#include "../../model/SolarCollectorPerformancePhotovoltaicThermalBIPVT.hpp"
+#include "../../model/Model.hpp"
+#include "../../model/SurfacePropertyOtherSideConditionsModel.hpp"
+#include "../../model/Schedule.hpp"
+
+#include <utilities/idd/SolarCollectorPerformance_PhotovoltaicThermal_BIPVT_FieldEnums.hxx>
+#include <utilities/idd/IddEnums.hxx>
+
+using namespace openstudio::model;
+
+namespace openstudio {
+
+namespace energyplus {
+
+  boost::optional<IdfObject> ForwardTranslator::translateSolarCollectorPerformancePhotovoltaicThermalBIPVT(
+    model::SolarCollectorPerformancePhotovoltaicThermalBIPVT& modelObject) {
+
+    // Instantiate an IdfObject of the class to store the values
+    IdfObject idfObject = createRegisterAndNameIdfObject(openstudio::IddObjectType::SolarCollectorPerformance_PhotovoltaicThermal_BIPVT, modelObject);
+
+    // Boundary Conditions Model Name: Required Object
+    {
+      auto boundaryConditionsModel = modelObject.boundaryConditionsModel();
+      if (boost::optional<IdfObject> wo_ = translateAndMapModelObject(boundaryConditionsModel)) {
+        idfObject.setString(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::BoundaryConditionsModelName, wo_->nameString());
+      }
+    }
+
+    // Availability Schedule Name: Optional Object (but required in model)
+    {
+      auto availabilitySchedule = modelObject.availabilitySchedule();
+      if (boost::optional<IdfObject> wo_ = translateAndMapModelObject(availabilitySchedule)) {
+        idfObject.setString(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::AvailabilityScheduleName, wo_->nameString());
+      }
+    }
+
+    // Effective Plenum Gap Thickness Behind PV Modules: Required Double
+    idfObject.setDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::EffectivePlenumGapThicknessBehindPVModules,
+                        modelObject.effectivePlenumGapThicknessBehindPVModules());
+
+    // PV Cell Normal Transmittance-Absorptance Product: Optional Double (but required in model)
+    idfObject.setDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::PVCellNormalTransmittanceAbsorptanceProduct,
+                        modelObject.pVCellNormalTransmittanceAbsorptanceProduct());
+
+    // Backing Material Normal Transmittance-Absorptance Product: Optional Double (but required in model)
+    idfObject.setDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::BackingMaterialNormalTransmittanceAbsorptanceProduct,
+                        modelObject.backingMaterialNormalTransmittanceAbsorptanceProduct());
+
+    // Cladding Normal Transmittance-Absorptance Product: Optional Double (but required in model)
+    idfObject.setDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::CladdingNormalTransmittanceAbsorptanceProduct,
+                        modelObject.claddingNormalTransmittanceAbsorptanceProduct());
+
+    // Fraction of Collector Gross Area Covered by PV Module: Optional Double (but required in model)
+    idfObject.setDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::FractionofCollectorGrossAreaCoveredbyPVModule,
+                        modelObject.fractionofCollectorGrossAreaCoveredbyPVModule());
+
+    // Fraction of PV Cell Area to PV Module Area: Optional Double (but required in model)
+    idfObject.setDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::FractionofPVCellAreatoPVModuleArea,
+                        modelObject.fractionofPVCellAreatoPVModuleArea());
+
+    // PV Module Top Thermal Resistance: Optional Double (but required in model)
+    idfObject.setDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::PVModuleTopThermalResistance,
+                        modelObject.pVModuleTopThermalResistance());
+
+    // PV Module Bottom Thermal Resistance: Optional Double (but required in model)
+    idfObject.setDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::PVModuleBottomThermalResistance,
+                        modelObject.pVModuleBottomThermalResistance());
+
+    // PV Module Front Longwave Emissivity: Optional Double (but required in model)
+    idfObject.setDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::PVModuleFrontLongwaveEmissivity,
+                        modelObject.pVModuleFrontLongwaveEmissivity());
+
+    // PV Module Back Longwave Emissivity: Optional Double (but required in model)
+    idfObject.setDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::PVModuleBackLongwaveEmissivity,
+                        modelObject.pVModuleBackLongwaveEmissivity());
+
+    // Glass Thickness: Optional Double (but required in model)
+    idfObject.setDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::GlassThickness, modelObject.glassThickness());
+
+    // Glass Refraction Index: Optional Double (but required in model)
+    idfObject.setDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::GlassRefractionIndex, modelObject.glassRefractionIndex());
+
+    // Glass Extinction Coefficient: Optional Double (but required in model)
+    idfObject.setDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::GlassExtinctionCoefficient,
+                        modelObject.glassExtinctionCoefficient());
+
+    return idfObject;
+  }  // End of translate function
+
+}  // end namespace energyplus
+}  // end namespace openstudio
diff --git a/src/energyplus/ReverseTranslator.cpp b/src/energyplus/ReverseTranslator.cpp
index bac566dddc7..fede8aacaf0 100644
--- a/src/energyplus/ReverseTranslator.cpp
+++ b/src/energyplus/ReverseTranslator.cpp
@@ -880,6 +880,10 @@ namespace energyplus {
         modelObject = translateSizingPeriodDesignDay(workspaceObject);
         break;
       }
+      case openstudio::IddObjectType::SolarCollectorPerformance_PhotovoltaicThermal_BIPVT: {
+        modelObject = translateSolarCollectorPerformancePhotovoltaicThermalBIPVT(workspaceObject);
+        break;
+      }
       case openstudio::IddObjectType::Sizing_System: {
         //modelObject = translateSizingSystem(workspaceObject);
         break;
@@ -908,28 +912,30 @@ namespace energyplus {
         modelObject = translateSurfacePropertyExposedFoundationPerimeter(workspaceObject);
         break;
       }
+      case openstudio::IddObjectType::SurfaceProperty_GroundSurfaces: {
+        modelObject = translateSurfacePropertyGroundSurfaces(workspaceObject);
+        break;
+      }
+      case openstudio::IddObjectType::SurfaceProperty_IncidentSolarMultiplier: {
+        modelObject = translateSurfacePropertyIncidentSolarMultiplier(workspaceObject);
+        break;
+      }
       case openstudio::IddObjectType::SurfaceProperty_LocalEnvironment: {
         modelObject = translateSurfacePropertyLocalEnvironment(workspaceObject);
         break;
       }
-      case openstudio::IddObjectType::SurfaceProperty_SurroundingSurfaces: {
-        modelObject = translateSurfacePropertySurroundingSurfaces(workspaceObject);
+      case openstudio::IddObjectType::SurfaceProperty_OtherSideConditionsModel: {
+        modelObject = translateSurfacePropertyOtherSideConditionsModel(workspaceObject);
         break;
       }
-      case openstudio::IddObjectType::SurfaceProperty_GroundSurfaces: {
-        modelObject = translateSurfacePropertyGroundSurfaces(workspaceObject);
+      case openstudio::IddObjectType::SurfaceProperty_SurroundingSurfaces: {
+        modelObject = translateSurfacePropertySurroundingSurfaces(workspaceObject);
         break;
       }
-      case openstudio::IddObjectType::SurfaceProperty_IncidentSolarMultiplier: {
-        modelObject = translateSurfacePropertyIncidentSolarMultiplier(workspaceObject);
+      case openstudio::IddObjectType::SwimmingPool_Indoor: {
+        // modelObject = translateSwimmingPoolIndoor(workspaceObject);
         break;
       }
-        //case openstudio::IddObjectType::SwimmingPool_Indoor :
-        //{
-        //modelObject = translateSwimmingPoolIndoor(workspaceObject);
-        //break;
-        //}
-
       case openstudio::IddObjectType::Table_Lookup: {
         modelObject = translateTableLookup(workspaceObject);
         break;
diff --git a/src/energyplus/ReverseTranslator.hpp b/src/energyplus/ReverseTranslator.hpp
index 822ae96d184..64f2b65daf1 100644
--- a/src/energyplus/ReverseTranslator.hpp
+++ b/src/energyplus/ReverseTranslator.hpp
@@ -295,6 +295,8 @@ namespace energyplus {
 
     boost::optional<model::ModelObject> translateSizingPeriodDesignDay(const WorkspaceObject& workspaceObject);
 
+    boost::optional<model::ModelObject> translateSolarCollectorPerformancePhotovoltaicThermalBIPVT(const WorkspaceObject& workspaceObject);
+
     boost::optional<model::ModelObject> translateRefrigerationCase(const WorkspaceObject& workspaceObject);
 
     boost::optional<model::ModelObject> translateRefrigerationCompressor(const WorkspaceObject& workspaceObject);
@@ -365,14 +367,16 @@ namespace energyplus {
 
     boost::optional<model::ModelObject> translateSurfacePropertyExposedFoundationPerimeter(const WorkspaceObject& workspaceObject);
 
-    boost::optional<model::ModelObject> translateSurfacePropertyLocalEnvironment(const WorkspaceObject& workspaceObject);
-
-    boost::optional<model::ModelObject> translateSurfacePropertySurroundingSurfaces(const WorkspaceObject& workspaceObject);
-
     boost::optional<model::ModelObject> translateSurfacePropertyGroundSurfaces(const WorkspaceObject& workspaceObject);
 
     boost::optional<model::ModelObject> translateSurfacePropertyIncidentSolarMultiplier(const WorkspaceObject& workspaceObject);
 
+    boost::optional<model::ModelObject> translateSurfacePropertyLocalEnvironment(const WorkspaceObject& workspaceObject);
+
+    boost::optional<model::ModelObject> translateSurfacePropertyOtherSideConditionsModel(const WorkspaceObject& workspaceObject);
+
+    boost::optional<model::ModelObject> translateSurfacePropertySurroundingSurfaces(const WorkspaceObject& workspaceObject);
+
     boost::optional<model::ModelObject> translateSwimmingPoolIndoor(const WorkspaceObject& workspaceObject);
 
     boost::optional<model::ModelObject> translateTableLookup(const WorkspaceObject& workspaceObject);
diff --git a/src/energyplus/ReverseTranslator/ReverseTranslateSolarCollectorPerformancePhotovoltaicThermalBIPVT.cpp b/src/energyplus/ReverseTranslator/ReverseTranslateSolarCollectorPerformancePhotovoltaicThermalBIPVT.cpp
new file mode 100644
index 00000000000..4fcd591ff37
--- /dev/null
+++ b/src/energyplus/ReverseTranslator/ReverseTranslateSolarCollectorPerformancePhotovoltaicThermalBIPVT.cpp
@@ -0,0 +1,177 @@
+/***********************************************************************************************************************
+*  OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved.
+*
+*  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+*  following conditions are met:
+*
+*  (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+*  disclaimer.
+*
+*  (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+*  disclaimer in the documentation and/or other materials provided with the distribution.
+*
+*  (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products
+*  derived from this software without specific prior written permission from the respective party.
+*
+*  (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works
+*  may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior
+*  written permission from Alliance for Sustainable Energy, LLC.
+*
+*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+*  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED
+*  STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+*  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+*  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+*  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+*  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************************************************************/
+
+#include "../ReverseTranslator.hpp"
+
+#include "../../model/SolarCollectorPerformancePhotovoltaicThermalBIPVT.hpp"
+
+#include "../../model/SurfacePropertyOtherSideConditionsModel.hpp"
+#include "../../model/SurfacePropertyOtherSideConditionsModel_Impl.hpp"
+
+#include "../../model/Schedule.hpp"
+#include "../../model/Schedule_Impl.hpp"
+
+#include <utilities/idd/SolarCollectorPerformance_PhotovoltaicThermal_BIPVT_FieldEnums.hxx>
+#include <utilities/idd/IddEnums.hxx>
+
+using namespace openstudio::model;
+
+namespace openstudio {
+
+namespace energyplus {
+
+  boost::optional<ModelObject> ReverseTranslator::translateSolarCollectorPerformancePhotovoltaicThermalBIPVT(const WorkspaceObject& workspaceObject) {
+
+    openstudio::model::SolarCollectorPerformancePhotovoltaicThermalBIPVT modelObject(m_model);
+
+    // Name
+    if (boost::optional<std::string> name_ = workspaceObject.name()) {
+      modelObject.setName(name_.get());
+    }
+
+    // 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.");
+    }
+    // Availability Schedule Name: Optional Object
+    if (boost::optional<WorkspaceObject> wo_ =
+          workspaceObject.getTarget(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::AvailabilityScheduleName)) {
+      if (boost::optional<ModelObject> mo_ = translateAndMapWorkspaceObject(wo_.get())) {
+        // TODO: check return types
+        if (boost::optional<Schedule> availabilitySchedule_ = mo_->optionalCast<Schedule>()) {
+          modelObject.setAvailabilitySchedule(availabilitySchedule_.get());
+        } else {
+          LOG(Warn, workspaceObject.briefDescription() << " has a wrong type for 'Availability Schedule Name'");
+        }
+      }
+    }
+    // Effective Plenum Gap Thickness Behind PV Modules: Required Double
+    if (boost::optional<double> effectivePlenumGapThicknessBehindPVModules_ =
+          workspaceObject.getDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::EffectivePlenumGapThicknessBehindPVModules)) {
+      modelObject.setEffectivePlenumGapThicknessBehindPVModules(effectivePlenumGapThicknessBehindPVModules_.get());
+    } else {
+      LOG(Error,
+          "For " << workspaceObject.briefDescription() << ", cannot find required property 'Effective Plenum Gap Thickness Behind PV Modules'");
+      return boost::none;
+    }
+
+    // PV Cell Normal Transmittance-Absorptance Product: Optional Double
+    if (boost::optional<double> pVCellNormalTransmittanceAbsorptanceProduct_ =
+          workspaceObject.getDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::PVCellNormalTransmittanceAbsorptanceProduct)) {
+      modelObject.setPVCellNormalTransmittanceAbsorptanceProduct(pVCellNormalTransmittanceAbsorptanceProduct_.get());
+    }
+
+    // Backing Material Normal Transmittance-Absorptance Product: Optional Double
+    if (boost::optional<double> backingMaterialNormalTransmittanceAbsorptanceProduct_ = workspaceObject.getDouble(
+          SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::BackingMaterialNormalTransmittanceAbsorptanceProduct)) {
+      modelObject.setBackingMaterialNormalTransmittanceAbsorptanceProduct(backingMaterialNormalTransmittanceAbsorptanceProduct_.get());
+    }
+
+    // Cladding Normal Transmittance-Absorptance Product: Optional Double
+    if (boost::optional<double> claddingNormalTransmittanceAbsorptanceProduct_ =
+          workspaceObject.getDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::CladdingNormalTransmittanceAbsorptanceProduct)) {
+      modelObject.setCladdingNormalTransmittanceAbsorptanceProduct(claddingNormalTransmittanceAbsorptanceProduct_.get());
+    }
+
+    // Fraction of Collector Gross Area Covered by PV Module: Optional Double
+    if (boost::optional<double> fractionofCollectorGrossAreaCoveredbyPVModule_ =
+          workspaceObject.getDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::FractionofCollectorGrossAreaCoveredbyPVModule)) {
+      modelObject.setFractionofCollectorGrossAreaCoveredbyPVModule(fractionofCollectorGrossAreaCoveredbyPVModule_.get());
+    }
+
+    // Fraction of PV Cell Area to PV Module Area: Optional Double
+    if (boost::optional<double> fractionofPVCellAreatoPVModuleArea_ =
+          workspaceObject.getDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::FractionofPVCellAreatoPVModuleArea)) {
+      modelObject.setFractionofPVCellAreatoPVModuleArea(fractionofPVCellAreatoPVModuleArea_.get());
+    }
+
+    // PV Module Top Thermal Resistance: Optional Double
+    if (boost::optional<double> pVModuleTopThermalResistance_ =
+          workspaceObject.getDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::PVModuleTopThermalResistance)) {
+      modelObject.setPVModuleTopThermalResistance(pVModuleTopThermalResistance_.get());
+    }
+
+    // PV Module Bottom Thermal Resistance: Optional Double
+    if (boost::optional<double> pVModuleBottomThermalResistance_ =
+          workspaceObject.getDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::PVModuleBottomThermalResistance)) {
+      modelObject.setPVModuleBottomThermalResistance(pVModuleBottomThermalResistance_.get());
+    }
+
+    // PV Module Front Longwave Emissivity: Optional Double
+    if (boost::optional<double> pVModuleFrontLongwaveEmissivity_ =
+          workspaceObject.getDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::PVModuleFrontLongwaveEmissivity)) {
+      modelObject.setPVModuleFrontLongwaveEmissivity(pVModuleFrontLongwaveEmissivity_.get());
+    }
+
+    // PV Module Back Longwave Emissivity: Optional Double
+    if (boost::optional<double> pVModuleBackLongwaveEmissivity_ =
+          workspaceObject.getDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::PVModuleBackLongwaveEmissivity)) {
+      modelObject.setPVModuleBackLongwaveEmissivity(pVModuleBackLongwaveEmissivity_.get());
+    }
+
+    // Glass Thickness: Optional Double
+    if (boost::optional<double> glassThickness_ =
+          workspaceObject.getDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::GlassThickness)) {
+      modelObject.setGlassThickness(glassThickness_.get());
+    }
+
+    // Glass Refraction Index: Optional Double
+    if (boost::optional<double> glassRefractionIndex_ =
+          workspaceObject.getDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::GlassRefractionIndex)) {
+      modelObject.setGlassRefractionIndex(glassRefractionIndex_.get());
+    }
+
+    // Glass Extinction Coefficient: Optional Double
+    if (boost::optional<double> glassExtinctionCoefficient_ =
+          workspaceObject.getDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::GlassExtinctionCoefficient)) {
+      modelObject.setGlassExtinctionCoefficient(glassExtinctionCoefficient_.get());
+    }
+
+    return modelObject;
+  }  // End of translate function
+
+}  // end namespace energyplus
+}  // end namespace openstudio
diff --git a/src/energyplus/ReverseTranslator/ReverseTranslateSurfacePropertyOtherSideConditionsModel.cpp b/src/energyplus/ReverseTranslator/ReverseTranslateSurfacePropertyOtherSideConditionsModel.cpp
new file mode 100644
index 00000000000..a3713b724af
--- /dev/null
+++ b/src/energyplus/ReverseTranslator/ReverseTranslateSurfacePropertyOtherSideConditionsModel.cpp
@@ -0,0 +1,61 @@
+/***********************************************************************************************************************
+*  OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved.
+*
+*  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+*  following conditions are met:
+*
+*  (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+*  disclaimer.
+*
+*  (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+*  disclaimer in the documentation and/or other materials provided with the distribution.
+*
+*  (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products
+*  derived from this software without specific prior written permission from the respective party.
+*
+*  (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works
+*  may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior
+*  written permission from Alliance for Sustainable Energy, LLC.
+*
+*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+*  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED
+*  STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+*  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+*  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+*  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+*  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************************************************************/
+
+#include "../ReverseTranslator.hpp"
+
+#include "../../model/SurfacePropertyOtherSideConditionsModel.hpp"
+
+#include <utilities/idd/SurfaceProperty_OtherSideConditionsModel_FieldEnums.hxx>
+#include <utilities/idd/IddEnums.hxx>
+
+using namespace openstudio::model;
+
+namespace openstudio {
+
+namespace energyplus {
+
+  boost::optional<ModelObject> ReverseTranslator::translateSurfacePropertyOtherSideConditionsModel(const WorkspaceObject& workspaceObject) {
+
+    openstudio::model::SurfacePropertyOtherSideConditionsModel modelObject(m_model);
+
+    // Name
+    if (boost::optional<std::string> name_ = workspaceObject.name()) {
+      modelObject.setName(name_.get());
+    }
+
+    // Type of Modeling: Optional String
+    if (boost::optional<std::string> typeofModeling_ = workspaceObject.getString(SurfaceProperty_OtherSideConditionsModelFields::TypeofModeling)) {
+      modelObject.setTypeOfModeling(typeofModeling_.get());
+    }
+
+    return modelObject;
+  }  // End of translate function
+
+}  // end namespace energyplus
+}  // end namespace openstudio
diff --git a/src/energyplus/Test/SolarCollectorPerformancePhotovoltaicThermalBIPVT_GTest.cpp b/src/energyplus/Test/SolarCollectorPerformancePhotovoltaicThermalBIPVT_GTest.cpp
new file mode 100644
index 00000000000..5e0c6fade8a
--- /dev/null
+++ b/src/energyplus/Test/SolarCollectorPerformancePhotovoltaicThermalBIPVT_GTest.cpp
@@ -0,0 +1,234 @@
+/***********************************************************************************************************************
+*  OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved.
+*
+*  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+*  following conditions are met:
+*
+*  (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+*  disclaimer.
+*
+*  (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+*  disclaimer in the documentation and/or other materials provided with the distribution.
+*
+*  (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products
+*  derived from this software without specific prior written permission from the respective party.
+*
+*  (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works
+*  may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior
+*  written permission from Alliance for Sustainable Energy, LLC.
+*
+*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+*  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED
+*  STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+*  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+*  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+*  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+*  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************************************************************/
+#include <gtest/gtest.h>
+#include "EnergyPlusFixture.hpp"
+
+#include "../ForwardTranslator.hpp"
+#include "../ReverseTranslator.hpp"
+
+#include "../../model/SolarCollectorPerformancePhotovoltaicThermalBIPVT.hpp"
+#include "../../model/SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl.hpp"
+#include "../../model/SolarCollectorFlatPlatePhotovoltaicThermal.hpp"
+#include "../../model/SurfacePropertyOtherSideConditionsModel.hpp"
+#include "../../model/SurfacePropertyOtherSideConditionsModel_Impl.hpp"
+#include "../../model/PlantLoop.hpp"
+#include "../../model/GeneratorPhotovoltaic.hpp"
+#include "../../model/ElectricLoadCenterDistribution.hpp"
+#include "../../model/ElectricLoadCenterInverterSimple.hpp"
+#include "../../model/Schedule.hpp"
+#include "../../model/ScheduleConstant.hpp"
+#include "../../model/ScheduleConstant_Impl.hpp"
+#include "../../model/Space.hpp"
+#include "../../model/Surface.hpp"
+#include "../../model/ThermalZone.hpp"
+#include "../../model/Model.hpp"
+
+#include "../../utilities/geometry/Point3d.hpp"
+#include "../../utilities/idf/Workspace.hpp"
+#include "../../utilities/idf/IdfObject.hpp"
+#include "../../utilities/idf/WorkspaceObject.hpp"
+
+// E+ FieldEnums
+#include <utilities/idd/IddEnums.hxx>
+#include <utilities/idd/IddFactory.hxx>
+
+#include <utilities/idd/SolarCollectorPerformance_PhotovoltaicThermal_BIPVT_FieldEnums.hxx>
+#include <utilities/idd/SolarCollector_FlatPlate_PhotovoltaicThermal_FieldEnums.hxx>
+
+#include <vector>
+
+using namespace openstudio::energyplus;
+using namespace openstudio::model;
+using namespace openstudio;
+
+TEST_F(EnergyPlusFixture, ForwardTranslator_SolarCollectorPerformancePhotovoltaicThermalBIPVT) {
+
+  ForwardTranslator ft;
+
+  Model m;
+
+  SolarCollectorPerformancePhotovoltaicThermalBIPVT performance(m);
+  performance.setName("BIPVT Perf");
+  SolarCollectorFlatPlatePhotovoltaicThermal pvt(performance);
+
+  PlantLoop p(m);
+  p.addSupplyBranchForComponent(pvt);
+
+  // Make a ShadingSurface, and a ShadingSurfaceGroup as it's needed
+  GeneratorPhotovoltaic panel = GeneratorPhotovoltaic::equivalentOneDiode(m);
+  panel.setHeatTransferIntegrationMode("PhotovoltaicThermalSolarCollector");
+  panel.setNumberOfModulesInParallel(12);
+  panel.setNumberOfModulesInSeries(8);
+  panel.setRatedElectricPowerOutput(9000);
+  auto alwaysOn = m.alwaysOnDiscreteSchedule();
+  panel.setAvailabilitySchedule(alwaysOn);
+
+  ElectricLoadCenterInverterSimple inverter(m);
+  ElectricLoadCenterDistribution elcd(m);
+  EXPECT_TRUE(elcd.addGenerator(panel));
+  EXPECT_TRUE(elcd.setInverter(inverter));
+
+  constexpr double width = 10.0;
+  constexpr double height = 3.0;
+
+  // Counterclockwise points
+  const std::vector<Point3d> floorPointsSpace1{{0.0, 0.0, 0.0}, {0.0, width, 0.0}, {width, width, 0.0}, {width, 0.0, 0.0}};
+
+  auto space = Space::fromFloorPrint(floorPointsSpace1, height, m).get();
+
+  auto roof = [&space]() -> Surface {
+    auto sfs = space.surfaces();
+    auto it = std::find_if(sfs.cbegin(), sfs.cend(), [](const auto& s) { return s.surfaceType() == "RoofCeiling"; });
+    OS_ASSERT(it != sfs.cend());
+    return *it;
+  }();
+
+  EXPECT_TRUE(panel.setSurface(roof));
+  EXPECT_TRUE(pvt.setSurface(roof));
+  EXPECT_TRUE(pvt.setGeneratorPhotovoltaic(panel));
+  EXPECT_TRUE(roof.setSurfacePropertyOtherSideConditionsModel(performance.boundaryConditionsModel()));
+
+  ThermalZone z(m);
+  EXPECT_TRUE(space.setThermalZone(z));
+
+  EXPECT_TRUE(performance.setEffectivePlenumGapThicknessBehindPVModules(0.5));
+
+  SurfacePropertyOtherSideConditionsModel oscm = performance.boundaryConditionsModel();
+  oscm.setName("BIPVT OtherSideConditionsModel");
+
+  ScheduleConstant availSch(m);
+  availSch.setName("BIPV AvailabilitySchedule");
+
+  EXPECT_TRUE(performance.setEffectivePlenumGapThicknessBehindPVModules(0.5));
+  EXPECT_TRUE(performance.setPVCellNormalTransmittanceAbsorptanceProduct(0.81));
+  EXPECT_TRUE(performance.setBackingMaterialNormalTransmittanceAbsorptanceProduct(0.82));
+  EXPECT_TRUE(performance.setCladdingNormalTransmittanceAbsorptanceProduct(0.83));
+  EXPECT_TRUE(performance.setFractionofCollectorGrossAreaCoveredbyPVModule(0.84));
+  EXPECT_TRUE(performance.setFractionofPVCellAreatoPVModuleArea(0.75));
+  EXPECT_TRUE(performance.setPVModuleTopThermalResistance(0.0054));
+  EXPECT_TRUE(performance.setPVModuleBottomThermalResistance(0.0049));
+  EXPECT_TRUE(performance.setPVModuleFrontLongwaveEmissivity(0.89));
+  EXPECT_TRUE(performance.setPVModuleBackLongwaveEmissivity(0.92));
+  EXPECT_TRUE(performance.setGlassThickness(0.009));
+  EXPECT_TRUE(performance.setGlassRefractionIndex(1.586));
+  EXPECT_TRUE(performance.setGlassExtinctionCoefficient(5.0));
+
+  const Workspace w = ft.translateModel(m);
+  const auto idfObjs = w.getObjectsByType(IddObjectType::SolarCollectorPerformance_PhotovoltaicThermal_BIPVT);
+  ASSERT_EQ(1u, idfObjs.size());
+
+  const auto& idfObject = idfObjs.front();
+  EXPECT_EQ("BIPVT Perf", idfObject.getString(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::Name).get());
+  EXPECT_EQ("BIPVT OtherSideConditionsModel",
+            idfObject.getString(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::BoundaryConditionsModelName).get());
+  EXPECT_EQ("Always On Discrete", idfObject.getString(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::AvailabilityScheduleName).get());
+  EXPECT_EQ(0.5, idfObject.getDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::EffectivePlenumGapThicknessBehindPVModules).get());
+  EXPECT_EQ(0.81, idfObject.getDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::PVCellNormalTransmittanceAbsorptanceProduct).get());
+  EXPECT_EQ(
+    0.82, idfObject.getDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::BackingMaterialNormalTransmittanceAbsorptanceProduct).get());
+  EXPECT_EQ(0.83,
+            idfObject.getDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::CladdingNormalTransmittanceAbsorptanceProduct).get());
+  EXPECT_EQ(0.84,
+            idfObject.getDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::FractionofCollectorGrossAreaCoveredbyPVModule).get());
+  EXPECT_EQ(0.75, idfObject.getDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::FractionofPVCellAreatoPVModuleArea).get());
+  EXPECT_EQ(0.0054, idfObject.getDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::PVModuleTopThermalResistance).get());
+  EXPECT_EQ(0.0049, idfObject.getDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::PVModuleBottomThermalResistance).get());
+  EXPECT_EQ(0.89, idfObject.getDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::PVModuleFrontLongwaveEmissivity).get());
+  EXPECT_EQ(0.92, idfObject.getDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::PVModuleBackLongwaveEmissivity).get());
+  EXPECT_EQ(0.009, idfObject.getDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::GlassThickness).get());
+  EXPECT_EQ(1.586, idfObject.getDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::GlassRefractionIndex).get());
+  EXPECT_EQ(5.0, idfObject.getDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::GlassExtinctionCoefficient).get());
+
+  const auto pvtObjs = w.getObjectsByType(IddObjectType::SolarCollector_FlatPlate_PhotovoltaicThermal);
+  ASSERT_EQ(1u, pvtObjs.size());
+  const auto& pvtObj = pvtObjs.front();
+  EXPECT_EQ("BIPVT Perf", pvtObj.getString(SolarCollector_FlatPlate_PhotovoltaicThermalFields::PhotovoltaicThermalModelPerformanceName).get());
+}
+
+TEST_F(EnergyPlusFixture, ReverseTranslator_SolarCollectorPerformancePhotovoltaicThermalBIPVT) {
+
+  ReverseTranslator rt;
+
+  Workspace w(StrictnessLevel::Minimal, IddFileType::EnergyPlus);
+
+  auto woPerf = w.addObject(IdfObject(IddObjectType::SolarCollectorPerformance_PhotovoltaicThermal_BIPVT)).get();
+  woPerf.setName("BIPVT Perf");
+
+  auto woBoundaryCond = w.addObject(IdfObject(IddObjectType::SurfaceProperty_OtherSideConditionsModel)).get();
+  woBoundaryCond.setName("BIPVT OtherSideConditionsModel");
+  EXPECT_TRUE(woPerf.setPointer(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::BoundaryConditionsModelName, woBoundaryCond.handle()));
+
+  auto woAvailSch = w.addObject(IdfObject(IddObjectType::Schedule_Constant)).get();
+  woAvailSch.setName("BIPVT AvailabilitySchedule");
+  EXPECT_TRUE(woPerf.setPointer(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::AvailabilityScheduleName, woAvailSch.handle()));
+
+  EXPECT_TRUE(woPerf.setDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::EffectivePlenumGapThicknessBehindPVModules, 0.5));
+  EXPECT_TRUE(woPerf.setDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::PVCellNormalTransmittanceAbsorptanceProduct, 0.81));
+  EXPECT_TRUE(
+    woPerf.setDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::BackingMaterialNormalTransmittanceAbsorptanceProduct, 0.82));
+  EXPECT_TRUE(woPerf.setDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::CladdingNormalTransmittanceAbsorptanceProduct, 0.83));
+  EXPECT_TRUE(woPerf.setDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::FractionofCollectorGrossAreaCoveredbyPVModule, 0.84));
+  EXPECT_TRUE(woPerf.setDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::FractionofPVCellAreatoPVModuleArea, 0.75));
+  EXPECT_TRUE(woPerf.setDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::PVModuleTopThermalResistance, 0.0054));
+  EXPECT_TRUE(woPerf.setDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::PVModuleBottomThermalResistance, 0.0049));
+  EXPECT_TRUE(woPerf.setDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::PVModuleFrontLongwaveEmissivity, 0.89));
+  EXPECT_TRUE(woPerf.setDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::PVModuleBackLongwaveEmissivity, 0.92));
+  EXPECT_TRUE(woPerf.setDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::GlassThickness, 0.009));
+  EXPECT_TRUE(woPerf.setDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::GlassRefractionIndex, 1.586));
+  EXPECT_TRUE(woPerf.setDouble(SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::GlassExtinctionCoefficient, 5.0));
+
+  const Model m = rt.translateWorkspace(w);
+
+  const auto perfs = m.getConcreteModelObjects<SolarCollectorPerformancePhotovoltaicThermalBIPVT>();
+  ASSERT_EQ(1, perfs.size());
+  const auto& perf = perfs.front();
+
+  EXPECT_EQ("BIPVT Perf", perf.nameString());
+
+  ASSERT_EQ(1, m.getConcreteModelObjects<SurfacePropertyOtherSideConditionsModel>().size());
+  ASSERT_TRUE(perf.boundaryConditionsModel().optionalCast<SurfacePropertyOtherSideConditionsModel>());
+  EXPECT_EQ("BIPVT OtherSideConditionsModel", perf.boundaryConditionsModel().nameString());
+
+  ASSERT_TRUE(perf.availabilitySchedule().optionalCast<ScheduleConstant>());
+  EXPECT_EQ("BIPVT AvailabilitySchedule", perf.availabilitySchedule().nameString());
+
+  EXPECT_EQ(0.5, perf.effectivePlenumGapThicknessBehindPVModules());
+  EXPECT_EQ(0.81, perf.pVCellNormalTransmittanceAbsorptanceProduct());
+  EXPECT_EQ(0.82, perf.backingMaterialNormalTransmittanceAbsorptanceProduct());
+  EXPECT_EQ(0.83, perf.claddingNormalTransmittanceAbsorptanceProduct());
+  EXPECT_EQ(0.84, perf.fractionofCollectorGrossAreaCoveredbyPVModule());
+  EXPECT_EQ(0.75, perf.fractionofPVCellAreatoPVModuleArea());
+  EXPECT_EQ(0.0054, perf.pVModuleTopThermalResistance());
+  EXPECT_EQ(0.0049, perf.pVModuleBottomThermalResistance());
+  EXPECT_EQ(0.89, perf.pVModuleFrontLongwaveEmissivity());
+  EXPECT_EQ(0.92, perf.pVModuleBackLongwaveEmissivity());
+  EXPECT_EQ(0.009, perf.glassThickness());
+  EXPECT_EQ(1.586, perf.glassRefractionIndex());
+  EXPECT_EQ(5.0, perf.glassExtinctionCoefficient());
+}
diff --git a/src/energyplus/Test/SurfacePropertyOtherSideConditionsModel_GTest.cpp b/src/energyplus/Test/SurfacePropertyOtherSideConditionsModel_GTest.cpp
new file mode 100644
index 00000000000..52cbae68fc1
--- /dev/null
+++ b/src/energyplus/Test/SurfacePropertyOtherSideConditionsModel_GTest.cpp
@@ -0,0 +1,121 @@
+/***********************************************************************************************************************
+*  OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved.
+*
+*  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+*  following conditions are met:
+*
+*  (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+*  disclaimer.
+*
+*  (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+*  disclaimer in the documentation and/or other materials provided with the distribution.
+*
+*  (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products
+*  derived from this software without specific prior written permission from the respective party.
+*
+*  (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works
+*  may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior
+*  written permission from Alliance for Sustainable Energy, LLC.
+*
+*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+*  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED
+*  STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+*  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+*  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+*  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+*  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************************************************************/
+
+#include <gtest/gtest.h>
+#include "EnergyPlusFixture.hpp"
+
+#include "../ErrorFile.hpp"
+#include "../ForwardTranslator.hpp"
+#include "../ReverseTranslator.hpp"
+
+#include "../../model/SurfacePropertyOtherSideConditionsModel.hpp"
+#include "../../model/SurfacePropertyOtherSideConditionsModel_Impl.hpp"
+#include "../../model/Space.hpp"
+#include "../../model/Surface.hpp"
+#include "../../model/ThermalZone.hpp"
+#include "../../model/Model.hpp"
+
+#include "../../utilities/geometry/Point3d.hpp"
+#include "../../utilities/idf/Workspace.hpp"
+#include "../../utilities/idf/IdfObject.hpp"
+#include "../../utilities/idf/WorkspaceObject.hpp"
+
+// E+ FieldEnums
+#include <utilities/idd/IddEnums.hxx>
+#include <utilities/idd/IddFactory.hxx>
+
+#include <utilities/idd/SurfaceProperty_OtherSideConditionsModel_FieldEnums.hxx>
+
+using namespace openstudio::energyplus;
+using namespace openstudio::model;
+using namespace openstudio;
+
+TEST_F(EnergyPlusFixture, ForwardTranslator_SurfacePropertyOtherSideConditionsModel) {
+
+  ForwardTranslator ft;
+
+  Model m;
+
+  SurfacePropertyOtherSideConditionsModel oscms(m);
+  oscms.setName("My Props");
+  EXPECT_TRUE(oscms.setTypeOfModeling("GroundCoupledSurface"));
+
+  // Not used = not translated
+  {
+    const Workspace w = ft.translateModel(m);
+    EXPECT_EQ(0u, w.getObjectsByType(IddObjectType::SurfaceProperty_OtherSideConditionsModel).size());
+  }
+
+  constexpr double width = 10.0;
+  constexpr double height = 3.0;
+  // Counterclockwise points
+  const std::vector<Point3d> floorPointsSpace1{{0.0, 0.0, 0.0}, {0.0, width, 0.0}, {width, width, 0.0}, {width, 0.0, 0.0}};
+
+  auto space = Space::fromFloorPrint(floorPointsSpace1, height, m).get();
+  ThermalZone z(m);
+  EXPECT_TRUE(space.setThermalZone(z));
+  auto roof = [&space]() -> Surface {
+    auto sfs = space.surfaces();
+    auto it = std::find_if(sfs.cbegin(), sfs.cend(), [](const auto& s) { return s.surfaceType() == "RoofCeiling"; });
+    OS_ASSERT(it != sfs.cend());
+    return *it;
+  }();
+
+  roof.setSurfacePropertyOtherSideConditionsModel(oscms);
+
+  {
+    const Workspace w = ft.translateModel(m);
+    const auto idfObjs = w.getObjectsByType(IddObjectType::SurfaceProperty_OtherSideConditionsModel);
+    ASSERT_EQ(1u, idfObjs.size());
+    const auto& idfObject = idfObjs.front();
+
+    EXPECT_EQ("My Props", idfObject.getString(SurfaceProperty_OtherSideConditionsModelFields::Name).get());
+    EXPECT_EQ("GroundCoupledSurface", idfObject.getString(SurfaceProperty_OtherSideConditionsModelFields::TypeofModeling).get());
+  }
+}
+
+TEST_F(EnergyPlusFixture, ReverseTranslator_SurfacePropertyOtherSideConditionsModel) {
+
+  ReverseTranslator rt;
+
+  Workspace w(StrictnessLevel::Minimal, IddFileType::EnergyPlus);
+
+  auto woProps = w.addObject(IdfObject(IddObjectType::SurfaceProperty_OtherSideConditionsModel)).get();
+  woProps.setName("My Props");
+  EXPECT_TRUE(woProps.setString(SurfaceProperty_OtherSideConditionsModelFields::TypeofModeling, "GroundCoupledSurface"));
+
+  const Model m = rt.translateWorkspace(w);
+
+  const auto oscms = m.getConcreteModelObjects<SurfacePropertyOtherSideConditionsModel>();
+  ASSERT_EQ(1, oscms.size());
+  const auto& oscm = oscms.front();
+
+  EXPECT_EQ("My Props", oscm.nameString());
+  EXPECT_EQ("GroundCoupledSurface", oscm.typeOfModeling());
+}
diff --git a/src/model/CMakeLists.txt b/src/model/CMakeLists.txt
index ea16d159bf9..7fa2e9b0a4f 100644
--- a/src/model/CMakeLists.txt
+++ b/src/model/CMakeLists.txt
@@ -1495,6 +1495,9 @@ set(${target_name}_src
   SolarCollectorPerformanceIntegralCollectorStorage.hpp
   SolarCollectorPerformanceIntegralCollectorStorage_Impl.hpp
   SolarCollectorPerformanceIntegralCollectorStorage.cpp
+  SolarCollectorPerformancePhotovoltaicThermalBIPVT.hpp
+  SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl.hpp
+  SolarCollectorPerformancePhotovoltaicThermalBIPVT.cpp
   SolarCollectorPerformancePhotovoltaicThermalSimple.hpp
   SolarCollectorPerformancePhotovoltaicThermalSimple_Impl.hpp
   SolarCollectorPerformancePhotovoltaicThermalSimple.cpp
@@ -2277,6 +2280,7 @@ set(${target_name}_test_src
   test/SolarCollectorFlatPlatePhotovoltaicThermal_GTest.cpp
   test/SolarCollectorFlatPlateWater_GTest.cpp
   test/SolarCollectorIntegralCollectorStorage_GTest.cpp
+  test/SolarCollectorPerformancePhotovoltaicThermalBIPVT_GTest.cpp
   test/SpaceInfiltrationDesignFlowRate_GTest.cpp
   test/SpaceInfiltrationEffectiveLeakageArea_GTest.cpp
   test/SpaceInfiltrationFlowCoefficient_GTest.cpp
diff --git a/src/model/ConcreteModelObjects.hpp b/src/model/ConcreteModelObjects.hpp
index 1d362b0de3e..28155acca11 100644
--- a/src/model/ConcreteModelObjects.hpp
+++ b/src/model/ConcreteModelObjects.hpp
@@ -480,6 +480,7 @@
 #include "SolarCollectorIntegralCollectorStorage.hpp"
 #include "SolarCollectorPerformanceFlatPlate.hpp"
 #include "SolarCollectorPerformanceIntegralCollectorStorage.hpp"
+#include "SolarCollectorPerformancePhotovoltaicThermalBIPVT.hpp"
 #include "SolarCollectorPerformancePhotovoltaicThermalSimple.hpp"
 #include "Space.hpp"
 #include "SpaceInfiltrationDesignFlowRate.hpp"
@@ -1026,6 +1027,7 @@
 #include "SolarCollectorIntegralCollectorStorage_Impl.hpp"
 #include "SolarCollectorPerformanceFlatPlate_Impl.hpp"
 #include "SolarCollectorPerformanceIntegralCollectorStorage_Impl.hpp"
+#include "SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl.hpp"
 #include "SolarCollectorPerformancePhotovoltaicThermalSimple_Impl.hpp"
 #include "Space_Impl.hpp"
 #include "SpaceInfiltrationDesignFlowRate_Impl.hpp"
diff --git a/src/model/Model.cpp b/src/model/Model.cpp
index 097e802b45c..610c1232284 100644
--- a/src/model/Model.cpp
+++ b/src/model/Model.cpp
@@ -4274,6 +4274,7 @@ namespace model {
     REGISTER_CONSTRUCTOR(SolarCollectorIntegralCollectorStorage);
     REGISTER_CONSTRUCTOR(SolarCollectorPerformanceFlatPlate);
     REGISTER_CONSTRUCTOR(SolarCollectorPerformanceIntegralCollectorStorage);
+    REGISTER_CONSTRUCTOR(SolarCollectorPerformancePhotovoltaicThermalBIPVT);
     REGISTER_CONSTRUCTOR(SolarCollectorPerformancePhotovoltaicThermalSimple);
     REGISTER_CONSTRUCTOR(Space);
     REGISTER_CONSTRUCTOR(SpaceInfiltrationDesignFlowRate);
@@ -4840,6 +4841,7 @@ namespace model {
     REGISTER_COPYCONSTRUCTORS(SolarCollectorIntegralCollectorStorage);
     REGISTER_COPYCONSTRUCTORS(SolarCollectorPerformanceFlatPlate);
     REGISTER_COPYCONSTRUCTORS(SolarCollectorPerformanceIntegralCollectorStorage);
+    REGISTER_COPYCONSTRUCTORS(SolarCollectorPerformancePhotovoltaicThermalBIPVT);
     REGISTER_COPYCONSTRUCTORS(SolarCollectorPerformancePhotovoltaicThermalSimple);
     REGISTER_COPYCONSTRUCTORS(Space);
     REGISTER_COPYCONSTRUCTORS(SpaceInfiltrationDesignFlowRate);
diff --git a/src/model/ModelHVAC.i b/src/model/ModelHVAC.i
index 8d932a5967e..eb1db772c24 100644
--- a/src/model/ModelHVAC.i
+++ b/src/model/ModelHVAC.i
@@ -221,6 +221,7 @@ MODELOBJECT_TEMPLATES(ChillerAbsorptionIndirect);
 MODELOBJECT_TEMPLATES(ChillerAbsorption);
 MODELOBJECT_TEMPLATES(SolarCollectorPerformanceFlatPlate);
 MODELOBJECT_TEMPLATES(SolarCollectorPerformanceIntegralCollectorStorage);
+MODELOBJECT_TEMPLATES(SolarCollectorPerformancePhotovoltaicThermalBIPVT);
 MODELOBJECT_TEMPLATES(SolarCollectorPerformancePhotovoltaicThermalSimple);
 MODELOBJECT_TEMPLATES(SwimmingPoolIndoor);
 
@@ -349,6 +350,7 @@ SWIG_MODELOBJECT(ChillerAbsorptionIndirect, 1);
 SWIG_MODELOBJECT(ChillerAbsorption, 1);
 SWIG_MODELOBJECT(SolarCollectorPerformanceFlatPlate, 1);
 SWIG_MODELOBJECT(SolarCollectorPerformanceIntegralCollectorStorage, 1);
+SWIG_MODELOBJECT(SolarCollectorPerformancePhotovoltaicThermalBIPVT, 1);
 SWIG_MODELOBJECT(SolarCollectorPerformancePhotovoltaicThermalSimple, 1);
 SWIG_MODELOBJECT(SwimmingPoolIndoor,1);
 
diff --git a/src/model/ScheduleTypeRegistry.cpp b/src/model/ScheduleTypeRegistry.cpp
index ad90489214e..54fda414008 100644
--- a/src/model/ScheduleTypeRegistry.cpp
+++ b/src/model/ScheduleTypeRegistry.cpp
@@ -390,6 +390,7 @@ namespace model {
       {"SizingZone", "Zone Humidistat Dehumidification Set Point", "zoneHumidistatDehumidificationSetPointSchedule", true, "Percent", 0.0, 100.0},
       {"SizingZone", "Zone Humidistat Humidification Set Point", "zoneHumidistatHumidificationSetPointSchedule", true, "Percent", 0.0, 100.0},
       {"SurfaceControlMovableInsulation", "Resistance Modifier Fraction", "schedule", true, "", 0.0, 1.0},
+      {"SolarCollectorPerformancePhotovoltaicThermalBIPVT", "Availability", "availabilitySchedule", false, "Availability", 0.0, 1.0},
       {"SolarCollectorPerformancePhotovoltaicThermalSimple", "Thermal Conversion Efficiency", "thermalConversionEfficiencySchedule", true, "", 0.0,
        1.0},
       {"SurfacePropertyConvectionCoefficients", "Convection Coefficient 1", "convectionCoefficient1Schedule", true, "", 0.1, 1000},
diff --git a/src/model/SolarCollectorFlatPlatePhotovoltaicThermal.cpp b/src/model/SolarCollectorFlatPlatePhotovoltaicThermal.cpp
index c4f119a5c0e..e12f4ea400d 100644
--- a/src/model/SolarCollectorFlatPlatePhotovoltaicThermal.cpp
+++ b/src/model/SolarCollectorFlatPlatePhotovoltaicThermal.cpp
@@ -36,6 +36,8 @@
 #include "Surface_Impl.hpp"
 #include "ShadingSurface.hpp"
 #include "ShadingSurface_Impl.hpp"
+#include "SolarCollectorPerformancePhotovoltaicThermalBIPVT.hpp"
+#include "SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl.hpp"
 #include "SolarCollectorPerformancePhotovoltaicThermalSimple.hpp"
 #include "SolarCollectorPerformancePhotovoltaicThermalSimple_Impl.hpp"
 #include "Node.hpp"
@@ -110,8 +112,7 @@ namespace model {
     std::vector<ModelObject> SolarCollectorFlatPlatePhotovoltaicThermal_Impl::children() const {
       std::vector<ModelObject> result;
 
-      SolarCollectorPerformancePhotovoltaicThermalSimple solarCollectorPerformance = this->solarCollectorPerformance();
-      result.push_back(solarCollectorPerformance);
+      result.push_back(this->solarCollectorPerformance());
 
       return result;
     }
@@ -145,10 +146,9 @@ namespace model {
       return false;
     }
 
-    SolarCollectorPerformancePhotovoltaicThermalSimple SolarCollectorFlatPlatePhotovoltaicThermal_Impl::solarCollectorPerformance() const {
-      boost::optional<SolarCollectorPerformancePhotovoltaicThermalSimple> value =
-        getObject<ModelObject>().getModelObjectTarget<SolarCollectorPerformancePhotovoltaicThermalSimple>(
-          OS_SolarCollector_FlatPlate_PhotovoltaicThermalFields::PhotovoltaicThermalModelPerformanceName);
+    ModelObject SolarCollectorFlatPlatePhotovoltaicThermal_Impl::solarCollectorPerformance() const {
+      boost::optional<ModelObject> value = getObject<ModelObject>().getModelObjectTarget<ModelObject>(
+        OS_SolarCollector_FlatPlate_PhotovoltaicThermalFields::PhotovoltaicThermalModelPerformanceName);
       if (!value) {
         // DLM: could default construct one here?
         LOG_AND_THROW(briefDescription() << " does not have an Solar Collector Performance attached.");
@@ -178,15 +178,34 @@ namespace model {
       return result;
     }
 
+    bool SolarCollectorFlatPlatePhotovoltaicThermal_Impl::setSolarCollectorPerformance(
+      const SolarCollectorPerformancePhotovoltaicThermalBIPVT& performance) {
+      bool result(false);
+      auto current = this->solarCollectorPerformance();
+      if (current.handle() == performance.handle()) {
+        return true;  // no-op
+      }
+      ModelObject clone = performance.clone(this->model());
+      result = setSolarCollectorPerformanceNoClone(clone);
+      if (result) {
+        current.remove();
+      } else {
+        result = setSolarCollectorPerformanceNoClone(current);
+        OS_ASSERT(result);
+        return false;
+      }
+      return result;
+    }
+
     bool SolarCollectorFlatPlatePhotovoltaicThermal_Impl::setSolarCollectorPerformance(
       const SolarCollectorPerformancePhotovoltaicThermalSimple& performance) {
       bool result(false);
-      SolarCollectorPerformancePhotovoltaicThermalSimple current = this->solarCollectorPerformance();
+      auto current = this->solarCollectorPerformance();
       if (current.handle() == performance.handle()) {
         return true;  // no-op
       }
       ModelObject clone = performance.clone(this->model());
-      result = setSolarCollectorPerformanceNoClone(clone.cast<SolarCollectorPerformancePhotovoltaicThermalSimple>());
+      result = setSolarCollectorPerformanceNoClone(clone);
       if (result) {
         current.remove();
       } else {
@@ -253,8 +272,7 @@ namespace model {
       OS_ASSERT(result);
     }
 
-    bool SolarCollectorFlatPlatePhotovoltaicThermal_Impl::setSolarCollectorPerformanceNoClone(
-      const SolarCollectorPerformancePhotovoltaicThermalSimple& performance) {
+    bool SolarCollectorFlatPlatePhotovoltaicThermal_Impl::setSolarCollectorPerformanceNoClone(const ModelObject& performance) {
       return setPointer(OS_SolarCollector_FlatPlate_PhotovoltaicThermalFields::PhotovoltaicThermalModelPerformanceName, performance.handle());
     }
 
@@ -282,8 +300,25 @@ namespace model {
 
     SolarCollectorPerformancePhotovoltaicThermalSimple performance(model);
 
-    bool ok = true;
-    ok = getImpl<detail::SolarCollectorFlatPlatePhotovoltaicThermal_Impl>()->setSolarCollectorPerformanceNoClone(performance);
+    const bool ok = getImpl<detail::SolarCollectorFlatPlatePhotovoltaicThermal_Impl>()->setSolarCollectorPerformanceNoClone(performance);
+    OS_ASSERT(ok);
+  }
+
+  SolarCollectorFlatPlatePhotovoltaicThermal::SolarCollectorFlatPlatePhotovoltaicThermal(
+    const SolarCollectorPerformancePhotovoltaicThermalBIPVT& performance)
+    : StraightComponent(SolarCollectorFlatPlatePhotovoltaicThermal::iddObjectType(), performance.model()) {
+    OS_ASSERT(getImpl<detail::SolarCollectorFlatPlatePhotovoltaicThermal_Impl>());
+
+    const bool ok = getImpl<detail::SolarCollectorFlatPlatePhotovoltaicThermal_Impl>()->setSolarCollectorPerformanceNoClone(performance);
+    OS_ASSERT(ok);
+  }
+
+  SolarCollectorFlatPlatePhotovoltaicThermal::SolarCollectorFlatPlatePhotovoltaicThermal(
+    const SolarCollectorPerformancePhotovoltaicThermalSimple& performance)
+    : StraightComponent(SolarCollectorFlatPlatePhotovoltaicThermal::iddObjectType(), performance.model()) {
+    OS_ASSERT(getImpl<detail::SolarCollectorFlatPlatePhotovoltaicThermal_Impl>());
+
+    const bool ok = getImpl<detail::SolarCollectorFlatPlatePhotovoltaicThermal_Impl>()->setSolarCollectorPerformanceNoClone(performance);
     OS_ASSERT(ok);
   }
 
@@ -291,7 +326,7 @@ namespace model {
     return {IddObjectType::OS_SolarCollector_FlatPlate_PhotovoltaicThermal};
   }
 
-  SolarCollectorPerformancePhotovoltaicThermalSimple SolarCollectorFlatPlatePhotovoltaicThermal::solarCollectorPerformance() const {
+  ModelObject SolarCollectorFlatPlatePhotovoltaicThermal::solarCollectorPerformance() const {
     return getImpl<detail::SolarCollectorFlatPlatePhotovoltaicThermal_Impl>()->solarCollectorPerformance();
   }
 
@@ -327,6 +362,11 @@ namespace model {
     getImpl<detail::SolarCollectorFlatPlatePhotovoltaicThermal_Impl>()->resetGeneratorPhotovoltaic();
   }
 
+  bool
+    SolarCollectorFlatPlatePhotovoltaicThermal::setSolarCollectorPerformance(const SolarCollectorPerformancePhotovoltaicThermalBIPVT& performance) {
+    return getImpl<detail::SolarCollectorFlatPlatePhotovoltaicThermal_Impl>()->setSolarCollectorPerformance(performance);
+  }
+
   bool
     SolarCollectorFlatPlatePhotovoltaicThermal::setSolarCollectorPerformance(const SolarCollectorPerformancePhotovoltaicThermalSimple& performance) {
     return getImpl<detail::SolarCollectorFlatPlatePhotovoltaicThermal_Impl>()->setSolarCollectorPerformance(performance);
diff --git a/src/model/SolarCollectorFlatPlatePhotovoltaicThermal.hpp b/src/model/SolarCollectorFlatPlatePhotovoltaicThermal.hpp
index b1103d07334..83eb5b21da1 100644
--- a/src/model/SolarCollectorFlatPlatePhotovoltaicThermal.hpp
+++ b/src/model/SolarCollectorFlatPlatePhotovoltaicThermal.hpp
@@ -39,6 +39,7 @@ namespace model {
 
   class PlanarSurface;
   class GeneratorPhotovoltaic;
+  class SolarCollectorPerformancePhotovoltaicThermalBIPVT;
   class SolarCollectorPerformancePhotovoltaicThermalSimple;
 
   namespace detail {
@@ -55,6 +56,8 @@ namespace model {
     //@{
 
     explicit SolarCollectorFlatPlatePhotovoltaicThermal(const Model& model);
+    explicit SolarCollectorFlatPlatePhotovoltaicThermal(const SolarCollectorPerformancePhotovoltaicThermalBIPVT& performance);
+    explicit SolarCollectorFlatPlatePhotovoltaicThermal(const SolarCollectorPerformancePhotovoltaicThermalSimple& performance);
 
     virtual ~SolarCollectorFlatPlatePhotovoltaicThermal() = default;
     // Default the copy and move operators because the virtual dtor is explicit
@@ -70,7 +73,7 @@ namespace model {
     /** @name Getters */
     //@{
 
-    SolarCollectorPerformancePhotovoltaicThermalSimple solarCollectorPerformance() const;
+    ModelObject solarCollectorPerformance() const;
 
     boost::optional<PlanarSurface> surface() const;
 
@@ -84,10 +87,11 @@ namespace model {
     /** @name Setters */
     //@{
 
-    /// Deletes the current parameters and clones the parameters passed in
-    bool setSolarCollectorPerformance(const SolarCollectorPerformancePhotovoltaicThermalSimple& parameters);
+    /// Deletes the current performance and clones the performance passed in
+    bool setSolarCollectorPerformance(const SolarCollectorPerformancePhotovoltaicThermalBIPVT& performance);
+    bool setSolarCollectorPerformance(const SolarCollectorPerformancePhotovoltaicThermalSimple& performance);
 
-    /// Deletes the current parameters and constructs a new default set of parameters
+    /// Deletes the current performance and constructs a new default set of performance
     void resetSolarCollectorPerformance();
 
     bool setSurface(const PlanarSurface& surface);
diff --git a/src/model/SolarCollectorFlatPlatePhotovoltaicThermal_Impl.hpp b/src/model/SolarCollectorFlatPlatePhotovoltaicThermal_Impl.hpp
index 670dd635d17..1013ad1c5b5 100644
--- a/src/model/SolarCollectorFlatPlatePhotovoltaicThermal_Impl.hpp
+++ b/src/model/SolarCollectorFlatPlatePhotovoltaicThermal_Impl.hpp
@@ -36,7 +36,9 @@
 namespace openstudio {
 namespace model {
 
+  class GeneratorPhotovoltaic;
   class PlanarSurface;
+  class SolarCollectorPerformancePhotovoltaicThermalBIPVT;
   class SolarCollectorPerformancePhotovoltaicThermalSimple;
 
   namespace detail {
@@ -86,7 +88,7 @@ namespace model {
 
       boost::optional<GeneratorPhotovoltaic> generatorPhotovoltaic() const;
 
-      SolarCollectorPerformancePhotovoltaicThermalSimple solarCollectorPerformance() const;
+      ModelObject solarCollectorPerformance() const;
 
       boost::optional<double> designFlowRate() const;
 
@@ -102,7 +104,8 @@ namespace model {
       /** @name Setters */
       //@{
 
-      bool setSolarCollectorPerformance(const SolarCollectorPerformancePhotovoltaicThermalSimple& parameters);
+      bool setSolarCollectorPerformance(const SolarCollectorPerformancePhotovoltaicThermalBIPVT& performance);
+      bool setSolarCollectorPerformance(const SolarCollectorPerformancePhotovoltaicThermalSimple& performance);
 
       void resetSolarCollectorPerformance();
 
@@ -129,7 +132,7 @@ namespace model {
      private:
       REGISTER_LOGGER("openstudio.model.SolarCollectorFlatPlatePhotovoltaicThermal");
 
-      bool setSolarCollectorPerformanceNoClone(const SolarCollectorPerformancePhotovoltaicThermalSimple& parameters);
+      bool setSolarCollectorPerformanceNoClone(const ModelObject& performance);
 
       friend class openstudio::model::SolarCollectorFlatPlatePhotovoltaicThermal;
     };
diff --git a/src/model/SolarCollectorPerformancePhotovoltaicThermalBIPVT.cpp b/src/model/SolarCollectorPerformancePhotovoltaicThermalBIPVT.cpp
new file mode 100644
index 00000000000..86cd61e5987
--- /dev/null
+++ b/src/model/SolarCollectorPerformancePhotovoltaicThermalBIPVT.cpp
@@ -0,0 +1,529 @@
+/***********************************************************************************************************************
+*  OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved.
+*
+*  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+*  following conditions are met:
+*
+*  (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+*  disclaimer.
+*
+*  (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+*  disclaimer in the documentation and/or other materials provided with the distribution.
+*
+*  (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products
+*  derived from this software without specific prior written permission from the respective party.
+*
+*  (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works
+*  may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior
+*  written permission from Alliance for Sustainable Energy, LLC.
+*
+*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+*  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED
+*  STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+*  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+*  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+*  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+*  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************************************************************/
+
+#include "SolarCollectorPerformancePhotovoltaicThermalBIPVT.hpp"
+#include "SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl.hpp"
+
+#include "SurfacePropertyOtherSideConditionsModel.hpp"
+#include "SurfacePropertyOtherSideConditionsModel_Impl.hpp"
+#include "Schedule.hpp"
+#include "Schedule_Impl.hpp"
+#include "ScheduleTypeLimits.hpp"
+#include "ScheduleTypeRegistry.hpp"
+#include "Model.hpp"
+
+#include "../utilities/core/Assert.hpp"
+
+#include <utilities/idd/IddEnums.hxx>
+#include <utilities/idd/OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVT_FieldEnums.hxx>
+
+namespace openstudio {
+namespace model {
+
+  namespace detail {
+
+    SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl(const IdfObject& idfObject,
+                                                                                                                   Model_Impl* model, bool keepHandle)
+      : ModelObject_Impl(idfObject, model, keepHandle) {
+      OS_ASSERT(idfObject.iddObject().type() == SolarCollectorPerformancePhotovoltaicThermalBIPVT::iddObjectType());
+    }
+
+    SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl(
+      const openstudio::detail::WorkspaceObject_Impl& other, Model_Impl* model, bool keepHandle)
+      : ModelObject_Impl(other, model, keepHandle) {
+      OS_ASSERT(other.iddObject().type() == SolarCollectorPerformancePhotovoltaicThermalBIPVT::iddObjectType());
+    }
+
+    SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl(
+      const SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl& other, Model_Impl* model, bool keepHandle)
+      : ModelObject_Impl(other, model, keepHandle) {}
+
+    const std::vector<std::string>& SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::outputVariableNames() const {
+      static const std::vector<std::string> result;
+      return result;
+    }
+
+    IddObjectType SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::iddObjectType() const {
+      return SolarCollectorPerformancePhotovoltaicThermalBIPVT::iddObjectType();
+    }
+
+    std::vector<ScheduleTypeKey> SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::getScheduleTypeKeys(const Schedule& schedule) const {
+      std::vector<ScheduleTypeKey> result;
+      const UnsignedVector fieldIndices = getSourceIndices(schedule.handle());
+      if (std::find(fieldIndices.cbegin(), fieldIndices.cend(),
+                    OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::AvailabilityScheduleName)
+          != fieldIndices.cend()) {
+        result.emplace_back("SolarCollectorPerformancePhotovoltaicThermalBIPVT", "Availability");
+      }
+      return result;
+    }
+
+    SurfacePropertyOtherSideConditionsModel SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::boundaryConditionsModel() const {
+      boost::optional<SurfacePropertyOtherSideConditionsModel> value = optionalBoundaryConditionsModel();
+      if (!value) {
+        LOG_AND_THROW(briefDescription() << " does not have an Boundary Conditions Model attached.");
+      }
+      return value.get();
+    }
+
+    Schedule SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::availabilitySchedule() const {
+      boost::optional<Schedule> value = optionalAvailabilitySchedule();
+      if (!value) {
+        LOG_AND_THROW(briefDescription() << " does not have an Availability Schedule attached.");
+      }
+      return value.get();
+    }
+
+    double SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::effectivePlenumGapThicknessBehindPVModules() const {
+      boost::optional<double> value =
+        getDouble(OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::EffectivePlenumGapThicknessBehindPVModules, true);
+      OS_ASSERT(value);
+      return value.get();
+    }
+
+    double SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::pVCellNormalTransmittanceAbsorptanceProduct() const {
+      boost::optional<double> value =
+        getDouble(OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::PVCellNormalTransmittanceAbsorptanceProduct, true);
+      OS_ASSERT(value);
+      return value.get();
+    }
+
+    double SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::backingMaterialNormalTransmittanceAbsorptanceProduct() const {
+      boost::optional<double> value =
+        getDouble(OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::BackingMaterialNormalTransmittanceAbsorptanceProduct, true);
+      OS_ASSERT(value);
+      return value.get();
+    }
+
+    double SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::claddingNormalTransmittanceAbsorptanceProduct() const {
+      boost::optional<double> value =
+        getDouble(OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::CladdingNormalTransmittanceAbsorptanceProduct, true);
+      OS_ASSERT(value);
+      return value.get();
+    }
+
+    double SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::fractionofCollectorGrossAreaCoveredbyPVModule() const {
+      boost::optional<double> value =
+        getDouble(OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::FractionofCollectorGrossAreaCoveredbyPVModule, true);
+      OS_ASSERT(value);
+      return value.get();
+    }
+
+    double SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::fractionofPVCellAreatoPVModuleArea() const {
+      boost::optional<double> value =
+        getDouble(OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::FractionofPVCellAreatoPVModuleArea, true);
+      OS_ASSERT(value);
+      return value.get();
+    }
+
+    double SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::pVModuleTopThermalResistance() const {
+      boost::optional<double> value = getDouble(OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::PVModuleTopThermalResistance, true);
+      OS_ASSERT(value);
+      return value.get();
+    }
+
+    double SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::pVModuleBottomThermalResistance() const {
+      boost::optional<double> value = getDouble(OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::PVModuleBottomThermalResistance, true);
+      OS_ASSERT(value);
+      return value.get();
+    }
+
+    double SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::pVModuleFrontLongwaveEmissivity() const {
+      boost::optional<double> value = getDouble(OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::PVModuleFrontLongwaveEmissivity, true);
+      OS_ASSERT(value);
+      return value.get();
+    }
+
+    double SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::pVModuleBackLongwaveEmissivity() const {
+      boost::optional<double> value = getDouble(OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::PVModuleBackLongwaveEmissivity, true);
+      OS_ASSERT(value);
+      return value.get();
+    }
+
+    double SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::glassThickness() const {
+      boost::optional<double> value = getDouble(OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::GlassThickness, true);
+      OS_ASSERT(value);
+      return value.get();
+    }
+
+    double SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::glassRefractionIndex() const {
+      boost::optional<double> value = getDouble(OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::GlassRefractionIndex, true);
+      OS_ASSERT(value);
+      return value.get();
+    }
+
+    double SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::glassExtinctionCoefficient() const {
+      boost::optional<double> value = getDouble(OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::GlassExtinctionCoefficient, true);
+      OS_ASSERT(value);
+      return value.get();
+    }
+
+    bool SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::setBoundaryConditionsModel(
+      const SurfacePropertyOtherSideConditionsModel& surfacePropertyOtherSideConditionsModel) {
+      const bool result = setPointer(OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::BoundaryConditionsModelName,
+                                     surfacePropertyOtherSideConditionsModel.handle());
+      return result;
+    }
+
+    bool SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::setAvailabilitySchedule(Schedule& schedule) {
+      const bool result = setSchedule(OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::AvailabilityScheduleName,
+                                      "SolarCollectorPerformancePhotovoltaicThermalBIPVT", "Availability", schedule);
+      return result;
+    }
+
+    bool SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::setEffectivePlenumGapThicknessBehindPVModules(
+      double effectivePlenumGapThicknessBehindPVModules) {
+      const bool result = setDouble(OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::EffectivePlenumGapThicknessBehindPVModules,
+                                    effectivePlenumGapThicknessBehindPVModules);
+      return result;
+    }
+
+    bool SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::setPVCellNormalTransmittanceAbsorptanceProduct(
+      double pVCellNormalTransmittanceAbsorptanceProduct) {
+      const bool result = setDouble(OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::PVCellNormalTransmittanceAbsorptanceProduct,
+                                    pVCellNormalTransmittanceAbsorptanceProduct);
+      return result;
+    }
+
+    bool SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::setBackingMaterialNormalTransmittanceAbsorptanceProduct(
+      double backingMaterialNormalTransmittanceAbsorptanceProduct) {
+      const bool result =
+        setDouble(OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::BackingMaterialNormalTransmittanceAbsorptanceProduct,
+                  backingMaterialNormalTransmittanceAbsorptanceProduct);
+      return result;
+    }
+
+    bool SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::setCladdingNormalTransmittanceAbsorptanceProduct(
+      double claddingNormalTransmittanceAbsorptanceProduct) {
+      const bool result = setDouble(OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::CladdingNormalTransmittanceAbsorptanceProduct,
+                                    claddingNormalTransmittanceAbsorptanceProduct);
+      return result;
+    }
+
+    bool SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::setFractionofCollectorGrossAreaCoveredbyPVModule(
+      double fractionofCollectorGrossAreaCoveredbyPVModule) {
+      const bool result = setDouble(OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::FractionofCollectorGrossAreaCoveredbyPVModule,
+                                    fractionofCollectorGrossAreaCoveredbyPVModule);
+      return result;
+    }
+
+    bool SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::setFractionofPVCellAreatoPVModuleArea(double fractionofPVCellAreatoPVModuleArea) {
+      const bool result = setDouble(OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::FractionofPVCellAreatoPVModuleArea,
+                                    fractionofPVCellAreatoPVModuleArea);
+      return result;
+    }
+
+    bool SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::setPVModuleTopThermalResistance(double pVModuleTopThermalResistance) {
+      const bool result =
+        setDouble(OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::PVModuleTopThermalResistance, pVModuleTopThermalResistance);
+      return result;
+    }
+
+    bool SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::setPVModuleBottomThermalResistance(double pVModuleBottomThermalResistance) {
+      const bool result =
+        setDouble(OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::PVModuleBottomThermalResistance, pVModuleBottomThermalResistance);
+      return result;
+    }
+
+    bool SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::setPVModuleFrontLongwaveEmissivity(double pVModuleFrontLongwaveEmissivity) {
+      const bool result =
+        setDouble(OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::PVModuleFrontLongwaveEmissivity, pVModuleFrontLongwaveEmissivity);
+      return result;
+    }
+
+    bool SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::setPVModuleBackLongwaveEmissivity(double pVModuleBackLongwaveEmissivity) {
+      const bool result =
+        setDouble(OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::PVModuleBackLongwaveEmissivity, pVModuleBackLongwaveEmissivity);
+      return result;
+    }
+
+    bool SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::setGlassThickness(double glassThickness) {
+      const bool result = setDouble(OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::GlassThickness, glassThickness);
+      return result;
+    }
+
+    bool SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::setGlassRefractionIndex(double glassRefractionIndex) {
+      const bool result = setDouble(OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::GlassRefractionIndex, glassRefractionIndex);
+      return result;
+    }
+
+    bool SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::setGlassExtinctionCoefficient(double glassExtinctionCoefficient) {
+      const bool result =
+        setDouble(OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::GlassExtinctionCoefficient, glassExtinctionCoefficient);
+      return result;
+    }
+
+    boost::optional<SurfacePropertyOtherSideConditionsModel>
+      SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::optionalBoundaryConditionsModel() const {
+      return getObject<ModelObject>().getModelObjectTarget<SurfacePropertyOtherSideConditionsModel>(
+        OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::BoundaryConditionsModelName);
+    }
+
+    boost::optional<Schedule> SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl::optionalAvailabilitySchedule() const {
+      return getObject<ModelObject>().getModelObjectTarget<Schedule>(
+        OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVTFields::AvailabilityScheduleName);
+    }
+
+  }  // namespace detail
+
+  SolarCollectorPerformancePhotovoltaicThermalBIPVT::SolarCollectorPerformancePhotovoltaicThermalBIPVT(const Model& model)
+    : ModelObject(SolarCollectorPerformancePhotovoltaicThermalBIPVT::iddObjectType(), model) {
+    OS_ASSERT(getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>());
+
+    SurfacePropertyOtherSideConditionsModel oscm(model);
+    oscm.setName("BIPVT Surface Property Other Side Conditions Model");
+    bool ok = setBoundaryConditionsModel(oscm);
+    OS_ASSERT(ok);
+    ok = oscm.setTypeOfModeling("GapConvectionRadiation");  // Explicitly set it, even if it's the default
+    OS_ASSERT(ok);
+
+    auto alwaysOn = model.alwaysOnDiscreteSchedule();
+    ok = setAvailabilitySchedule(alwaysOn);
+    OS_ASSERT(ok);
+
+    ok = setEffectivePlenumGapThicknessBehindPVModules(0.1);  // 10cm. Taken from ShopWithBIPVT.idf
+    OS_ASSERT(ok);
+
+    // IDD Defaults
+    ok = setPVCellNormalTransmittanceAbsorptanceProduct(0.957);
+    OS_ASSERT(ok);
+    ok = setBackingMaterialNormalTransmittanceAbsorptanceProduct(0.87);
+    OS_ASSERT(ok);
+    ok = setCladdingNormalTransmittanceAbsorptanceProduct(0.85);
+    OS_ASSERT(ok);
+    ok = setFractionofCollectorGrossAreaCoveredbyPVModule(0.85);
+    OS_ASSERT(ok);
+    ok = setFractionofPVCellAreatoPVModuleArea(0.9);
+    OS_ASSERT(ok);
+    ok = setPVModuleTopThermalResistance(0.0044);
+    OS_ASSERT(ok);
+    ok = setPVModuleBottomThermalResistance(0.0039);
+    OS_ASSERT(ok);
+    ok = setPVModuleFrontLongwaveEmissivity(0.85);
+    OS_ASSERT(ok);
+    ok = setPVModuleBackLongwaveEmissivity(0.9);
+    OS_ASSERT(ok);
+    ok = setGlassThickness(0.002);
+    OS_ASSERT(ok);
+    ok = setGlassRefractionIndex(1.526);
+    OS_ASSERT(ok);
+    ok = setGlassExtinctionCoefficient(4.0);
+    OS_ASSERT(ok);
+  }
+
+  SolarCollectorPerformancePhotovoltaicThermalBIPVT::SolarCollectorPerformancePhotovoltaicThermalBIPVT(
+    const SurfacePropertyOtherSideConditionsModel& oscm)
+    : ModelObject(SolarCollectorPerformancePhotovoltaicThermalBIPVT::iddObjectType(), oscm.model()) {
+    OS_ASSERT(getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>());
+
+    bool ok = setBoundaryConditionsModel(oscm);
+    OS_ASSERT(ok);
+
+    auto alwaysOn = oscm.model().alwaysOnDiscreteSchedule();
+    ok = setAvailabilitySchedule(alwaysOn);
+    OS_ASSERT(ok);
+
+    ok = setEffectivePlenumGapThicknessBehindPVModules(0.1);  // 10cm. Taken from ShopWithBIPVT.idf
+    OS_ASSERT(ok);
+
+    // IDD Defaults
+    ok = setPVCellNormalTransmittanceAbsorptanceProduct(0.957);
+    OS_ASSERT(ok);
+    ok = setBackingMaterialNormalTransmittanceAbsorptanceProduct(0.87);
+    OS_ASSERT(ok);
+    ok = setCladdingNormalTransmittanceAbsorptanceProduct(0.85);
+    OS_ASSERT(ok);
+    ok = setFractionofCollectorGrossAreaCoveredbyPVModule(0.85);
+    OS_ASSERT(ok);
+    ok = setFractionofPVCellAreatoPVModuleArea(0.9);
+    OS_ASSERT(ok);
+    ok = setPVModuleTopThermalResistance(0.0044);
+    OS_ASSERT(ok);
+    ok = setPVModuleBottomThermalResistance(0.0039);
+    OS_ASSERT(ok);
+    ok = setPVModuleFrontLongwaveEmissivity(0.85);
+    OS_ASSERT(ok);
+    ok = setPVModuleBackLongwaveEmissivity(0.9);
+    OS_ASSERT(ok);
+    ok = setGlassThickness(0.002);
+    OS_ASSERT(ok);
+    ok = setGlassRefractionIndex(1.526);
+    OS_ASSERT(ok);
+    ok = setGlassExtinctionCoefficient(4.0);
+    OS_ASSERT(ok);
+  }
+
+  IddObjectType SolarCollectorPerformancePhotovoltaicThermalBIPVT::iddObjectType() {
+    return {IddObjectType::OS_SolarCollectorPerformance_PhotovoltaicThermal_BIPVT};
+  }
+
+  SurfacePropertyOtherSideConditionsModel SolarCollectorPerformancePhotovoltaicThermalBIPVT::boundaryConditionsModel() const {
+    return getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>()->boundaryConditionsModel();
+  }
+
+  Schedule SolarCollectorPerformancePhotovoltaicThermalBIPVT::availabilitySchedule() const {
+    return getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>()->availabilitySchedule();
+  }
+
+  double SolarCollectorPerformancePhotovoltaicThermalBIPVT::effectivePlenumGapThicknessBehindPVModules() const {
+    return getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>()->effectivePlenumGapThicknessBehindPVModules();
+  }
+
+  double SolarCollectorPerformancePhotovoltaicThermalBIPVT::pVCellNormalTransmittanceAbsorptanceProduct() const {
+    return getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>()->pVCellNormalTransmittanceAbsorptanceProduct();
+  }
+
+  double SolarCollectorPerformancePhotovoltaicThermalBIPVT::backingMaterialNormalTransmittanceAbsorptanceProduct() const {
+    return getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>()->backingMaterialNormalTransmittanceAbsorptanceProduct();
+  }
+
+  double SolarCollectorPerformancePhotovoltaicThermalBIPVT::claddingNormalTransmittanceAbsorptanceProduct() const {
+    return getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>()->claddingNormalTransmittanceAbsorptanceProduct();
+  }
+
+  double SolarCollectorPerformancePhotovoltaicThermalBIPVT::fractionofCollectorGrossAreaCoveredbyPVModule() const {
+    return getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>()->fractionofCollectorGrossAreaCoveredbyPVModule();
+  }
+
+  double SolarCollectorPerformancePhotovoltaicThermalBIPVT::fractionofPVCellAreatoPVModuleArea() const {
+    return getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>()->fractionofPVCellAreatoPVModuleArea();
+  }
+
+  double SolarCollectorPerformancePhotovoltaicThermalBIPVT::pVModuleTopThermalResistance() const {
+    return getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>()->pVModuleTopThermalResistance();
+  }
+
+  double SolarCollectorPerformancePhotovoltaicThermalBIPVT::pVModuleBottomThermalResistance() const {
+    return getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>()->pVModuleBottomThermalResistance();
+  }
+
+  double SolarCollectorPerformancePhotovoltaicThermalBIPVT::pVModuleFrontLongwaveEmissivity() const {
+    return getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>()->pVModuleFrontLongwaveEmissivity();
+  }
+
+  double SolarCollectorPerformancePhotovoltaicThermalBIPVT::pVModuleBackLongwaveEmissivity() const {
+    return getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>()->pVModuleBackLongwaveEmissivity();
+  }
+
+  double SolarCollectorPerformancePhotovoltaicThermalBIPVT::glassThickness() const {
+    return getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>()->glassThickness();
+  }
+
+  double SolarCollectorPerformancePhotovoltaicThermalBIPVT::glassRefractionIndex() const {
+    return getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>()->glassRefractionIndex();
+  }
+
+  double SolarCollectorPerformancePhotovoltaicThermalBIPVT::glassExtinctionCoefficient() const {
+    return getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>()->glassExtinctionCoefficient();
+  }
+
+  bool SolarCollectorPerformancePhotovoltaicThermalBIPVT::setBoundaryConditionsModel(
+    const SurfacePropertyOtherSideConditionsModel& surfacePropertyOtherSideConditionsModel) {
+    return getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>()->setBoundaryConditionsModel(
+      surfacePropertyOtherSideConditionsModel);
+  }
+
+  bool SolarCollectorPerformancePhotovoltaicThermalBIPVT::setAvailabilitySchedule(Schedule& schedule) {
+    return getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>()->setAvailabilitySchedule(schedule);
+  }
+
+  bool SolarCollectorPerformancePhotovoltaicThermalBIPVT::setEffectivePlenumGapThicknessBehindPVModules(
+    double effectivePlenumGapThicknessBehindPVModules) {
+    return getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>()->setEffectivePlenumGapThicknessBehindPVModules(
+      effectivePlenumGapThicknessBehindPVModules);
+  }
+
+  bool SolarCollectorPerformancePhotovoltaicThermalBIPVT::setPVCellNormalTransmittanceAbsorptanceProduct(
+    double pVCellNormalTransmittanceAbsorptanceProduct) {
+    return getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>()->setPVCellNormalTransmittanceAbsorptanceProduct(
+      pVCellNormalTransmittanceAbsorptanceProduct);
+  }
+
+  bool SolarCollectorPerformancePhotovoltaicThermalBIPVT::setBackingMaterialNormalTransmittanceAbsorptanceProduct(
+    double backingMaterialNormalTransmittanceAbsorptanceProduct) {
+    return getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>()->setBackingMaterialNormalTransmittanceAbsorptanceProduct(
+      backingMaterialNormalTransmittanceAbsorptanceProduct);
+  }
+
+  bool SolarCollectorPerformancePhotovoltaicThermalBIPVT::setCladdingNormalTransmittanceAbsorptanceProduct(
+    double claddingNormalTransmittanceAbsorptanceProduct) {
+    return getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>()->setCladdingNormalTransmittanceAbsorptanceProduct(
+      claddingNormalTransmittanceAbsorptanceProduct);
+  }
+
+  bool SolarCollectorPerformancePhotovoltaicThermalBIPVT::setFractionofCollectorGrossAreaCoveredbyPVModule(
+    double fractionofCollectorGrossAreaCoveredbyPVModule) {
+    return getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>()->setFractionofCollectorGrossAreaCoveredbyPVModule(
+      fractionofCollectorGrossAreaCoveredbyPVModule);
+  }
+
+  bool SolarCollectorPerformancePhotovoltaicThermalBIPVT::setFractionofPVCellAreatoPVModuleArea(double fractionofPVCellAreatoPVModuleArea) {
+    return getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>()->setFractionofPVCellAreatoPVModuleArea(
+      fractionofPVCellAreatoPVModuleArea);
+  }
+
+  bool SolarCollectorPerformancePhotovoltaicThermalBIPVT::setPVModuleTopThermalResistance(double pVModuleTopThermalResistance) {
+    return getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>()->setPVModuleTopThermalResistance(pVModuleTopThermalResistance);
+  }
+
+  bool SolarCollectorPerformancePhotovoltaicThermalBIPVT::setPVModuleBottomThermalResistance(double pVModuleBottomThermalResistance) {
+    return getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>()->setPVModuleBottomThermalResistance(
+      pVModuleBottomThermalResistance);
+  }
+
+  bool SolarCollectorPerformancePhotovoltaicThermalBIPVT::setPVModuleFrontLongwaveEmissivity(double pVModuleFrontLongwaveEmissivity) {
+    return getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>()->setPVModuleFrontLongwaveEmissivity(
+      pVModuleFrontLongwaveEmissivity);
+  }
+
+  bool SolarCollectorPerformancePhotovoltaicThermalBIPVT::setPVModuleBackLongwaveEmissivity(double pVModuleBackLongwaveEmissivity) {
+    return getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>()->setPVModuleBackLongwaveEmissivity(
+      pVModuleBackLongwaveEmissivity);
+  }
+
+  bool SolarCollectorPerformancePhotovoltaicThermalBIPVT::setGlassThickness(double glassThickness) {
+    return getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>()->setGlassThickness(glassThickness);
+  }
+
+  bool SolarCollectorPerformancePhotovoltaicThermalBIPVT::setGlassRefractionIndex(double glassRefractionIndex) {
+    return getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>()->setGlassRefractionIndex(glassRefractionIndex);
+  }
+
+  bool SolarCollectorPerformancePhotovoltaicThermalBIPVT::setGlassExtinctionCoefficient(double glassExtinctionCoefficient) {
+    return getImpl<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl>()->setGlassExtinctionCoefficient(glassExtinctionCoefficient);
+  }
+
+  /// @cond
+  SolarCollectorPerformancePhotovoltaicThermalBIPVT::SolarCollectorPerformancePhotovoltaicThermalBIPVT(
+    std::shared_ptr<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl> impl)
+    : ModelObject(std::move(impl)) {}
+  /// @endcond
+
+}  // namespace model
+}  // namespace openstudio
diff --git a/src/model/SolarCollectorPerformancePhotovoltaicThermalBIPVT.hpp b/src/model/SolarCollectorPerformancePhotovoltaicThermalBIPVT.hpp
new file mode 100644
index 00000000000..a442f28235f
--- /dev/null
+++ b/src/model/SolarCollectorPerformancePhotovoltaicThermalBIPVT.hpp
@@ -0,0 +1,166 @@
+/***********************************************************************************************************************
+*  OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved.
+*
+*  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+*  following conditions are met:
+*
+*  (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+*  disclaimer.
+*
+*  (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+*  disclaimer in the documentation and/or other materials provided with the distribution.
+*
+*  (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products
+*  derived from this software without specific prior written permission from the respective party.
+*
+*  (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works
+*  may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior
+*  written permission from Alliance for Sustainable Energy, LLC.
+*
+*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+*  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED
+*  STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+*  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+*  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+*  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+*  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************************************************************/
+
+#ifndef MODEL_SOLARCOLLECTORPERFORMANCEPHOTOVOLTAICTHERMALBIPVT_HPP
+#define MODEL_SOLARCOLLECTORPERFORMANCEPHOTOVOLTAICTHERMALBIPVT_HPP
+
+#include <model/ModelAPI.hpp>
+#include "ModelObject.hpp"
+
+namespace openstudio {
+
+namespace model {
+
+  class SurfacePropertyOtherSideConditionsModel;
+  class Schedule;
+
+  namespace detail {
+
+    class SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl;
+
+  }  // namespace detail
+
+  /** SolarCollectorPerformancePhotovoltaicThermalBIPVT is a ModelObject that wraps the OpenStudio IDD object 'OS:SolarCollectorPerformance:PhotovoltaicThermal:BIPVT'. */
+  class MODEL_API SolarCollectorPerformancePhotovoltaicThermalBIPVT : public ModelObject
+  {
+   public:
+    /** @name Constructors and Destructors */
+    //@{
+
+    explicit SolarCollectorPerformancePhotovoltaicThermalBIPVT(const Model& model);
+    explicit SolarCollectorPerformancePhotovoltaicThermalBIPVT(const SurfacePropertyOtherSideConditionsModel& oscm);
+
+    virtual ~SolarCollectorPerformancePhotovoltaicThermalBIPVT() = default;
+    // Default the copy and move operators because the virtual dtor is explicit
+    SolarCollectorPerformancePhotovoltaicThermalBIPVT(const SolarCollectorPerformancePhotovoltaicThermalBIPVT& other) = default;
+    SolarCollectorPerformancePhotovoltaicThermalBIPVT(SolarCollectorPerformancePhotovoltaicThermalBIPVT&& other) = default;
+    SolarCollectorPerformancePhotovoltaicThermalBIPVT& operator=(const SolarCollectorPerformancePhotovoltaicThermalBIPVT&) = default;
+    SolarCollectorPerformancePhotovoltaicThermalBIPVT& operator=(SolarCollectorPerformancePhotovoltaicThermalBIPVT&&) = default;
+
+    //@}
+
+    static IddObjectType iddObjectType();
+
+    /** @name Getters */
+    //@{
+
+    SurfacePropertyOtherSideConditionsModel boundaryConditionsModel() const;
+
+    Schedule availabilitySchedule() const;
+
+    double effectivePlenumGapThicknessBehindPVModules() const;
+
+    double pVCellNormalTransmittanceAbsorptanceProduct() const;
+
+    double backingMaterialNormalTransmittanceAbsorptanceProduct() const;
+
+    double claddingNormalTransmittanceAbsorptanceProduct() const;
+
+    double fractionofCollectorGrossAreaCoveredbyPVModule() const;
+
+    double fractionofPVCellAreatoPVModuleArea() const;
+
+    double pVModuleTopThermalResistance() const;
+
+    double pVModuleBottomThermalResistance() const;
+
+    double pVModuleFrontLongwaveEmissivity() const;
+
+    double pVModuleBackLongwaveEmissivity() const;
+
+    double glassThickness() const;
+
+    double glassRefractionIndex() const;
+
+    double glassExtinctionCoefficient() const;
+
+    //@}
+    /** @name Setters */
+    //@{
+
+    bool setBoundaryConditionsModel(const SurfacePropertyOtherSideConditionsModel& surfacePropertyOtherSideConditionsModel);
+
+    bool setAvailabilitySchedule(Schedule& schedule);
+
+    bool setEffectivePlenumGapThicknessBehindPVModules(double effectivePlenumGapThicknessBehindPVModules);
+
+    bool setPVCellNormalTransmittanceAbsorptanceProduct(double pVCellNormalTransmittanceAbsorptanceProduct);
+
+    bool setBackingMaterialNormalTransmittanceAbsorptanceProduct(double backingMaterialNormalTransmittanceAbsorptanceProduct);
+
+    bool setCladdingNormalTransmittanceAbsorptanceProduct(double claddingNormalTransmittanceAbsorptanceProduct);
+
+    bool setFractionofCollectorGrossAreaCoveredbyPVModule(double fractionofCollectorGrossAreaCoveredbyPVModule);
+
+    bool setFractionofPVCellAreatoPVModuleArea(double fractionofPVCellAreatoPVModuleArea);
+
+    bool setPVModuleTopThermalResistance(double pVModuleTopThermalResistance);
+
+    bool setPVModuleBottomThermalResistance(double pVModuleBottomThermalResistance);
+
+    bool setPVModuleFrontLongwaveEmissivity(double pVModuleFrontLongwaveEmissivity);
+
+    bool setPVModuleBackLongwaveEmissivity(double pVModuleBackLongwaveEmissivity);
+
+    bool setGlassThickness(double glassThickness);
+
+    bool setGlassRefractionIndex(double glassRefractionIndex);
+
+    bool setGlassExtinctionCoefficient(double glassExtinctionCoefficient);
+
+    //@}
+    /** @name Other */
+    //@{
+
+    //@}
+   protected:
+    /// @cond
+    using ImplType = detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl;
+
+    explicit SolarCollectorPerformancePhotovoltaicThermalBIPVT(std::shared_ptr<detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl> impl);
+
+    friend class detail::SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl;
+    friend class Model;
+    friend class IdfObject;
+    friend class openstudio::detail::IdfObject_Impl;
+    /// @endcond
+   private:
+    REGISTER_LOGGER("openstudio.model.SolarCollectorPerformancePhotovoltaicThermalBIPVT");
+  };
+
+  /** \relates SolarCollectorPerformancePhotovoltaicThermalBIPVT*/
+  using OptionalSolarCollectorPerformancePhotovoltaicThermalBIPVT = boost::optional<SolarCollectorPerformancePhotovoltaicThermalBIPVT>;
+
+  /** \relates SolarCollectorPerformancePhotovoltaicThermalBIPVT*/
+  using SolarCollectorPerformancePhotovoltaicThermalBIPVTVector = std::vector<SolarCollectorPerformancePhotovoltaicThermalBIPVT>;
+
+}  // namespace model
+}  // namespace openstudio
+
+#endif  // MODEL_SOLARCOLLECTORPERFORMANCEPHOTOVOLTAICTHERMALBIPVT_HPP
diff --git a/src/model/SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl.hpp b/src/model/SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl.hpp
new file mode 100644
index 00000000000..8f981fa9318
--- /dev/null
+++ b/src/model/SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl.hpp
@@ -0,0 +1,158 @@
+/***********************************************************************************************************************
+*  OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved.
+*
+*  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+*  following conditions are met:
+*
+*  (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+*  disclaimer.
+*
+*  (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+*  disclaimer in the documentation and/or other materials provided with the distribution.
+*
+*  (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products
+*  derived from this software without specific prior written permission from the respective party.
+*
+*  (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works
+*  may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior
+*  written permission from Alliance for Sustainable Energy, LLC.
+*
+*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+*  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED
+*  STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+*  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+*  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+*  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+*  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************************************************************/
+
+#ifndef MODEL_SOLARCOLLECTORPERFORMANCEPHOTOVOLTAICTHERMALBIPVT_IMPL_HPP
+#define MODEL_SOLARCOLLECTORPERFORMANCEPHOTOVOLTAICTHERMALBIPVT_IMPL_HPP
+
+#include <model/ModelAPI.hpp>
+#include "ModelObject_Impl.hpp"
+
+namespace openstudio {
+namespace model {
+
+  class SurfacePropertyOtherSideConditionsModel;
+  class Schedule;
+
+  namespace detail {
+
+    /** SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl is a ModelObject_Impl that is the implementation class for SolarCollectorPerformancePhotovoltaicThermalBIPVT.*/
+    class MODEL_API SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl : public ModelObject_Impl
+    {
+     public:
+      /** @name Constructors and Destructors */
+      //@{
+
+      SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl(const IdfObject& idfObject, Model_Impl* model, bool keepHandle);
+
+      SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl(const openstudio::detail::WorkspaceObject_Impl& other, Model_Impl* model,
+                                                             bool keepHandle);
+
+      SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl(const SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl& other, Model_Impl* model,
+                                                             bool keepHandle);
+
+      virtual ~SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl() = default;
+
+      //@}
+      /** @name Virtual Methods */
+      //@{
+
+      virtual const std::vector<std::string>& outputVariableNames() const override;
+
+      virtual IddObjectType iddObjectType() const override;
+
+      virtual std::vector<ScheduleTypeKey> getScheduleTypeKeys(const Schedule& schedule) const override;
+
+      //@}
+      /** @name Getters */
+      //@{
+
+      SurfacePropertyOtherSideConditionsModel boundaryConditionsModel() const;
+
+      Schedule availabilitySchedule() const;
+
+      double effectivePlenumGapThicknessBehindPVModules() const;
+
+      double pVCellNormalTransmittanceAbsorptanceProduct() const;
+
+      double backingMaterialNormalTransmittanceAbsorptanceProduct() const;
+
+      double claddingNormalTransmittanceAbsorptanceProduct() const;
+
+      double fractionofCollectorGrossAreaCoveredbyPVModule() const;
+
+      double fractionofPVCellAreatoPVModuleArea() const;
+
+      double pVModuleTopThermalResistance() const;
+
+      double pVModuleBottomThermalResistance() const;
+
+      double pVModuleFrontLongwaveEmissivity() const;
+
+      double pVModuleBackLongwaveEmissivity() const;
+
+      double glassThickness() const;
+
+      double glassRefractionIndex() const;
+
+      double glassExtinctionCoefficient() const;
+
+      //@}
+      /** @name Setters */
+      //@{
+
+      bool setBoundaryConditionsModel(const SurfacePropertyOtherSideConditionsModel& surfacePropertyOtherSideConditionsModel);
+
+      bool setAvailabilitySchedule(Schedule& schedule);
+
+      bool setEffectivePlenumGapThicknessBehindPVModules(double effectivePlenumGapThicknessBehindPVModules);
+
+      bool setPVCellNormalTransmittanceAbsorptanceProduct(double pVCellNormalTransmittanceAbsorptanceProduct);
+
+      bool setBackingMaterialNormalTransmittanceAbsorptanceProduct(double backingMaterialNormalTransmittanceAbsorptanceProduct);
+
+      bool setCladdingNormalTransmittanceAbsorptanceProduct(double claddingNormalTransmittanceAbsorptanceProduct);
+
+      bool setFractionofCollectorGrossAreaCoveredbyPVModule(double fractionofCollectorGrossAreaCoveredbyPVModule);
+
+      bool setFractionofPVCellAreatoPVModuleArea(double fractionofPVCellAreatoPVModuleArea);
+
+      bool setPVModuleTopThermalResistance(double pVModuleTopThermalResistance);
+
+      bool setPVModuleBottomThermalResistance(double pVModuleBottomThermalResistance);
+
+      bool setPVModuleFrontLongwaveEmissivity(double pVModuleFrontLongwaveEmissivity);
+
+      bool setPVModuleBackLongwaveEmissivity(double pVModuleBackLongwaveEmissivity);
+
+      bool setGlassThickness(double glassThickness);
+
+      bool setGlassRefractionIndex(double glassRefractionIndex);
+
+      bool setGlassExtinctionCoefficient(double glassExtinctionCoefficient);
+
+      //@}
+      /** @name Other */
+      //@{
+
+      //@}
+     protected:
+     private:
+      REGISTER_LOGGER("openstudio.model.SolarCollectorPerformancePhotovoltaicThermalBIPVT");
+
+      // Optional getters for use by methods like children() so can remove() if the constructor fails.
+      boost::optional<SurfacePropertyOtherSideConditionsModel> optionalBoundaryConditionsModel() const;
+      boost::optional<Schedule> optionalAvailabilitySchedule() const;
+    };
+
+  }  // namespace detail
+
+}  // namespace model
+}  // namespace openstudio
+
+#endif  // MODEL_SOLARCOLLECTORPERFORMANCEPHOTOVOLTAICTHERMALBIPVT_IMPL_HPP
diff --git a/src/model/SolarCollectorPerformancePhotovoltaicThermalSimple.hpp b/src/model/SolarCollectorPerformancePhotovoltaicThermalSimple.hpp
index 46d42cbc7eb..faa4b7c6723 100644
--- a/src/model/SolarCollectorPerformancePhotovoltaicThermalSimple.hpp
+++ b/src/model/SolarCollectorPerformancePhotovoltaicThermalSimple.hpp
@@ -54,6 +54,8 @@ namespace model {
     /** @name Constructors and Destructors */
     //@{
 
+    explicit SolarCollectorPerformancePhotovoltaicThermalSimple(const Model& model);
+
     virtual ~SolarCollectorPerformancePhotovoltaicThermalSimple() = default;
     // Default the copy and move operators because the virtual dtor is explicit
     SolarCollectorPerformancePhotovoltaicThermalSimple(const SolarCollectorPerformancePhotovoltaicThermalSimple& other) = default;
@@ -109,8 +111,6 @@ namespace model {
     /// @cond
     using ImplType = detail::SolarCollectorPerformancePhotovoltaicThermalSimple_Impl;
 
-    explicit SolarCollectorPerformancePhotovoltaicThermalSimple(const Model& model);
-
     explicit SolarCollectorPerformancePhotovoltaicThermalSimple(
       std::shared_ptr<detail::SolarCollectorPerformancePhotovoltaicThermalSimple_Impl> impl);
 
diff --git a/src/model/SubSurface.cpp b/src/model/SubSurface.cpp
index 38c29782a64..246fb8c4f70 100644
--- a/src/model/SubSurface.cpp
+++ b/src/model/SubSurface.cpp
@@ -900,7 +900,7 @@ namespace model {
       return getObject<SubSurface>().getModelObjectTarget<SurfacePropertyOtherSideCoefficients>(OS_SubSurfaceFields::OutsideBoundaryConditionObject);
     }
 
-    bool SubSurface_Impl::setSurfacePropertyOtherSideCoefficients(SurfacePropertyOtherSideCoefficients& otherSideCoefficients) {
+    bool SubSurface_Impl::setSurfacePropertyOtherSideCoefficients(const SurfacePropertyOtherSideCoefficients& otherSideCoefficients) {
       boost::optional<SubSurface> adjacentSubSurface = this->adjacentSubSurface();
       if (adjacentSubSurface) {
         resetAdjacentSubSurface();
@@ -926,7 +926,7 @@ namespace model {
         OS_SubSurfaceFields::OutsideBoundaryConditionObject);
     }
 
-    bool SubSurface_Impl::setSurfacePropertyOtherSideConditionsModel(SurfacePropertyOtherSideConditionsModel& otherSideModel) {
+    bool SubSurface_Impl::setSurfacePropertyOtherSideConditionsModel(const SurfacePropertyOtherSideConditionsModel& otherSideModel) {
       boost::optional<SubSurface> adjacentSubSurface = this->adjacentSubSurface();
       if (adjacentSubSurface) {
         resetAdjacentSubSurface();
@@ -1554,7 +1554,7 @@ namespace model {
     return getImpl<detail::SubSurface_Impl>()->surfacePropertyOtherSideCoefficients();
   }
 
-  bool SubSurface::setSurfacePropertyOtherSideCoefficients(SurfacePropertyOtherSideCoefficients& otherSideCoefficients) {
+  bool SubSurface::setSurfacePropertyOtherSideCoefficients(const SurfacePropertyOtherSideCoefficients& otherSideCoefficients) {
     return getImpl<detail::SubSurface_Impl>()->setSurfacePropertyOtherSideCoefficients(otherSideCoefficients);
   }
 
@@ -1566,7 +1566,7 @@ namespace model {
     return getImpl<detail::SubSurface_Impl>()->surfacePropertyOtherSideConditionsModel();
   }
 
-  bool SubSurface::setSurfacePropertyOtherSideConditionsModel(SurfacePropertyOtherSideConditionsModel& otherSideModel) {
+  bool SubSurface::setSurfacePropertyOtherSideConditionsModel(const SurfacePropertyOtherSideConditionsModel& otherSideModel) {
     return getImpl<detail::SubSurface_Impl>()->setSurfacePropertyOtherSideConditionsModel(otherSideModel);
   }
 
diff --git a/src/model/SubSurface.hpp b/src/model/SubSurface.hpp
index de9c38cea04..e1dfb8806c4 100644
--- a/src/model/SubSurface.hpp
+++ b/src/model/SubSurface.hpp
@@ -212,7 +212,7 @@ namespace model {
     boost::optional<SurfacePropertyOtherSideCoefficients> surfacePropertyOtherSideCoefficients() const;
 
     /** Sets the SurfacePropertyOtherSideCoefficients. */
-    bool setSurfacePropertyOtherSideCoefficients(SurfacePropertyOtherSideCoefficients& otherSideCoefficients);
+    bool setSurfacePropertyOtherSideCoefficients(const SurfacePropertyOtherSideCoefficients& otherSideCoefficients);
 
     /** Resets the SurfacePropertyOtherSideCoefficients. */
     void resetSurfacePropertyOtherSideCoefficients();
@@ -221,7 +221,7 @@ namespace model {
     boost::optional<SurfacePropertyOtherSideConditionsModel> surfacePropertyOtherSideConditionsModel() const;
 
     /** Sets the SurfacePropertyOtherSideConditionsModel. */
-    bool setSurfacePropertyOtherSideConditionsModel(SurfacePropertyOtherSideConditionsModel& otherSideModel);
+    bool setSurfacePropertyOtherSideConditionsModel(const SurfacePropertyOtherSideConditionsModel& otherSideModel);
 
     /** Resets the SurfacePropertyOtherSideConditionsModel. */
     void resetSurfacePropertyOtherSideConditionsModel();
diff --git a/src/model/SubSurface_Impl.hpp b/src/model/SubSurface_Impl.hpp
index 73ecdb5f229..9833448fa46 100644
--- a/src/model/SubSurface_Impl.hpp
+++ b/src/model/SubSurface_Impl.hpp
@@ -244,7 +244,7 @@ namespace model {
       boost::optional<SurfacePropertyOtherSideCoefficients> surfacePropertyOtherSideCoefficients() const;
 
       /** Sets the SurfacePropertyOtherSideCoefficients. */
-      bool setSurfacePropertyOtherSideCoefficients(SurfacePropertyOtherSideCoefficients& otherSideCoefficients);
+      bool setSurfacePropertyOtherSideCoefficients(const SurfacePropertyOtherSideCoefficients& otherSideCoefficients);
 
       /** Resets the SurfacePropertyOtherSideCoefficients. */
       void resetSurfacePropertyOtherSideCoefficients();
@@ -253,7 +253,7 @@ namespace model {
       boost::optional<SurfacePropertyOtherSideConditionsModel> surfacePropertyOtherSideConditionsModel() const;
 
       /** Sets the SurfacePropertyOtherSideConditionsModel. */
-      bool setSurfacePropertyOtherSideConditionsModel(SurfacePropertyOtherSideConditionsModel& otherSideModel);
+      bool setSurfacePropertyOtherSideConditionsModel(const SurfacePropertyOtherSideConditionsModel& otherSideModel);
 
       /** Resets the SurfacePropertyOtherSideConditionsModel. */
       void resetSurfacePropertyOtherSideConditionsModel();
diff --git a/src/model/Surface.cpp b/src/model/Surface.cpp
index 99efcf3943a..aeef1713c6d 100644
--- a/src/model/Surface.cpp
+++ b/src/model/Surface.cpp
@@ -931,7 +931,7 @@ namespace model {
       return getObject<Surface>().getModelObjectTarget<SurfacePropertyOtherSideCoefficients>(OS_SurfaceFields::OutsideBoundaryConditionObject);
     }
 
-    bool Surface_Impl::setSurfacePropertyOtherSideCoefficients(SurfacePropertyOtherSideCoefficients& otherSideCoefficients) {
+    bool Surface_Impl::setSurfacePropertyOtherSideCoefficients(const SurfacePropertyOtherSideCoefficients& otherSideCoefficients) {
       boost::optional<Surface> adjacentSurface = this->adjacentSurface();
       if (adjacentSurface) {
         resetAdjacentSurface();
@@ -972,7 +972,7 @@ namespace model {
       return getObject<Surface>().getModelObjectTarget<SurfacePropertyOtherSideConditionsModel>(OS_SurfaceFields::OutsideBoundaryConditionObject);
     }
 
-    bool Surface_Impl::setSurfacePropertyOtherSideConditionsModel(SurfacePropertyOtherSideConditionsModel& otherSideModel) {
+    bool Surface_Impl::setSurfacePropertyOtherSideConditionsModel(const SurfacePropertyOtherSideConditionsModel& otherSideModel) {
       boost::optional<Surface> adjacentSurface = this->adjacentSurface();
       if (adjacentSurface) {
         resetAdjacentSurface();
@@ -2299,7 +2299,7 @@ namespace model {
     return getImpl<detail::Surface_Impl>()->surfacePropertyOtherSideCoefficients();
   }
 
-  bool Surface::setSurfacePropertyOtherSideCoefficients(SurfacePropertyOtherSideCoefficients& otherSideCoefficients) {
+  bool Surface::setSurfacePropertyOtherSideCoefficients(const SurfacePropertyOtherSideCoefficients& otherSideCoefficients) {
     return getImpl<detail::Surface_Impl>()->setSurfacePropertyOtherSideCoefficients(otherSideCoefficients);
   }
 
@@ -2311,7 +2311,7 @@ namespace model {
     return getImpl<detail::Surface_Impl>()->surfacePropertyOtherSideConditionsModel();
   }
 
-  bool Surface::setSurfacePropertyOtherSideConditionsModel(SurfacePropertyOtherSideConditionsModel& otherSideModel) {
+  bool Surface::setSurfacePropertyOtherSideConditionsModel(const SurfacePropertyOtherSideConditionsModel& otherSideModel) {
     return getImpl<detail::Surface_Impl>()->setSurfacePropertyOtherSideConditionsModel(otherSideModel);
   }
 
diff --git a/src/model/Surface.hpp b/src/model/Surface.hpp
index b03ed3ee556..8825bb6c59f 100644
--- a/src/model/Surface.hpp
+++ b/src/model/Surface.hpp
@@ -195,7 +195,7 @@ namespace model {
     boost::optional<SurfacePropertyOtherSideCoefficients> surfacePropertyOtherSideCoefficients() const;
 
     /** Sets the SurfacePropertyOtherSideCoefficients. */
-    bool setSurfacePropertyOtherSideCoefficients(SurfacePropertyOtherSideCoefficients& otherSideCoefficients);
+    bool setSurfacePropertyOtherSideCoefficients(const SurfacePropertyOtherSideCoefficients& otherSideCoefficients);
 
     /** Resets the SurfacePropertyOtherSideCoefficients. */
     void resetSurfacePropertyOtherSideCoefficients();
@@ -204,7 +204,7 @@ namespace model {
     boost::optional<SurfacePropertyOtherSideConditionsModel> surfacePropertyOtherSideConditionsModel() const;
 
     /** Sets the SurfacePropertyOtherSideConditionsModel. */
-    bool setSurfacePropertyOtherSideConditionsModel(SurfacePropertyOtherSideConditionsModel& otherSideModel);
+    bool setSurfacePropertyOtherSideConditionsModel(const SurfacePropertyOtherSideConditionsModel& otherSideModel);
 
     /** Resets the SurfacePropertyOtherSideConditionsModel. */
     void resetSurfacePropertyOtherSideConditionsModel();
diff --git a/src/model/SurfacePropertyOtherSideConditionsModel.cpp b/src/model/SurfacePropertyOtherSideConditionsModel.cpp
index 3e90493d0d5..ad06e6ca6e1 100644
--- a/src/model/SurfacePropertyOtherSideConditionsModel.cpp
+++ b/src/model/SurfacePropertyOtherSideConditionsModel.cpp
@@ -106,11 +106,6 @@ namespace model {
   SurfacePropertyOtherSideConditionsModel::SurfacePropertyOtherSideConditionsModel(const Model& model)
     : ResourceObject(SurfacePropertyOtherSideConditionsModel::iddObjectType(), model) {
     OS_ASSERT(getImpl<detail::SurfacePropertyOtherSideConditionsModel_Impl>());
-
-    // TODO: Appropriately handle the following required object-list fields.
-    bool ok = true;
-    // ok = setHandle();
-    OS_ASSERT(ok);
   }
 
   IddObjectType SurfacePropertyOtherSideConditionsModel::iddObjectType() {
diff --git a/src/model/Surface_Impl.hpp b/src/model/Surface_Impl.hpp
index ed8d794c6fb..e6b321aa352 100644
--- a/src/model/Surface_Impl.hpp
+++ b/src/model/Surface_Impl.hpp
@@ -212,13 +212,13 @@ namespace model {
 
       boost::optional<SurfacePropertyOtherSideCoefficients> surfacePropertyOtherSideCoefficients() const;
 
-      bool setSurfacePropertyOtherSideCoefficients(SurfacePropertyOtherSideCoefficients& otherSideCoefficients);
+      bool setSurfacePropertyOtherSideCoefficients(const SurfacePropertyOtherSideCoefficients& otherSideCoefficients);
 
       void resetSurfacePropertyOtherSideCoefficients();
 
       boost::optional<SurfacePropertyOtherSideConditionsModel> surfacePropertyOtherSideConditionsModel() const;
 
-      bool setSurfacePropertyOtherSideConditionsModel(SurfacePropertyOtherSideConditionsModel& otherSideModel);
+      bool setSurfacePropertyOtherSideConditionsModel(const SurfacePropertyOtherSideConditionsModel& otherSideModel);
 
       void resetSurfacePropertyOtherSideConditionsModel();
 


Test patch:
diff --git a/src/model/test/SolarCollectorFlatPlatePhotovoltaicThermal_GTest.cpp b/src/model/test/SolarCollectorFlatPlatePhotovoltaicThermal_GTest.cpp
index 148ca417334..4c4d2d3224b 100644
--- a/src/model/test/SolarCollectorFlatPlatePhotovoltaicThermal_GTest.cpp
+++ b/src/model/test/SolarCollectorFlatPlatePhotovoltaicThermal_GTest.cpp
@@ -31,6 +31,8 @@
 #include "ModelFixture.hpp"
 #include "../SolarCollectorFlatPlatePhotovoltaicThermal.hpp"
 #include "../SolarCollectorFlatPlatePhotovoltaicThermal_Impl.hpp"
+#include "../SolarCollectorPerformancePhotovoltaicThermalBIPVT.hpp"
+#include "../SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl.hpp"
 #include "../SolarCollectorPerformancePhotovoltaicThermalSimple.hpp"
 #include "../SolarCollectorPerformancePhotovoltaicThermalSimple_Impl.hpp"
 #include "../GeneratorPhotovoltaic.hpp"
@@ -50,18 +52,28 @@
 using namespace openstudio;
 using namespace openstudio::model;
 
-TEST_F(ModelFixture, SolarCollectorFlatPlatePhotovoltaicThermal_SolarCollectorFlatPlatePhotovoltaicThermal) {
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+TEST_F(ModelFixture, SolarCollectorFlatPlatePhotovoltaicThermal_SolarCollectorFlatPlatePhotovoltaicThermal_Ctors) {
 
-  ASSERT_EXIT(
-    {
-      Model m;
-      SolarCollectorFlatPlatePhotovoltaicThermal testObject(m);
-      SolarCollectorPerformancePhotovoltaicThermalSimple performance = testObject.solarCollectorPerformance();
-
-      exit(0);
-    },
-    ::testing::ExitedWithCode(0), "");
+  {
+    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);
+  }
 }
 
 TEST_F(ModelFixture, SolarCollectorFlatPlatePhotovoltaicThermal_addToNode) {
@@ -96,7 +108,7 @@ TEST_F(ModelFixture, SolarCollectorFlatPlatePhotovoltaicThermal_addToNode) {
   EXPECT_EQ(1u, model.getObjectsByType(SolarCollectorFlatPlatePhotovoltaicThermal::iddObjectType()).size());
   EXPECT_EQ(1u, model.getObjectsByType(SolarCollectorPerformancePhotovoltaicThermalSimple::iddObjectType()).size());
 
-  SolarCollectorPerformancePhotovoltaicThermalSimple performance = collector.solarCollectorPerformance();
+  auto performance = collector.solarCollectorPerformance();
 
   EXPECT_TRUE(collector.addToNode(node));
 
@@ -142,7 +154,8 @@ TEST_F(ModelFixture, SolarCollectorFlatPlatePhotovoltaicThermal_SetPerformance)
     EXPECT_EQ(1u, model.getObjectsByType(SolarCollectorPerformancePhotovoltaicThermalSimple::iddObjectType()).size());
     EXPECT_NO_THROW(collector.solarCollectorPerformance());
 
-    collector.setSolarCollectorPerformance(collector.solarCollectorPerformance());
+    EXPECT_TRUE(
+      collector.setSolarCollectorPerformance(collector.solarCollectorPerformance().cast<SolarCollectorPerformancePhotovoltaicThermalSimple>()));
     EXPECT_EQ(1u, model.getObjectsByType(SolarCollectorFlatPlatePhotovoltaicThermal::iddObjectType()).size());
     EXPECT_EQ(1u, model.getObjectsByType(SolarCollectorPerformancePhotovoltaicThermalSimple::iddObjectType()).size());
     EXPECT_NO_THROW(collector.solarCollectorPerformance());
@@ -157,7 +170,8 @@ TEST_F(ModelFixture, SolarCollectorFlatPlatePhotovoltaicThermal_SetPerformance)
     EXPECT_NO_THROW(collector.solarCollectorPerformance());
     EXPECT_NO_THROW(collector2.solarCollectorPerformance());
 
-    collector.setSolarCollectorPerformance(collector2.solarCollectorPerformance());
+    EXPECT_TRUE(
+      collector.setSolarCollectorPerformance(collector2.solarCollectorPerformance().cast<SolarCollectorPerformancePhotovoltaicThermalSimple>()));
     EXPECT_EQ(2u, model.getObjectsByType(SolarCollectorFlatPlatePhotovoltaicThermal::iddObjectType()).size());
     EXPECT_EQ(2u, model.getObjectsByType(SolarCollectorPerformancePhotovoltaicThermalSimple::iddObjectType()).size());
     EXPECT_NO_THROW(collector.solarCollectorPerformance());
@@ -170,7 +184,7 @@ TEST_F(ModelFixture, SolarCollectorFlatPlatePhotovoltaicThermal_PV) {
   Model model;
 
   SolarCollectorFlatPlatePhotovoltaicThermal collector(model);
-  SolarCollectorPerformancePhotovoltaicThermalSimple performance = collector.solarCollectorPerformance();
+  auto performance = collector.solarCollectorPerformance();
 
   EXPECT_FALSE(collector.generatorPhotovoltaic());
 
@@ -190,7 +204,7 @@ TEST_F(ModelFixture, SolarCollectorFlatPlatePhotovoltaicThermal_Clone) {
   {
     Model model;
     SolarCollectorFlatPlatePhotovoltaicThermal collector(model);
-    SolarCollectorPerformancePhotovoltaicThermalSimple performance = collector.solarCollectorPerformance();
+    auto performance = collector.solarCollectorPerformance();
 
     GeneratorPhotovoltaic pv = GeneratorPhotovoltaic::simple(model);
     EXPECT_TRUE(collector.setGeneratorPhotovoltaic(pv));
@@ -210,7 +224,7 @@ TEST_F(ModelFixture, SolarCollectorFlatPlatePhotovoltaicThermal_Clone) {
     ModelObject clone = collector.clone(model);
     ASSERT_TRUE(clone.optionalCast<SolarCollectorFlatPlatePhotovoltaicThermal>());
     auto collector2 = clone.cast<SolarCollectorFlatPlatePhotovoltaicThermal>();
-    SolarCollectorPerformancePhotovoltaicThermalSimple performance2 = collector2.solarCollectorPerformance();
+    auto performance2 = collector2.solarCollectorPerformance();
 
     EXPECT_NE(collector.handle(), collector2.handle());
     EXPECT_NE(performance.handle(), performance2.handle());
@@ -231,7 +245,7 @@ TEST_F(ModelFixture, SolarCollectorFlatPlatePhotovoltaicThermal_Clone) {
   {
     Model model;
     SolarCollectorFlatPlatePhotovoltaicThermal collector(model);
-    SolarCollectorPerformancePhotovoltaicThermalSimple performance = collector.solarCollectorPerformance();
+    auto performance = collector.solarCollectorPerformance();
 
     GeneratorPhotovoltaic pv = GeneratorPhotovoltaic::simple(model);
     EXPECT_TRUE(collector.setGeneratorPhotovoltaic(pv));
@@ -252,7 +266,7 @@ TEST_F(ModelFixture, SolarCollectorFlatPlatePhotovoltaicThermal_Clone) {
     ModelObject clone = collector.clone(model2);
     ASSERT_TRUE(clone.optionalCast<SolarCollectorFlatPlatePhotovoltaicThermal>());
     auto collector2 = clone.cast<SolarCollectorFlatPlatePhotovoltaicThermal>();
-    SolarCollectorPerformancePhotovoltaicThermalSimple performance2 = collector2.solarCollectorPerformance();
+    auto performance2 = collector2.solarCollectorPerformance();
 
     EXPECT_NE(collector.handle(), collector2.handle());
     EXPECT_NE(performance.handle(), performance2.handle());
diff --git a/src/model/test/SolarCollectorPerformancePhotovoltaicThermalBIPVT_GTest.cpp b/src/model/test/SolarCollectorPerformancePhotovoltaicThermalBIPVT_GTest.cpp
new file mode 100644
index 00000000000..2a7a2ea6b9c
--- /dev/null
+++ b/src/model/test/SolarCollectorPerformancePhotovoltaicThermalBIPVT_GTest.cpp
@@ -0,0 +1,152 @@
+/***********************************************************************************************************************
+*  OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved.
+*
+*  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+*  following conditions are met:
+*
+*  (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+*  disclaimer.
+*
+*  (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+*  disclaimer in the documentation and/or other materials provided with the distribution.
+*
+*  (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products
+*  derived from this software without specific prior written permission from the respective party.
+*
+*  (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works
+*  may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior
+*  written permission from Alliance for Sustainable Energy, LLC.
+*
+*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+*  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED
+*  STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+*  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+*  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+*  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+*  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************************************************************/
+
+#include "ModelFixture.hpp"
+
+#include "../SolarCollectorPerformancePhotovoltaicThermalBIPVT.hpp"
+#include "../SolarCollectorPerformancePhotovoltaicThermalBIPVT_Impl.hpp"
+
+#include "../SurfacePropertyOtherSideConditionsModel.hpp"
+#include "../Schedule.hpp"
+#include "../ScheduleConstant.hpp"
+
+using namespace openstudio;
+using namespace openstudio::model;
+
+TEST_F(ModelFixture, SolarCollectorPerformancePhotovoltaicThermalBIPVT_GettersSetters) {
+  Model m;
+  SolarCollectorPerformancePhotovoltaicThermalBIPVT solarCollectorPerformancePhotovoltaicThermalBIPVT(m);
+
+  solarCollectorPerformancePhotovoltaicThermalBIPVT.setName("My SolarCollectorPerformancePhotovoltaicThermalBIPVT");
+
+  // Boundary Conditions Model Name: Required Object
+  {
+    SurfacePropertyOtherSideConditionsModel oscm(m);
+    EXPECT_TRUE(solarCollectorPerformancePhotovoltaicThermalBIPVT.setBoundaryConditionsModel(oscm));
+    EXPECT_EQ(oscm, solarCollectorPerformancePhotovoltaicThermalBIPVT.boundaryConditionsModel());
+  }
+
+  // Availability Schedule Name: Required Object
+  {
+    ScheduleConstant sch(m);
+    EXPECT_TRUE(solarCollectorPerformancePhotovoltaicThermalBIPVT.setAvailabilitySchedule(sch));
+    EXPECT_EQ(sch, solarCollectorPerformancePhotovoltaicThermalBIPVT.availabilitySchedule());
+  }
+
+  // Effective Plenum Gap Thickness Behind PV Modules: Required Double
+  EXPECT_TRUE(solarCollectorPerformancePhotovoltaicThermalBIPVT.setEffectivePlenumGapThicknessBehindPVModules(0.5));
+  EXPECT_EQ(0.5, solarCollectorPerformancePhotovoltaicThermalBIPVT.effectivePlenumGapThicknessBehindPVModules());
+  // Bad Value
+  EXPECT_FALSE(solarCollectorPerformancePhotovoltaicThermalBIPVT.setEffectivePlenumGapThicknessBehindPVModules(-10.0));
+  EXPECT_EQ(0.5, solarCollectorPerformancePhotovoltaicThermalBIPVT.effectivePlenumGapThicknessBehindPVModules());
+
+  // PV Cell Normal Transmittance-Absorptance Product: Required Double
+  EXPECT_TRUE(solarCollectorPerformancePhotovoltaicThermalBIPVT.setPVCellNormalTransmittanceAbsorptanceProduct(0.857));
+  EXPECT_EQ(0.857, solarCollectorPerformancePhotovoltaicThermalBIPVT.pVCellNormalTransmittanceAbsorptanceProduct());
+  // Bad Value
+  EXPECT_FALSE(solarCollectorPerformancePhotovoltaicThermalBIPVT.setPVCellNormalTransmittanceAbsorptanceProduct(-10.0));
+  EXPECT_EQ(0.857, solarCollectorPerformancePhotovoltaicThermalBIPVT.pVCellNormalTransmittanceAbsorptanceProduct());
+
+  // Backing Material Normal Transmittance-Absorptance Product: Required Double
+  EXPECT_TRUE(solarCollectorPerformancePhotovoltaicThermalBIPVT.setBackingMaterialNormalTransmittanceAbsorptanceProduct(0.875));
+  EXPECT_EQ(0.875, solarCollectorPerformancePhotovoltaicThermalBIPVT.backingMaterialNormalTransmittanceAbsorptanceProduct());
+  // Bad Value
+  EXPECT_FALSE(solarCollectorPerformancePhotovoltaicThermalBIPVT.setBackingMaterialNormalTransmittanceAbsorptanceProduct(-10.0));
+  EXPECT_EQ(0.875, solarCollectorPerformancePhotovoltaicThermalBIPVT.backingMaterialNormalTransmittanceAbsorptanceProduct());
+
+  // Cladding Normal Transmittance-Absorptance Product: Required Double
+  EXPECT_TRUE(solarCollectorPerformancePhotovoltaicThermalBIPVT.setCladdingNormalTransmittanceAbsorptanceProduct(0.889));
+  EXPECT_EQ(0.889, solarCollectorPerformancePhotovoltaicThermalBIPVT.claddingNormalTransmittanceAbsorptanceProduct());
+  // Bad Value
+  EXPECT_FALSE(solarCollectorPerformancePhotovoltaicThermalBIPVT.setCladdingNormalTransmittanceAbsorptanceProduct(-10.0));
+  EXPECT_EQ(0.889, solarCollectorPerformancePhotovoltaicThermalBIPVT.claddingNormalTransmittanceAbsorptanceProduct());
+
+  // Fraction of Collector Gross Area Covered by PV Module: Required Double
+  EXPECT_TRUE(solarCollectorPerformancePhotovoltaicThermalBIPVT.setFractionofCollectorGrossAreaCoveredbyPVModule(0.9));
+  EXPECT_EQ(0.9, solarCollectorPerformancePhotovoltaicThermalBIPVT.fractionofCollectorGrossAreaCoveredbyPVModule());
+  // Bad Value
+  EXPECT_FALSE(solarCollectorPerformancePhotovoltaicThermalBIPVT.setFractionofCollectorGrossAreaCoveredbyPVModule(-10.0));
+  EXPECT_EQ(0.9, solarCollectorPerformancePhotovoltaicThermalBIPVT.fractionofCollectorGrossAreaCoveredbyPVModule());
+
+  // Fraction of PV Cell Area to PV Module Area: Required Double
+  EXPECT_TRUE(solarCollectorPerformancePhotovoltaicThermalBIPVT.setFractionofPVCellAreatoPVModuleArea(0.909));
+  EXPECT_EQ(0.909, solarCollectorPerformancePhotovoltaicThermalBIPVT.fractionofPVCellAreatoPVModuleArea());
+  // Bad Value
+  EXPECT_FALSE(solarCollectorPerformancePhotovoltaicThermalBIPVT.setFractionofPVCellAreatoPVModuleArea(-10.0));
+  EXPECT_EQ(0.909, solarCollectorPerformancePhotovoltaicThermalBIPVT.fractionofPVCellAreatoPVModuleArea());
+
+  // PV Module Top Thermal Resistance: Required Double
+  EXPECT_TRUE(solarCollectorPerformancePhotovoltaicThermalBIPVT.setPVModuleTopThermalResistance(1.1));
+  EXPECT_EQ(1.1, solarCollectorPerformancePhotovoltaicThermalBIPVT.pVModuleTopThermalResistance());
+  // Bad Value
+  EXPECT_FALSE(solarCollectorPerformancePhotovoltaicThermalBIPVT.setPVModuleTopThermalResistance(-10.0));
+  EXPECT_EQ(1.1, solarCollectorPerformancePhotovoltaicThermalBIPVT.pVModuleTopThermalResistance());
+
+  // PV Module Bottom Thermal Resistance: Required Double
+  EXPECT_TRUE(solarCollectorPerformancePhotovoltaicThermalBIPVT.setPVModuleBottomThermalResistance(1.2));
+  EXPECT_EQ(1.2, solarCollectorPerformancePhotovoltaicThermalBIPVT.pVModuleBottomThermalResistance());
+  // Bad Value
+  EXPECT_FALSE(solarCollectorPerformancePhotovoltaicThermalBIPVT.setPVModuleBottomThermalResistance(-10.0));
+  EXPECT_EQ(1.2, solarCollectorPerformancePhotovoltaicThermalBIPVT.pVModuleBottomThermalResistance());
+
+  // PV Module Front Longwave Emissivity: Required Double
+  EXPECT_TRUE(solarCollectorPerformancePhotovoltaicThermalBIPVT.setPVModuleFrontLongwaveEmissivity(0.929));
+  EXPECT_EQ(0.929, solarCollectorPerformancePhotovoltaicThermalBIPVT.pVModuleFrontLongwaveEmissivity());
+  // Bad Value
+  EXPECT_FALSE(solarCollectorPerformancePhotovoltaicThermalBIPVT.setPVModuleFrontLongwaveEmissivity(-10.0));
+  EXPECT_EQ(0.929, solarCollectorPerformancePhotovoltaicThermalBIPVT.pVModuleFrontLongwaveEmissivity());
+
+  // PV Module Back Longwave Emissivity: Required Double
+  EXPECT_TRUE(solarCollectorPerformancePhotovoltaicThermalBIPVT.setPVModuleBackLongwaveEmissivity(0.933));
+  EXPECT_EQ(0.933, solarCollectorPerformancePhotovoltaicThermalBIPVT.pVModuleBackLongwaveEmissivity());
+  // Bad Value
+  EXPECT_FALSE(solarCollectorPerformancePhotovoltaicThermalBIPVT.setPVModuleBackLongwaveEmissivity(-10.0));
+  EXPECT_EQ(0.933, solarCollectorPerformancePhotovoltaicThermalBIPVT.pVModuleBackLongwaveEmissivity());
+
+  // Glass Thickness: Required Double
+  EXPECT_TRUE(solarCollectorPerformancePhotovoltaicThermalBIPVT.setGlassThickness(0.009));
+  EXPECT_EQ(0.009, solarCollectorPerformancePhotovoltaicThermalBIPVT.glassThickness());
+  // Bad Value
+  EXPECT_FALSE(solarCollectorPerformancePhotovoltaicThermalBIPVT.setGlassThickness(-10.0));
+  EXPECT_EQ(0.009, solarCollectorPerformancePhotovoltaicThermalBIPVT.glassThickness());
+
+  // Glass Refraction Index: Required Double
+  EXPECT_TRUE(solarCollectorPerformancePhotovoltaicThermalBIPVT.setGlassRefractionIndex(9.471));
+  EXPECT_EQ(9.471, solarCollectorPerformancePhotovoltaicThermalBIPVT.glassRefractionIndex());
+  // Bad Value
+  EXPECT_FALSE(solarCollectorPerformancePhotovoltaicThermalBIPVT.setGlassRefractionIndex(-9.0));
+  EXPECT_EQ(9.471, solarCollectorPerformancePhotovoltaicThermalBIPVT.glassRefractionIndex());
+
+  // Glass Extinction Coefficient: Required Double
+  EXPECT_TRUE(solarCollectorPerformancePhotovoltaicThermalBIPVT.setGlassExtinctionCoefficient(94.444));
+  EXPECT_EQ(94.444, solarCollectorPerformancePhotovoltaicThermalBIPVT.glassExtinctionCoefficient());
+  // Bad Value
+  EXPECT_FALSE(solarCollectorPerformancePhotovoltaicThermalBIPVT.setGlassExtinctionCoefficient(-10.0));
+  EXPECT_EQ(94.444, solarCollectorPerformancePhotovoltaicThermalBIPVT.glassExtinctionCoefficient());
+}