TEST_F(UnitsFixture,IddUnits_BtuSystem) { IddUnitString iddString("Btu/h-ft-F"); EXPECT_EQ("Btu/h*ft*R",iddString.toStandardUnitString()); OptionalUnit unit = createUnit(iddString.toStandardUnitString()); ASSERT_TRUE(unit); EXPECT_TRUE(unit->system() == UnitSystem::BTU); }
TEST_F(IddFixture,IddFactory_OpenStudioUnits_SubTest2) { IddObjectVector objects = IddFactory::instance().getObjects(IddFileType(IddFileType::OpenStudio)); bool found = false; for (const IddObject& object : objects) { IddFieldVector fields = object.nonextensibleFields(); IddFieldVector temp = object.extensibleGroup(); fields.insert(fields.end(),temp.begin(),temp.end()); for (const IddField& field : fields) { if (OptionalString iddUnits = field.properties().units) { if (*iddUnits == "kg-H2O/kg-Air") { found = true; OptionalUnit siUnit = field.getUnits(); ASSERT_TRUE(siUnit); EXPECT_TRUE(siUnit->system() == UnitSystem::SI); EXPECT_EQ("",siUnit->standardString()); EXPECT_EQ("kg_{H2O}/kg_{air}",siUnit->prettyString()); break; } } } if (found) { break; } } EXPECT_TRUE(found); }
TEST_F(IddFixture,IddFactory_OpenStudioUnits_SubTest3) { IddObjectVector objects = IddFactory::instance().getObjects(IddFileType(IddFileType::OpenStudio)); bool found = false; for (const IddObject& object : objects) { IddFieldVector fields = object.nonextensibleFields(); IddFieldVector temp = object.extensibleGroup(); fields.insert(fields.end(),temp.begin(),temp.end()); for (const IddField& field : fields) { if (OptionalString iddUnits = field.properties().ipUnits) { if (*iddUnits == "gal/min") { if (object.type() == IddObjectType::OS_AirTerminal_SingleDuct_ParallelPIU_Reheat) { LOG(Debug,"Gal/min field: " << field.name()); } found = true; OptionalUnit ipUnit = field.getUnits(true); ASSERT_TRUE(ipUnit); EXPECT_TRUE(ipUnit->system() == UnitSystem::Mixed); EXPECT_EQ("crgal^3/min",ipUnit->standardString()); EXPECT_EQ("gal/min",ipUnit->prettyString()); } } } } EXPECT_TRUE(found); }
TEST_F(IddFixture,IddFactory_OpenStudioUnits_SubTest1) { IddObjectVector objects = IddFactory::instance().getObjects(IddFileType(IddFileType::OpenStudio)); bool found = false; for (const IddObject& object : objects) { IddFieldVector fields = object.nonextensibleFields(); IddFieldVector temp = object.extensibleGroup(); fields.insert(fields.end(),temp.begin(),temp.end()); for (const IddField& field : fields) { if (OptionalString iddUnits = field.properties().ipUnits) { if (*iddUnits == "Btu/h-ft-F") { found = true; OptionalUnit siUnit = field.getUnits(false); ASSERT_TRUE(siUnit); EXPECT_TRUE(siUnit->system() == UnitSystem::SI); EXPECT_EQ("kg*m/s^3*K",siUnit->standardString(false)); OptionalUnit ipUnit = field.getUnits(true); ASSERT_TRUE(ipUnit); EXPECT_TRUE(ipUnit->system() == UnitSystem::BTU); Quantity q(1.0,*ipUnit); OptionalQuantity testQ = convert(q,*siUnit); EXPECT_TRUE(testQ); break; } } } if (found) { break; } } EXPECT_TRUE(found); }
TEST_F(UnitsFixture,IddUnits_Grams) { IddUnitString iddString("g/m-s-K"); EXPECT_EQ("mkg/m*s*K",iddString.toStandardUnitString()); OptionalUnit unit = createUnit(iddString.toStandardUnitString()); ASSERT_TRUE(unit); EXPECT_TRUE(unit->system() == UnitSystem::SI); EXPECT_EQ(-3,unit->scale().exponent); }
/* Test for bug found in #2900 where it currently returns "1/ftH_{2}O^2" (this is a createUnit problem really...) */ TEST_F(UnitsFixture,UnitFactory_IP_Pressure_wc) { { OptionalUnit unit = openstudio::createUnit("1/ftH_{2}O"); ASSERT_TRUE(unit); EXPECT_EQ("1/ftH_{2}O", unit->standardString()); } { OptionalUnit unit = openstudio::createUnit("1/inH_{2}O"); ASSERT_TRUE(unit); EXPECT_EQ("1/inH_{2}O", unit->standardString()); } }
boost::optional<Quantity> ScheduleBase_Impl::toQuantity(double value, bool returnIP) const { OptionalQuantity result; if (OptionalScheduleTypeLimits scheduleTypeLimits = this->scheduleTypeLimits()) { if (OptionalUnit siUnits = ScheduleTypeLimits::units(scheduleTypeLimits->unitType(),false)) { result = Quantity(value,*siUnits); if (returnIP) { OptionalUnit ipUnits = ScheduleTypeLimits::units(scheduleTypeLimits->unitType(),returnIP); OS_ASSERT(ipUnits); if (ipUnits.get() != siUnits.get()) { result = convert(*result,*ipUnits); } } } } return result; }
OSQuantityVector ScheduleBase_Impl::getValues(bool returnIP) const { OSQuantityVector result; if (OptionalScheduleTypeLimits scheduleTypeLimits = this->scheduleTypeLimits()) { if (OptionalUnit siUnits = ScheduleTypeLimits::units(scheduleTypeLimits->unitType(),false)) { result = OSQuantityVector(*siUnits,values()); if (returnIP) { OptionalUnit ipUnits = ScheduleTypeLimits::units(scheduleTypeLimits->unitType(),returnIP); OS_ASSERT(ipUnits); if (ipUnits.get() != siUnits.get()) { result = convert(result,*ipUnits); } } } } return result; }
OSOptionalQuantity ScheduleTypeLimits_Impl::getQuantityFromDouble(unsigned index, boost::optional<double> value, bool returnIP) const { OptionalUnit siUnits = ScheduleTypeLimits::units(unitType(),false); OS_ASSERT(siUnits); OptionalUnit units = siUnits->clone(); if (returnIP) { units = ScheduleTypeLimits::units(unitType(),true); OS_ASSERT(units); } if (value) { Quantity siQuantity(*value,*siUnits); if (!returnIP || (siUnits.get() == units.get())) { return OSOptionalQuantity(siQuantity); } else { OptionalQuantity result = convert(siQuantity,*units); OS_ASSERT(result); return OSOptionalQuantity(*result); } } return OSOptionalQuantity(*units); }
TEST_F(IddFixture,IddFactory_Units) { std::vector<boost::regex> unsupported; unsupported.push_back(boost::regex("\\$")); unsupported.push_back(boost::regex("eV")); unsupported.push_back(boost::regex("hh:mm")); unsupported.push_back(boost::regex("percent")); unsupported.push_back(boost::regex("ppm")); IddObjectVector objects = IddFactory::instance().getObjects(IddFileType(IddFileType::WholeFactory)); StringSet goodUnits; StringSet badUnits; for (const IddObject& object : objects) { IddFieldVector fields = object.nonextensibleFields(); IddFieldVector temp = object.extensibleGroup(); fields.insert(fields.end(),temp.begin(),temp.end()); for (const IddField& field : fields) { OptionalString iddUnits = field.properties().units; OptionalUnit siUnit; if (iddUnits) { // check if already tested units if (goodUnits.find(*iddUnits) != goodUnits.end()) { continue; } if (badUnits.find(*iddUnits) != badUnits.end()) { continue; } // screen for unsupported units for (const boost::regex& re : unsupported) { if (boost::regex_search(*iddUnits,re)) { iddUnits = boost::none; break; } } if (!iddUnits) { continue; } siUnit = field.getUnits(false); EXPECT_TRUE(siUnit || field.unitsBasedOnOtherField()) << object.name() << " field: " << field.name(); if (siUnit) { // could just return junk unit. if not junk, quantity will be convertible // to UnitSystem::SI. Quantity q(1.0,*siUnit); OptionalQuantity testQ = convert(q,UnitSystem(UnitSystem::SI)); EXPECT_TRUE(testQ) << "Unable to convert unit '" << *iddUnits << "' to SI for field '" << field.name() << "' in IddObject '" << object.name() << "'."; if (testQ) { goodUnits.insert(*iddUnits); EXPECT_TRUE(testQ->system() == UnitSystem::SI); } else { badUnits.insert(*iddUnits); LOG(Debug,"Unable to convert unit '" << *iddUnits << "' to SI for field '" << field.name() << "' in IddObject '" << object.name() << "'."); } } else if (field.unitsBasedOnOtherField()) { goodUnits.insert(*iddUnits); continue; } else { badUnits.insert(*iddUnits); LOG(Debug,"Unable to instantiate unit '" << *iddUnits << "' for field '" << field.name() << "' in IddObject '" << object.name() << "'."); continue; } OptionalUnit ipUnit = field.getUnits(true); EXPECT_TRUE(ipUnit); if (ipUnit) { // could just return junk unit. if not junk, quantity will be convertable // to *siUnit or UnitSystem::SI. Quantity q(1.0,*ipUnit); OptionalQuantity testQ; if (siUnit) { testQ = convert(q,*siUnit); } else { testQ = convert(q,UnitSystem(UnitSystem::SI)); } EXPECT_TRUE(testQ); if (testQ) { goodUnits.insert(*iddUnits); } else { badUnits.insert(ipUnit->standardString()); LOG(Debug,"Unable to convert unit " << *ipUnit << " to IDD/SI units " << *siUnit << " for field '" << field.name() << "' in IddObject '" << object.name() << "'."); } } else { badUnits.insert(*iddUnits); LOG(Debug,"Unable to instantiate ipUnit for field " << field.name() << " in IddObject " << object.name() << ", which has units " << *siUnit << "."); } } } } LOG(Info,"IddUnitStrings not handled properly by the Factories and Converter:"); for (const std::string& str : badUnits) { LOG(Info," " << str); } LOG(Info,"IddUnitStrings handled properly by the Factories and Converter:"); for (const std::string& str : goodUnits) { LOG(Info," " << str); } }
boost::optional<Unit> UnitFactorySingleton::createUnit(const std::string& unitString, UnitSystem system) const { if (m_callbackMaps.size() == 0) { LOG(Warn,"UnitFactorySingleton::createUnit called, but the maps appear to be empty."); } if (!unitString.empty() && !isUnit(unitString)) { LOG(Error,unitString << " is not properly formatted."); return boost::none; } OptionalUnit result = createUnitSimple(unitString,system); if (result) { return *result; } // no luck--start parsing std::string wUnitString(unitString); ScaleConstant scale = ScaleFactory::instance().createScale(0); if (isScaledUnit(wUnitString)) { std::pair<std::string,std::string> scaleAndUnit = decomposeScaledUnitString(wUnitString); scale = ScaleFactory::instance().createScale(scaleAndUnit.first); if (scale().value == 0.0) { LOG(Error,"Scaled unit string " << wUnitString << " uses invalid scale abbreviation " << scaleAndUnit.first << "."); return boost::none; } wUnitString = scaleAndUnit.second; } // wUnitString should now be compound unit std::pair< std::vector<std::string>,std::vector<std::string> > atomicUnits = decomposeCompoundUnitString(wUnitString); // loop through numerator std::vector<std::string>::const_iterator atomicUnitIter; std::vector<std::string>::const_iterator vectorEnd = atomicUnits.first.end(); std::pair<std::string,int> atomicUnit; for (atomicUnitIter = atomicUnits.first.begin(); atomicUnitIter != vectorEnd; ++atomicUnitIter) { // decompose into baseUnit and exponent atomicUnit = decomposeAtomicUnitString(*atomicUnitIter); // look for baseUnit OptionalUnit baseUnit = createUnitSimple(atomicUnit.first,system); if (!baseUnit) { // decompose into scale, baseUnit std::pair<std::string,std::string> scaleAndBaseUnit = extractScaleAbbreviation(atomicUnit.first); if (!scaleAndBaseUnit.first.empty()) { baseUnit = createUnitSimple(scaleAndBaseUnit.second,system); if (!baseUnit) { baseUnit = Unit(); baseUnit->setBaseUnitExponent(scaleAndBaseUnit.second,1); } baseUnit->setScale(scaleAndBaseUnit.first); } else { baseUnit = Unit(); baseUnit->setBaseUnitExponent(atomicUnit.first,1); } } baseUnit->pow(atomicUnit.second); if (!result) { result = baseUnit; } else { result = (*result) * (*baseUnit); } } // loop through denominator vectorEnd = atomicUnits.second.end(); for (atomicUnitIter = atomicUnits.second.begin(); atomicUnitIter != vectorEnd; ++atomicUnitIter) { // decompose into baseUnit and exponent atomicUnit = decomposeAtomicUnitString(*atomicUnitIter); // look for baseUnit OptionalUnit baseUnit = createUnitSimple(atomicUnit.first,system); if (!baseUnit) { // decompose into scale, baseUnit std::pair<std::string,std::string> scaleAndBaseUnit = extractScaleAbbreviation(atomicUnit.first); if (!scaleAndBaseUnit.first.empty()) { baseUnit = createUnitSimple(scaleAndBaseUnit.second,system); if (!baseUnit) { LOG(Info,scaleAndBaseUnit.second << " is not a registered baseUnit (in the selected system). " << "Returning it as-is in a mixed Unit (not SI, IP, etc.)."); baseUnit = Unit(); baseUnit->setBaseUnitExponent(scaleAndBaseUnit.second,1); } baseUnit->setScale(scaleAndBaseUnit.first); } else { LOG(Info,scaleAndBaseUnit.second << " is not a registered baseUnit (in the selected system). " << "Returning it as-is in a mixed Unit (not SI, IP, etc.)."); baseUnit = Unit(); baseUnit->setBaseUnitExponent(atomicUnit.first,1); } } baseUnit->pow(atomicUnit.second); if (!result) { baseUnit->pow(-1); result = baseUnit; } else { result = (*result) / (*baseUnit); } } BOOST_ASSERT(result); // impose overall scale if (scale().exponent != 0) { ScaleOpReturnType resultScale = scale()*result->scale(); result->setScale(resultScale.first().exponent); } return result; }
boost::optional<Unit> ScheduleTypeLimits::units(std::string unitType, bool returnIP) { boost::to_lower(unitType); OptionalUnit result; if (unitType.empty() || (unitType == "dimensionless") || (unitType == "availability") || (unitType == "controlmode")) { if (returnIP) { result = IPUnit(); } else { result = SIUnit(); } return result; } char firstLetter = unitType[0]; switch (firstLetter) { case 'a' : { if (unitType == "activitylevel") { result = (createSIPower() / createSIPeople()); } else if (unitType == "angle") { result = createIPAngle(); } break; } case 'c' : { if (unitType == "capacity") { if (returnIP) { result = BTUUnit(BTUExpnt(1,0,-1)); } else { result = createSIPower(); } } else if (unitType == "clothinginsulation") { result = Unit(); result->setBaseUnitExponent("clo",1); } else if (unitType == "convectioncoefficient") { if (returnIP) { result = BTUUnit(BTUExpnt(1,-2,-1,-1)); } else { result = createSIThermalConductance(); } } break; } case 'd' : { if (unitType == "deltatemperature") { if (returnIP) { result = createFahrenheitTemperature(); result->cast<TemperatureUnit>().setAsRelative(); } else { result = createCelsiusTemperature(); result->cast<TemperatureUnit>().setAsRelative(); } } break; } case 'l' : { if (unitType == "linearpowerdensity") { if (returnIP) { result = (createIPPower() / createIPLength()); } else { result = (createSIPower() / createSILength()); } } break; } case 'm' : { if (unitType == "massflowrate") { if (returnIP) { result = IPUnit(IPExpnt(1,0,-1)); } else { result = SIUnit(SIExpnt(1,0,-1)); } } break; } case 'p' : { if (unitType == "percent") { result = Unit(); result->setBaseUnitExponent("%",1); } else if (unitType == "power") { result = createSIPower(); } else if (unitType == "precipitationrate") { if (returnIP) { result = BTUUnit(BTUExpnt(0,1,-1)); } else { result = WhUnit(WhExpnt(0,-1,1)); } } else if (unitType == "pressure") { if (returnIP) { result = createIPPressure(); } else { result = createSIPressure(); } } break; } case 'r' : { if (unitType == "rotationsperminute") { result = createCFMFrequency(); } break; } case 's' : { if (unitType == "solarenergy") { result = WhUnit(WhExpnt(1,1,-2)); } break; } case 't' : { if (unitType == "temperature") { if (returnIP) { result = createFahrenheitTemperature(); } else { result = createCelsiusTemperature(); } } break; } case 'v' : { if (unitType == "velocity") { if (returnIP) { result = CFMUnit(CFMExpnt(1,-1)); } else { result = SIUnit(SIExpnt(0,1,-1)); } } if (unitType == "volumetricflowrate") { if (returnIP) { result = IPUnit(IPExpnt(0,3,-1)); } else { result = SIUnit(SIExpnt(0,3,-1)); } } break; } } return result; }