TEST_F(IdfFixture,WorkspaceObject_Construction) { // get vector of IdfFile objects as fodder for tests IdfObjectVector idfObjects = epIdfFile.objects(); OptionalWorkspaceObject w; OptionalHandleVector hv; // construct empty workspace, and set Idd to be EnergyPlusIdd StrictnessLevel level(StrictnessLevel::Draft); IddFileType fileType(IddFileType::EnergyPlus); Workspace ws(level,fileType); // add object with no pointers. should be successful. w = ws.addObject(idfObjects[0]); // Building ASSERT_TRUE(w); // should return OptionalHandle instead OptionalWorkspaceObject object = ws.getObject(w->handle()); ASSERT_TRUE(object); EXPECT_TRUE(object->iddObject().type() == openstudio::IddObjectType::Building); // add object with pointer, and do not include pointed to object. should be successful, but // pointer should be null. object.canBeSource() should be true. // add object with pointer, and do include pointed to object. should be successful, and // following pointer should yield target object. source should be source, target should be // target. }
TEST_F(IdfFixture, WorkspaceObject_Lights_Strictness_Draft) { Workspace workspace(StrictnessLevel::Draft,IddFileType::EnergyPlus); EXPECT_TRUE(workspace.isValid()); OptionalWorkspaceObject w = workspace.addObject(IdfObject(IddObjectType::Lights)); ASSERT_TRUE(w); OptionalWorkspaceObject light = workspace.getObject(w->handle()); ASSERT_TRUE(light); // certain things we can't invalidate EXPECT_TRUE(light->setString(LightsFields::Name, "")); EXPECT_TRUE(light->setDouble(LightsFields::Name, 0)); EXPECT_TRUE(light->setString(LightsFields::ZoneorZoneListName, "")); // PointerType error EXPECT_TRUE(light->setPointer(LightsFields::ZoneorZoneListName, Handle())); // PointerType error EXPECT_TRUE(light->setString(LightsFields::ScheduleName, "")); // PointerType error EXPECT_TRUE(light->setPointer(LightsFields::ScheduleName, Handle())); // PointerType error EXPECT_TRUE(light->setString(LightsFields::DesignLevelCalculationMethod, "")); // this is ok because there is a default EXPECT_FALSE(light->setString(LightsFields::DesignLevelCalculationMethod, "Hi")); // DataType error EXPECT_FALSE(light->setDouble(LightsFields::DesignLevelCalculationMethod, 0)); // DataType error EXPECT_FALSE(light->setString(LightsFields::LightingLevel, "Hi")); // DataType error EXPECT_FALSE(light->setDouble(LightsFields::LightingLevel, -1)); // NumericBound error EXPECT_TRUE(light->setDouble(LightsFields::LightingLevel, 0)); EXPECT_TRUE(light->setDouble(LightsFields::LightingLevel, 1)); EXPECT_TRUE(workspace.isValid(StrictnessLevel::None)); EXPECT_TRUE(workspace.isValid(StrictnessLevel::Draft)); EXPECT_FALSE(workspace.isValid(StrictnessLevel::Final)); }
TEST_F(IdfFixture, WorkspaceObject_Lights_Strictness_None) { Workspace workspace(StrictnessLevel::None,IddFileType::EnergyPlus); EXPECT_TRUE(workspace.isValid()); OptionalWorkspaceObject w = workspace.addObject(IdfObject(IddObjectType::Lights)); ASSERT_TRUE(w); OptionalWorkspaceObject light = workspace.getObject(w->handle()); ASSERT_TRUE(light); // can invalidate all we want EXPECT_TRUE(light->setString(LightsFields::Name, "")); EXPECT_TRUE(light->setDouble(LightsFields::Name, 0)); EXPECT_TRUE(light->setString(LightsFields::ZoneorZoneListName, "")); EXPECT_TRUE(light->setPointer(LightsFields::ZoneorZoneListName, Handle())); EXPECT_TRUE(light->setString(LightsFields::ScheduleName, "")); EXPECT_TRUE(light->setPointer(LightsFields::ScheduleName, Handle())); EXPECT_TRUE(light->setString(LightsFields::DesignLevelCalculationMethod, "")); EXPECT_TRUE(light->setDouble(LightsFields::DesignLevelCalculationMethod, 0)); EXPECT_TRUE(light->setString(LightsFields::LightingLevel, "Hi")); EXPECT_TRUE(light->setDouble(LightsFields::LightingLevel, -1)); EXPECT_TRUE(light->setDouble(LightsFields::LightingLevel, 0)); EXPECT_TRUE(light->setDouble(LightsFields::LightingLevel, 1)); EXPECT_TRUE(workspace.isValid(StrictnessLevel::None)); EXPECT_FALSE(workspace.isValid(StrictnessLevel::Draft)); EXPECT_FALSE(workspace.isValid(StrictnessLevel::Final)); }
TEST_F(IdfFixture,WorkspaceObjectWatcher_RelationshipFieldChanges_TargetDeleted) { IdfObject object(IddObjectType::Lights); Workspace workspace(StrictnessLevel::Draft, IddFileType::EnergyPlus); OptionalWorkspaceObject owo = workspace.addObject(object); ASSERT_TRUE(owo); WorkspaceObject workspaceObject = *owo; WorkspaceObjectWatcher watcher(workspaceObject); EXPECT_FALSE(watcher.dirty()); OptionalWorkspaceObject oZone = workspace.addObject(IdfObject(IddObjectType::Zone)); ASSERT_TRUE(oZone); EXPECT_TRUE(workspaceObject.setPointer(LightsFields::ZoneorZoneListName, oZone->handle())); EXPECT_TRUE(watcher.dirty()); EXPECT_FALSE(watcher.dataChanged()); EXPECT_FALSE(watcher.nameChanged()); EXPECT_TRUE(watcher.relationshipChanged()); watcher.clearState(); EXPECT_FALSE(watcher.dirty()); EXPECT_FALSE(watcher.dataChanged()); EXPECT_FALSE(watcher.nameChanged()); EXPECT_FALSE(watcher.relationshipChanged()); oZone->remove(); EXPECT_TRUE(watcher.dirty()); EXPECT_FALSE(watcher.dataChanged()); EXPECT_FALSE(watcher.nameChanged()); EXPECT_TRUE(watcher.relationshipChanged()); }
TEST_F(IdfFixture, WorkspaceObject_Filter_Sources) { Workspace ws; OptionalWorkspaceObject node = ws.addObject(IdfObject(IddObjectType::OS_Node)); OptionalWorkspaceObject node2 = ws.addObject(IdfObject(IddObjectType::OS_Node)); OptionalWorkspaceObject node3 = ws.addObject(IdfObject(IddObjectType::OS_Node)); OptionalWorkspaceObject spm = ws.addObject(IdfObject(IddObjectType::OS_SetpointManager_MixedAir)); EXPECT_TRUE(spm->setPointer(OS_SetpointManager_MixedAirFields::SetpointNodeorNodeListName, node->handle())); EXPECT_TRUE(spm->setPointer(OS_SetpointManager_MixedAirFields::FanInletNodeName,node->handle())); EXPECT_TRUE(spm->setPointer(OS_SetpointManager_MixedAirFields::FanOutletNodeName,node2->handle())); EXPECT_TRUE(spm->setPointer(OS_SetpointManager_MixedAirFields::ReferenceSetpointNodeName,node3->handle())); WorkspaceObjectVector sourcesVector = node->sources(); EXPECT_EQ(1, sourcesVector.size()); sourcesVector = node->getSources(IddObjectType::OS_SetpointManager_MixedAir); EXPECT_EQ(1, sourcesVector.size()); }
TEST_F(EnergyPlusFixture,ReverseTranslator_Zone) { Workspace inWorkspace(StrictnessLevel::None, IddFileType::EnergyPlus); OptionalWorkspaceObject zoneObject = inWorkspace.addObject(IdfObject(IddObjectType::Zone)); ASSERT_TRUE(zoneObject); OptionalWorkspaceObject lightsObject = inWorkspace.addObject(IdfObject(IddObjectType::Lights)); ASSERT_TRUE(lightsObject); EXPECT_TRUE(lightsObject->setPointer(openstudio::LightsFields::ZoneorZoneListName, zoneObject->handle())); ReverseTranslator reverseTranslator; ASSERT_NO_THROW(reverseTranslator.translateWorkspace(inWorkspace)); Model model = reverseTranslator.translateWorkspace(inWorkspace); ASSERT_EQ(static_cast<unsigned>(1), model.getModelObjects<openstudio::model::ThermalZone>().size()); openstudio::model::ThermalZone zone = model.getModelObjects<openstudio::model::ThermalZone>()[0]; ASSERT_EQ(static_cast<unsigned>(1), model.getModelObjects<openstudio::model::Space>().size()); openstudio::model::Space space = model.getModelObjects<openstudio::model::Space>()[0]; ASSERT_EQ(static_cast<unsigned>(1), model.getModelObjects<openstudio::model::Lights>().size()); openstudio::model::Lights lights = model.getModelObjects<openstudio::model::Lights>()[0]; ASSERT_TRUE(lights.space()); EXPECT_TRUE(space.handle() == lights.space()->handle()); ASSERT_TRUE(lights.space()->thermalZone()); EXPECT_TRUE(zone.handle() == lights.space()->thermalZone()->handle()); }
OptionalModelObject ReverseTranslator::translateFenestrationSurfaceDetailed( const WorkspaceObject & workspaceObject ) { if( workspaceObject.iddObject().type() != IddObjectType::FenestrationSurface_Detailed ){ LOG(Error, "WorkspaceObject is not IddObjectType: Site:FenestrationSurface_Detailed"); return boost::none; } openstudio::Point3dVector vertices = getVertices(FenestrationSurface_DetailedFields::NumberofVertices + 1, workspaceObject); boost::optional<SubSurface> subSurface; try{ subSurface = SubSurface(vertices, m_model); }catch(const std::exception&){ LOG(Error, "Cannot create SubSurface for object: " << workspaceObject); return boost::none; } OptionalString s = workspaceObject.name(); if(s) { subSurface->setName(*s); } OptionalWorkspaceObject target = workspaceObject.getTarget(openstudio::FenestrationSurface_DetailedFields::ConstructionName); if (target){ OptionalModelObject modelObject = translateAndMapWorkspaceObject(*target); if (modelObject){ if (modelObject->optionalCast<ConstructionBase>()){ subSurface->setConstruction(modelObject->cast<ConstructionBase>()); } } } target = workspaceObject.getTarget(openstudio::FenestrationSurface_DetailedFields::BuildingSurfaceName); if (target){ OptionalModelObject modelObject = translateAndMapWorkspaceObject(*target); if (modelObject){ if (modelObject->optionalCast<Surface>()){ subSurface->setSurface(modelObject->cast<Surface>()); } } } // needs to be after .setSurface. s = workspaceObject.getString(FenestrationSurface_DetailedFields::SurfaceType); if (s) { if (istringEqual("Window", *s)){ s = "FixedWindow"; boost::optional<Surface> surface = subSurface->surface(); if (surface){ if ((surface->surfaceType() == "RoofCeiling") && (surface->outsideBoundaryCondition() == "Outdoors")){ s = "Skylight"; } } } subSurface->setSubSurfaceType(*s); } target = workspaceObject.getTarget(openstudio::FenestrationSurface_DetailedFields::OutsideBoundaryConditionObject); if (target){ if (target->iddObject().type() == IddObjectType::Zone){ // Zone boundary condition OptionalModelObject modelObject = translateAndMapWorkspaceObject(*target); if(modelObject->optionalCast<Space>()){ Space adjacentSpace = modelObject->cast<Space>(); OptionalSurface surface = subSurface->surface(); if (surface && surface->space()){ Space space = surface->space().get(); if (surface->adjacentSurface()){ Surface adjacentSurface = surface->adjacentSurface().get(); if (adjacentSurface.space() && adjacentSpace.handle() == adjacentSurface.space()->handle()){ Transformation transformation = adjacentSpace.transformation().inverse()*surface->space()->transformation(); // duplicate subsurface in other space SubSurface adjacentSubSurface = subSurface->clone(m_model).cast<SubSurface>(); adjacentSubSurface.setName(subSurface->name().get() + " Reversed"); std::reverse(vertices.begin(), vertices.end()); adjacentSubSurface.setVertices(transformation*vertices); adjacentSubSurface.setSurface(adjacentSurface); subSurface->setAdjacentSubSurface(adjacentSubSurface); return subSurface.get(); } } } } }else if (target->iddObject().type() == IddObjectType::FenestrationSurface_Detailed){ // SubSurface boundary condition // see if we have already mapped other sub surface, don't do it here because that is circular auto it = m_workspaceToModelMap.find(target->handle()); if( it != m_workspaceToModelMap.end()){ if (it->second.optionalCast<SubSurface>()){ // this will set other side boundary object on both surfaces SubSurface adjacentSubSurface = it->second.cast<SubSurface>(); subSurface->setAdjacentSubSurface(adjacentSubSurface); return subSurface.get(); } } }else{ LOG(Error, "OutsideBoundaryConditionObject not yet mapped for object of type " << target->iddObject().name()); } } // DLM: should these be before control paths that return above? OptionalDouble d = workspaceObject.getDouble(FenestrationSurface_DetailedFields::ViewFactortoGround); if (d) { subSurface->setViewFactortoGround(*d); } target = workspaceObject.getTarget(openstudio::FenestrationSurface_DetailedFields::ShadingControlName); if (target){ LOG(Warn, "Shading Control Name not yet mapped for FenestrationSurface:Detailed"); } target = workspaceObject.getTarget(openstudio::FenestrationSurface_DetailedFields::FrameandDividerName); if (target){ LOG(Warn, "Frame and Divider Name not yet mapped for FenestrationSurface:Detailed"); } OptionalInt i = workspaceObject.getInt(FenestrationSurface_DetailedFields::Multiplier); if (i) { subSurface->setMultiplier(*i); } return subSurface.get(); }
OptionalModelObject ReverseTranslator::translateBuildingSurfaceDetailed( const WorkspaceObject & workspaceObject ) { if( workspaceObject.iddObject().type() != IddObjectType::BuildingSurface_Detailed ){ LOG(Error, "WorkspaceObject is not IddObjectType: BuildingSurface:Detailed"); return boost::none; } openstudio::Point3dVector vertices = getVertices(BuildingSurface_DetailedFields::NumberofVertices + 1, workspaceObject); boost::optional<Surface> surface; try{ surface = Surface(vertices, m_model); }catch(const std::exception&){ LOG(Error, "Cannot create Surface for object: " << workspaceObject); return boost::none; } OptionalString s = workspaceObject.name(); if(s) { surface->setName(*s); } OptionalWorkspaceObject target = workspaceObject.getTarget(openstudio::BuildingSurface_DetailedFields::ConstructionName); if (target){ OptionalModelObject modelObject = translateAndMapWorkspaceObject(*target); if (modelObject){ if (modelObject->optionalCast<ConstructionBase>()){ surface->setConstruction(modelObject->cast<ConstructionBase>()); } } } target = workspaceObject.getTarget(openstudio::BuildingSurface_DetailedFields::ZoneName); if (target){ OptionalModelObject modelObject = translateAndMapWorkspaceObject(*target); if (modelObject){ if (modelObject->optionalCast<Space>()){ surface->setSpace(modelObject->cast<Space>()); } } } s = workspaceObject.getString(BuildingSurface_DetailedFields::SurfaceType); if (s) { if (istringEqual("Roof", *s) || istringEqual("Ceiling", *s)){ s = "RoofCeiling"; } surface->setSurfaceType(*s); } //std::string surfaceType = surface->surfaceType(); s = workspaceObject.getString(BuildingSurface_DetailedFields::SunExposure); if (s) { surface->setSunExposure(*s); } s = workspaceObject.getString(BuildingSurface_DetailedFields::WindExposure); if (s) { surface->setWindExposure(*s); } OptionalDouble d = workspaceObject.getDouble(BuildingSurface_DetailedFields::ViewFactortoGround); if (d) { surface->setViewFactortoGround(*d); } target = workspaceObject.getTarget(openstudio::BuildingSurface_DetailedFields::OutsideBoundaryConditionObject); if (target){ if (target->iddObject().type() == IddObjectType::Zone){ // Zone boundary condition OptionalModelObject modelObject = translateAndMapWorkspaceObject(*target); if(modelObject->optionalCast<Space>()){ Space adjacentSpace = modelObject->cast<Space>(); if (surface->space()){ // insert this surface in the map so subsurface translation can find it m_workspaceToModelMap.insert(std::make_pair(workspaceObject.handle(), surface.get())); // need to translate all sub surfaces here so they will be in adjacent space for (const WorkspaceObject& workspaceSubSurface : workspaceObject.getSources(IddObjectType::FenestrationSurface_Detailed)){ translateAndMapWorkspaceObject(workspaceSubSurface); } // create adjacent surface in other space surface->createAdjacentSurface(adjacentSpace); return surface.get(); } } }else if (target->iddObject().type() == IddObjectType::BuildingSurface_Detailed){ // Surface boundary condition // see if we have already mapped other surface, don't do it here because that is circular if (target->handle() == workspaceObject.handle() ){ // these objects are the same, set boundary condition to adiabatic surface->setOutsideBoundaryCondition("Adiabatic"); return surface.get(); }else{ auto it = m_workspaceToModelMap.find(target->handle()); if( it != m_workspaceToModelMap.end()){ if (it->second.optionalCast<Surface>()){ // this will set other side boundary object on both surfaces Surface adjacentSurface = it->second.cast<Surface>(); surface->setAdjacentSurface(adjacentSurface); return surface.get(); } } } }else{ LOG(Error, "OutsideBoundaryConditionObject not yet mapped for object of type " << target->iddObject().name()); } } s = workspaceObject.getString(BuildingSurface_DetailedFields::OutsideBoundaryCondition); if (s) { surface->setOutsideBoundaryCondition(*s); } return surface.get(); }
TEST_F(IdfFixture, WorkspaceObject_FieldSettingWithHiddenPushes) { Workspace scratch(StrictnessLevel::None,IddFileType::EnergyPlus); // Strictness level None std::stringstream text; text << "ZoneHVAC:HighTemperatureRadiant," << std::endl << " MyRadiantSystem," << std::endl << " MyHVACSchedule," << std::endl << " MyCoreZone," << std::endl << " HeatingDesignCapacity," << std::endl << " Autosize," << std::endl << " ," << std::endl << " ," << std::endl << " Electricity;"; OptionalIdfObject oObj = IdfObject::load(text.str()); ASSERT_TRUE(oObj); IdfObject idfObject = *oObj; OptionalWorkspaceObject w1 = scratch.addObject(idfObject); ASSERT_TRUE(w1); OptionalWorkspaceObject tObject = scratch.getObject(w1->handle ()); ASSERT_TRUE(tObject); WorkspaceObject object = *tObject; EXPECT_EQ(static_cast<unsigned>(8),object.numFields()); // create schedule object to point to from non-extensible field text.str(""); text << "Schedule:Compact," << std::endl << " AlwaysOn," << std::endl << " ," << std::endl << " For: AllOtherDays," << std::endl << " Until: 24:00," << std::endl << " 1.0;"; oObj = IdfObject::load(text.str()); ASSERT_TRUE(oObj); idfObject = *oObj; ASSERT_TRUE(idfObject.iddObject().type() == IddObjectType::Schedule_Compact); OptionalWorkspaceObject w2 = scratch.addObject(idfObject); ASSERT_TRUE(w2); EXPECT_TRUE(object.setPointer(14,w2->handle ())); EXPECT_EQ(15u,object.numFields()); tObject = object.getTarget(14); ASSERT_TRUE(tObject); EXPECT_TRUE(tObject->handle() == w2->handle()); // hidden pushing for setting extensible string pointer EXPECT_TRUE(object.setString(16,*(tObject->name()))); // should only work at strictness none tObject = object.getTarget(16); ASSERT_TRUE(tObject); EXPECT_TRUE(tObject->handle() == w2->handle()); EXPECT_EQ(18u,object.numFields()); // hidden pushing for setting extensible double EXPECT_TRUE(object.setDouble(19,0.5)); EXPECT_EQ(20u,object.numFields()); OptionalDouble dValue = object.getDouble(19); ASSERT_TRUE(dValue); EXPECT_NEAR(0.5,*dValue,tol); // SHOULD NOT BE VALID scratch = Workspace(StrictnessLevel::Draft, IddFileType::EnergyPlus); // Non-null data must be valid text.str(""); text << "ZoneHVAC:HighTemperatureRadiant," << std::endl << " MyRadiantSystem," << std::endl << " MyHVACSchedule," << std::endl << " MyCoreZone," << std::endl << " HeatingDesignCapacity," << std::endl << " Autosize," << std::endl << " ," << std::endl << " ," << std::endl << " Electricity;"; oObj = IdfObject::load(text.str()); ASSERT_TRUE(oObj); idfObject = *oObj; w2 = scratch.addObject(idfObject); ASSERT_TRUE(w2); tObject = scratch.getObject(w2->handle()); ASSERT_TRUE(tObject); object = *tObject; // hidden pushing for setting nonextensible double EXPECT_FALSE(object.setDouble(9,1.5)); EXPECT_EQ(8u,object.numFields()); EXPECT_TRUE(object.setDouble(9,0.6)); EXPECT_EQ(10u,object.numFields()); // hidden pushing for setting nonextensible string EXPECT_FALSE(object.setString(12,"bad key")); EXPECT_EQ(10u,object.numFields()); EXPECT_TRUE(object.setString(12,"MeanAirTemperature")); EXPECT_EQ(13u,object.numFields()); // hidden pushing for setting nonextensible pointer EXPECT_TRUE(object.setString(14,"")); EXPECT_EQ(15u,object.numFields()); // hidden pushing for setting extensible string pointer EXPECT_FALSE(object.setString(16,"MySurface")); EXPECT_EQ(15u,object.numFields()); EXPECT_TRUE(object.setString(16,"")); EXPECT_EQ(18u,object.numFields()); // hidden pushing for setting extensible double EXPECT_FALSE(object.setDouble(21,-1.5)); EXPECT_EQ(18u,object.numFields()); EXPECT_TRUE(object.setDouble(19,0.5)); EXPECT_EQ(20u,object.numFields()); }