Repository: NREL/OpenStudio (language: python)

Issue:
Update to EnergyPlus 22.2.0
Enhancement Request
--------------
Once v22.2-IOFreeze is released, we should update to it.

## Detailed Description

https://github.com/NREL/EnergyPlus/blob/develop/src/Transition/InputRulesFiles/Rules22-1-0-to-22-2-0.md

### Major changes
- [x] https://github.com/NREL/OpenStudio/issues/4647
  - https://github.com/NREL/OpenStudio/pull/4652
  - https://github.com/NREL/OpenStudio-resources/pull/173
- [x] https://github.com/NREL/OpenStudio/issues/4645
  - https://github.com/NREL/OpenStudio/pull/4672 
- [x] #4673

### New additions
- [x] https://github.com/NREL/OpenStudio/issues/4656
  - https://github.com/NREL/OpenStudio/pull/4687
  - https://github.com/NREL/OpenStudio-resources/pull/179
- [x] https://github.com/NREL/OpenStudio/issues/4648
  - https://github.com/NREL/OpenStudio/pull/4676
  - https://github.com/NREL/OpenStudio-resources/pull/177
- [x] https://github.com/NREL/OpenStudio/issues/4654
  - https://github.com/NREL/OpenStudio/pull/4676
  - https://github.com/NREL/OpenStudio-resources/pull/177
- [x] https://github.com/NREL/OpenStudio/issues/4646
  - https://github.com/NREL/OpenStudio/pull/4666
  - https://github.com/NREL/OpenStudio-resources/pull/176
- [x] https://github.com/NREL/OpenStudio/issues/4668
  - https://github.com/NREL/OpenStudio/pull/4669
- [x] https://github.com/NREL/OpenStudio/pull/4665
- [x] https://github.com/NREL/OpenStudio/pull/4661
- [x] https://github.com/NREL/OpenStudio/pull/4671
- [x] https://github.com/NREL/OpenStudio/pull/4662
- [x] https://github.com/NREL/OpenStudio/issues/4675
  - https://github.com/NREL/OpenStudio/pull/4677

### Minor stuff
- [x] `FuelFactors`: eliminate second/third input parameters.
- [x] `Construction:InternalSource`: min/max changes
- [x] `SwimmingPool:Indoor`: field `Make-up Water Supply Schedule Name` no longer required
  - 2f7a98f6cd8dd2669e48346ba59c1ebb505d07b4
- [x] https://github.com/NREL/OpenStudio/issues/4630 (could probably sneak this in)
  - https://github.com/NREL/OpenStudio/pull/4685

### Other



Discussion / hints:

Fix patch:
diff --git a/resources/model/OpenStudio.idd b/resources/model/OpenStudio.idd
index 1dc138092d6..c866a3e4ce7 100644
--- a/resources/model/OpenStudio.idd
+++ b/resources/model/OpenStudio.idd
@@ -5422,11 +5422,21 @@ OS:Space,
   A10, \field Building Unit Name
        \type object-list
        \object-list BuildingUnitNames
-  N5; \field Volume
+  N5, \field Volume
        \type real
        \units m3
        \autocalculatable
        \default autocalculate
+  N6, \field Ceiling Height
+       \type real
+       \units m
+       \autocalculatable
+       \default autocalculate
+  N7; \field Floor Area
+       \type real
+       \units m2
+       \autocalculatable
+       \default autocalculate
 
 OS:Surface,
        \extensible:3
diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateSpace.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateSpace.cpp
index 00ebde20f0e..be5bb3da464 100644
--- a/src/energyplus/ForwardTranslator/ForwardTranslateSpace.cpp
+++ b/src/energyplus/ForwardTranslator/ForwardTranslateSpace.cpp
@@ -81,12 +81,21 @@ namespace energyplus {
     // Space
     IdfObject idfObject = createRegisterAndNameIdfObject(openstudio::IddObjectType::Space, modelObject);
 
+    // ZoneName
     if (boost::optional<ThermalZone> thermalZone = modelObject.thermalZone()) {
       idfObject.setString(SpaceFields::ZoneName, thermalZone->name().get());
     }
 
+    // CeilingHeight
+    idfObject.setDouble(SpaceFields::CeilingHeight, modelObject.ceilingHeight());
+
+    // Volume
+    idfObject.setDouble(SpaceFields::Volume, modelObject.volume());
+
+    // FloorArea
     idfObject.setDouble(SpaceFields::FloorArea, modelObject.floorArea());
 
+    // SpaceType
     if (boost::optional<SpaceType> spaceType_ = modelObject.spaceType()) {
       if (auto idf_spaceType_ = translateAndMapModelObject(spaceType_.get())) {
         idfObject.setString(SpaceFields::SpaceType, idf_spaceType_->nameString());
diff --git a/src/model/Space.cpp b/src/model/Space.cpp
index 4789338e1fa..171fbe57897 100644
--- a/src/model/Space.cpp
+++ b/src/model/Space.cpp
@@ -497,6 +497,22 @@ namespace model {
       OS_ASSERT(result);
     }
 
+    bool Space_Impl::setCeilingHeight(double ceilingHeight) {
+      bool result = setDouble(OS_SpaceFields::CeilingHeight, ceilingHeight);
+      OS_ASSERT(result);
+      return result;
+    }
+
+    void Space_Impl::autocalculateCeilingHeight() {
+      bool result = setString(OS_SpaceFields::CeilingHeight, "Autocalculate");
+      OS_ASSERT(result);
+    }
+
+    void Space_Impl::resetCeilingHeight() {
+      bool result = setString(OS_SpaceFields::CeilingHeight, "");
+      OS_ASSERT(result);
+    }
+
     bool Space_Impl::setVolume(double volume) {
       bool result = setDouble(OS_SpaceFields::Volume, volume);
       OS_ASSERT(result);
@@ -513,6 +529,22 @@ namespace model {
       OS_ASSERT(result);
     }
 
+    bool Space_Impl::setFloorArea(double floorArea) {
+      bool result = setDouble(OS_SpaceFields::FloorArea, floorArea);
+      OS_ASSERT(result);
+      return result;
+    }
+
+    void Space_Impl::autocalculateFloorArea() {
+      bool result = setString(OS_SpaceFields::FloorArea, "Autocalculate");
+      OS_ASSERT(result);
+    }
+
+    void Space_Impl::resetFloorArea() {
+      bool result = setString(OS_SpaceFields::FloorArea, "");
+      OS_ASSERT(result);
+    }
+
     boost::optional<SpaceType> Space_Impl::spaceType() const {
       boost::optional<SpaceType> result = getObject<ModelObject>().getModelObjectTarget<SpaceType>(OS_SpaceFields::SpaceTypeName);
       if (!result) {
@@ -867,19 +899,6 @@ namespace model {
       return result;
     }
 
-    double Space_Impl::floorArea() const {
-      double result = 0;
-      for (const Surface& surface : this->surfaces()) {
-        if (istringEqual(surface.surfaceType(), "Floor")) {
-          if (surface.isAirWall()) {
-            continue;
-          }
-          result += surface.grossArea();
-        }
-      }
-      return result;
-    }
-
     double Space_Impl::exteriorArea() const {
       double result = 0;
       for (const Surface& surface : this->surfaces()) {
@@ -922,22 +941,12 @@ namespace model {
       return isVolEnclosed;
     }
 
-    double Space_Impl::volume() const {
-      boost::optional<double> value = getDouble(OS_SpaceFields::Volume, true);
+    double Space_Impl::ceilingHeight() const {
+      boost::optional<double> value = getDouble(OS_SpaceFields::CeilingHeight, true);
       if (value) {
         return value.get();
       }
 
-      auto volumePoly = this->polyhedron();
-
-      auto [isVolEnclosed, edgesNot2] = volumePoly.isEnclosedVolume();
-      if (isVolEnclosed) {
-        return volumePoly.calcPolyhedronVolume();
-      }
-
-      LOG(Warn, briefDescription() << " is not enclosed, there are " << edgesNot2.size()
-                                   << " edges that aren't used exactly twice. Volume calculation will be potentially inaccurate");
-
       double result = 0;
 
       // TODO: need a better method
@@ -962,9 +971,45 @@ namespace model {
       if ((numRoof > 0) && (numFloor > 0)) {
         roofHeight /= numRoof;
         floorHeight /= numFloor;
-        result = (roofHeight - floorHeight) * this->floorArea();
+        result = roofHeight - floorHeight;
+      }
+
+      return result;
+    }
+
+    bool Space_Impl::isCeilingHeightDefaulted() const {
+      return isEmpty(OS_SpaceFields::CeilingHeight);
+    }
+
+    bool Space_Impl::isCeilingHeightAutocalculated() const {
+      bool result = false;
+      boost::optional<std::string> value = getString(OS_SpaceFields::CeilingHeight, true);
+      if (value) {
+        result = openstudio::istringEqual(value.get(), "Autocalculate");
+      }
+      return result;
+    }
+
+    double Space_Impl::volume() const {
+      boost::optional<double> value = getDouble(OS_SpaceFields::Volume, true);
+      if (value) {
+        return value.get();
+      }
+
+      auto volumePoly = this->polyhedron();
+
+      auto [isVolEnclosed, edgesNot2] = volumePoly.isEnclosedVolume();
+      if (isVolEnclosed) {
+        return volumePoly.calcPolyhedronVolume();
       }
 
+      LOG(Warn, briefDescription() << " is not enclosed, there are " << edgesNot2.size()
+                                   << " edges that aren't used exactly twice. Volume calculation will be potentially inaccurate");
+
+      double result = 0;
+
+      result = this->ceilingHeight() * this->floorArea();
+
       return result;
     }
 
@@ -981,6 +1026,37 @@ namespace model {
       return result;
     }
 
+    double Space_Impl::floorArea() const {
+      boost::optional<double> value = getDouble(OS_SpaceFields::FloorArea, true);
+      if (value) {
+        return value.get();
+      }
+
+      double result = 0;
+      for (const Surface& surface : this->surfaces()) {
+        if (istringEqual(surface.surfaceType(), "Floor")) {
+          if (surface.isAirWall()) {
+            continue;
+          }
+          result += surface.grossArea();
+        }
+      }
+      return result;
+    }
+
+    bool Space_Impl::isFloorAreaDefaulted() const {
+      return isEmpty(OS_SpaceFields::FloorArea);
+    }
+
+    bool Space_Impl::isFloorAreaAutocalculated() const {
+      bool result = false;
+      boost::optional<std::string> value = getString(OS_SpaceFields::FloorArea, true);
+      if (value) {
+        result = openstudio::istringEqual(value.get(), "Autocalculate");
+      }
+      return result;
+    }
+
     double Space_Impl::numberOfPeople() const {
       double result = 0.0;
       double area = floorArea();
@@ -2928,6 +3004,18 @@ namespace model {
     getImpl<detail::Space_Impl>()->resetPartofTotalFloorArea();
   }
 
+  bool Space::setCeilingHeight(double ceilingHeight) {
+    return getImpl<detail::Space_Impl>()->setCeilingHeight(ceilingHeight);
+  }
+
+  void Space::autocalculateCeilingHeight() {
+    getImpl<detail::Space_Impl>()->autocalculateCeilingHeight();
+  }
+
+  void Space::resetCeilingHeight() {
+    getImpl<detail::Space_Impl>()->resetCeilingHeight();
+  }
+
   bool Space::setVolume(double volume) {
     return getImpl<detail::Space_Impl>()->setVolume(volume);
   }
@@ -2940,6 +3028,18 @@ namespace model {
     getImpl<detail::Space_Impl>()->resetVolume();
   }
 
+  bool Space::setFloorArea(double floorArea) {
+    return getImpl<detail::Space_Impl>()->setFloorArea(floorArea);
+  }
+
+  void Space::autocalculateFloorArea() {
+    getImpl<detail::Space_Impl>()->autocalculateFloorArea();
+  }
+
+  void Space::resetFloorArea() {
+    getImpl<detail::Space_Impl>()->resetFloorArea();
+  }
+
   boost::optional<SpaceType> Space::spaceType() const {
     return getImpl<detail::Space_Impl>()->spaceType();
   }
@@ -3128,10 +3228,6 @@ namespace model {
     return getImpl<detail::Space_Impl>()->multiplier();
   }
 
-  double Space::floorArea() const {
-    return getImpl<detail::Space_Impl>()->floorArea();
-  }
-
   double Space::exteriorArea() const {
     return getImpl<detail::Space_Impl>()->exteriorArea();
   }
@@ -3140,6 +3236,18 @@ namespace model {
     return getImpl<detail::Space_Impl>()->exteriorWallArea();
   }
 
+  double Space::ceilingHeight() const {
+    return getImpl<detail::Space_Impl>()->ceilingHeight();
+  }
+
+  bool Space::isCeilingHeightDefaulted() const {
+    return getImpl<detail::Space_Impl>()->isCeilingHeightDefaulted();
+  }
+
+  bool Space::isCeilingHeightAutocalculated() const {
+    return getImpl<detail::Space_Impl>()->isCeilingHeightAutocalculated();
+  }
+
   double Space::volume() const {
     return getImpl<detail::Space_Impl>()->volume();
   }
@@ -3152,6 +3260,18 @@ namespace model {
     return getImpl<detail::Space_Impl>()->isVolumeAutocalculated();
   }
 
+  double Space::floorArea() const {
+    return getImpl<detail::Space_Impl>()->floorArea();
+  }
+
+  bool Space::isFloorAreaDefaulted() const {
+    return getImpl<detail::Space_Impl>()->isFloorAreaDefaulted();
+  }
+
+  bool Space::isFloorAreaAutocalculated() const {
+    return getImpl<detail::Space_Impl>()->isFloorAreaAutocalculated();
+  }
+
   double Space::numberOfPeople() const {
     return getImpl<detail::Space_Impl>()->numberOfPeople();
   }
diff --git a/src/model/Space.hpp b/src/model/Space.hpp
index 351668e85e9..b53ef9f1186 100644
--- a/src/model/Space.hpp
+++ b/src/model/Space.hpp
@@ -114,12 +114,24 @@ namespace model {
 
     void resetPartofTotalFloorArea();
 
+    bool setCeilingHeight(double ceilingHeight);
+
+    void autocalculateCeilingHeight();
+
+    void resetCeilingHeight();
+
     bool setVolume(double volume);
 
     void autocalculateVolume();
 
     void resetVolume();
 
+    bool setFloorArea(double floorArea);
+
+    void autocalculateFloorArea();
+
+    void resetFloorArea();
+
     //@}
     /** @name Other */
 
@@ -270,12 +282,6 @@ namespace model {
     /// Returns the multiplier for this space, comes from thermal zone, defaults to 1.
     int multiplier() const;
 
-    /// Returns the floor area (m^2).
-    /// Does not include area of floor surfaces which are air walls.
-    /// Does not consider if space is included in building floor area.
-    /// Does not include space multiplier in calculation.
-    double floorArea() const;
-
     /// Returns the exterior area (gross area of surfaces with outdoor boundary condition) (m^2).
     /// Does not include space multiplier in calculation.
     double exteriorArea() const;
@@ -284,6 +290,14 @@ namespace model {
     /// Does not include space multiplier in calculation.
     double exteriorWallArea() const;
 
+    /// Returns the ceiling height (m).
+    /// Does not include space multiplier in calculation.
+    double ceilingHeight() const;
+
+    bool isCeilingHeightDefaulted() const;
+
+    bool isCeilingHeightAutocalculated() const;
+
     /// Returns the volume (m^3).
     /// Does not include space multiplier in calculation.
     double volume() const;
@@ -292,6 +306,16 @@ namespace model {
 
     bool isVolumeAutocalculated() const;
 
+    /// Returns the floor area (m^2).
+    /// Does not include area of floor surfaces which are air walls.
+    /// Does not consider if space is included in building floor area.
+    /// Does not include space multiplier in calculation.
+    double floorArea() const;
+
+    bool isFloorAreaDefaulted() const;
+
+    bool isFloorAreaAutocalculated() const;
+
     /** Returns the number of people in the space (people). */
     /// Does not include space multiplier in calculation.
     /// Does include people multiplier in calculation.
diff --git a/src/model/Space_Impl.hpp b/src/model/Space_Impl.hpp
index 289f9977470..0b44459b37a 100644
--- a/src/model/Space_Impl.hpp
+++ b/src/model/Space_Impl.hpp
@@ -166,12 +166,24 @@ namespace model {
 
       void resetPartofTotalFloorArea();
 
+      bool setCeilingHeight(double ceilingHeight);
+
+      void autocalculateCeilingHeight();
+
+      void resetCeilingHeight();
+
       bool setVolume(double volume);
 
       void autocalculateVolume();
 
       void resetVolume();
 
+      bool setFloorArea(double floorArea);
+
+      void autocalculateFloorArea();
+
+      void resetFloorArea();
+
       //@}
 
       /// Returns the space type for this space.
@@ -321,18 +333,28 @@ namespace model {
       /// Returns the multiplier for this space, comes from thermal zone, defaults to 1.
       int multiplier() const;
 
-      double floorArea() const;
-
       double exteriorArea() const;
 
       double exteriorWallArea() const;
 
+      double ceilingHeight() const;
+
+      bool isCeilingHeightDefaulted() const;
+
+      bool isCeilingHeightAutocalculated() const;
+
       double volume() const;
 
       bool isVolumeDefaulted() const;
 
       bool isVolumeAutocalculated() const;
 
+      double floorArea() const;
+
+      bool isFloorAreaDefaulted() const;
+
+      bool isFloorAreaAutocalculated() const;
+
       double numberOfPeople() const;
 
       bool setNumberOfPeople(double numberOfPeople);


Test patch:
diff --git a/src/model/test/Space_GTest.cpp b/src/model/test/Space_GTest.cpp
index 5b95a242c36..9163b7dea3a 100644
--- a/src/model/test/Space_GTest.cpp
+++ b/src/model/test/Space_GTest.cpp
@@ -2782,7 +2782,7 @@ TEST_F(ModelFixture, ExposedPerimeter) {
   }
 }
 
-TEST_F(ModelFixture, Space_setVolume) {
+TEST_F(ModelFixture, Space_setVolumeAndCeilingHeightAndFloorArea) {
   // create from floor print
   Model model;
   Point3dVector floorPrint;
@@ -2797,30 +2797,39 @@ TEST_F(ModelFixture, Space_setVolume) {
   // check dimensions
   EXPECT_TRUE(space.isVolumeAutocalculated());
   EXPECT_TRUE(space.isVolumeDefaulted());
+  EXPECT_TRUE(space.isCeilingHeightAutocalculated());
+  EXPECT_TRUE(space.isCeilingHeightDefaulted());
+  EXPECT_TRUE(space.isFloorAreaAutocalculated());
+  EXPECT_TRUE(space.isFloorAreaDefaulted());
   EXPECT_DOUBLE_EQ(100.0, space.floorArea());
   EXPECT_DOUBLE_EQ(360.0, space.volume());
+  EXPECT_DOUBLE_EQ(3.6, space.ceilingHeight());
   EXPECT_DOUBLE_EQ(144.0, space.exteriorWallArea());
   EXPECT_DOUBLE_EQ(244.0, space.exteriorArea());  // ground does not count
 
-  // set volume
+  // VOLUME
+
+  // set
   EXPECT_TRUE(space.setVolume(365.0));
   EXPECT_FALSE(space.isVolumeAutocalculated());
   EXPECT_FALSE(space.isVolumeDefaulted());
   EXPECT_DOUBLE_EQ(100.0, space.floorArea());
   EXPECT_DOUBLE_EQ(365.0, space.volume());
+  EXPECT_DOUBLE_EQ(3.6, space.ceilingHeight());
   EXPECT_DOUBLE_EQ(144.0, space.exteriorWallArea());
   EXPECT_DOUBLE_EQ(244.0, space.exteriorArea());  // ground does not count
 
-  // reset volume
+  // reset
   space.resetVolume();
   EXPECT_TRUE(space.isVolumeAutocalculated());
   EXPECT_TRUE(space.isVolumeDefaulted());
   EXPECT_DOUBLE_EQ(100.0, space.floorArea());
   EXPECT_DOUBLE_EQ(360.0, space.volume());
+  EXPECT_DOUBLE_EQ(3.6, space.ceilingHeight());
   EXPECT_DOUBLE_EQ(144.0, space.exteriorWallArea());
   EXPECT_DOUBLE_EQ(244.0, space.exteriorArea());  // ground does not count
 
-  // autocalculate volume
+  // autocalculate
   EXPECT_TRUE(space.setVolume(370.0));
   EXPECT_FALSE(space.isVolumeAutocalculated());
   EXPECT_FALSE(space.isVolumeDefaulted());
@@ -2829,6 +2838,77 @@ TEST_F(ModelFixture, Space_setVolume) {
   EXPECT_FALSE(space.isVolumeDefaulted());
   EXPECT_DOUBLE_EQ(100.0, space.floorArea());
   EXPECT_DOUBLE_EQ(360.0, space.volume());
+  EXPECT_DOUBLE_EQ(3.6, space.ceilingHeight());
+  EXPECT_DOUBLE_EQ(144.0, space.exteriorWallArea());
+  EXPECT_DOUBLE_EQ(244.0, space.exteriorArea());  // ground does not count
+
+  // CEILING HEIGHT
+
+  // set
+  EXPECT_TRUE(space.setCeilingHeight(8.0));
+  EXPECT_FALSE(space.isCeilingHeightAutocalculated());
+  EXPECT_FALSE(space.isCeilingHeightDefaulted());
+  EXPECT_DOUBLE_EQ(100.0, space.floorArea());
+  EXPECT_DOUBLE_EQ(360.0, space.volume());
+  EXPECT_DOUBLE_EQ(8.0, space.ceilingHeight());
+  EXPECT_DOUBLE_EQ(144.0, space.exteriorWallArea());
+  EXPECT_DOUBLE_EQ(244.0, space.exteriorArea());  // ground does not count
+
+  // reset
+  space.resetCeilingHeight();
+  EXPECT_TRUE(space.isCeilingHeightAutocalculated());
+  EXPECT_TRUE(space.isCeilingHeightDefaulted());
+  EXPECT_DOUBLE_EQ(100.0, space.floorArea());
+  EXPECT_DOUBLE_EQ(360.0, space.volume());
+  EXPECT_DOUBLE_EQ(3.6, space.ceilingHeight());
+  EXPECT_DOUBLE_EQ(144.0, space.exteriorWallArea());
+  EXPECT_DOUBLE_EQ(244.0, space.exteriorArea());  // ground does not count
+
+  // autocalculate
+  EXPECT_TRUE(space.setCeilingHeight(9.0));
+  EXPECT_FALSE(space.isCeilingHeightAutocalculated());
+  EXPECT_FALSE(space.isCeilingHeightDefaulted());
+  space.autocalculateCeilingHeight();
+  EXPECT_TRUE(space.isCeilingHeightAutocalculated());
+  EXPECT_FALSE(space.isCeilingHeightDefaulted());
+  EXPECT_DOUBLE_EQ(100.0, space.floorArea());
+  EXPECT_DOUBLE_EQ(360.0, space.volume());
+  EXPECT_DOUBLE_EQ(3.6, space.ceilingHeight());
+  EXPECT_DOUBLE_EQ(144.0, space.exteriorWallArea());
+  EXPECT_DOUBLE_EQ(244.0, space.exteriorArea());  // ground does not count
+
+  // FLOOR AREA
+
+  // set
+  EXPECT_TRUE(space.setFloorArea(400.0));
+  EXPECT_FALSE(space.isFloorAreaAutocalculated());
+  EXPECT_FALSE(space.isFloorAreaDefaulted());
+  EXPECT_DOUBLE_EQ(400.0, space.floorArea());
+  EXPECT_DOUBLE_EQ(360.0, space.volume());
+  EXPECT_DOUBLE_EQ(3.6, space.ceilingHeight());
+  EXPECT_DOUBLE_EQ(144.0, space.exteriorWallArea());
+  EXPECT_DOUBLE_EQ(244.0, space.exteriorArea());  // ground does not count
+
+  // reset
+  space.resetFloorArea();
+  EXPECT_TRUE(space.isFloorAreaAutocalculated());
+  EXPECT_TRUE(space.isFloorAreaDefaulted());
+  EXPECT_DOUBLE_EQ(100.0, space.floorArea());
+  EXPECT_DOUBLE_EQ(360.0, space.volume());
+  EXPECT_DOUBLE_EQ(3.6, space.ceilingHeight());
+  EXPECT_DOUBLE_EQ(144.0, space.exteriorWallArea());
+  EXPECT_DOUBLE_EQ(244.0, space.exteriorArea());  // ground does not count
+
+  // autocalculate
+  EXPECT_TRUE(space.setFloorArea(500.0));
+  EXPECT_FALSE(space.isFloorAreaAutocalculated());
+  EXPECT_FALSE(space.isFloorAreaDefaulted());
+  space.autocalculateFloorArea();
+  EXPECT_TRUE(space.isFloorAreaAutocalculated());
+  EXPECT_FALSE(space.isFloorAreaDefaulted());
+  EXPECT_DOUBLE_EQ(100.0, space.floorArea());
+  EXPECT_DOUBLE_EQ(360.0, space.volume());
+  EXPECT_DOUBLE_EQ(3.6, space.ceilingHeight());
   EXPECT_DOUBLE_EQ(144.0, space.exteriorWallArea());
   EXPECT_DOUBLE_EQ(244.0, space.exteriorArea());  // ground does not count
 }