diff --git a/src/osversion/VersionTranslator.cpp b/src/osversion/VersionTranslator.cpp index 0e4f3897f21..1b8531422fc 100644 --- a/src/osversion/VersionTranslator.cpp +++ b/src/osversion/VersionTranslator.cpp @@ -8960,6 +8960,10 @@ namespace osversion { IdfFile targetIdf(idd_3_8_0.iddFile()); ss << targetIdf.versionObject().get(); + constexpr std::array hx_old_100effectiveness_idxs{4, 5, 8, 9}; + constexpr std::array hx_new_effectiveness_curves_idxs{20, 21, 22, 23}; + constexpr std::array hx_new_table_names{"SensHeat", "LatHeat", "SensCool", "LatCool"}; + for (const IdfObject& object : idf_3_7_0.objects()) { auto iddname = object.iddObject().name(); @@ -8998,30 +9002,32 @@ namespace osversion { } } - std::string varListHandle = toString(createUUID()); - std::vector e_idxs = {4, 5, 8, 9}; - std::vector c_idxs = {20, 21, 22, 23}; + const std::string varListHandle = toString(createUUID()); bool tableAdded = false; - for (size_t i = 0; i < e_idxs.size(); ++i) { - if (auto e100 = object.getDouble(e_idxs[i])) { // Sensible/Latent Effectiveness at 100% Heating/Cooling Air Flow {dimensionless} - if (auto e75 = object.getDouble(e_idxs[i] + 2)) { // Sensible/Latent Effectiveness at 75% Heating/Cooling Air Flow {dimensionless} + for (size_t i = 0; i < hx_old_100effectiveness_idxs.size(); ++i) { + // Sensible/Latent Effectiveness at 100% Heating/Cooling Air Flow {dimensionless} + if (auto e100 = object.getDouble(hx_old_100effectiveness_idxs[i])) { + // Sensible/Latent Effectiveness at 75% Heating/Cooling Air Flow {dimensionless} + + if (auto e75 = object.getDouble(hx_old_100effectiveness_idxs[i] + 2)) { if (e100.get() != e75.get()) { tableAdded = true; IdfObject tableLookup(idd_3_8_0.getObject("OS:Table:Lookup").get()); std::string uuid = toString(createUUID()); - tableLookup.setString(0, uuid); // Handle - tableLookup.setString(1, object.nameString() + "_" + std::to_string(i + 1)); // Name - tableLookup.setString(2, varListHandle); // Independent Variable List Name - tableLookup.setString(3, "DivisorOnly"); // Normalization Method - tableLookup.setDouble(4, e100.get()); // Normalization Divisor - tableLookup.setDouble(5, 0.0); // Minimum Output - tableLookup.setDouble(6, 10.0); // Maximum Output - tableLookup.setString(7, "Dimensionless"); // Output Unit Type - tableLookup.pushExtensibleGroup().setDouble(0, e75.get()); // Output Value 1 - tableLookup.pushExtensibleGroup().setDouble(0, e100.get()); // Output Value 2 - - newObject.setString(c_idxs[i], uuid); // Sensible/Latent Effectiveness of Heating/Cooling Air Flow Curve Name + tableLookup.setString(0, uuid); // Handle + tableLookup.setString(1, fmt::format("{}_{}Eff", object.nameString(), hx_new_table_names[i])); // Name + tableLookup.setString(2, varListHandle); // Independent Variable List Name + tableLookup.setString(3, "DivisorOnly"); // Normalization Method + tableLookup.setDouble(4, e100.get()); // Normalization Divisor + tableLookup.setDouble(5, 0.0); // Minimum Output + tableLookup.setDouble(6, 10.0); // Maximum Output + tableLookup.setString(7, "Dimensionless"); // Output Unit Type + tableLookup.pushExtensibleGroup().setDouble(0, e75.get()); // Output Value 1 + tableLookup.pushExtensibleGroup().setDouble(0, e100.get()); // Output Value 2 + + // Sensible/Latent Effectiveness of Heating/Cooling Air Flow Curve Name + newObject.setString(hx_new_effectiveness_curves_idxs[i], uuid); ss << tableLookup; m_new.push_back(tableLookup); @@ -9030,8 +9036,8 @@ namespace osversion { } } - m_refactored.push_back(RefactoredObjectData(object, newObject)); ss << newObject; + m_refactored.emplace_back(object, std::move(newObject)); if (tableAdded) { IdfObject varList(idd_3_8_0.getObject("OS:ModelObjectList").get()); @@ -9051,11 +9057,11 @@ namespace osversion { var.pushExtensibleGroup().setDouble(0, 0.75); // Value 1 var.pushExtensibleGroup().setDouble(0, 1.0); // Value 2 - m_new.push_back(varList); ss << varList; + m_new.emplace_back(std::move(varList)); - m_new.push_back(var); ss << var; + m_new.emplace_back(std::move(var)); } // No-op diff --git a/src/osversion/test/3_8_0/test_vt_HeatExchangerAirToAirSensibleAndLatent.osm b/src/osversion/test/3_8_0/test_vt_HeatExchangerAirToAirSensibleAndLatent.osm index c302dbf0ae7..3e1852fdb07 100644 --- a/src/osversion/test/3_8_0/test_vt_HeatExchangerAirToAirSensibleAndLatent.osm +++ b/src/osversion/test/3_8_0/test_vt_HeatExchangerAirToAirSensibleAndLatent.osm @@ -1,25 +1,25 @@ OS:Version, - {5a8dca7f-9180-4865-acc0-eac9963d8ef3}, !- Handle + {35621888-8471-4654-b196-7a10e6d60d77}, !- Handle 3.7.0; !- Version Identifier OS:HeatExchanger:AirToAir:SensibleAndLatent, - {e04c7943-5596-465d-878a-0db9f84f6c93}, !- Handle - Heat Exchanger Air To Air Sensible And Latent 1, !- Name - {47eea206-1ff3-4b61-88b1-7bc9ead8760a}, !- Availability Schedule + {67e2de0d-3ea9-42c1-88b8-0a04128deac9}, !- Handle + ERV, !- Name + {2a77b641-92f2-4915-a135-3d358f2ed6d0}, !- Availability Schedule autosize, !- Nominal Supply Air Flow Rate {m3/s} 0.76, !- Sensible Effectiveness at 100% Heating Air Flow {dimensionless} 0.68, !- Latent Effectiveness at 100% Heating Air Flow {dimensionless} 0.81, !- Sensible Effectiveness at 75% Heating Air Flow {dimensionless} 0.73, !- Latent Effectiveness at 75% Heating Air Flow {dimensionless} - 0.76, !- Sensible Effectiveness at 100% Cooling Air Flow {dimensionless} - 0.68, !- Latent Effectiveness at 100% Cooling Air Flow {dimensionless} - 0.81, !- Sensible Effectiveness at 75% Cooling Air Flow {dimensionless} - 0.73, !- Latent Effectiveness at 75% Cooling Air Flow {dimensionless} - , !- Supply Air Inlet Node - , !- Supply Air Outlet Node - , !- Exhaust Air Inlet Node - , !- Exhaust Air Outlet Node + 0.74, !- Sensible Effectiveness at 100% Cooling Air Flow {dimensionless} + 0.67, !- Latent Effectiveness at 100% Cooling Air Flow {dimensionless} + 0.8, !- Sensible Effectiveness at 75% Cooling Air Flow {dimensionless} + 0.72, !- Latent Effectiveness at 75% Cooling Air Flow {dimensionless} + {0a300f71-b1bc-4ad0-b33d-78538aba9f4d}, !- Supply Air Inlet Node + {d8090337-7cf3-4469-91e6-4cf247eb4a14}, !- Supply Air Outlet Node + {96f29526-15b8-419d-9d22-18e2f34655b7}, !- Exhaust Air Inlet Node + {34c68d89-61b1-4354-9845-2bcbfa55bdde}, !- Exhaust Air Outlet Node 0, !- Nominal Electric Power {W} Yes, !- Supply Air Outlet Temperature Control Plate, !- Heat Exchanger Type @@ -27,19 +27,133 @@ OS:HeatExchanger:AirToAir:SensibleAndLatent, 1.7, !- Threshold Temperature {C} , !- Initial Defrost Time Fraction {dimensionless} , !- Rate of Defrost Time Fraction Increase {1/K} - Yes; !- Economizer Lockout + No; !- Economizer Lockout OS:Schedule:Constant, - {47eea206-1ff3-4b61-88b1-7bc9ead8760a}, !- Handle + {2a77b641-92f2-4915-a135-3d358f2ed6d0}, !- Handle Always On Discrete, !- Name - {f1aa0f40-39f0-4ad4-a148-2ca756a8d74f}, !- Schedule Type Limits Name + {424ab631-0001-433e-a6c6-3c9bf194df94}, !- Schedule Type Limits Name 1; !- Value OS:ScheduleTypeLimits, - {f1aa0f40-39f0-4ad4-a148-2ca756a8d74f}, !- Handle + {424ab631-0001-433e-a6c6-3c9bf194df94}, !- Handle OnOff, !- Name 0, !- Lower Limit Value 1, !- Upper Limit Value Discrete, !- Numeric Type Availability; !- Unit Type +OS:Controller:OutdoorAir, + {2f48a111-690e-4cac-a0c4-4a7daaf03f94}, !- Handle + Controller Outdoor Air 1, !- Name + , !- Relief Air Outlet Node Name + , !- Return Air Node Name + , !- Mixed Air Node Name + , !- Actuator Node Name + 0, !- Minimum Outdoor Air Flow Rate {m3/s} + Autosize, !- Maximum Outdoor Air Flow Rate {m3/s} + NoEconomizer, !- Economizer Control Type + ModulateFlow, !- Economizer Control Action Type + 28, !- Economizer Maximum Limit Dry-Bulb Temperature {C} + 64000, !- Economizer Maximum Limit Enthalpy {J/kg} + , !- Economizer Maximum Limit Dewpoint Temperature {C} + , !- Electronic Enthalpy Limit Curve Name + -100, !- Economizer Minimum Limit Dry-Bulb Temperature {C} + NoLockout, !- Lockout Type + FixedMinimum, !- Minimum Limit Type + , !- Minimum Outdoor Air Schedule Name + , !- Minimum Fraction of Outdoor Air Schedule Name + , !- Maximum Fraction of Outdoor Air Schedule Name + {5b6f1b3f-2d43-4874-8e80-1f863931595b}, !- Controller Mechanical Ventilation + , !- Time of Day Economizer Control Schedule Name + No, !- High Humidity Control + , !- Humidistat Control Zone Name + , !- High Humidity Outdoor Air Flow Ratio + , !- Control High Indoor Humidity Based on Outdoor Humidity Ratio + BypassWhenWithinEconomizerLimits, !- Heat Recovery Bypass Control Type + InterlockedWithMechanicalCooling; !- Economizer Operation Staging + +OS:Controller:MechanicalVentilation, + {5b6f1b3f-2d43-4874-8e80-1f863931595b}, !- Handle + Controller Mechanical Ventilation 1, !- Name + {2a77b641-92f2-4915-a135-3d358f2ed6d0}, !- Availability Schedule + , !- Demand Controlled Ventilation + ; !- System Outdoor Air Method + +OS:AirLoopHVAC:OutdoorAirSystem, + {a5b85d9c-2fc9-4b26-aa5c-da16db98efaa}, !- Handle + Air Loop HVAC Outdoor Air System 1, !- Name + {2f48a111-690e-4cac-a0c4-4a7daaf03f94}, !- Controller Name + , !- Outdoor Air Equipment List Name + , !- Availability Manager List Name + , !- Mixed Air Node Name + {d5901fbe-722e-4175-810f-d57fef602118}, !- Outdoor Air Stream Node Name + {c8a3f5a9-2e0b-43b2-abb7-d71fb91d455f}, !- Relief Air Stream Node Name + ; !- Return Air Stream Node Name + +OS:Node, + {97f5f18a-aef2-498e-9178-a51afbe800f2}, !- Handle + Outboard OA Node, !- Name + , !- Inlet Port + {0a300f71-b1bc-4ad0-b33d-78538aba9f4d}; !- Outlet Port + +OS:Node, + {eaed6165-9257-4d9a-ae4f-acf7c2f2397f}, !- Handle + Relief Node, !- Name + {34c68d89-61b1-4354-9845-2bcbfa55bdde}, !- Inlet Port + ; !- Outlet Port + +OS:Node, + {90d802c8-2719-485c-a00b-a18a2e352174}, !- Handle + Node 2, !- Name + {d8090337-7cf3-4469-91e6-4cf247eb4a14}, !- Inlet Port + {d5901fbe-722e-4175-810f-d57fef602118}; !- Outlet Port + +OS:Connection, + {0a300f71-b1bc-4ad0-b33d-78538aba9f4d}, !- Handle + {97f5f18a-aef2-498e-9178-a51afbe800f2}, !- Source Object + 3, !- Outlet Port + {67e2de0d-3ea9-42c1-88b8-0a04128deac9}, !- Target Object + 12; !- Inlet Port + +OS:Connection, + {d8090337-7cf3-4469-91e6-4cf247eb4a14}, !- Handle + {67e2de0d-3ea9-42c1-88b8-0a04128deac9}, !- Source Object + 13, !- Outlet Port + {90d802c8-2719-485c-a00b-a18a2e352174}, !- Target Object + 2; !- Inlet Port + +OS:Connection, + {d5901fbe-722e-4175-810f-d57fef602118}, !- Handle + {90d802c8-2719-485c-a00b-a18a2e352174}, !- Source Object + 3, !- Outlet Port + {a5b85d9c-2fc9-4b26-aa5c-da16db98efaa}, !- Target Object + 6; !- Inlet Port + +OS:Node, + {381769e1-53aa-4267-abed-5d8adb16f251}, !- Handle + Node 3, !- Name + {c8a3f5a9-2e0b-43b2-abb7-d71fb91d455f}, !- Inlet Port + {96f29526-15b8-419d-9d22-18e2f34655b7}; !- Outlet Port + +OS:Connection, + {c8a3f5a9-2e0b-43b2-abb7-d71fb91d455f}, !- Handle + {a5b85d9c-2fc9-4b26-aa5c-da16db98efaa}, !- Source Object + 7, !- Outlet Port + {381769e1-53aa-4267-abed-5d8adb16f251}, !- Target Object + 2; !- Inlet Port + +OS:Connection, + {96f29526-15b8-419d-9d22-18e2f34655b7}, !- Handle + {381769e1-53aa-4267-abed-5d8adb16f251}, !- Source Object + 3, !- Outlet Port + {67e2de0d-3ea9-42c1-88b8-0a04128deac9}, !- Target Object + 14; !- Inlet Port + +OS:Connection, + {34c68d89-61b1-4354-9845-2bcbfa55bdde}, !- Handle + {67e2de0d-3ea9-42c1-88b8-0a04128deac9}, !- Source Object + 15, !- Outlet Port + {eaed6165-9257-4d9a-ae4f-acf7c2f2397f}, !- Target Object + 2; !- Inlet Port + diff --git a/src/osversion/test/3_8_0/test_vt_HeatExchangerAirToAirSensibleAndLatent.rb b/src/osversion/test/3_8_0/test_vt_HeatExchangerAirToAirSensibleAndLatent.rb index d14c87b7ca0..b0addc1d250 100644 --- a/src/osversion/test/3_8_0/test_vt_HeatExchangerAirToAirSensibleAndLatent.rb +++ b/src/osversion/test/3_8_0/test_vt_HeatExchangerAirToAirSensibleAndLatent.rb @@ -5,5 +5,28 @@ m = Model.new hx = HeatExchangerAirToAirSensibleAndLatent.new(m) +hx.setName("ERV") -m.save('test_vt_HeatExchangerAirToAirSensibleAndLatent.osm', true) \ No newline at end of file +hx.autosizeNominalSupplyAirFlowRate + +hx.setSensibleEffectivenessat100HeatingAirFlow(0.76) +hx.setLatentEffectivenessat100HeatingAirFlow(0.68) + +hx.setSensibleEffectivenessat75HeatingAirFlow(0.81) +hx.setLatentEffectivenessat75HeatingAirFlow(0.73) + +hx.setSensibleEffectivenessat100CoolingAirFlow(0.74) +hx.setLatentEffectivenessat100CoolingAirFlow(0.67) + +hx.setSensibleEffectivenessat75CoolingAirFlow(0.80) +hx.setLatentEffectivenessat75CoolingAirFlow(0.72) + +# Field right after is the supply air inlet node +controller = ControllerOutdoorAir.new(m) +oaSystem = AirLoopHVACOutdoorAirSystem.new(m, controller) +hx.addToNode(oaSystem.outboardOANode.get) + +# Last field +hx.setEconomizerLockout(false) + +m.save('test_vt_HeatExchangerAirToAirSensibleAndLatent.osm', true) diff --git a/src/osversion/test/VersionTranslator_GTest.cpp b/src/osversion/test/VersionTranslator_GTest.cpp index 4f54433e734..a0db9801537 100644 --- a/src/osversion/test/VersionTranslator_GTest.cpp +++ b/src/osversion/test/VersionTranslator_GTest.cpp @@ -4036,40 +4036,39 @@ TEST_F(OSVersionFixture, update_3_7_0_to_3_8_0_HeatExchangerAirToAirSensibleAndL ASSERT_EQ(1u, hxs.size()); WorkspaceObject hx = hxs[0]; - EXPECT_EQ("Heat Exchanger Air To Air Sensible And Latent 1", hx.getString(1).get()); // Name - EXPECT_EQ("Always On Discrete", hx.getTarget(2)->nameString()); // Availability Schedule - EXPECT_EQ("autosize", hx.getString(3).get()); // Nominal Supply Air Flow Rate - EXPECT_EQ(0.76, hx.getDouble(4).get()); // Sensible Effectiveness at 100% Heating Air Flow - EXPECT_EQ(0.68, hx.getDouble(5).get()); // Latent Effectiveness at 100% Heating Air Flow - EXPECT_EQ(0.76, hx.getDouble(6).get()); // Sensible Effectiveness at 100% Cooling Air Flow - EXPECT_EQ(0.68, hx.getDouble(7).get()); // Latent Effectiveness at 100% Cooling Air Flow - EXPECT_TRUE(hx.isEmpty(8)); // Supply Air Inlet Node - EXPECT_TRUE(hx.isEmpty(9)); // Supply Air Outlet Node - EXPECT_TRUE(hx.isEmpty(10)); // Exhaust Air Inlet Node - EXPECT_TRUE(hx.isEmpty(11)); // Exhaust Air Outlet Node - EXPECT_EQ(0, hx.getDouble(12).get()); // Nominal Electric Power - EXPECT_EQ("Yes", hx.getString(13).get()); // Supply Air Outlet Temperature Control - EXPECT_EQ("Plate", hx.getString(14).get()); // Heat Exchanger Type - EXPECT_EQ("None", hx.getString(15).get()); // Frost Control Type - EXPECT_EQ(1.7, hx.getDouble(16).get()); // Threshold Temperature - EXPECT_TRUE(hx.isEmpty(17)); // Initial Defrost Time Fraction - EXPECT_TRUE(hx.isEmpty(18)); // Rate of Defrost Time Fraction Increase - EXPECT_EQ("Yes", hx.getString(19).get()); // Economizer Lockout - EXPECT_EQ("Heat Exchanger Air To Air Sensible And Latent 1_1", + EXPECT_EQ("ERV", hx.getString(1).get()); // Name + EXPECT_EQ("Always On Discrete", hx.getTarget(2)->nameString()); // Availability Schedule + EXPECT_EQ("autosize", hx.getString(3).get()); // Nominal Supply Air Flow Rate + EXPECT_EQ(0.76, hx.getDouble(4).get()); // Sensible Effectiveness at 100% Heating Air Flow + EXPECT_EQ(0.68, hx.getDouble(5).get()); // Latent Effectiveness at 100% Heating Air Flow + EXPECT_EQ(0.74, hx.getDouble(6).get()); // Sensible Effectiveness at 100% Cooling Air Flow + EXPECT_EQ(0.67, hx.getDouble(7).get()); // Latent Effectiveness at 100% Cooling Air Flow + // Supply Air Inlet Node + EXPECT_FALSE(hx.isEmpty(8)); + EXPECT_EQ("Outboard OA Node", hx.getTarget(8)->getTarget(OS_ConnectionFields::SourceObject)->nameString()); + EXPECT_FALSE(hx.isEmpty(9)); // Supply Air Outlet Node + EXPECT_FALSE(hx.isEmpty(10)); // Exhaust Air Inlet Node + EXPECT_FALSE(hx.isEmpty(11)); + // Exhaust Air Outlet Node + EXPECT_EQ("Relief Node", hx.getTarget(11)->getTarget(OS_ConnectionFields::TargetObject)->nameString()); + + // Former last field + EXPECT_EQ("No", hx.getString(19).get()); // Economizer Lockout + EXPECT_EQ("ERV_SensHeatEff", hx.getTarget(20)->nameString()); // Sensible Effectiveness of Heating Air Flow Curve Name - EXPECT_EQ("Heat Exchanger Air To Air Sensible And Latent 1_2", + EXPECT_EQ("ERV_LatHeatEff", hx.getTarget(21)->nameString()); // Latent Effectiveness of Heating Air Flow Curve Name - EXPECT_EQ("Heat Exchanger Air To Air Sensible And Latent 1_3", + EXPECT_EQ("ERV_SensCoolEff", hx.getTarget(22)->nameString()); // Sensible Effectiveness of Cooling Air Flow Curve Name - EXPECT_EQ("Heat Exchanger Air To Air Sensible And Latent 1_4", + EXPECT_EQ("ERV_LatCoolEff", hx.getTarget(23)->nameString()); // Latent Effectiveness of Cooling Air Flow Curve Name std::vector tableLookups = model->getObjectsByType("OS:Table:Lookup"); ASSERT_EQ(4u, tableLookups.size()); - auto& tableLookup = tableLookups.front(); + auto tableLookup = hx.getTarget(20).get(); - EXPECT_EQ("Heat Exchanger Air To Air Sensible And Latent 1_1", tableLookup.nameString()); // Name - EXPECT_EQ("Heat Exchanger Air To Air Sensible And Latent 1_IndependentVariableList", + EXPECT_EQ("ERV_SensHeatEff", tableLookup.nameString()); // Name + EXPECT_EQ("ERV_IndependentVariableList", tableLookup.getTarget(2)->nameString()); // Independent Variable List Name EXPECT_EQ("DivisorOnly", tableLookup.getString(3).get()); // Normalization Method EXPECT_EQ(0.76, tableLookup.getDouble(4).get()); // Normalization Divisor @@ -4089,26 +4088,26 @@ TEST_F(OSVersionFixture, update_3_7_0_to_3_8_0_HeatExchangerAirToAirSensibleAndL ASSERT_EQ(1u, varLists.size()); WorkspaceObject varList = varLists[0]; - EXPECT_EQ("Heat Exchanger Air To Air Sensible And Latent 1_IndependentVariableList", varList.nameString()); // Name + EXPECT_EQ("ERV_IndependentVariableList", varList.nameString()); // Name ASSERT_EQ(1, varList.numExtensibleGroups()); auto var_ = varList.extensibleGroups().front().cast().getTarget(0); // Model Object 1 ASSERT_TRUE(var_); - EXPECT_EQ("Heat Exchanger Air To Air Sensible And Latent 1_IndependentVariable", var_->nameString()); + EXPECT_EQ("ERV_IndependentVariable", var_->nameString()); std::vector vars = model->getObjectsByType("OS:Table:IndependentVariable"); ASSERT_EQ(1u, vars.size()); WorkspaceObject var = vars[0]; - EXPECT_EQ("Heat Exchanger Air To Air Sensible And Latent 1_IndependentVariable", var.nameString()); // Name - EXPECT_EQ("Linear", var.getString(2).get()); // Interpolation Method - EXPECT_EQ("Linear", var.getString(3).get()); // Extrapolation Method - EXPECT_EQ(0.0, var.getDouble(4).get()); // Minimum Value - EXPECT_EQ(10.0, var.getDouble(5).get()); // Maximum Value - EXPECT_TRUE(var.isEmpty(6)); // Normalization Reference Value - EXPECT_EQ("Dimensionless", var.getString(7).get()); // Unit Type - EXPECT_TRUE(var.isEmpty(8)); // External File Name - EXPECT_TRUE(var.isEmpty(9)); // External File Column Number - EXPECT_TRUE(var.isEmpty(10)); // External File Starting Row Number + EXPECT_EQ("ERV_IndependentVariable", var.nameString()); // Name + EXPECT_EQ("Linear", var.getString(2).get()); // Interpolation Method + EXPECT_EQ("Linear", var.getString(3).get()); // Extrapolation Method + EXPECT_EQ(0.0, var.getDouble(4).get()); // Minimum Value + EXPECT_EQ(10.0, var.getDouble(5).get()); // Maximum Value + EXPECT_TRUE(var.isEmpty(6)); // Normalization Reference Value + EXPECT_EQ("Dimensionless", var.getString(7).get()); // Unit Type + EXPECT_TRUE(var.isEmpty(8)); // External File Name + EXPECT_TRUE(var.isEmpty(9)); // External File Column Number + EXPECT_TRUE(var.isEmpty(10)); // External File Starting Row Number ASSERT_EQ(2, var.numExtensibleGroups()); auto eg4 = var.extensibleGroups()[0]; EXPECT_EQ(0.75, eg4.getDouble(0).get()); // Value 1