bool ScheduleYear_Impl::setScheduleTypeLimits(const ScheduleTypeLimits& scheduleTypeLimits) { if (scheduleTypeLimits.model() != model()) { return false; } if (!candidateIsCompatibleWithCurrentUse(scheduleTypeLimits)) { return false; } return setPointer(OS_Schedule_YearFields::ScheduleTypeLimitsName, scheduleTypeLimits.handle()); }
TEST_F(ModelFixture, ComponentWatcher_FromScratch) { // create schedule component Model justASchedule; ScheduleTypeLimits typeLimits(justASchedule); typeLimits.setName("Fraction"); typeLimits.setLowerLimitValue(0.0); typeLimits.setUpperLimitValue(1.0); typeLimits.setNumericType("Continuous"); ScheduleCompact schedule(justASchedule); EXPECT_TRUE(schedule.setPointer(OS_Schedule_CompactFields::ScheduleTypeLimitsName, typeLimits.handle())); Component scheduleComponent = schedule.createComponent(); // create model with Lights objects and insert schedule component Model justLights; LightsDefinition lightsDefinition(justLights); Lights light1(lightsDefinition); OptionalComponentData ocd = justLights.insertComponent(scheduleComponent); // get ComponentData object ASSERT_TRUE(ocd); ComponentData componentData = *ocd; UUID versionUUID = componentData.versionUUID(); // setting lighting schedule does not invalidate schedule component, or change its version UUID OptionalScheduleCompact oSchedule = componentData.primaryComponentObject().optionalCast<ScheduleCompact>(); ASSERT_TRUE(oSchedule); schedule = *oSchedule; EXPECT_TRUE(light1.setSchedule(schedule)); ASSERT_TRUE(componentData.initialized()); EXPECT_EQ(versionUUID,componentData.versionUUID()); // changing data field in componentObject does not invalidate schedule component, but does change version UUID StringVector values; values.push_back("Through: 12/31"); IdfExtensibleGroup eg = componentData.primaryComponentObject().pushExtensibleGroup(values); EXPECT_FALSE(eg.empty()); ASSERT_TRUE(componentData.initialized()); EXPECT_NE(versionUUID,componentData.versionUUID()); versionUUID = componentData.versionUUID(); // changing type limits used by schedule in component invalidates the component Handle h = componentData.handle(); EXPECT_TRUE(justLights.isMember(h)); ScheduleTypeLimits newTypeLimits = typeLimits.clone(justLights).cast<ScheduleTypeLimits>(); EXPECT_FALSE(newTypeLimits.handle() == typeLimits.handle()); EXPECT_TRUE(schedule.setPointer(OS_Schedule_CompactFields::ScheduleTypeLimitsName,newTypeLimits.handle())); EXPECT_FALSE(componentData.initialized()); EXPECT_FALSE(justLights.isMember(h)); }
boost::optional<IdfObject> ForwardTranslator::translateScheduleTypeLimits( ScheduleTypeLimits & modelObject ) { IdfObject idfObject(openstudio::IddObjectType::ScheduleTypeLimits); m_idfObjects.push_back(idfObject); idfObject.setString(ScheduleTypeLimitsFields::Name, modelObject.name().get()); OptionalDouble d = modelObject.getDouble(OS_ScheduleTypeLimitsFields::LowerLimitValue, false); if (d){ idfObject.setDouble(ScheduleTypeLimitsFields::LowerLimitValue, *d); } d = modelObject.getDouble(OS_ScheduleTypeLimitsFields::UpperLimitValue, false); if (d){ idfObject.setDouble(ScheduleTypeLimitsFields::UpperLimitValue, *d); } OptionalString s = modelObject.getString(OS_ScheduleTypeLimitsFields::NumericType, false, true); if (s){ idfObject.setString(ScheduleTypeLimitsFields::NumericType, *s); } s = modelObject.getString(OS_ScheduleTypeLimitsFields::UnitType, false, true); if (s){ std::string unitType = *s; boost::to_lower(unitType); if ((unitType == "clothinginsulation") || (unitType == "rotationsperminute") || (unitType == "massflowrate") || (unitType == "pressure") || (unitType == "solarenergy")) { // unit type key is unsupported in EnergyPlus--fall back on 'Any Number' m_idfObjects.pop_back(); if (!m_anyNumberScheduleTypeLimits) { IdfObject anyNumberLimits(IddObjectType::ScheduleTypeLimits); m_idfObjects.push_back(anyNumberLimits); anyNumberLimits.setName("Any Number"); m_anyNumberScheduleTypeLimits = anyNumberLimits; } return m_anyNumberScheduleTypeLimits; } idfObject.setString(ScheduleTypeLimitsFields::UnitType, unitType); } return boost::optional<IdfObject>(idfObject); }
bool ScheduleVariableInterval_Impl::setScheduleTypeLimits(const ScheduleTypeLimits& scheduleTypeLimits) { if (scheduleTypeLimits.model() != model()) { return false; } return setPointer(OS_Schedule_VariableIntervalFields::ScheduleTypeLimitsName,scheduleTypeLimits.handle()); }
TEST_F(ModelFixture, ScheduleTypeRegistry_UseInSetSchedule) { Model model; // create a schedule ScheduleConstant schedule(model); // set a minimal schedule type limits ScheduleTypeLimits anyNumber(model); anyNumber.setName("Any Number"); bool ok = schedule.setScheduleTypeLimits(anyNumber); EXPECT_TRUE(ok); // try to set Lights schedule--should fail b/c needs between 0 and 1 LightsDefinition definition(model); definition.setLightingLevel(100.0); Lights light(definition); ok = light.setSchedule(schedule); EXPECT_FALSE(ok); // set Availablity schedule type limits ScheduleType scheduleType = ScheduleTypeRegistry::instance().getScheduleType("CoilCoolingDXSingleSpeed","Availability"); ScheduleTypeLimits availabilityLimits = ScheduleTypeRegistry::instance().getOrCreateScheduleTypeLimits(scheduleType,model); ok = schedule.setScheduleTypeLimits(availabilityLimits); EXPECT_TRUE(ok); // try to set Lights schedule--used to fail b/c lights schedule is Dimensionless, not Availability, now passes ok = light.setSchedule(schedule); EXPECT_TRUE(ok); // clear conflicting information availabilityLimits.resetNumericType(); availabilityLimits.resetUnitType(); // set Lights schedule--should succeed b/c not in conflict ok = light.setSchedule(schedule); EXPECT_TRUE(ok); // try to clear schedule type limits--should fail b/c in use ok = schedule.resetScheduleTypeLimits(); EXPECT_FALSE(ok); // reset Lights schedule light.resetSchedule(); // try to clear schedule type limits--should succeed ok = schedule.resetScheduleTypeLimits(); EXPECT_TRUE(ok); EXPECT_FALSE(schedule.scheduleTypeLimits()); // set Lights schedule--should succeed and assign an appropriate ScheduleTypeLimits ok = light.setSchedule(schedule); EXPECT_TRUE(ok); ASSERT_TRUE(schedule.scheduleTypeLimits()); ScheduleTypeLimits lightsLimits = schedule.scheduleTypeLimits().get(); EXPECT_EQ("Fractional",lightsLimits.name().get()); ASSERT_TRUE(lightsLimits.numericType()); EXPECT_EQ("Continuous",lightsLimits.numericType().get()); EXPECT_EQ("Dimensionless",lightsLimits.unitType()); EXPECT_TRUE(lightsLimits.isUnitTypeDefaulted()); ASSERT_TRUE(lightsLimits.lowerLimitValue()); EXPECT_DOUBLE_EQ(0.0,lightsLimits.lowerLimitValue().get()); ASSERT_TRUE(lightsLimits.upperLimitValue()); EXPECT_DOUBLE_EQ(1.0,lightsLimits.upperLimitValue().get()); }
TEST_F(ModelFixture, ScheduleTypeRegistry_GetOrCreateScheduleTypeLimits) { { Model model; ScheduleType scheduleType = ScheduleTypeRegistry::instance().getScheduleType("People", "Activity Level"); ASSERT_TRUE(scheduleType.lowerLimitValue); EXPECT_EQ(0.0, scheduleType.lowerLimitValue.get()); EXPECT_FALSE(scheduleType.upperLimitValue); ScheduleTypeLimits limits = ScheduleTypeRegistry::instance().getOrCreateScheduleTypeLimits(scheduleType, model); ScheduleTypeLimits limits2 = ScheduleTypeRegistry::instance().getOrCreateScheduleTypeLimits(scheduleType, model); EXPECT_EQ(limits.handle(), limits2.handle()); EXPECT_TRUE(isCompatible(scheduleType, limits)); } { Model model; ScheduleType scheduleType = ScheduleTypeRegistry::instance().getScheduleType("RefrigerationCase", "Refrigerated Case Restocking"); ASSERT_TRUE(scheduleType.lowerLimitValue); EXPECT_EQ(0.0, scheduleType.lowerLimitValue.get()); EXPECT_FALSE(scheduleType.upperLimitValue); ScheduleTypeLimits limits = ScheduleTypeRegistry::instance().getOrCreateScheduleTypeLimits(scheduleType, model); ScheduleTypeLimits limits2 = ScheduleTypeRegistry::instance().getOrCreateScheduleTypeLimits(scheduleType, model); EXPECT_EQ(limits.handle(), limits2.handle()); EXPECT_TRUE(isCompatible(scheduleType, limits)); } { Model model; ScheduleType scheduleType = ScheduleTypeRegistry::instance().getScheduleType("ThermostatSetpointDualSetpoint", "Heating Setpoint Temperature"); EXPECT_FALSE(scheduleType.lowerLimitValue); EXPECT_FALSE(scheduleType.upperLimitValue); ScheduleTypeLimits limits = ScheduleTypeRegistry::instance().getOrCreateScheduleTypeLimits(scheduleType, model); ScheduleTypeLimits limits2 = ScheduleTypeRegistry::instance().getOrCreateScheduleTypeLimits(scheduleType, model); EXPECT_EQ(limits.handle(), limits2.handle()); EXPECT_EQ("Temperature", limits.name().get()); EXPECT_TRUE(isCompatible(scheduleType, limits)); ASSERT_EQ(1u, model.getConcreteModelObjectsByName<ScheduleTypeLimits>("Temperature").size()); EXPECT_EQ("Temperature", model.getConcreteModelObjectsByName<ScheduleTypeLimits>("Temperature")[0].name().get()); ModelObject scheduleType2 = limits.clone(); EXPECT_EQ("Temperature 1", scheduleType2.name().get()); EXPECT_EQ(2u, model.getConcreteModelObjectsByName<ScheduleTypeLimits>("Temperature").size()); limits.remove(); ASSERT_EQ(1u, model.getConcreteModelObjectsByName<ScheduleTypeLimits>("Temperature").size()); EXPECT_EQ("Temperature 1", model.getConcreteModelObjectsByName<ScheduleTypeLimits>("Temperature 1")[0].name().get()); limits = ScheduleTypeRegistry::instance().getOrCreateScheduleTypeLimits(scheduleType, model); EXPECT_EQ(limits.handle(), scheduleType2.handle()); EXPECT_EQ("Temperature 1", limits.name().get()); } { Model model; for (auto className : ScheduleTypeRegistry::instance().classNames()){ for (auto scheduleType : ScheduleTypeRegistry::instance().getScheduleTypesByClassName(className)){ ScheduleTypeLimits limits = ScheduleTypeRegistry::instance().getOrCreateScheduleTypeLimits(scheduleType, model); ScheduleTypeLimits limits2 = ScheduleTypeRegistry::instance().getOrCreateScheduleTypeLimits(scheduleType, model); EXPECT_EQ(limits.handle(), limits2.handle()); EXPECT_EQ(ScheduleTypeLimits::units(scheduleType.unitType, false), ScheduleTypeLimits::units(limits.unitType(), false)); EXPECT_TRUE(isCompatible(scheduleType, limits)); } } } }
bool isCompatible(const ScheduleTypeLimits &parentLimits, const ScheduleTypeLimits &candidate) { if (candidate == parentLimits) { return true; } // check continuous/discrete if (OptionalString numericType = parentLimits.numericType()) { if (!candidate.numericType() || !istringEqual(candidate.numericType().get(),*numericType)) { return false; } } // check unit type std::string unitType = parentLimits.unitType(); if (parentLimits.isUnitTypeDefaulted() || istringEqual("Dimensionless",unitType)) { if (!(candidate.isUnitTypeDefaulted() || (istringEqual("Dimensionless",candidate.unitType())))) { return false; } } else { if (!istringEqual(candidate.unitType(),unitType)) { return false; } } // check lower limit if (parentLimits.lowerLimitValue()) { if (!candidate.lowerLimitValue() || (candidate.lowerLimitValue().get() < parentLimits.lowerLimitValue().get())) { return false; } } // check upper limit if (parentLimits.upperLimitValue()) { if (!candidate.upperLimitValue() || (candidate.upperLimitValue().get() > parentLimits.upperLimitValue().get())) { return false; } } // passed all checks return true; }